10

我有一个大文件(比 RAM 大,不能一次读取整个文件),我需要逐行处理它(在 C++ 中)。我想使用多个内核,最好使用 Intel TBB或 Microsoft PPL。我宁愿避免预处理这个文件(比如把它分成 4 个部分等)。

我正在考虑使用 4 个迭代器,初始化为文件中的 (0, n/4, 2*n/4 3*n/4) 位置等。

这是一个很好的解决方案,是否有简单的方法来实现它?

或者,也许您知道一些支持高效、并发读取流的库?

更新

我做了测试。IO不是瓶颈,CPU才是。而且我有很多用于缓冲区的 RAM。

我需要解析记录(var 大小,每个大约 2000 字节,记录由唯一的 '\0' 字符分隔),验证它,进行一些计算,并将结果写入另一个文件

4

5 回答 5

14

由于您可以将其拆分为多个N部分,因此听起来每一行的处理在很大程度上是独立的。在这种情况下,我认为最简单的解决方案是设置一个线程逐行读取文件并将每一行放入tbb::concurrent_queue. 然后根据需要生成尽可能多的线程,从该队列中拉出行并处理它们。

此解决方案与文件大小无关,如果您发现需要更多(或更少)工作线程,则更改数量很简单。但是,如果行之间存在某种依赖关系,这将不起作用......除非您设置第二个“后处理”线程轮询来处理它,但是事情可能会开始变得过于复杂。

于 2011-05-20T10:58:36.820 回答
6

我的建议是使用 TBB 的管道模式。流水线的第一个串行阶段从文件中读取所需的数据部分;随后的阶段并行处理数据块,最后阶段写入另一个文件,可能与读取数据的顺序相同。

TBB 发行版中提供了这种方法的示例;请参阅示例/管道/正方形。它使用“旧”接口、通过指针传递数据的类tbb::pipeline和过滤器(继承自 的类)。一个更新的、类型安全的和对 lambda 友好的“声明式”接口可能更方便使用。tbb::filtervoid*tbb::parallel_pipeline()

于 2011-05-20T13:12:27.930 回答
3

ianmac 已经暗示了 seek 问题。您的迭代器想法是合理的,但略有不同:将它们初始化为 0、1、2 和 3,并分别递增 4。因此,第一个线程适用于项目 0、4、8 等。操作系统将确保文件正在尽快提供给您的应用程序。可能会告诉您的操作系统您将对文件进行顺序扫描(例如,在 Windows 上,它是 的标志CreateFile)。

于 2011-05-20T10:59:35.977 回答
0

在从文件中读取方面,我不建议这样做。据我所知,硬盘驱动器一次不能从多个地方读取。

但是,处理数据完全是另一回事,您可以轻松地在多个线程中完成。(以正确的顺序保持数据也不会/不应该是困难的。)

于 2011-05-20T10:51:10.337 回答
0

您并没有过多地说明您打算进行哪种类型的处理。目前尚不清楚您是否希望该进程受计算或 I/O 限制,不同行的处理之间是否存在数据依赖关系等。

在任何情况下,从一个大文件中的四个截然不同的位置并行读取可能效率低下(最终,磁头将不得不在硬盘驱动器的不同区域之间来回移动,从而对吞吐量产生负面影响)。

您可能会考虑从头到尾顺序读取文件,并将单个行(或行块)扇出到工作线程进行处理。

于 2011-05-20T10:57:31.683 回答