如何在delphi中为下到循环并行编码,在列表上激活,在运行时删除项目?

如何在delphi中为下到循环并行编码,在列表上激活,在运行时删除项目?,delphi,for-loop,parallel-processing,delphi-xe2,omnithreadlibrary,Delphi,For Loop,Parallel Processing,Delphi Xe2,Omnithreadlibrary,以以下代码为例: for i := (myStringList.Count - 1) DownTo 0 do begin dataList := SplitString(myStringList[i], #9); x := StrToFloat(dataList[0]); y := StrToFloat(dataList[1]); z := StrToFloat(dataList[2]); //Do something with these variables myOut

以以下代码为例:

for i := (myStringList.Count - 1) DownTo 0 do begin
  dataList := SplitString(myStringList[i], #9);
  x := StrToFloat(dataList[0]);
  y := StrToFloat(dataList[1]);
  z := StrToFloat(dataList[2]);
  //Do something with these variables
  myOutputRecordArray[i] := {SomeFunctionOf}(x,y,z)
  //Free Used List Item 
  myStringList.Delete(i);
end;
//Free Memory
myStringList.Free;
例如,您将如何使用OmniThreadLibrary将其并行化?可能吗?还是需要重组


我叫myStringList.Deletei;在每次迭代中,由于StringList很大,在每次迭代中使用后释放项目对于最小化内存使用非常重要。

简单回答:你不会

更复杂的回答:在并行化操作中,您最不希望做的事情是修改共享状态,例如这个delete调用。由于不能保证每个单独的任务都能按顺序完成,事实上,它们很可能至少不会完成一次,而且这种可能性很快就会接近100%,如果你在总工作量中添加的任务越多,那么这就是玩火


您可以在执行时销毁项目并序列化,也可以并行执行,更快完成,然后销毁整个列表。但我不认为有任何办法可以两全其美。

简单的回答:你不会

更复杂的回答:在并行化操作中,您最不希望做的事情是修改共享状态,例如这个delete调用。由于不能保证每个单独的任务都能按顺序完成,事实上,它们很可能至少不会完成一次,而且这种可能性很快就会接近100%,如果你在总工作量中添加的任务越多,那么这就是玩火


您可以在执行时销毁项目并序列化,也可以并行执行,更快完成,然后销毁整个列表。但我不认为有任何办法可以两全其美。

你可以作弊。将字符串值设置为空字符串将释放大部分内存,并且是线程安全的。在处理结束时,您可以清除列表

Parallel.ForEach(0, myStringList.Count - 1).Execute(
  procedure (const index: integer)
  var
    dataList: TStringDynArray;
    x, y, z: Single;
  begin
    dataList := SplitString(myStringList[index], #9);
    x := StrToFloat(dataList[0]);
    y := StrToFloat(dataList[1]);
    z := StrToFloat(dataList[2]);
    //Do something with these variables
    myOutputRecordArray[index] := {SomeFunctionOf}(x,y,z);
    //Free Used List Item
    myStringList[index] := '';
  end);
myStringList.Clear;

这段代码是安全的,因为我们从不从多个线程写入共享对象。您需要确保您使用的所有通常是本地的变量都在线程块中声明。

您可以作弊。将字符串值设置为空字符串将释放大部分内存,并且是线程安全的。在处理结束时,您可以清除列表

Parallel.ForEach(0, myStringList.Count - 1).Execute(
  procedure (const index: integer)
  var
    dataList: TStringDynArray;
    x, y, z: Single;
  begin
    dataList := SplitString(myStringList[index], #9);
    x := StrToFloat(dataList[0]);
    y := StrToFloat(dataList[1]);
    z := StrToFloat(dataList[2]);
    //Do something with these variables
    myOutputRecordArray[index] := {SomeFunctionOf}(x,y,z);
    //Free Used List Item
    myStringList[index] := '';
  end);
myStringList.Clear;

这段代码是安全的,因为我们从不从多个线程写入共享对象。您需要确保您使用的所有通常是本地的变量都在线程块中声明。

我不打算尝试演示如何执行您最初要求的操作,因为这是一个不好的主意,不会提高性能。甚至不假设您在建议的并行实现中处理许多不同的数据竞争

这里的瓶颈是磁盘I/O。将整个文件读入内存,然后处理内容是导致内存问题的设计选择。解决这个问题的正确方法是使用管道

管道的步骤1将磁盘上的文件作为输入。这里的代码读取文件的块,然后将这些块分解成行。这些行是此步骤的输出。整个文件不会同时在内存中。你必须调整你读到的块的大小

步骤2将步骤1生成的字符串作为输入。步骤2使用这些字符串并生成向量。这些向量将添加到向量列表中


步骤2将比步骤1快,因为I/0非常昂贵。因此,尝试用并行算法优化这两个步骤都不会有什么好处。即使在单处理器机器上,这种流水线实现也可能比非流水线实现更快

我不打算尝试演示如何执行您最初要求的操作,因为这是一个不好的主意,不会提高性能。甚至不假设您在建议的并行实现中处理许多不同的数据竞争

这里的瓶颈是磁盘I/O。将整个文件读入内存,然后处理内容是导致内存问题的设计选择。解决这个问题的正确方法是使用管道

管道的步骤1将磁盘上的文件作为输入。这里的代码读取文件的块,然后将这些块分解成行。这些行是此步骤的输出。整个文件不会同时在内存中。你必须调整你读到的块的大小

步骤2将步骤1生成的字符串作为输入。步骤2使用这些字符串并生成向量。这些向量将添加到向量列表中

步骤2将比步骤1快,因为I/0非常昂贵。因此,尝试用并行算法优化这两个步骤都不会有什么好处。即使在单处理器机器上,这种流水线实现也可能比非流水线实现更快

虽然释放了一个
在每次迭代中使用后,对您很重要,它可能会对性能产生影响。如果您考虑的是线程,那么该字符串列表将需要为关键部分的每次访问锁定,这自然会导致成批处理这些项—成批处理几行。但我说的是您描述的工作流,它有一个字符串列表,您将从中删除已处理的项目。您确定这是一个瓶颈,线程中的并行执行是解决方案吗?如果内存使用是一个问题,那么你的解决方案将不会有帮助。当所有字符串都在内存中时,您已经有了一个瞬间。几乎可以肯定,你提出的解决方案不会有帮助。告诉我们这个问题。@DavidHeffernan如果{SomeFunctionOf}返回一个对象,那么在处理过程中内存可能会增加。我同意我们需要更多关于这个问题的信息,因为可能会有更多更好、更聪明的解决方案。好吧,让我们先问一个明显的问题。如果在使用Graymatter的解决方案时执行中途停止,并且进程挂起,那么在您实现Graymatter的解决方案之前它是否也这样做?您的并行实现存在严重缺陷。Random不是线程安全的。是TAppender吗?正如梅森所说,共享数据扼杀了可伸缩性。我仍然怀疑你提出的解决方案是否有帮助。从某种程度上说,磁盘IO是瓶颈。串行代码将是最快的。虽然在每次迭代中使用后释放项目对您很重要,但它可能会对性能产生影响。如果您考虑的是线程,那么该字符串列表将需要为关键部分的每次访问锁定,这自然会导致成批处理这些项—成批处理几行。但我说的是您描述的工作流,它有一个字符串列表,您将从中删除已处理的项目。您确定这是一个瓶颈,线程中的并行执行是解决方案吗?如果内存使用是一个问题,那么你的解决方案将不会有帮助。当所有字符串都在内存中时,您已经有了一个瞬间。几乎可以肯定,你提出的解决方案不会有帮助。告诉我们这个问题。@DavidHeffernan如果{SomeFunctionOf}返回一个对象,那么在处理过程中内存可能会增加。我同意我们需要更多关于这个问题的信息,因为可能会有更多更好、更聪明的解决方案。好吧,让我们先问一个明显的问题。如果在使用Graymatter的解决方案时执行中途停止,并且进程挂起,那么在您实现Graymatter的解决方案之前它是否也这样做?您的并行实现存在严重缺陷。Random不是线程安全的。是TAppender吗?正如梅森所说,共享数据扼杀了可伸缩性。我仍然怀疑你提出的解决方案是否有帮助。从某种程度上说,磁盘IO是瓶颈。串行代码将是最快的。谢谢。这段代码可以运行,但似乎不能并行运行。在我的四核中,它的处理器使用率约为25%,与上面的顺序实现相同。谢谢。这段代码可以运行,但似乎不能并行运行。在我的四核中,它的处理器使用率约为25%,与上面的顺序实现相同。