4

我有一个执行一组实验的软件(C++)。如果不存储结果,所有实验都需要一分钟多一点的时间。生成的总数据量为 2.5 GB,太大了,无法在实验结束前存储在内存中,然后再写入文件。因此,我将它们分块编写。

for(int i = 0; i < chunkSize;i++){
    outfile << results_experiments[i] << endl;
}

其中 ofstream outfile("data"); 并且 outfile 仅在最后关闭。

但是,当我将它们写入 4700 KB 的块(实际上是 4700/Chunksize = results_experiments 元素的大小)时,实验需要大约 50 倍的时间(超过一个小时......)。这是不可接受的,并且使我之前的优化尝试看起来相当愚蠢。特别是因为这些实验再次需要使用许多不同的参数设置等进行。(至少 100 次,但最好更多)

具体我的问题是:

  • 理想的块大小是多少?

  • 有没有比我目前写入数据的方式更有效的方式(或效率非常低的方式)?

基本上:帮助我尽可能少地引入文件 IO 开销..

我认为应该可以更快地完成此操作,因为复制(写入和读取!)生成的文件(相同大小)需要我不到一分钟的时间..

代码应该是完全独立于平台的,并且不使用任何(非标准)库(我可以为单独的平台提供单独的版本和更复杂的安装说明,但这很麻烦..)如果获得总实验时间不可行在 5 分钟内,没有平台/库依赖(并且可能有),我会认真考虑引入这些。(平台是windows,但至少应该有一个简单的linux端口)

感谢你的付出。

4

3 回答 3

5

对于初学者来说,不为每个块刷新缓冲区似乎是个好主意。似乎也可以异步执行 IO,因为它完全独立于计算。您还可以使用它mmap来提高文件 I/O 的性能。

于 2012-06-06T16:24:08.207 回答
3

如果输出不必是人类可读的,那么您可以研究二进制格式。以二进制格式存储数据比文本格式占用更少的空间,因此需要更少的磁盘 i/o。但是如果数据都是字符串,那差别不大。因此,如果您尽可能多地写出数字而不是格式化文本,您可以获得很大的收益。

但是我不确定这是否/如何使用 STL iostreams 完成。C 风格的方式是使用fopen(..., "wb")and fwrite(&object, ...)

我认为boost::Serialisation可以使用<<运算符进行二进制输出。

另外,你能减少你写的数量吗?例如,没有格式或多余的文本,只是最低限度。

于 2012-06-06T19:23:57.767 回答
0

endl 在写入 ofstream 时是否刷新缓冲区取决于实现——

您也可以尝试增加 ofstream 的缓冲区大小

char *biggerbuffer = new char[512000];

  outfile.rdbuf()->pubsetbuf(biggerbuffer,512000);

pubsetbuf 的可用性可能因您的 iostream 实现而异

于 2012-06-06T16:51:19.120 回答