许多小文件或一个大文件? (或者,打开和关闭文件句柄的开销)(C ++)

时间:2009-07-29 05:15:29

标签: c++ optimization file-io

我创建了一个执行以下操作的应用程序:

  1. 进行一些计算,计算数据写入文件 - 重复500,000次(总计,一个接一个地写500,000个文件) - 再重复2次(总共1.5个文件是写)。
  2. 从文件中读取数据,使用文件中的数据进行一些强烈的计算 - 重复1,500,000次迭代(迭代在步骤1中写入的所有文件。)
  3. 重复步骤2进行200次迭代。
  4. 每个文件大约是212k,所以我总共拥有~300Gb的数据。在使用2.8 Ghz的Core 2 Duo CPU上看起来整个过程需要大约40天。

    我的问题是(正如你可能猜到的)是完成整个过程所需的时间。所有计算都是串行的(每个计算都取决于之前的计算),因此我无法将此过程与不同的CPU或PC并行。我正在考虑如何使这个过程更有效率,我很确定大部分开销都用于文件系统访问(呃...)。每次我访问文件时,我打开一个句柄,然后在我读完数据后关闭它。

    我改善运行时间的一个想法是使用一个300Gb的大文件(或者每个50Gb的几个大文件),然后我只使用一个打开的文件句柄,只需查找每个相关数据并阅读它,但我不是打开和关闭文件句柄的开销。有人可以对此有所了解吗?

    我的另一个想法是尝试将文件分组到更大的~100Mb文件,然后我每次读取100Mb而不是大量的212k读取,但实现起来要比上面的想法复杂得多。

    无论如何,如果有人可以就此提出一些建议或者知道如何改善运行时间我会很感激!

    感谢。

    Profiler更新:

    我在流程上运行了一个分析器,看起来计算需要62%的运行时间,而文件读取需要34%。这意味着,即使我奇迹般地将文件i / o成本降低了34倍,我仍然留下了24天,这是一个相当大的改进,但仍然很长一段时间:)

6 个答案:

答案 0 :(得分:12)

打开文件句柄不太可能成为瓶颈;实际的磁盘IO是。如果您可以并行化磁盘访问(例如,使用多个磁盘,更快的磁盘,RAM磁盘......),您可能会受益更多。此外,确保IO不阻止应用程序:从磁盘读取,并在等待IO时进行处理。例如。用读者和处理器线程。

另一件事:如果下一步取决于当前的计算,为什么要将其保存到磁盘呢?也许对于进程的依赖关系的另一种观点,你可以重做数据流并摆脱大量的IO。

哦,是的,测量它:)

答案 1 :(得分:10)

  

每个文件都是〜212k,所以我拥有   ~300Gb的数据。它看起来像   整个过程需要大约40天......一会儿   计算是连续的(每个   计算取决于一个   之前),所以我不能平行这个   处理到不同的CPU或PC。 ... 漂亮   确定大部分开销都来自   文件系统访问...每一个   我打开手柄时访问文件的时间   一旦我完成它然后关闭它   阅读数据。

连续写入数据300GB的数据可能需要40分钟,而这只是40天的一小部分。磁盘写入性能不应成为问题。

您只想打开一次文件的想法就是现货。在每次操作之后可能关闭文件会导致处理阻塞,直到磁盘完全写出所有数据为止,否定了磁盘缓存的好处。

我敢打赌,这个应用程序的最快实现将使用内存映射文件,所有现代操作系统都具备此功能。它最终也可能是最简单的代码。你需要一个64位处理器和操作系统,你应该需要300GB的RAM。将整个文件一次映射到地址空间,只需用指针读取和写入数据。

答案 2 :(得分:4)

在进行任何更改之前,运行探查器跟踪以确定大部分时间用于确保实际优化实际问题的位置可能很有用。

答案 3 :(得分:4)

从你的简短解释中,听起来像xtofl线程建议是正确的方法。我建议您首先分析您的应用程序,但要确保时间在IO和CPU之间分配。

然后我会考虑由两个队列连接的三个线程。

  1. 线程1读取文件并将其加载到ram中,然后将数据/指针放入队列中。如果队列超过一定大小,则线程会休眠,如果它低于某个大小则再次启动。
  2. 线程2从队列中读取数据并进行计算,然后将数据写入第二个队列
  3. 线程3读取第二个队列并将数据写入磁盘
  4. 您可以考虑合并线程1和3,这可能会减少磁盘上的争用,因为您的应用一次只会执行一个磁盘操作。

    操作系统如何处理所有文件?它们都在一个目录中吗?什么是浏览目录时的性能(gui filemanager / dir / ls)?如果此性能不佳,您可能正在文件系统舒适区之外工作。虽然你只能在unix上更改它,但是一些文件系统针对不同类型的文件使用进行了优化,例如大文件,大量小文件等。您还可以考虑在不同目录中拆分文件。

答案 4 :(得分:3)

使用SQLite怎么样?我想你可以摆脱一张桌子。

答案 5 :(得分:2)

应调查使用内存映射文件,因为它会减少系统调用次数。