![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | 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, однако многое осталось мне непонятным.
Цитата:
Это я понял, но как это сделать. Возможно это сделать внутри одной функции? Мне нужны все полученные элементы массива, чтобы потом произвести над ними необходимые операции в 4-м блоке (и не только сумму, но три блока все равно должны остаться независимыми).Цитата:
Можете рассказать как это сделать? Я слышал про Execute и Override, но с чем их едят? И как запустить три треда внутри одной функции? И что такое Sleep и FreeAndNil() (я думаю что это освобождение потока). Могли бы показать на простейшем и понятном мне примере? Спасибо Вам еще раз. Последний раз редактировалось cadavar, 09.07.2013 в 13:42. |
|
#6
|
||||
|
||||
|
В коде lmikle все подробно описано. Создается 3 потока, каждому указывается стартовый индекс массива и конечный. Каждый из потоков должен выполнить операции над своим блоком, потом просуммировать и поставить флаг "закончил". Основной поток в цикле ждет установки всех трех флагов "закончил". Что такое Sleep и FreeAndNil можно было догадаться по смыслу или посмотреть в гугле. Sleep чтобы не тратить время на главный поток, он будет работать только раз в 200 мс. Про Execute тоже можно было без проблем почитать в гугле - примеров море, и сотый раз перепечатывать сюда 5-страничные трактаты на тему Execute нет смысла.
|
|
#7
|
|||
|
|||
|
> - примеров море, и сотый раз перепечатывать сюда 5-страничные трактаты на тему Execute нет смысла.
Единственное, что не нужно желать - весь код Execute засовывать в Synchronize. Таких примеров в сети тоже полно |
|
#8
|
|||
|
|||
|
Цитата:
Зачем перепечатывать? Я поэтому и попросил на простом примере, а не копипасту. И при чем тут гугл, зачем тогда нужны форумы если в них говорят "читай хелпы" или "гуглируй". |
|
#9
|
||||
|
||||
|
Свободен.
Цитата:
Невозможно научиться программировать, если клянчить готовые решения и не прикладывать усилий к поиску информации. Например, найти информацию о работе загрузчиков ОС или каких-нибудь устройствах часто можно в единственном экземпляре в виде официальной документации. Без всяких примеров и разжевываний. На этот же вопрос информации можно накопать тонну. Если вы не хотите учиться делать что-то сам - у меня (и у многих других) нет желания вам помогать. Последний раз редактировалось Bargest, 09.07.2013 в 16:24. |
|
#10
|
|||
|
|||
|
Ну чтобы начать
Menu->New->Other... ->[Здесь может быть меню Delphi Project->Delphi Files]Thread Object Получишь заготовку модуля. Затем внимательно читаешь, что здесь еще тебе насоветовали, и правишь метод Execute. |
| Этот пользователь сказал Спасибо icWasya за это полезное сообщение: | ||
cadavar (09.07.2013)
| ||