如何将 N 体模拟录制为视频?
How to record N-body simulation as a video?
我已经在 Python 中使用 Barnes-Hut 优化实现了 N 体模拟,它对 N=10,000 个物体以不可接受的速度运行,但它仍然太慢无法实时观看。
每个时间步都会生成一个新的框架,要显示框架,我们必须首先计算物体的新位置,然后将它们全部绘制出来。对于 N=10,000,生成一帧大约需要 5 秒(这太高了,因为 Barnes-Hut 应该会给出更好的结果)。显示是通过pygame模块完成的。
因此我想记录我的模拟并在以更高的速度完成后重播一次。
如何在不降低程序速度或超出内存限制的情况下完成此操作?
一个可能的解决方案是简单地在每个时间步保存 pygame 屏幕,但这显然很慢。
我还考虑过存储每个时间步生成的物体位置列表,然后在情况结束后重新绘制所有帧。绘制框架仍然需要一些时间,但不会像计算新位置所花费的时间那么多。
您将纯 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 似乎有一个递归的方面,所以你应该检查记忆那部分的可能性。
我已经在 Python 中使用 Barnes-Hut 优化实现了 N 体模拟,它对 N=10,000 个物体以不可接受的速度运行,但它仍然太慢无法实时观看。
每个时间步都会生成一个新的框架,要显示框架,我们必须首先计算物体的新位置,然后将它们全部绘制出来。对于 N=10,000,生成一帧大约需要 5 秒(这太高了,因为 Barnes-Hut 应该会给出更好的结果)。显示是通过pygame模块完成的。
因此我想记录我的模拟并在以更高的速度完成后重播一次。
如何在不降低程序速度或超出内存限制的情况下完成此操作?
一个可能的解决方案是简单地在每个时间步保存 pygame 屏幕,但这显然很慢。
我还考虑过存储每个时间步生成的物体位置列表,然后在情况结束后重新绘制所有帧。绘制框架仍然需要一些时间,但不会像计算新位置所花费的时间那么多。
您将纯 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 似乎有一个递归的方面,所以你应该检查记忆那部分的可能性。