如何改进python中大数组上的循环



在对StackOverflow进行了一些研究后,我没有找到一个简单的答案来解决我的问题。因此,我与您分享我的代码,以便找到一些帮助。

S=np.random.random((495,930,495,3,3))
#The shape of S is (495,930,495,3,3)
#I want to calculate for each small array (z,y,x,3,3) some features
for z in range(S.shape[0]):
for y in range(S.shape[1]):
for x in range(S.shape[2]):
res[z,y,x,0]=np.array(np.linalg.det(S[z,y,x])/np.trace(S[z,y,x]))
res[z,y,x,1]=np.array(S[z,y,x].mean())
res[z,y,x,2:]=np.array(np.linalg.eigvals(S[z,y,x]))

这是我的问题。S阵列的大小是巨大的。所以我想知道是否有可能使循环更快。

我不得不将形状缩减为(49,93,49,3,3),以便它在我的硬件上以可接受的时间运行。通过避免不必要的工作(没有优化你的算法(,我可以减少5-10%。不必要的工作包括但不限于:

  • 执行(全局(查找
  • 多次计算相同的值

您可能还想尝试不同的python运行时,例如PyPy而不是CPython。

这是你的脚本的更新版本:

#!/usr/bin/python
import numpy as np
def main():
# avoid lookups
array = np.array
trace = np.trace
eigvals = np.linalg.eigvals
det = np.linalg.det
#The shape of S is (495,930,495,3,3)
shape = (49,93,49,3,3) # so my computer can run it
S=np.random.random(shape)
res = np.ndarray(shape) # missing from the question, I hope this is correct
#I want to calculate for each small array (z,y,x,3,3) some features
# get shape only once, instead of z times for shape1 and z*y times for shape2
shape1 = S.shape[1]
shape2 = S.shape[2]
for z in range(S.shape[0]):
for y in range(shape1):
for x in range(shape2):
# get value once instead of 4 times
s = S[z,y,x]
res[z,y,x,0]=array(det(s)/trace(s))
res[z,y,x,1]=array(s.mean())
res[z,y,x,2:]=array(eigvals(s))
# function to have local (vs. global) lookups
main()

运行时间从25秒减少到23秒(用超精细测量(。

有用的参考资料:

  • 为什么Python代码在函数中运行得更快
  • Python:两个简单的函数,为什么第一个比第二个快
  • Python导入X还是从X导入Y?(性能(
  • 将python导入函数是否会带来性能成本

最新更新