用delphi OmniThreadLibrary读取平面文件

时间:2014-03-17 13:01:05

标签: delphi omnithreadlibrary

我正在使用delphi阅读非常广泛的文件

该文件以逗号分隔,大部分时间用于解析字符串。

逻辑如下

  1. 打开文件
  2. 读取行
  3. 将行拆分为记录数组
  4. 将spitted数组传递给下一个程序
  5. 转到第2步
  6. 关闭文件。
  7. 我希望并行运行第3步,目前正在查看OmniThreadLibrary。

    最好的方法是什么?

    我要使用Parallel For吗? Pipelene?还是队列?

    我正在考虑使用'Parallel For',但问题是我不知道该文件有多少行

3 个答案:

答案 0 :(得分:1)

使用多个线程来读取文件没有任何好处。该过程的一部分是I / O绑定而不是CPU绑定。因此,您最好从单个线程中读取整个文件。

然后,您需要将文件拆分为多行。由于存在依赖性问题,因此很难再次并行执行。线N + 1从线N结束的地方开始。在单个线程中分割成行是最简单的。

但是你可以在I / O和分成行之间运行一个管道。以大块读取文件(一次说几十KB)。并将每个块传递到管道中以进行处理。您可能需要在任何时刻设置允许在管道中放置多少数据的上限。否则,如果可以比处理文件更快地读取文件,则可能耗尽内存。

因此,对于这个管道,你有一个读取文件的生产者,以及一个将文件内容分成行的消费者。

然后你可以运行另一个管道。在生产者端,您有上一步生成的行列表。这会将管道推向处理每条生产线的消费者。消费者将以并行方式执行此操作。

答案 1 :(得分:0)

将解析拆分成例如10.000行的块可能是一种选择。我不知道OmniThread库,所以<对ARR并行处理>你必须自己做的部分,但代码的基本结构是这样的:

CONST ChunkSize = 10000;

VAR ARR : ARRAY[1..ChunkSize] OF STRING;
VAR Lines : Cardinal;
VAR TXT : TextFile;
VAR FileName : STRING;

Lines:=0;
AssignFile(TXT,FileName); RESET(TXT);
WHILE NOT EOF(TXT) DO BEGIN
  IF Lines=ChunkSize THEN BEGIN
    <Do Parallel For on ARR>;
    Lines:=0
  END;
  INC(Lines);
  READLN(ARR[Lines])
END;
<Do Parallel For on ARR - only "Lines" lines>

请注意,该代码假定&lt; Do Parallel For ARR&gt;部分仅在处理完阵列中的所有条目后才继续。

答案 2 :(得分:0)

您不需要知道要使用Parallel-For的总行数,因为您可以使用Blocking Collection进行迭代。添加最后一行时,不要错过调用CompleteAdding。

请注意,与线程和队列管理相比,当每个单个任务只需要少量时间时,Parallel-For的性能可能会大幅降低。

您也可以考虑使用BackgroundWorker抽象并在每个WorkItems中安排多行。