我写了一个Python函数,它计算大数目(N~10^3)粒子之间的成对电磁相互作用,并将结果存储在NxN complex128 ndarray中。它运行,但它是一个更大程序中最慢的部分,当N=900[修正]时,大约需要40秒。原始代码如下所示:
import numpy as np
def interaction(s,alpha,kprop): # s is an Nx3 real array
# alpha is complex
# kprop is float
ndipoles = s.shape[0]
Amat = np.zeros((ndipoles,3, ndipoles, 3), dtype=np.complex128)
I = np.array([[1,0,0],[0,1,0],[0,0,1]])
im = complex(0,1)
k2 = kprop*kprop
for i in range(ndipoles):
xi = s[i,:]
for j in range(ndipoles):
if i != j:
xj = s[j,:]
dx = xi-xj
R = np.sqrt(dx.dot(dx))
n = dx/R
kR = kprop*R
kR2 = kR*kR
A = ((1./kR2) - im/kR)
nxn = np.outer(n, n)
nxn = (3*A-1)*nxn + (1-A)*I
nxn *= -alpha*(k2*np.exp(im*kR))/R
else:
nxn = I
Amat[i,:,j,:] = nxn
return(Amat.reshape((3*ndipoles,3*ndipoles)))
我以前从未使用过Cython,但这似乎是我加快速度的一个好地方,所以我几乎盲目地采用了我在在线教程中找到的技术。我得到了一些加速(30秒vs.40秒),但没有我预期的那么戏剧化,所以我想知道我是做错了什么,还是错过了关键的一步。以下是我对上述例行公事的最佳尝试:
^{pr2}$
NumPy的真正威力在于以向量化的方式跨大量元素执行一个操作,而不是在循环中分块使用该操作。在您的例子中,您使用了两个嵌套循环和一个IF条件语句。我建议扩展中间数组的维数,这将使^{} 发挥作用,因此可以一次性对所有元素使用相同的操作,而不是循环中的小数据块。在
为了扩展维度,可以使用^{}/^{} 。那么,遵循这样一个前提的向量化实现应该是这样的-
输出测试和运行时验证-
案例1:
^{pr2}$案例2:
案例三:
相关问题 更多 >
编程相关推荐