Dec 01, 2009 22:55
Все уже привыкли - если хочешь написать для многоядерной системы алгоритм распределяющий нагрузку между ядрами надо использовать... много чего. Мутексы, критические секции и чего только ещё не придумано для синхронизации.
На самом деле можно реализовать такую задачу намного проще и прозрачнее. Будет некоторая потеря производительности, но зато реализация значительно упростится. Особенно хорошо нижеописанный метод подойдёт для долгоиграющих обсчётов, когда есть необходимость загрузить каждый отдельный ЦП (или элемент кластера) надолго обсчётом большого объекта.
Ниже приведу реально работающий класс на Delphi, использующий данный подход.
TWagAnalyzeThread = class(TThread)
PRIVATE
FFRBSDB: TFRBSConstructivDB;
FConstructiv: TConstructiv;
PROTECTED
procedure Execute; OVERRIDE;
PUBLIC
Index: Integer;
Result: TPatternIdCharacteristics;
constructor Create(const FRBSDB: TFRBSConstructivDB;
const Constructiv: TConstructiv; Index: Integer);
end;
constructor TWagAnalyzeThread.Create(const FRBSDB: TFRBSConstructivDB;
const Constructiv: TConstructiv; Index: Integer);
begin
inherited Create(TRUE);
FreeOnTerminate := FALSE;
FFRBSDB := FRBSDB;
FConstructiv := Constructiv;
Result.DBIndex := 0;
Result.Similarity := 0;
Result.DeltaX := 0;
Self.Index := Index;
Resume;
end;
procedure TWagAnalyzeThread.Execute;
begin
try
FFRBSDB.AnalyzeWagon(FConstructiv, Result);
finally
Terminate;
end;
end;
Как можно заметить - ничего ужасного и никаких синхронизаций.
Использование:
var
i, t: Integer;
ThreadArray: array [0..3] of TWagAnalyzeThread;
function FindFreeThread: Integer;
var
t: Integer;
begin
result := -1;
for t := 0 to 3 do
if ThreadArray[t].Terminated then
begin
result := t;
break;
end;
end;
begin
....
// запустим обработку для первых четырёх картинок
for t := 0 to min(3, ConstructivList.Count - 1) do
ThreadArray[t] := TWagAnalyzeThread.Create(Self, ConstructivList[t], t);
// если их больше - будем ждать когда освободится какой-нить поток
if (ConstructivList.Count > 4) then
begin
Sleep(1);
for I := 4 to ConstructivList.Count - 1 do
repeat
t := FindFreeThread;
if (t <> -1) then
begin
pica[ThreadArray[t].Index] := ThreadArray[t].Result;
FreeAndNil(ThreadArray[t]);
sleep(1);
ThreadArray[t] := TWagAnalyzeThread.Create(Self, ConstructivList[i], i);
end
else
sleep(1);
until (t <> -1) or (ProgramTerminated);
end;
// освободим ресурсы
for t := 0 to min(3, ConstructivList.Count - 1) do
begin
while (not ThreadArray[t].Terminated) do
Sleep(1);
pica[ThreadArray[t].Index] := ThreadArray[t].Result;
FreeAndNil(ThreadArray[t]);
end;
end;
end;
вот и всё - никаких сложностей. Конечно можно всё "нарисовать" красивее - но этому пусть вас на соответствующем курсе научат.
В потоке можно создавать коннект к элементу кластера и так далее.
образование,
программирование