Delphi'de paralel döngü nasıl gerçekleştirilir (Delphi 200X, Delphi XE)? En iyi nasıl yapılır? Ve herhangi bir evrensel çözüm var mı?Delphi'de paralel döngü nasıl gerçekleştirilir?
Örneklerle lütfen.
Delphi'de paralel döngü nasıl gerçekleştirilir (Delphi 200X, Delphi XE)? En iyi nasıl yapılır? Ve herhangi bir evrensel çözüm var mı?Delphi'de paralel döngü nasıl gerçekleştirilir?
Örneklerle lütfen.
Muhtemelen en iyi çözüm, OmniThreadLibrary numaralı telefondaki Paralel For Loop yapısıdır. Bir koleksiyon veya alt ve üst sınırları temsil eden bir çift tamsayı ve döngü gövdesini temsil eden anonim bir yöntem iletirsiniz ve for döngüsünü paralel olarak çalıştırmak için bir iş parçacığı havuzu kullanır.
Bunun yalnızca döngü gövdesi yöntemi kendi kendine ayakta durabiliyorsa çalışacağını unutmayın. Herhangi bir dış değişkeni değiştirirse veya döngüde daha önce yapılan bir hesaplama değerine dayanıyorsa, paralelleştirilemez.
Paralel olarak OmniThreadLibrary için bir giriş here bulunabilir. Örneğin, sayıların üzerinde döngü iterating için basit şuna benzer:
Parallel.ForEach(1, testSize).Execute(
procedure (const elem: integer)
begin
// do something with 'elem'
end);
Paralel döngü ve uygulama/uygulama ile ne demek istediğinize bağlıdır.
TThread ve TMultiReadExclusiveWriteSynchronizer'a bir göz atın.
Ben bir şeye benziyorum [parallel for i: = 1 to 10 do MyProc (i); ] veya belki bir şey gibi [ParallelDo (i, 1,10, MyProc)] – Astronavigator
Eğer bu kodu kullanabilirsiniz ParallelFor sadece gerekirse: Daha parçacığı "şeyler" gerekirse, Ancak
interface
uses
Classes, SysUtils;
type
TParallelProc = reference to procedure(i: Integer; ThreadID: Integer);
TParallel = class(TThread)
private
FProc: TParallelProc;
FThreadID: Integer; //current thread ID
protected
procedure Execute; override;
function GetNextValue: Integer;
public
constructor Create;
destructor Destroy; override;
property Proc: TParallelProc
read FProc write FProc;
class var
CurrPos: Integer; //current loop index
MaxPos: Integer; //max loops index
cs: TCriticalSection;
ThCount: Integer; //thread counter - how much threads have finished execution
end;
{** ParallelFor Loop - all iterations will be performed in chosen threads
@param nMin - Loop min value (first iteration)
@param nMax - Loop max value (last iteration)
@param nThreads - how much threads to use
@param aProc - anonymous procedure which will be performed in loop thread
}
procedure ParallelFor(nMin, nMax, nThreads: Integer; aProc: TParallelProc); overload;
{** ParallelFor Loop - all iterations will be performed in max cpu cores
@param nMin - Loop min value (first iteration)
@param nMax - Loop max value (last iteration)
@param aProc - anonymous procedure which will be performed in loop thread
}
procedure ParallelFor(nMin, nMax: Integer; aProc: TParallelProc); overload;
implementation
uses
{$IFDEF MSWINDOWS}
Windows,
{$ENDIF}
SyncObjs;
procedure ParallelFor(nMin, nMax, nThreads: Integer; aProc: TParallelProc);
var
threads: array of TParallel;
I: Integer;
begin
if nMin > nMax then
Exit;
// initialize TParallel class data
TParallel.CurrPos := nMin;
TParallel.MaxPos := nMax;
TParallel.cs := TCriticalSection.Create;
TParallel.ThCount := 0;
// create the threads
SetLength (threads, nThreads);
for I := 0 to nThreads - 1 do
begin
threads[I] := TParallel.Create; // suspended
threads[I].FThreadID := I;
threads[I].Proc := aProc;
threads[I].Start;
end;
for I := 0 to nThreads - 1 do
begin
threads[I].WaitFor;
end;
for I := 0 to nThreads - 1 do
begin
threads[I].Free;
end;
TParallel.cs.Free;
end;
procedure ParallelFor(nMin, nMax: Integer; aProc: TParallelProc);
begin
ParallelFor(nMin, nMax, CPUCount, aProc);
end;
{ TParallel }
constructor TParallel.Create;
begin
inherited Create(True); // suspended
InterlockedIncrement(ThCount);
FreeOnTerminate := False;
FThreadID := 0;
end;
destructor TParallel.Destroy;
begin
InterlockedDecrement(ThCount);
inherited;
end;
procedure TParallel.Execute;
var
nCurrent: Integer;
begin
nCurrent := GetNextValue;
while nCurrent <= MaxPos do
begin
Proc(nCurrent, FThreadID);
nCurrent := GetNextValue;
end;
end;
function TParallel.GetNextValue: Integer;
begin
cs.Acquire;
try
Result := CurrPos;
Inc(CurrPos);
finally
cs.Release;
end;
end;
seni Üçüncü parti kütüphaneleri kullanmayı düşünmelidir.
Oldukça karmaşık bir çözüm ... – Astronavigator
Sizin için ne kadar karmaşık? Bu çok basit bir çözüm IMO. OmniThreadLibrary kullanmanın çok daha basit. Şöyle bir şey yazabilirsiniz: ParallelFor (0, Sayım - 1, prosedür (i: Tamsayı; ThreadID: Tamsayı), bir şeyler yapmaya başlar. – Linas
Bence bir kütüphane çözümü (Omni bariz bir seçimdir) bazı avantajlara sahiptir. Bu kodun başlangıcı için, amaçlanan hiçbir ihlal, performans sorunları vardır. ParallelFor'u her aradığınızda parçacıkları oluşturmak ve yok etmek pahalıdır. Daha iyi bir havuz gitmek için hazır bekliyor. Bir döngüde WaitFor'u çağırmak da bir hatadır, Win32'daki birden çok nesne bekleme işlevlerinden birini kullanmalısınız. Kritik bölüm savurganlıktır - kilitli artış daha iyidir. Bu görevler küçük olduğunda önemli sorunlar olabilir. Ayrıca önemli bir ihmal olan istisnalar ele alınmamaktadır. –
Bu harika görünüyor. –
OmniThreadLibrart kullanarak paralel döngü gerçekleştirme örneği gönderebilir mi? Ya da örneğin – Astronavigator
@Astronavigator'a bağlantı: Örnekler için son paragraftaki bağlantıya bakın. –