用c++对文件进行多线程读取

Multi threaded reading from a file in c++?

本文关键字:多线程 读取 文件 c++      更新时间:2023-10-16

我的应用程序使用文本文件将数据存储到文件中。我正在测试通过多线程操作读取它的最快方法。我使用了以下两种技术:

  1. 使用与NUMBER_OF_PROCESSORS环境变量一样多的流。每个流都在不同的线程上。将文件中的行总数平均除以每个流。分析文本。

  2. 只有一个流解析整个文件并将数据加载到内存中。创建线程(=NUMBER_OF_PROCESSORS-1)来解析内存中的数据。

该测试在大小为100kB-800MB的各种文件上运行。文件中的数据:

100.23123 -42343.342555 ...(and so on)
4928340 -93240.2 349 ...
...

数据存储在CCD_ 1的2D阵列中。

结果:两种方法解析文件所花费的时间大致相同。

问题:我应该选择哪种方法?

方法1对硬盘不利,因为同时在随机位置执行多个读取访问。

方法2不好,因为所需内存与文件大小成比例。这可以通过将容器限制为固定大小、删除解析后的内容并从读取器中重新填充来部分克服。但这增加了处理时间。

方法2有一个顺序瓶颈(工作项的单线程读取和分发)。根据Amdahls定律,这不会无限期扩大。不过,这是一个非常公平和可靠的方法。

方法1没有瓶颈,将扩展。请确保不会在磁盘上造成随机IO。我会使用互斥锁一次只读取一个线程。读取4-16MB的大顺序块。在磁盘进行单磁头寻道时,它可能读取大约1MB的数据。

如果解析行需要相当长的时间,则不能使用方法2,因为顺序部分很大。它不会扩大规模。不过,如果解析很快,请使用方法2,因为它更容易正确。

为了说明瓶颈的概念:想象一下,1.000000个计算线程要求一个读取器线程给它们行。一个读者线程将无法像要求的那样快速地分发行。您不会获得1e6倍的吞吐量。这不会扩大规模。但是,如果1e6线程从一个非常快的IO设备独立读取,您将获得1e6倍的吞吐量,因为没有瓶颈。(我用极端数字来说明这一点。同样的想法也适用于小型。)

我更喜欢稍微修改一下的2方法。我会在单个线程中按大块顺序读取数据。就绪区块被传递到线程池,在线程池中处理数据。所以你可以同时阅读&处理

有了足够的RAM,就可以在没有单线程瓶颈的情况下完成这项工作。对于Linux:

1) 使用MAP_LOCKED将整个文件映射到RAM,需要根目录或系统范围的权限调整。或者没有针对SSD的MAP_LOCKED,它们可以很好地处理随机访问。

2) 给每个线程一个起始位置。处理从自启动位置后的第一个换行到下一个线程启动位置后第一个换行的数据。

PS你的程序CPU负载是多少?硬盘可能是瓶颈。