在我的程序中,我正在模拟大量迭代的N体系统。对于每次迭代,我生成一组6N坐标,我需要将其附加到文件,然后用于执行下一次迭代。代码是用C ++编写的,目前使用ofstream
的方法write()
在每次迭代时以二进制格式写入数据。
我不是这个领域的专家,但我想改进这部分程序,因为我正在优化整个代码。我觉得与在每个周期写入计算结果相关的延迟会显着降低软件的性能。
我很困惑,因为我没有实际并行编程和低级文件I / O的经验。我想到了一些我想象的可以实现的抽象技术,因为我正在使用Unix操作系统编写现代(可能是多核)的机器:
mmap
(文件大小可能很大,按GB的顺序,这种方法是否足够强大?)但是,我不知道如何最好地实施它们并将它们恰当地结合起来。
答案 0 :(得分:3)
当然,在每次迭代时写入文件效率很低,很可能会降低计算速度。 (根据经验,取决于你的实际情况)
您必须使用producer -> consumer设计模式。它们将通过排队链接,如传送带。
通过拆分两者,您可以更轻松地提高性能,因为每个过程都更简单,并且对另一个过程的干扰更少。
无需来优化两者。只优化最慢(瓶颈)。
实际上,您在它们之间使用线程和同步队列。有关实现提示,请查看here,尤其是§18.12“生产者 - 消费者模式”。
关于流量管理,您必须通过选择“最大队列大小”来增加一点复杂性,并在队列空间不足时让生产者等待。那么要小心死锁,仔细编码。 (参见我给出的维基百科链接)
注意:使用boost线程是个好主意,因为线程不是很便携。 (好吧,它们是从C ++ 0x开始,但C ++ 0x可用性还不好)
答案 1 :(得分:1)
最好将操作拆分为两个独立的流程:data-producing
和file-writing
。 Data-producing
将使用一些缓冲区进行迭代数据传递,file-writing
将使用队列来存储写请求。然后,data-producing
只发布一个写请求然后继续,而file-writing
则会在后台处理写作。
基本上,如果数据生成的速度比可能存储的速度快得多,那么您很快就会将大部分数据保存在缓冲区中。在这种情况下,你的实际方法似乎是非常合理的,因为很少可以通过编程方式完成,然后改善情况。
答案 2 :(得分:1)
如果您不想在不同的线程中玩游戏,可以尝试使用允许异步写入的aio_write()。基本上你给操作系统写缓冲区,函数立即返回,并在程序继续时完成写操作,稍后你可以检查写操作是否完成。
这个解决方案仍然会遇到其他答案中提到的生产者/消费者问题,如果你的算法生成的数据比写入的速度快,最终你会耗尽内存来存储算法和写入之间的结果,所以你必须尝试一下,看看它是如何运作的。
答案 3 :(得分:0)
“使用mmap(文件大小可能很大,按GB的顺序,是这个 方法足够健壮?)“
mmap是操作系统加载程序,共享库和页面/交换文件的方法 - 它与任何其他文件I / O一样健壮,通常性能更高。
但是在大多数操作系统上,在使用映射文件时,扩展映射文件的大小是不好/困难/不可能的。因此,如果您知道数据的大小,或者您只是阅读,那就太棒了。对于你不断添加的日志/转储,它不太适合 - 除非你知道一些最大的大小。