【问题标题】:How to parallelize file reading and writing如何并行文件读写
【发布时间】:2010-12-31 21:51:13
【问题描述】:

我有一个程序从 2 个文本文件中读取数据,然后将结果保存到另一个文件中。由于要读取和写入的数据很多,会导致性能下降,因此我想将读取和写入操作并行化。

我最初的想法是,以2个线程为例,一个线程从头开始读/写,另一个线程从文件中间读/写。由于我的文件被格式化为行,而不是字节(每行可能有不同的数据字节),按字节查找对我不起作用。而我能想到的解决方案是先使用 getline() 跳过前面的行,这可能效率不高。

有什么好的方法可以找到文件中的指定行吗?或者你有什么其他的想法来并行文件读写?

环境:Win32、C++、NTFS、单硬盘

谢谢。

-Dbger

【问题讨论】:

  • 您的文件系统是什么,您使用什么硬件?如果你只有一个控制器/磁盘,并行 I/O 可能效率不高
  • 那么是不是意味着如果只在同一个磁盘上读/写,并行化磁盘 I/O 总是会导致性能下降?
  • Dbger:如果使用硬盘,是的。
  • 如果您正在处理文件,您可能需要考虑重叠 I/O 和计算。如果你真的想尝试并行,你可以将你的文件分割成段(逻辑上),寻找那个段,找到段中的行首,然后读到下一个段。
  • @unknown 我对“将文件拆分成段”了解不多,但是如果磁盘 I/O 更喜欢顺序访问,那么分段方法会起作用吗?

标签: multithreading file


【解决方案1】:

一般来说,您不想并行化磁盘 I/O。硬盘不喜欢随机 I/O,因为它们必须不断地四处寻找数据。假设您没有使用 RAID,并且您使用的是硬盘驱动器而不是一些固态内存,如果并行化 I/O,您将​​看到严重的性能下降(即使使用类似的技术,您仍然可以看到一些性能执行大量随机 I/O 时性能下降)。

要回答您的第二个问题,确实没有寻找文件中某一行的好方法;您只能使用read 函数显式查找字节偏移量(有关如何使用它的更多详细信息,请参阅this page

【讨论】:

  • 所以在文件读/写中,磁盘寻道大部分时间都是消耗的,多线程环境下是这样的,对吗?
  • 是的,磁盘寻道时间通常是多线程 I/O 环境的瓶颈。你应该尽可能地序列化你的 I/O。
  • 谢谢Mike,只是确认一下,这是否只适用于读取单个文件,或者也适用于读取多个文件(线程1读取文件1,线程2读取文件2)
  • 我所说的适用于单个磁盘上的任何磁盘 I/O,无论是否有单独的文件。当然,操作系统或磁盘的缓存对实际效果会有一定的影响。
  • 但是有些文件系统允许您将文件分布在不同的磁盘/磁盘部分以线性扩展您的 I/O。
【解决方案2】:

当您在一个磁盘上运行时,将多个读取和写入排队将无济于事。如果您的应用程序也在 CPU 中执行了大量工作,那么您可以异步执行读写操作,让 CPU 在后台发生磁盘 I/O 时工作。或者,获得第二个物理硬盘驱动器:从一个读取,写入另一个。对于规模适中的数据集,这通常比编写代码更有效且成本更低。

【讨论】:

  • 当CPU忙于计算时,使用后台线程逐渐写入输出数据,这是个好主意。但是在阅读方面,由于数据还没有准备好,所以没有太多的工作可以做。
  • Dbger,这取决于您的数据的性质。如果您能够在处理第一次获取的数据时对第二次异步获取进行排队以满足您的业务。同样,如果磁盘不忙于其他 I/O,这是最有效的,因此可能不适用于您的当前情况。
【解决方案3】:

这并不是您问题的真正答案,而是重新设计(我们都讨厌但又忍不住这样做)。如前所述,尝试在具有多个线程的硬盘上加速 I/O 可能无济于事。

但是,根据数据敏感性、吞吐量需求、数据大小等,可能会使用另一种方法。在内存中创建一个结构来维护数据图片并允许轻松/快速更新并不难数据中任意位置的文本行数。然后,您可以使用一个专用线程来简单地监视该结构以及将数据写入磁盘的工作。将数据顺序写入磁盘可以非常快;它比随机寻找不同的部分并分段编写要快得多。

【讨论】:

  • 当我将大约 2M 的数据顺序写入文本文件时,在我的机器上花费大约 1 秒,这对我来说太慢了。至于读取,为了形成文件​​的内存结构,我需要先读取里面的数据,这也太慢了,不能满足我的要求。不过,我会调查有关重叠 I/O 和 Memorymap 文件的主题,看看是否有帮助。
  • 1 秒写入 2MB?这似乎慢得惊人。我刚刚运行了一个测试,在大约 100 毫秒内将 10M 写入文件,而我的 PC 不是真正的速度机器(3.2GHz 和我 认为 7200rpm 驱动器)。您使用哪些 API 来打开和写入文件?
  • 我正在使用 std::ofstream 在循环中保存大量分离的数据。像“for(...){streamOut
  • 这很有趣。如果我有时间,出于好奇,我可能不得不在我的 PC 上进行测试。我只是在使用 Win32 API(CreateFile、WriteFile)。但实际上,我希望 streamio 能够通过 Win32 上的这些 API。或者如果不是,它仍然会通过某种缓冲 I/O。 7200 rpm 磁盘的平均延迟应低于 5 毫秒。这应该允许大量缓冲写入。我想如果磁盘完全被分割成 4096 个块,它会达到 1 秒/MB。
  • MarkW,事实证明,在调用“streamOut
猜你喜欢
  • 1970-01-01
  • 2018-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多