使用并行编程库在计算值列表中查找最大值

Find the Maximum in a List of calculated values using the Parallel Programming Library

我有一个值列表。我想找到最大值。这是一项常见的任务。一个简单的版本可能是:

iBest := -1;
iMax := -1e20;
for i := 0 to List.Count - 1 do
begin
  if List[i].Value > iMax then
  begin
    iBest := i;
    iMax := List[i].Value;
  end;
end;

在我的例子中,.Value getter 是性能瓶颈,因为它调用耗时的计算(~100 毫秒),returns 最终值。

如何使用并行编程库实现并行?

如果该值是一个计算值并且您可以负担得起缓存,一个简单的解决方案可能如下所示:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils, Threading, DateUtils, Math, Generics.Collections, StrUtils;

type
  TFoo = class
  private
    FCachedValue : double;
    function GetValue : double;
  public
    property CalculateValue : double read GetValue;
    property CachedValue : double read FCachedValue;
  end;

  TFooList = class(TObjectList<TFoo>)
    public
      procedure CalculateValues;
      function GetMaxValue(var BestIndex : integer) : double;
  end;


function TFoo.GetValue : double;
begin
  sleep(10);   // simulate taking some time... make up a value
  FCachedValue := DateUtils.MilliSecondOfTheSecond(now);
  result := FCachedValue;
end;

procedure TFooList.CalculateValues;
begin
  TParallel.For(0, Count - 1,
    procedure (j:integer)
    begin
      self[j].CalculateValue;
    end);
end;

function TFooList.GetMaxValue(var BestIndex : Integer) : double;
var
  i, iBest : integer;
  maxval : double;
begin
  CalculateValues;
  iBest := 0;
  maxval := self[0].CachedValue;
  for i := 0 to self.Count - 1 do
  begin
    if self[i].CachedValue > maxval then
    begin
      iBest := i;
      maxval := self[i].CachedValue;
    end;
  end;
  BestIndex := iBest;
  result := maxval;
end;


var
  LFooList : TFooList;
  i, iBest : integer;
  maxval : double;
begin
  LFooList := TFooList.Create(true);
  try
    for i := 0 to 9999 do LFooList.Add(TFoo.Create);
    maxval := LFooList.GetMaxValue(iBest);
    WriteLn(Format('Max value index %d', [iBest]));
    WriteLn(Format('Max value %.6f', [maxval]));
  finally
    LFooList.Free;
  end;
  ReadLn;
end.

这样,您的对象会保留上次计算值的缓存,您可以随时刷新,但也可以快速访问。并行化列表的完整计算比并行化 min/max 搜索要容易一些,如果瓶颈是计算,那么将增加的复杂性限制在单独的操作(你知道开销的地方)是有意义的是值得的)。