我有一个三维的numpy数组A。我想要将每个元素A[i,j,k]乘以w*( i / Lx + j / Ly + k / Lz ),其中w、Lx、Ly和Lz都是实数(浮点数)。使用for循环执行此操作非常不切实际,因为我需要能够对大型数组进行缩放,而对三个索引ijk进行for循环的缩放的时间复杂度为O(N^3)。
是否有一种有效的方法来对numpy数组的每个元素执行操作,并考虑索引?
是否有一种有效的方法来对numpy数组的每个元素执行操作,并考虑索引?
broadcasting
) -M,N,R = A.shape
p1 = np.arange(M)[:,None,None]/Lx
p2 = np.arange(N)[:,None]/Ly
p3 = np.arange(R)/Lz
out = A/(w*(p1 + p2 + p3))
np.ix_
来得到更加优美的解决方案。M,N,R = A.shape
X,Y,Z = np.ix_(np.arange(M),np.arange(N),np.arange(R))
out = A/(w*((X/Lx) + (Y/Ly) + (Z/Lz)))
运行时测试和输出验证 -
函数定义:
def vectorized_app1(A, w, Lx, Ly, Lz ):
M,N,R = A.shape
p1 = np.arange(M)[:,None,None]/Lx
p2 = np.arange(N)[:,None]/Ly
p3 = np.arange(R)/Lz
return A/(w*(p1 + p2 + p3))
def vectorized_app2(A, w, Lx, Ly, Lz ):
M,N,R = A.shape
X,Y,Z = np.ix_(np.arange(M),np.arange(N),np.arange(R))
return A/(w*((X/Lx) + (Y/Ly) + (Z/Lz)))
def original_app(A, w, Lx, Ly, Lz ):
out = np.empty_like(A)
M,N,R = A.shape
for i in range(M):
for j in range(N):
for k in range(R):
out[i,j,k] = A[i,j,k]/(w*( (i / Lx) + (j / Ly) + (k / Lz) ))
return out
时间:
In [197]: # Inputs
...: A = np.random.rand(100,100,100)
...: w, Lx, Ly, Lz = 2.3, 3.2, 4.2, 5.2
...:
In [198]: np.allclose(original_app(A,w,Lx,Ly,Lz),vectorized_app1(A,w,Lx,Ly,Lz))
Out[198]: True
In [199]: np.allclose(original_app(A,w,Lx,Ly,Lz),vectorized_app2(A,w,Lx,Ly,Lz))
Out[199]: True
In [200]: %timeit original_app(A, w, Lx, Ly, Lz )
1 loops, best of 3: 1.39 s per loop
In [201]: %timeit vectorized_app1(A, w, Lx, Ly, Lz )
10 loops, best of 3: 24.6 ms per loop
In [202]: %timeit vectorized_app2(A, w, Lx, Ly, Lz )
10 loops, best of 3: 24.2 ms per loop