|
|
Регистрация Восстановить пароль |
Повторная активизация e-mail |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
|
|
Опции темы | Поиск в этой теме |
08.12.2016, 11:16 | #1 |
Форумчанин
Регистрация: 10.02.2014
Сообщений: 526
|
Работа с большим списком: как обезопаситься от переизбытка?
Здравствуйте!
История. (можно опустить, вопросы выделены дальше) Что-то решил заморочиться простыми числами и решил сделать программу для их поиска. Сначала программка казалась простой. Поиск идёт банальным делением чисел цикла от 2 до N на список уже найденных простых чисел, в который они добавляются, если число не удалось поделить нацело. Пока верхний предел был не больше 1 000 000. А вот когда решил замахнуться на 1 000 000 000 - тут уже стал серьёзно задумываться Во-первых, цикл завешивает всю программу, и на больших числах уже может оказаться проблемным определить: работает программа и проверяет очередное число по всем предыдущим найденным или просто зависла. (Вывод каждого цикла сразу отрубил для экономии времени на вывод, ограничив его каждым 10 000) Во-вторых, если у меня за всё возможное время работы программы (с утра и до вечера) все числа найтись не успеют - как быть с этим, если вывод всех найденных простых чисел у меня происходит только после завершения поиска (возможно, тоже экономит время)? Я раньше никогда не работал с потоками. Решил, что пришло таки время. Забил в поисковик, вроде, нашёл. Поверхность оказалась не сложной и интересной. Запустил цикл в поток, заодно в потоке объявил четыре переменных, по которым была бы возможность дополнительно отслеживать процесс и остановить его при необходимости без потери найденных данных. ОК. За день все циклы действительно не прошли. Сохранил имеющиеся данные, решил чуть подправить программку для возможности продолжения поиска. Одно изменение было элементарным - задать произвольное начало цикла по Edit. Второе - загрузка уже найденного списка. И вот тут начались ещё одни проблемы. Найденные простые числа я добавляю в TStringList (попытался работать с просто TList, но почему-то у меня не захотело работать деление i mod prochis[j] (prochis: TList). Решил перейти на TStringList. За прошлый день у меня обработалось больше 17 000 000 чисел, из которых больше 1 000 000 оказалось простыми. В конце работы список простых чисел у меня через цикл выводится в Memo, из которого я его без проблем, выделив всё, скопировал и сохранил в блокноте. А вот при загрузке так просто уже не получилось. Код:
Создал отдельную загрузку в ListBox через чтение текстового файла Readln. Зависает, но по появляющемуся "ползунку" ListBox'а хоть понятно, что приняла данные и надо просто подождать. Дальше пытался перенести уже оттуда в ProChis. Сначала через Код:
Но как быть теперь? Вопросы: Как ещё переделать программку чтоб она не зависала без возможности проверить работу в момент загрузки найденной базы перед новым стартом? Как обезопасить себя от зависания при выводе найденной базы в Memo после остановки? Как обезопасить себя от переполнения TStringList? Если учесть правило форума: одна тема - один вопрос, можно и так: как сделать программу работоспособной для больших чисел и списков? Надеюсь, тут найдутся люди, которые мне смогут помочь... Текущий код программки: Код:
Последний раз редактировалось Ship_1; 08.12.2016 в 12:34. |
08.12.2016, 12:31 | #2 | ||||
Старожил
Регистрация: 20.04.2008
Сообщений: 5,526
|
Цитата:
Для остановки потока УЖЕ есть готовый функционал. свойство terminated (имеющая ровно тот же смысл и задачу что и твоя переменная IsWork ). Да и используемая ровно также (в проверках и условиях цикла обработки). Код:
Код:
есть правило ВЫЗЫВАЕМЫЙ (в данном случае поток OneMoreThread) должен как можно меньше знать о том кто его использует (в данном случае Form1). его могут в теории вызвать САМЫЕ разные формы, а то и вовсе какая нибудь консольная программа БЕЗ формы. В твоем случае это пока не так, НО .... в идеале в теле потока Не должно быть ни одного упоминания о Form1. В то же время ВЫЗЫВАЮЩИЙ (form1) может (и имеет право) многое знать о том кого он вызвал (он же и так знает кого именно он вызвал). Form1 имеет право НЕЗАВИСИМО от работы потока периодически (обычно это бывает таймер) узнать его состояние (те самые четыре переменные ) и отобразить их так как считает нужным и так часто как считает нужным (просто меняем интервал срабатывания таймера). ЕСЛИ поток все же решает САМ работать с формами (VCL объектами), то для этого ЕМУ требуется использовать Synchronize (на форуме это самая распространенная тема в потоках). В некоторых простых случаях "прокатывает" и без, НО ... ЭТО общие замечания. Цитата:
Цитата:
а для хранения использовать все тот же TStringList и сохранять его ВНЕ потока сразу же после нахождения очередного простого числа. еще одна переменная задаваемая в потоке, я нашел новое простое число, прошу вас сохраните наши числа. вот здесь-то и пригодится Synchnize как защита от записи очередного числа ДО выполнения записи данных в файл. и сброс этой переменной после записи данных. Цитата:
количество строк 2^31 = 2 147 483 647 Мало ??? для оптимизации добавления СРАЗУ большого числа строк читаем про CapaCity. визуальные компоненты + BeginUpdate/EndUpdate.
программа — запись алгоритма на языке понятном транслятору
Последний раз редактировалось evg_m; 08.12.2016 в 12:42. |
||||
08.12.2016, 12:53 | #3 | |
Форумчанин
Регистрация: 10.02.2014
Сообщений: 526
|
Вроде, должно хватить... По грубым подсчётам из уже имеющихся данных в итоге у меня получится около 60 000 000 строк.
Поясню первый вопрос: как лучше загрузить большой объём данных из текстового файла в TStringList, чтобы можно было следить за процессом загрузки для понимания, что программа пока не зависла? Напрямую через цикл While i, открыв текстовый файл через AssignFile, считывая информацию через Readln добавлять считанную строку в StringList? Для отслеживания периодически выводить эту i. Нормально ли будет переместить этот цикл загрузки из Button4Click сразу в поток, или для грамотного программирования этого делать не стоит? По поводу работы с формами из потока: просто я хотел бы, чтобы кроме текущего значения в любой момент, цикл выводил бы значения через определённое количество (каждые 10 000 циклов). Думаю, для этого Вы и упомянули Synchronize. Попробую разобраться с этим, как появится ещё промежуток времени для этого. Цитата:
UPD: после 20-го миллиона скорость замедлилась до 20 000 циклов в минуту. Последний раз редактировалось Ship_1; 08.12.2016 в 13:21. |
|
08.12.2016, 13:09 | #4 | |
Старожил
Регистрация: 17.11.2010
Сообщений: 18,922
|
Это не самый эффективный алгоритм. Посмотри решето Эратосфена и его модификации
Цитата:
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Последний раз редактировалось Аватар; 08.12.2016 в 13:18. |
|
08.12.2016, 13:18 | #5 |
Форумчанин
Регистрация: 10.02.2014
Сообщений: 526
|
Аватар, спасибо за совет, обязательно попробую найти и понять, но эта программка стала мне уже интересна ещё и с точки зрения работы с большими списками. После изучения вопроса по Вашей наводке, возможно, сделаю другую программку.
|
08.12.2016, 14:09 | #6 | |||
Старожил
Регистрация: 20.04.2008
Сообщений: 5,526
|
Цитата:
Цитата:
- наличие желания сохранить (например прошло 5 минут после предыдущего сохранения) и - наличие "новой" информации в данных (переменная потока отвечающая за это). - .... другие пожелания (условия) при выполнении условиЙ Делаем сохранение, "сбрасываем" наличие новых данных(изменяем переменную), отмечаем время нашего нового сохранения и выполняем другие действия (по "другим пожеланиям"). Цитата:
http://www.programmersforum.ru/showp...87&postcount=5 и далее по ссылкам.
программа — запись алгоритма на языке понятном транслятору
Последний раз редактировалось evg_m; 08.12.2016 в 14:24. |
|||
08.12.2016, 14:33 | #7 |
Форумчанин
Регистрация: 10.02.2014
Сообщений: 526
|
Т.е. сделать вот так?
Код:
|
08.12.2016, 14:50 | #8 |
Старожил
Регистрация: 20.04.2008
Сообщений: 5,526
|
Код:
Код:
Код:
программа — запись алгоритма на языке понятном транслятору
|
08.12.2016, 15:58 | #9 |
Форумчанин
Регистрация: 10.02.2014
Сообщений: 526
|
evg_m, спасибо! Теперь есть о чём пока поразмышлять на досуге в эхтом направлении. Я вот только пока не понял: если я цикл начальной загрузки хочу тоже в поток отправить, мне для него надо отдельный class(tthread) делать и отдельную execute?
Аватар, глянул на это решето. Может, оно и быстрее будет, но у этого цикла один недостаток: мы не получим простых чисел пока алгоритм не выполнится полностью. А здесь же все числа, оставшиеся после прохождения цикла, уже простые, и если надоест или нет времени больше ждать - у нас уже есть какая-то база простых чисел. Но всё равно ещё раз спасибо, я попробую реализовать и этот алгоритм. |
08.12.2016, 16:11 | #10 |
Старожил
Регистрация: 17.11.2010
Сообщений: 18,922
|
1. Он не просто быстрее, а на много быстрее. Для того, что хочешь получить он возможно выполнится за вполне приемлемое время
2. Кто мешает прерывать вычисления и сохранять промежуточные результаты, восстанавливая их при следующем входе? В твоем подходе можно, почему здесь нельзя? 3. Ну и да, речь конечно не идет о числах порядка 2^64 и выше По поводу времени вычислений посмотри и сравни со своим. Там конечно алгоритм решета вылизан до предела, но все же
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Последний раз редактировалось Аватар; 08.12.2016 в 16:20. |
|
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Как можно обезопаситься от этого | faarigia | Безопасность, Шифрование | 2 | 11.02.2015 20:08 |
FileMapping. Работа с большим количеством страниц | munthrekosh | Общие вопросы Delphi | 1 | 25.05.2012 22:26 |
Работа с большим массивом данных | Freimaks | Общие вопросы Delphi | 21 | 20.04.2012 18:37 |
Работа с большим количеством текста в String иTextbox | Дмитрий999 | Visual C++ | 0 | 20.02.2012 20:07 |
работа с большим объемом данных | Ckif | Microsoft Office Excel | 1 | 14.09.2010 17:05 |