Delphi(Delphi 200X、Delphi XE)で並列ループを実現する方法は?どのようにこの最善の方法を行うには?そして、普遍的な解決策はありますか?どのようにDelphiで並列ループを実現するには?
例を含めてください。
Delphi(Delphi 200X、Delphi XE)で並列ループを実現する方法は?どのようにこの最善の方法を行うには?そして、普遍的な解決策はありますか?どのようにDelphiで並列ループを実現するには?
例を含めてください。
おそらく、現時点で最善の解決策は、並列ループの構文がOmniThreadLibraryであることでしょう。コレクション、または下限と上限を表す整数の組と、ループ本体を表す匿名メソッドを渡します。スレッドプールを使用して、forループを並列に実行します。
これは、ループボディメソッドが単独で機能することができる場合にのみ機能することに注意してください。外部変数を変更したり、ループの初期に行われた計算の値に依存したりすると、並列化できません。
omniThreadLibrary parallel forの紹介はhereです。あなたはこのコードを使用することができますParallelForのみが必要な場合
Parallel.ForEach(1, testSize).Execute(
procedure (const elem: integer)
begin
// do something with 'elem'
end);
並列ループとアプリケーション/実装の意味によって異なります。
TThreadとTMultiReadExclusiveWriteSynchronizerを見てください。
私は[私のための並列:1〜10はMyProc(i)を行うようなものです。 ]または多分[ParallelDo(i、1,10、MyProc)]のようなもの – Astronavigator
:たとえば、数字を反復ループのためのシンプルな、このようになります
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;
をしかし、あなたはより多くのスレッドが必要な場合は、「もの」君サードパーティライブラリの使用を検討する必要があります。
かなり複雑な解決策... – Astronavigator
あなたはとても複雑ですか?それは非常に簡単なソリューションのIMOです。 OmniThreadLibraryを使用するよりもずっと簡単です。次のように書くことができます:ParallelFor(0、Count - 1、procedure(i:Integer; ThreadID:Integer)begin {do something} end); – Linas
私はライブラリソリューション(オムニは明らかな選択肢です)はいくつかの利点があると思います。開始のために、このコードは意図された犯罪ではなく、パフォーマンス上の問題があります。 ParallelForを呼び出すたびにスレッドを作成して破棄するのは高価です。プールを準備するのを待つことをお勧めします。ループでWaitForを呼び出すのも間違いですが、Win32では複数のオブジェクト待機関数を一度使用する必要があります。クリティカルセクションは無駄です。インターロックされたインクリメントが優れています。これらは、タスクが小さい場合に重大な問題になる可能性があります。重要な省略である例外の処理もありません。 –
これはクールだ。 –
OmniThreadLibrartを使用した並列ループ実現の例を掲載できますか?例: – Astronavigator
@Astronavigatorへのリンク:例については、最後の段落のリンクを参照してください。 –