1

我正在用delphi阅读非常宽的文件

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

逻辑如下

  1. 打开文件
  2. 读线
  3. 将行拆分为记录数组
  4. 将吐出的数组传递给下一个过程
  5. 转到第 2 步
  6. 关闭文件。

我想并行运行第 3 步,目前正在查看 OmniThreadLibrary。

最好的方法是什么?

我应该使用 Parallel For 吗?胡椒烯?或队列?

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

4

3 回答 3

2

使用多个线程读取文件没有任何好处。该过程的那部分是 I/O 限制的,而不是 CPU 限制的。所以你最好从一个线程中读取整个文件。

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

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

因此,对于这个管道,您有一个读取文件的生产者和一个将文件内容拆分为行的消费者。

然后你可以运行另一个管道。在生产者端,您有上一步生成的行列表。这被推到了处理每一行的消费者的管道上。消费者将使用 parallel for 来做到这一点。

于 2014-03-17T13:37:38.597 回答
0

将解析拆分为例如 10.000 行的块可能是一种选择。我不知道 OmniThread 库,所以 <Do Parallel For on 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>

请注意,代码假定 <Do Parallel For on ARR> 部分仅在数组中的所有条目都已处理后才继续。

于 2014-03-17T15:02:24.337 回答
0

您不需要知道使用 Parallel-For 的总行数,因为您可以使用阻塞集合来迭代。当您添加最后一行时,不要错过调用 CompleteAdding 。

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

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

于 2014-03-17T15:46:01.293 回答