看板 GameDesign 關於我們 聯絡資訊
最近用C++搭Python開發的2D地圖引擎 做了一些最佳化,有一點心得分享一下 為了讓Python可以存取C++裡的程式 我用的是Boost.Python做binding 畫圖用的是DirectX 9 最初我只把DirectX 9的2D畫圖用C++寫包裝給Python用 地圖的呈現都用純Python寫,結果效能很差 http://static.ez2learn.com/client05.PNG
像這樣的場景FPS只有30,最根本的原因是 地圖引擎在畫磚塊的迴圈很吃重 Python本身的效率差C++的大約在10~100倍之間 同樣的程式,Python的overhead太重 在迴圈中累積多了,再怎樣改善演算d法都不會有太大的幫助 除此之外還有個嚴重的問題,就是Python的GIL 簡單的來說是Python的一個全域鎖 主要是Python的物件都有reference count 因此在multi-thread跑時需要去取得GIL才能碰Python的物件 否則會crash 所以Python的thread實際同時在跑的thread只能有一個 而這個GIL造成在多核心開多thread反而會跑更慢 (因為多thread狂搶GIL) 這文章有講,可以參考看看 http://www.dabeaz.com/python/UnderstandingGIL.pdf 純Python thread是無法增加平行處理的能力 為了解決效率太差的問題,我用C++寫game thread的部份 感謝Boost.Python的簡單好用,事實上我寫的C++ 並沒有特別去為python做什麼調整,都是以C++做為思考在寫的 等到要expose到python時,Boost.Python幾乎都有簡單好用的方法可以用 有些地方要做點特別處理,但不多 而為了必免碰到GIL,C++的類別也都不去碰Python的任何東西 它們都是設計來被使用的,而有時需要callback回Python 這些都用Boost.Signal2來解開藕合 而expose時要注意一下,因為會有來自非Python建的thread 一來是在module開始時要呼叫一下初始化thread BOOST_PYTHON_MODULE(core) { PyEval_InitThreads(); .... } 二來是從C++建的thread callback回python時要取得GIL 不然會crash void do_callback() { AcquireGIL gil; callback(); // callback object in Python } 幾乎一模一樣的程式,用C++重寫後包裝給Python用 這抓圖是地圖上塞了5000個骨髏角色,FPS可以到80 而且還沒做更進一步的最佳化 http://static.ez2learn.com/client16.PNG
這樣把核心封裝給Python操作有個好處 就是當底層的這些都完成後 剩下的高階控制的程式都用Python寫 改起來輕鬆愉快,不用再等編譯 開發效率會快很多 大略就這樣,有人有興趣的話 我有空或許可以再寫一些相關的心得 -- ▂▁ ▄▄▄▄ 程式寫到鬼打牆? ψ 贛! xx▄▄▄▄▄ 快上 http://ghosthitswall.com/ xxx xxxxxxx ▋│xx* xxxxxxx ⊙-⊙ 這該死的BUG!!! Φ ◣ ◢xxx xxxxxxx - ˊ ▃▅▇▅▃  ̄ ̄╩@__ ◣◣◣◣ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.227.214.207
VVll:感謝分享 11/17 14:53
art1:eve online後來為了效率也改用c++搭配Python 11/17 16:59
chchwy:python開發真的快很多 C++光是等編譯就不知道花掉多少時間 11/17 21:18
damody:感謝分享 個人都用lua 不過最近看到anglescript好像不錯 11/17 21:41
VVll:C++編譯要快 就是cpu好一點 跟ssd買下去了xd 11/17 21:42
damody:SSD+16g ram+i7 超讚 編譯超快 11/17 21:44
yoco315:py 包 c++ 超讚的 11/17 22:53
NIKE74731:推~ 11/18 00:33
su31o4gj83:推~感謝分享~ 11/18 15:25