![]() |
|
![]() |
#1 |
Gold Member
Регистрация: 25.06.2005
Адрес: F000:FFF0
Сообщений: 1,820
|
![]()
Хотелось бы обменятся опытом по следующему интересному вопросу.
Есть некоторый класс задач (поставленный какой-нибудь прикладной наукой), входные и выходные данны четко определены, метод решения также известен. Все что требуется - написать программу для расчета, в которую можно ввести входные данные, выполнить расчет и вывести результаты. В общем все просто, стандартно и банально до безобразия. В принципе даже школьник осилит, если метод не особо замороченный. Также договоримся, что программа пишется под Windows с использова- нием доступных элементов графического интерфейса пользователя, пре- доставляемых как самой ОС, так и средой разработки GUI-приложений. А теперь нюансы... Метод решения может оказаться не особо сложным для понимания, а вот с вычислительной точки зрения очень трудоемким. Соответственно, если расчет "долгий", то окно программы "умирает" на время вычислений, никак не откликаясь на воздействия пользователя. Соответственно, хотелось бы чтобы программа расчета умела следующее: 1) Не "умирать" при выполнении длительных расчетов и быть "отзывчивой". 2) Предоставлять возможность корректно прерывать расчеты в любой мо- мент по желанию пользователя, при этом культурно подчищая все хвосты: освобождая выделенные блоки памяти, закрывая открытые файлы и прочее. 3) Предоставлять возможность следить за текущим состоянием выполняемых расчетов. В простейшем случае - процент завершенности. В более сложных случаях - подробная детализация внутреннего состояния решаемой задачи. У меня, разумеется, за годы выработался свой шаблон для подобных программ, который, разумеется, включает использование отдельных потоков (thread), но там есть свои подводные камни и нюансы, вот о них и хотелось бы поговорить. P.S. Про распараллеливание самого метода решения здесь говорить не будем, это уже совсем отдельная тема... долгая, нудная, многотомная и бесконечная. P.P.S. Да чуть не забыл... Все вышеперечисленные "удобства" ни в коим случае не должны сколь-либо существенно увеличивать общее время решения задачи. Кроме того, главный поток не должен захлёбываться от прорвы Windows message. Ну, и, наконец, обойти все случаи, приводящие к dead-lock (взаимоблокировке). Последний раз редактировалось Paul Kellerman; 14.01.2011 в 14:38. |
![]() |
![]() |
Реклама | |
|
![]() |
#2 |
Gold Member
Регистрация: 07.09.2005
Сообщений: 1,326
|
![]()
Во-первых, программа должна периодически что называется "отдавать управление" (это справедливо для всех ОС, только конкретный механизм может быть разным), про конкретику чуть ниже.
Во-вторых, такая вычислительная программа состоит, очевидно, как минимум из одного цикла (чаще - из N вложенных циклов). Так вот во время каждой итерации (главного цикла) и следует отдавать управление, а также обновлять индикатор прогресса и т.п. В-третьих, целесообразнее такую программу организовать как многопоточную, уж во всяком случае выделив в разные потоки (thread) вычислительную часть и GUI. И наконец, про передачу управления. Если нужно вернуть управление ОС, то в Win32 API это делается посредством ф-ций Sleep(), WaitForXXXX и т.п. Передача управления же от вычислительного потока к GUI-потоку этого же процесса производится путем просматривания очереди сообщений и их направления получателям (по типу того как это делается в ф-ции WinMain). |
![]() |
![]() |
![]() |
#3 |
Gold Member
Регистрация: 25.06.2005
Адрес: F000:FFF0
Сообщений: 1,820
|
![]()
Что же, прошло достаточно много времени с момента поднятия данной темы.
Хочу поделиться простеньким примером программы, выполняющей "длитель- ные расчеты", послушать мнения и предложения спецов в программировании. Суть самой программы простейший: вводите количество испытаний n и веро- ятность успеха в отдельном испытании p, ну и запускаете расчет, в котором простым итерационным способом проводится n испытаний и подсчитывается количество успехов. Параметр n, целое число в пределах от 0 до 999999999, а p, действительное число (и в качестве разделителя целой и дробной части используется точка, а не запятая), от 0 до 1. Очевидно, при большом n испы- тания и подсчет успехов могут затянуться, поэтому требуется особый подход. Программа написана с использованием традиций объектно-ориентированного программирования и событийно-ориентированного подхода в Delphi, и к этому всему добавлен многопоточный подход со всеми вытекающими особенностями. Исходный код сосредоточен в двух модулях: основном (lm_main.pas) и матема- тическом (lm_math.pas). Исходный код достаточно подробно закомментирован. Основные особенности моего подхода в данной программе: - Математическая обработка выполняется в отдельном потоке SolverThread, ко- торый запускается в обработчике события нажатия кнопки "Пуск". Далее либо он самостоятельно завершается (все испытания проведены) либо прерывается пользователем кнопкой "Стоп", при этом для события завершения потока есть свой отдельный обработчик, где в частности выводятся результаты испытаний. - Математическая обработка реализована не как "отдельно-висящая" функция, а как самостоятельный класс "математического аппарата" (TMathEngine), и он вынесен в отдельный математический модуль программы (это делает программу более структурированной и читабельной). Класс содержит конструктор, дест- руктор, ну и метод (функцию), выполняющую вычисления и испытания в одном цикле. Вычислительный метод (Solve) при вызове из главного модуля программы получает не только параметры n и p, но и два указателя: на специальный флаг, которым можно управлять "извне" для принудительного завершения вычислений, и на специальную структурную переменную, в которую записывается состояние матаппарата, для возможности слежения за "ходом" вычислений "извне". В цикле вычислительного метода на каждой итерации проверяется флаг принудительного завершения, плюс обновляется структурная переменная состояния матаппарата. - Для периодического отображения текущего состояния (хода вычислений) мат- аппарата применен следующий прием. В программе создается специальный тай- мер UpdateTimer, который с периодом 20 миллисекунд срабатывает и операцион- ная система посылает главному окну программы Windows-сообщение WM_TIMER. Это сообщение обрабатывается в главной "оконной" процедуре WndProc, привя- занной к основному окну программы. При обработке сообщений WM_TIMER, про- веряется активен ли данный момент поток матобработки, и если да, то считыва- ется структурная переменная состояния матобработки, вычисляется "прогресс" (доля завершенности) матобработки и обновляется соответ. полоса прогресса. P.S. На всякий случай скажу, что это не лучший пример моего программирова- ния, сам я оцениваю свой подход к реализации сложных расчетов на "четыре". Некоторые проверки и оптимизации я намеренно удалил, чтобы пример был как можно проще и короче, но даже с учетом этого получилось около 450 строк ![]() Последний раз редактировалось Paul Kellerman; 26.03.2011 в 14:21. |
![]() |
![]() |
![]() |
#4 |
Advanced Member
Регистрация: 10.09.2007
Сообщений: 258
|
![]()
Я бы сделал многонитевой демон, выполняющий собственно рассчёты и простую морду к нему на чём-нибудь вроде PyGTK или Vala. IPC - через d-bus. Это заодно позволило бы избежать потери производительности при рассчётах, вызванной странным требованием "программа пишется под Windows" - благо d-bus и по сети отлично работает.
|
![]() |
![]() |
![]() |
#5 |
Gold Member
Регистрация: 07.09.2005
Сообщений: 1,326
|
![]()
Вам лет-то сколько ? Вы вообще реальным разработчиком работали когда-нибудь ?
Открою секрет (КО): софт разрабатывается исходя из требований заказчика, а не ваших эротических фантазий. И, согласно этим требованиям, где-то в 90 % случаев как раз "программа пишется под Windows". |
![]() |
![]() |
![]() |
#6 |
Silver Member
Регистрация: 03.09.2004
Сообщений: 895
|
![]() |
![]() |
![]() |
![]() |
#7 |
Gold Member
Регистрация: 07.09.2005
Сообщений: 1,326
|
![]()
gav, да я тоже дано заметил, что этому товарисчу присущ технологический экстремизм.
|
![]() |
![]() |
![]() |
#8 |
Gold Member
Регистрация: 07.09.2005
Сообщений: 1,326
|
![]()
Недавно реализовывал простейший клауд на основе самопального протокола аля XML-RPC (разумеется поверх HTTP).
|
![]() |
![]() |
![]() |
#9 |
Advanced Member
Регистрация: 10.09.2007
Сообщений: 258
|
![]() |
![]() |
![]() |
![]() |
#10 | |
Gold Member
Регистрация: 07.09.2005
Сообщений: 1,326
|
![]()
На брудершафт пили ?
Цитата:
|
|
![]() |
![]() |