Problem jest typowy dla dziedziny Parallel Grid Computation. Mamy tablicę wartości liczbowych na której działamy w pętli. Obliczenia w każdej komórce tablicy zależą od wartości sąsiednich komórek z poprzedniej iteracji. Pytanie brzmi: jak najefektywniej zrealizować takie zagadnienie w Delphi z zastosowaniem obliczeń równoległych ?
Najprostszy pomysł to wykorzystanie wielowątkowości. Tablice dzielę na kilka możliwie równych części (np. na tyle ile mam dostępnych w sytemie rdzeni). Następnie dla każdego fragmentu tablicy tworzę nowy wątek obliczeniowy. Po każdekj iteracji muszę złożyć tablicę w całość - czyli poczekać aż wszystkie wątki dokończą daną iterację i przejść do następnej.
Problem jest właśnie w tym czekaniu, które w wielu przypadkach może trwać dłużej niż same obliczenia. Oczywiście jest wiele technik i algorytmów, które mają na celu ograniczenie konieczności synchronizacji wątków do absolutnego minimum ale to zagadnienie na razie pomijam.
Mój pomysł na poradzenie sobie z tym problem wygląda następująco:
W wątku głównym tworzę kilka wątków obliczeniowych, które przechowuje w tablicy:
TablicaWatkow: array [0..7] of TMojThread;
Każdy wątek w ramach konstruktora otrzymuje swój unikalny numer (nr) odpowiadający jego indeksowi w tablicy:
for i := 0 to 7 do
TablicaWatkow[i]:=TMojThread.Create(i);
Utworzyłem również w wątku głównym tablicę zdarzeń (TEvent) w celu określenia czy wszystkie wątki wykonały daną pętle:
TablicaZdarzen: array [0..7] of TEvent;
TablicaUchwytowZdarzen: array [0..7] of THandle;
Po wykonaniu danej pętli każdy wątek czeka na wykonanie się pętli w wątkach równoległych:
procedure TMojThread.Execute;
...
begin
for i := 0 to liczba_petli //główna pętla obliczeniowa
begin
WaitForMultipleObjects(8, @Watek_glowny.TablicaUchwytowZdarzen, True, INFINITE);
Watek_glowny.TablicaZdarzen[nr].ResetEvent;
... //właściwe obliczenia na tablicy
Watek_glowny.TablicaZdarzen[nr].SetEvent;
end;
end;
czas na pytanie :) Czy taka metoda synchronizacji wątków (poprzez wykorzystanie instrukcji WaitForMultipleObjects dla kilku zdarzeń odpowiadających poszczególnym wątkom) jest najbardziej efektywna ? Czy można to jakoś przyspieszyć ? Chciałbym również wykorzystać instrukcję WaitForMultipleObjects(8, @TablicaUchwytow, True, INFINITE) w wątku głównym do sprawdzenia czy wszystkie wątki obliczeniowe zakończyły się, niesty jej dodanie powoduje zatrzymanie wszystkich wątków (łącznie z głównym) - nic się nie dzieje. Jakieś pomysły dlaczego tak jest ?
Pozdrawiam i z góry dziękuje za pomoc.