作为一名长期的C ++开发人员我刚开始研究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 :(得分:5)
相比之下,时间看起来很大,因为mathutils.geometry.intersect_ray_tri()
是快。该方法在扩展中实现,并以本机速度执行。
该方法的Python时间转到:
mathutils.geometry
和mathutils.geometry.intersect_ray_tri
以及poly.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作为将此代码转换为也可以以原生速度运行的编译扩展的简单途径。