![]() |
|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
![]() О задаче:
имеется функция состоящая из 4 блоков: блок 1 вычисляются элементы (с первого по N) для одномерного массива, по некой формуле блок 2 вычисляются элементы (с N+1 по N+M) по другой формуле блок 3 вычисляются элементы (с N+M+1 по N+M+K) по третьей формуле блок 4 результат функции который вычислит сумму всех элементов (от 1 до N+M+K) для массива _____________ Сама задача решена и программа работает правильно, однако это очень длительный (многочасовой) процесс. Мне хотелось сократить время выполения задачи, так как блоки 1, 2 и 3 абсолютно паралелльны и никак не зависят друг от друга. И только четвертый блок, т.е. сам результ зависит от них. Эта программа грузит только одно ядро. Хочется разбросать задачу на три ядра или треда. _____________ Вопрос: Как сделать так, чтобы блоки 1, 2 и 3 в этой функции прогонялись паралелльно (грузя 3 ядра, а не одно), и чтобы четвертый блок дождавшись их выполнил преобразования и выдал необходимый результат. Я никогда не работал с мульти-тредингом, область для меня совсем новая. Поэтому пожалуйста объясните подробно как разрешить данную проблему. Если нужно я приведу сам пример. Или выберите подходящий пример на Ваше усмотрение. Мне главное понять суть распараллеливания. Читал хелпы мануалы и прочее. Везде про треды рассказывается довольно мутно и непонятно на каких-то нудных примерах. Спасибо. |
#2
|
||||
|
||||
![]() Если функция выполняет вычисления с данными в массиве, при этом сам массив не изменяется, думаю, логично создать 3 отдельных процесса, каждый из которых будет выполнять свои действия независимо друг от друга. Выделить место для хранения результатов каждого процесса, а массив для всех один, и из него производится лишь чтение.
|
#3
|
|||
|
|||
![]() Цитата:
вот грубый пример: Код:
function deystvie(a,b:real):real; const n=1000; m=1200; k=189; var i:integer; d:array[1..n+m+k] of real; c:real; begin {block 1} for i:=1 to n do d[i]:=exp(0.2*i)*36598/sin(pi*i)+a; {block 2} for i:=n+1 to n+m do d[i]:=cos(pi*i)*exp(2*i)-b; {block 3} for i:=n+m+1 to n+m+k do d[i]:=1987456*i-3243555*sqrt(i)*sqr(a*b); c:=0; for i:=1 to n+m+k do c:=c+d[i] Result:=c end; Цитата:
|
#4
|
|||
|
|||
![]() На самом деле даже последний, четвертый, блок вполне параллелится (ну если действительно надо просто посчитать сумму элементов). Тебе надо сделать 3 потока, каждый из которых вычислит свои элементы и проссумирует их. После окончания работы он, соответственно, просигналит основному потоку о завершении. Основной поток возьмет 3 числа, сложит их и выдаст конечный результат.
Примерно так: Код:
type // Базовый класс для тредов TCalcThread = class(TThread) private FIsDone : Boolean; FFrom, FTo : Integer; FSum : Integer; ... public constructor Create(AFrom, ATo : Integer); virtual; property IsDone : Boolean read FIsDone; property Sum : Integer read FSum; end; constructor TCalcThread.Create(AFrom, ATo : Integer); begin inherited Create(False); FFrom := AFrom; FTo := ATo; FIsDone := False; FSum := 0; end; Код главного потока: Код:
var t1, t2, t3 : TCalcThread; S : Integer; begin t1 := T1st.Create(1, N); t2 := T2nd.Create(N+1,N+M); t3 := T3rd.Create(N+M+1,N+M+K); While True Do Begin If t1.IsDone And t2.IsDone And t3.IsDone Then Begin S := t1.Sum + t2.Sum + t3.Sum; FreeAndNil(t1); FreeAndNil(t2); FreeAndNil(t3); End; Sleep(200); End; WriteLn('S=',S); // Вывод результата |
Этот пользователь сказал Спасибо lmikle за это полезное сообщение: | ||
cadavar (09.07.2013)
|
#5
|
|||
|
|||
![]() Спасибо за Ваши объяснения lmikle, однако многое осталось мне непонятным.
Цитата:
Это я понял, но как это сделать. ![]() Цитата:
Можете рассказать как это сделать? Я слышал про Execute и Override, но с чем их едят? И как запустить три треда внутри одной функции? И что такое Sleep и FreeAndNil() (я думаю что это освобождение потока). Могли бы показать на простейшем и понятном мне примере? Спасибо Вам еще раз. Последний раз редактировалось cadavar, 09.07.2013 в 13:42. |
#6
|
||||
|
||||
![]() В коде lmikle все подробно описано. Создается 3 потока, каждому указывается стартовый индекс массива и конечный. Каждый из потоков должен выполнить операции над своим блоком, потом просуммировать и поставить флаг "закончил". Основной поток в цикле ждет установки всех трех флагов "закончил". Что такое Sleep и FreeAndNil можно было догадаться по смыслу или посмотреть в гугле. Sleep чтобы не тратить время на главный поток, он будет работать только раз в 200 мс. Про Execute тоже можно было без проблем почитать в гугле - примеров море, и сотый раз перепечатывать сюда 5-страничные трактаты на тему Execute нет смысла.
jmp $ ; Happy End! The Cake Is A Lie. |
#7
|
|||
|
|||
![]() > - примеров море, и сотый раз перепечатывать сюда 5-страничные трактаты на тему Execute нет смысла.
Единственное, что не нужно желать - весь код Execute засовывать в Synchronize. Таких примеров в сети тоже полно |
#8
|
|||
|
|||
![]() Цитата:
Зачем перепечатывать? Я поэтому и попросил на простом примере, а не копипасту. И при чем тут гугл, зачем тогда нужны форумы если в них говорят "читай хелпы" или "гуглируй". |
#9
|
||||
|
||||
![]() Свободен.
Цитата:
Невозможно научиться программировать, если клянчить готовые решения и не прикладывать усилий к поиску информации. Например, найти информацию о работе загрузчиков ОС или каких-нибудь устройствах часто можно в единственном экземпляре в виде официальной документации. Без всяких примеров и разжевываний. На этот же вопрос информации можно накопать тонну. Если вы не хотите учиться делать что-то сам - у меня (и у многих других) нет желания вам помогать. jmp $ ; Happy End! The Cake Is A Lie. Последний раз редактировалось Bargest, 09.07.2013 в 16:24. |
#10
|
|||
|
|||
![]() Ну чтобы начать
Menu->New->Other... ->[Здесь может быть меню Delphi Project->Delphi Files]Thread Object Получишь заготовку модуля. Затем внимательно читаешь, что здесь еще тебе насоветовали, и правишь метод Execute. |
Этот пользователь сказал Спасибо icWasya за это полезное сообщение: | ||
cadavar (09.07.2013)
|