【问题标题】:Multi threaded reading from a file in c++?从 C++ 中的文件多线程读取?
【发布时间】:2014-01-07 07:48:15
【问题描述】:

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

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

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

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

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

数据存储在double的二维数组中。

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

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

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

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

【问题讨论】:

  • 方法一中如何将文件拆分成多个流?毕竟线程必须从行首开始读取。
  • 备选方案 3:Memory-mapped files.
  • @usr 通过寻找为每个流标记的特定位置。
  • IMO 没关系,除非您使用并行文件系统和硬件。瓶颈将始终位于 HDD 控制器上。您只能尝试保持顺序读取顺序。
  • 如果性能是一个如此关键的问题,你能把你的文件变成二进制文件吗?这将大大减少文件的大小和读取文件所需的 IO。

标签: c++ multithreading file


【解决方案1】:

方法 2 存在顺序瓶颈(单线程读取和分发工作项)。根据阿姆达尔定律,这不会无限期地扩展。不过,这是一种非常公平和可靠的方法。

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

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

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

【讨论】:

  • 单线程读取文件和多线程读取但互相阻塞有什么区别?
  • 你能告诉我你所说的“规模”是什么意思吗?
  • @Vadim 阻塞只发生在 IO 上,而不是解析上。无论如何,你不能比磁盘上的单线程更快。
  • @Cool_Coder 缩放意味着通过增加资源获得更好的性能。在这种情况下,请考虑使用多个 CPU 内核的应用程序的速度。当你让许多核心工作,并且它们通过同步相互干扰时,你从额外的核心中得到的东西很少。完美的扩展意味着 2 倍的吞吐量和 2 倍的内核数量。完全不缩放意味着获得 1 倍的性能。
  • @usr - 这就是我无法理解的。如果你阻止你的 IO,那么这两种选择会变得非常相似
【解决方案2】:

我更喜欢稍作修改的 2 方法。我会在单个线程中按大块顺序读取数据。就绪块被传递到处理数据的线程池。所以你有并发读取和处理

【讨论】:

  • 你必须在分发之前解析块,因为你必须分发整行。
  • 是的,你是对的。你如何看待这样的方案:线程 A 为块分配内存,读取文件并将准备好的块传递给线程 B,一个拆分行上的块并将其传递给线程池
【解决方案3】:

只要有足够的 RAM,您就可以在没有单线程瓶颈的情况下做到这一点。对于 Linux:

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

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

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

【讨论】:

    猜你喜欢
    • 2019-06-02
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-09
    相关资源
    最近更新 更多