2017-09-26 18 views
3

我已經實現了使用Python中的巴恩斯必勝客優化其在未接受速度對於N = 10,000機構運行的N體模擬,但它仍然太慢觀看實時。如何記錄N體模擬的視頻?

一個新幀生成的每個時間步長,並顯示該幀首先要計算機構的新位置,然後繪製它們。對於N = 10,000時,它需要約5秒,以生成一個幀(這是waaay過高作爲巴恩斯小屋應當給予更好的結果)。顯示是通過pygame模塊完成的。

因此,我想記錄我的模擬,它的以較高的速度完成一次後重播。

我怎樣才能做到這一點,而不會減慢程序或超過內存限制?

一個潛在的解決方法是保存pygame的屏幕的每個時間步長,但是這顯然是非常緩慢的。

我也想過存儲體的位置列表生成的每個時間步長,然後重新繪製所有的幀一旦形勢完成。繪製框架仍需要一些時間,但計算新位置的時間並不多。

+1

不是真的有關,但爲什麼你認爲「(這是waaay過高的巴恩斯必勝客應給予更好的結果)」 –

+0

@ juanpa.arrivillaga:與天真的直接O(N^2運行比較好以後)算法,我證實Barnes-Hut的確如預期的那樣在O(NlogN)中工作。在直接比較中,N = 10,000甚至不可行。但是,我已經看到其他Barnes-Hut實現在線,N = 10,000時每幀僅需0.5秒。我還沒有發現緩慢的來源,但我相信我的代碼可以比現在快10倍。 –

+0

*純python *中的那些實現?或者其他一些語言,或者他們可能使用像'numpy'這樣的數字計算軟件包? –

回答

1

你純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,多人遊戲,殭屍重播數據以後看一個簡單的方法。


特別要提到memoization,它非常適合數學計算。只需緩存遞歸定義函數的結果,即可節省大量不必要的計算,只需很少的內存成本。 Barnes-Hut似乎有一個遞歸方面,因此您應該檢查記憶該部分的可能性。