![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
Добрый день всем. Требуется распараллелить вычисление интеграла. Алгоритм сам выглядит так:
Необходимо посчитать интеграл в диапазоне [a,b] f(t)=sin(x*t)dx (на деле формула в три раза длиннее). Поскольку интервал очень большой и из-за специфики функции его расчет возможен только по расчету суммы на каждом периоде sin. Т.е. в программе сделан цикл по каждому периоду синуса и общая сумма потом складывается. Считает все это программа довольно медленно. Поэтому решено сделать расчет с использованием потоков. Прочитал что есть класс TTask. Сделал: Код:
Для теста можно функцию integrator в любом виде представить.
var
tasks: array of ITask;
sums:array of double;
i:integer;
int_period_start,int_period_end:extended;
total:extended;
begin
Setlength (tasks ,norm_period_count); //число периодов синуса в [a,b]
Setlength (sums ,norm_period_count);// массив куда суммы на каждом периоде записывать
for i := 0 to trunc(norm_period_count)-1 do //цикл по периодам
begin
int_period_start:=i*period; //a
int_period_end:=(i+1)*period; //b
// диапазон на котором интегрировать на каждом потоке
Tasks[i] := TTask.Create (procedure()
begin
//в поток выносим вычисление.
res:=Integrator(i*period, (i+1)*period,current_time);
//current_time - это "t" или точка времени в которой надо посчитать интеграл.
//TInterlocked.Exchange(sums[i],res);
//Result:=res;
// TThread.Synchronize(nil,
// procedure
// begin
// sums[1]:=res;
// end);
end);
Tasks[i].Start; //запускаем поток
end;
TTask.WaitForAll(tasks); //ждем завершения
total:=0;
for i := 0 to High(sums) do
begin
total:=total+sums[i];// считает сумму и выдаем результат.
end;
Result:=total;
К сожалению моих знаний катастрофически не хватает. В текущем варианте функция даже работает но в массив sums ничего не записывает. Пробовал оба варианта. Они закомментированы сейчас. Прошу помощи как отладить данный алгоритм. Может быть надо iFuture использовать... хотя я тоже пробовал, но не смог реализовать. Повторюсь что задача состоит в том, чтобы запустить параллельно в отдельном потоке вычисление интегрирования на заданном участке. В ответ получить значение суммы и потом просто сложить их. Количество периодов будет расти и довольно сильно т.к. sin (2*pi/t), а t это время которое считает от 1мкс до 800мкс в среднем. Заранее спасибо. Могу поблагодарить если потребуется. Последний раз редактировалось drcham, 24.06.2016 в 20:22. |
|
#2
|
|||
|
|||
|
Похоже, это что-то из нового. Для старого варианта потоков:
Поток: Код:
TMyThread = class(TThread) private function GetIntegralValue(a, b : Extended) : Double; public IsDone : Boolean; Value : Double; a, b : Extended; protected procedure Execute; override; end; ... function TMythread.GetIntegralValue(a, b : Extended) : Double; begin // Твоя функция result := Random * Random(100); end; procedure TMythread.Execute; begin IsDone := False; Value := GetIntegralValue(a,b); IsDone := True; end; Основной код: Код:
var
Result : Double;
N : Integer;
a, b : Extended;
a1, b1 : Extended;
i : Integer;
threads : array Of TMyThread;
f : Boolean;
begin
// интервал
a := ...;
b := ...;
// Кол-во потоков
N := 10;
SetLength(threads,N);
// Создаем и запускаем потоки
For I := 0 To N-1 Do
begin
threads[i] := TMyThread.Create(True);
threads[i].a := a + I*((b-a)/N);
threads[i].b := threads[i].a + ((b-a)/N);
threads[i].FreeOnTerminate := False;
threads[i].Resume;
end;
// Ждем пока все выполнится
sleep(1000); // 1 сек
repeat
f := true;
For I := 0 To N-1 Do
f := f and threads[i].IsDone;
until f;
// все готово, собибаем результат и убиваем потоки
Result := 0;
For I := 0 To N-1 Do
begin
Result := Result + threads[i].Value;
threads[i].Free;
end;Как-то так. Вот еще для информации родной пример: http://docwiki.embarcadero.com/CodeE...epSort_(Delphi) Можно сделать так, что потоки сами будут через синхронизацию писать результат по переданному адресу, ну и вообще код упростить. Но для общего понимания такой вариант проще. ЗЫ. Для тех, кто святее папы римского. Я знаю, что код написан довольно грязно. Но лишние строк 20-30 только усложнят понимание сути, так что это сделано намеренно. Последний раз редактировалось lmikle, 25.06.2016 в 19:10. |
|
#3
|
|||
|
|||
|
Спасибо. Добрался до компа. Сейчас буду разбираться.
|