【发布时间】:2012-06-21 23:00:40
【问题描述】:
我编写了一个 Python 脚本来计算 3D 空间中两点之间的距离,同时考虑周期性边界条件。问题是我需要对很多很多点进行这个计算,而且计算速度很慢。这是我的功能。
def PBCdist(coord1,coord2,UC):
dx = coord1[0] - coord2[0]
if (abs(dx) > UC[0]*0.5):
dx = UC[0] - dx
dy = coord1[1] - coord2[1]
if (abs(dy) > UC[1]*0.5):
dy = UC[1] - dy
dz = coord1[2] - coord2[2]
if (abs(dz) > UC[2]*0.5):
dz = UC[2] - dz
dist = np.sqrt(dx**2 + dy**2 + dz**2)
return dist
然后我就这样调用函数
for i, coord2 in enumerate(coordlist):
if (PBCdist(coord1,coord2,UC) < radius):
do something with i
最近我读到使用列表理解可以大大提高性能。以下适用于非 PBC 案例,但不适用于 PBC 案例
coord_indices = [i for i, y in enumerate([np.sqrt(np.sum((coord2-coord1)**2)) for coord2 in coordlist]) if y < radius]
for i in coord_indices:
do something
对于 PBC 案,有什么方法可以做到这一点吗?有没有更好的替代方法?
【问题讨论】:
-
您正在使用 NumPy,因此您应该对循环进行矢量化以提高性能。
coordlist的结构到底是什么?它应该是一个二维 NumPy 数组,以便能够使用 NumPy ufunc 优化循环。 -
coordlist 是一个形状约为 (5711,3) 的 numpy 数组。 coordlist 本身来自一个更大的列表,所以我有效地循环 coordlist 20,000 次,而 coordlist 的列表循环了大约 50 次......你明白了。
-
"Vectorising" 在 NumPy 的上下文中意味着您使用 NumPy ufunc 将循环移动,否则您必须在 Python 代码中执行 C 代码(就像我在回答中所做的那样)。如果您担心性能,我建议您阅读一下 NumPy。
标签: python optimization list-comprehension