如何在Delphi(Delphi 200X,Delphi XE)中实现并行循环?怎么做这个最好的方法?有没有通用的解决方案?
请举例说明。
答案 0 :(得分:11)
目前最好的解决方案可能是OmniThreadLibrary中的Parallel For Loop构造。您传递一个集合,或表示下限和上限的一对整数,以及表示循环体的匿名方法,它使用线程池并行运行for循环。
请注意,这只有在循环体方法能够独立存在时才有效。如果它修改了任何外部变量或依赖于先前在循环中进行的计算的值,那么它就无法并行化。
可以找到OmniThreadLibrary并行的介绍here。例如,迭代数字的简单for循环如下所示:
Parallel.ForEach(1, testSize).Execute(
procedure (const elem: integer)
begin
// do something with 'elem'
end);
答案 1 :(得分:4)
如果只需要ParallelFor,可以使用以下代码:
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;
但是,如果你需要更多线程“东西”,你应该考虑使用第三方库。
答案 2 :(得分:0)
取决于并行循环和应用程序/实现的含义。
看看TThread和TMultiReadExclusiveWriteSynchronizer。