我使用Python中的Barnes-Hut优化实现了N体仿真,对于N = 10,000个物体,它以不可接受的速度运行,但它仍然太慢而无法实时观察。
每个时间步都会生成一个新帧,要显示帧,我们必须首先计算实体的新位置,然后全部绘制它们。对于N = 10,000,生成一帧需要大约5秒钟(由于Barnes-Hut应该给出更好的结果,这是太高了)。显示通过pygame模块完成。
我希望能够以更高的速度录制我的模拟并重播一次。
如何在不降低程序速度或超出内存限制的情况下实现此目的?
一个潜在的解决方案就是每一步都保存pygame屏幕,但这显然非常慢。
我还考虑过存储每个时间步骤生成的实体的位置列表,然后在情境结束后重新绘制所有帧。绘制一个框架仍然需要一些时间,但没有计算新位置所花费的时间。
答案 0 :(得分:1)
你将纯python与各种调用代码编译代码的程序进行比较。纯python比优化编译器生成的代码慢几个数量级。抛开语言战争,有些情况下python对脚本语言的执行速度非常快,而且有些情况下执行速度很慢。
我制作的许多苛刻的python项目都需要使用numpy/pandas/scipy
或者像Pypy这样的解释器来编译一些python代码,以便立即提高它们的执行速度。编译器倾向于生成更快的代码,因为它们可以脱机进行优化,而不是试图在运行时的时间压力下执行它们。
视频文件是最通用且易于管理的播放格式,但需要一些胶水代码。要制作一个,您需要一个库来将可视化帧编码为视频帧。您似乎已经能够每帧生成图像,因此剩下的唯一步骤就是找到视频编解码器。
可以通过命令行界面调用FFMPEG将帧转储到视频文件中:http://zulko.github.io/blog/2013/09/27/read-and-write-video-frames-in-python-using-ffmpeg/
写作的示例代码是:
command = [ FFMPEG_BIN,
'-y', # (optional) overwrite output file if it exists
'-f', 'rawvideo',
'-vcodec','rawvideo',
'-s', '420x360', # size of one frame
'-pix_fmt', 'rgb24',
'-r', '24', # frames per second
'-i', '-', # The imput comes from a pipe
'-an', # Tells FFMPEG not to expect any audio
'-vcodec', 'mpeg'",
'my_output_videofile.mp4' ]
pipe = sp.Popen( command, stdin=sp.PIPE, stderr=sp.PIPE)
使用此方法,如果使用numpy数组,则可以使用此方法转储帧:
pipe.proc.stdin.write( image_array.tostring() )
此方法已由ffmpy库包装。
还有一个简单的选项,但它牺牲了视频文件的多功能性(以及真正令人印象深刻的有损压缩算法)。将可视化框架转换为生成文件。修改可视化工具以从文件中读取帧并以指定的速率播放它们。
这是一种直接的方法,我过去用来保存重播数据,以便稍后我玩机器人的多人游戏vindinium时观看。
应特别提及记忆,这非常适合数学计算。只需缓存递归定义的函数的结果,您可以节省大量的不必要的计算成本。 Barnes-Hut似乎有一个递归的方面,所以你应该检查记忆那个部分的可能性。