我有一个大文件(比RAM大,不能一次读取整个文件),我需要逐行处理它(在c ++中)。我想利用多个内核,最好使用英特尔 TBB 或Microsoft PPL 。我宁愿避免预处理这个文件(比如把它分成4个部分等)。
我在考虑使用4个迭代器,在文件中初始化为(0,n / 4,2 * n / 4 3 * n / 4)位置等。
这是一个很好的解决方案吗?是否有简单的方法来实现它?
或者您可能知道一些支持高效,并发读取流的库?
更新:
我做了测试。 IO不是瓶颈,CPU是。我有很多缓冲区的RAM。
我需要解析记录(var大小,每个大约2000个字节,记录由唯一的'\ 0'char分隔),验证它,做一些计算,并将结果写入另一个文件
答案 0 :(得分:14)
由于您可以将其拆分为N
部分,因此听起来每行的处理在很大程度上是独立的。在这种情况下,我认为最简单的解决方案是设置一个线程逐行读取文件并将每一行放入tbb::concurrent_queue
。然后生成尽可能多的线程,以便从该队列中拉出行并处理它们。
此解决方案与文件大小无关,如果您发现需要更多(或更少)工作线程,则可以轻松更改数字。但是如果行之间存在某种依赖关系,这将无法工作......除非你设置第二个“后处理”线程轮询来处理它,但事情可能会开始变得太复杂。
答案 1 :(得分:6)
我的建议是使用TBB的管道模式。管道的第一个串行阶段从文件中读取所需的数据部分;后续阶段并行处理数据块,最后一阶段写入另一个文件,可能与读取数据的顺序相同。
这种方法的一个例子可以在TBB分发中找到;见例子/管道/广场。它使用“旧”接口,类tbb::pipeline
和过滤器(继承自tbb::filter
的类),通过void*
指针传递数据。更新,类型安全和lambda友好的“声明”界面tbb::parallel_pipeline()
可能更方便使用。
答案 2 :(得分:3)
ianmac已经暗示了寻求问题。你的迭代器想法是合理的稍微扭曲:将它们初始化为0,1,2和3,并将每个递增4。因此,第一个线程适用于项目0,4,8等。操作系统将确保文件正在尽快送到您的应用程序。有可能告诉您的操作系统您将对文件进行顺序扫描(例如,在Windows上,它是CreateFile
的标志)。
答案 3 :(得分:0)
在阅读文件方面,我不建议这样做。据我所知,硬盘驱动器一次不能从多个地方读取。
但是,处理数据完全不同,您可以轻松地在多个线程中执行此操作。 (保持数据的正确顺序也不会/不应该是困难的。)
答案 4 :(得分:0)
您并未详细说明您打算采用何种类型的处理方式。目前还不清楚您是否期望该进程是计算或I / O绑定的,是否存在不同行处理之间的数据依赖性等。
在任何情况下,从一个大文件中的四个截然不同的位置并行读取可能效率低下(最终,磁头必须在硬盘的不同区域之间来回移动,对于吞吐量)。
您可能会考虑的是从开始到结束顺序读取文件,并将各个行(或行块)扇出到工作线程进行处理。