2017-10-04 91 views
3

是一個很長時間的C++開發人員我剛開始着手Python中的算法。我目前正在分析我的代碼,以瞭解如何在Python中高效編程。有一件事特別突出,我很樂意得到專家的解釋。Python元素訪問性能

我寫此包裝函數的光線 - 三角形相交:

def rayIntersectsTriangle(origin , direction , meshData , poly , worldCoordinateVertices): 
    return mathutils.geometry.intersect_ray_tri(worldCoordinateVertices[ meshData.loops[ poly.loop_start ].vertex_index ], 
               worldCoordinateVertices[ meshData.loops[ poly.loop_start + 1 ].vertex_index ], 
               worldCoordinateVertices[ meshData.loops[ poly.loop_start + 2 ].vertex_index ], 
               direction , origin) != None 

如果在分析(使用CPROFILE)執行該功能有很多次代碼我有以下的結果:

ncalls tottime percall cumtime percall filename:lineno(function) 
15694126 22.314 0.000 25.812 0.000 ****.py:176(rayIntersectsPoly) 
[...] 
15694126 3.497 0.000 3.497 0.000 {built-in method mathutils.geometry.intersect_ray_tri} 

這個包裝怎麼會增加這麼多的開銷?我唯一能看到的是數組元素訪問。來自C++這真讓我困惑:D

任何對此的幫助將超級讚賞。我想盡可能快地獲得我的算法。

在此先感謝!乾杯!

+0

請參閱https://wiki.python.org/moin/TimeComplexity –

+0

......順便說一句,如果以數學爲中心的工作負載的運行時性能是您的首要目標,那麼Python可能不是您的語言。我可能會建議[Julia](https://julialang.org/)或[Go](https://golang.org/)? (Julia的網頁涵蓋了這兩個基準)。 –

+0

太棒了。感謝您的資源。我目前正在爲Blender開發一個插件,所以我沒有替代Python的 – Marcel

回答

5

時間看起來比較大,因爲mathutils.geometry.intersect_ray_tri()是這樣很快。該方法在擴展中實現並以本機速度執行。

Python的時間,則該方法進行:

  • 創建新的功能框架(只有一個表達式時需要相當大的比例)
  • 全球名稱查找(這是針對一個完成映射,本地名稱使用數組)。
  • 屬性查找,像mathutils.geometrymathutils.geometry.intersect_ray_tripoly.loop_start
  • 索引,所以worldCoordinateVertices[ ... ]

你可以通過緩存的一些這些地方的名稱或默認參數的結果使它更快一點:

def rayIntersectsTriangle(
     origin, direction, meshData, poly, worldCoordinateVertices 
     _intersect_ray_tri=mathutils.geometry.intersect_ray_tri): 
    loop_start = poly.loop_start 
    meshData_loops = meshData.loops 
    return _intersect_ray_tri(
     worldCoordinateVertices[meshData_loops[loop_start].vertex_index], 
     worldCoordinateVertices[meshData_loops[loop_start + 1].vertex_index], 
     worldCoordinateVertices[meshData_loops[loop_start + 2].vertex_index], 
     direction, origin) is not None 

我也用is not None;這是一個指針操作,建議用於測試None單身人士。

這會將8個屬性查找降低到2,並刪除mathutils的全局名稱查找。

儘管如此,這些都是微觀優化,只有在確實有影響的情況下才能做到這些(例如,在代碼中調用該方法的方法)。如果這對你來說確實是一個瓶頸,那麼考慮使用Cython作爲將此代碼轉換爲也可以本機速度運行的已編譯擴展的簡單途徑。

+0

哇,非常感謝。多麼詳細和快速的答案。這絕對給了我很多見解 – Marcel