python - 加速 python 中的嵌套 for 循环/通过 numpy 数组

标签 python arrays numpy for-loop

假设我有 4 个 numpy 数组 A,B,C,D ,每个数组的大小为 (256,256,1792)。 我想遍历这些数组的每个元素并对它做一些事情,但是我需要以 256x256x256 立方体的 block 来做。

我的代码是这样的:

for l in range(7): 
    x, y, z, t = 0,0,0,0
    for m in range(a.shape[0]):
        for n in range(a.shape[1]):
            for o in range(256*l,256*(l+1)):
                t += D[m,n,o] * constant
                x += A[m,n,o] * D[m,n,o] * constant
                y += B[m,n,o] * D[m,n,o] * constant
                z += C[m,n,o] * D[m,n,o] * constant
    final = (x+y+z)/t
    doOutput(final)

该代码可以正常运行并输出我想要的内容,但速度非常慢。我在网上读到,在 python 中应该避免那种嵌套的 for 循环。最干净的解决方案是什么? (现在我正尝试在 C 中完成我的这部分代码,并通过 Cython 或其他工具以某种方式导入它,但我喜欢纯 python 解决方案)

谢谢

添加

Willem Van Onsem 对第一部分的解决方案似乎工作得很好,我想我理解它。但是现在我想在求和之前修改我的值。看起来像

(在外层 l 循环内)

for m in range(a.shape[0]):
    for n in range(a.shape[1]):
        for o in range(256*l,256*(l+1)):
            R += (D[m,n,o] * constant * (A[m,n,o]**2 
            + B[m,n,o]**2 + C[m,n,o]**2)/t - final**2)
doOutput(R)

我显然不能只对总和求平方 x = (A[:a.shape[0],:a.shape[1],256*l:256*(l+1)]*Dsub .sum()**2*constant 因为 (A²+B²) != (A+B)² 如何重做最后一个 for 循环?

最佳答案

自从您更新 t m in range(a.shape[0]) 的每个元素, n in range(a.shape[1])o in range(256*l,256*(l+1)) ,你可以替代:

for m in range(a.shape[0]):
    for n in range(a.shape[1]):
        for o in range(256*l,256*(l+1)):
            t += D[m,n,o]

与:

t += D[:a.shape[0],:a.shape[1],256*l:256*(l+1)].sum()

其他作业也一样。因此,您可以将代码重写为:

for l in range(7): 
    Dsub = D[:a.shape[0],:a.shape[1],256*l:256*(l+1)]
    x = (A[:a.shape[0],:a.shape[1],256*l:256*(l+1)]*Dsub).sum()*constant
    y = (B[:a.shape[0],:a.shape[1],256*l:256*(l+1)]*Dsub).sum()*constant
    z = (C[:a.shape[0],:a.shape[1],256*l:256*(l+1)]*Dsub).sum()*constant
    t = Dsub.sum()*constant
   final = (x+y+z)/t
   doOutput(final)

请注意 *numpy 中是element-wise 乘法,不是矩阵乘积。您可以在求和之前进行乘法运算,但由于与常数相乘的总和等于该常数与总和的乘积,我认为在循环外执行此操作更有效。

如果a.shape[0]等于D.shape[0]等。您可以使用 :而不是 :a.shape[0] .根据您的问题,似乎是这样。所以:

# only when `a.shape[0] == D.shape[0], a.shape[1] == D.shape[1] (and so for A, B and C)`
for l in range(7): 
    Dsub = D[:,:,256*l:256*(l+1)]
    x = (A[:,:,256*l:256*(l+1)]*Dsub).sum()*constant
    y = (B[:,:,256*l:256*(l+1)]*Dsub).sum()*constant
    z = (C[:,:,256*l:256*(l+1)]*Dsub).sum()*constant
    t = Dsub.sum()*constant
    final = (x+y+z)/t
    doOutput(final)

正在处理 .sum()numpy 上level 将提高性能,因为您不使用 .sum() 来回转换值,你使用了一个循环。

编辑:

您更新后的问题没有太大变化。您可以简单地使用:

m,n,_* = a.shape
lo,hi = 256*l,256*(l+1)
R = (D[:m,:n,lo:hi]*constant*(A[:m,:n,lo:hi]**2+B[:m,:n,lo:hi]**2+D[:m,:n,lo:hi]**2)/t-final**2)).sum()
doOutput(R)

关于python - 加速 python 中的嵌套 for 循环/通过 numpy 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43068785/

相关文章:

python - NumPy 中如何处理大整数?

python - 如果我从 python 中的多个不同进程登录同一个文件会发生什么?

php - 如何在满足条件时从数组中删除元素

arrays - MongoDB - 通过整数数组搜索文档

c - 从外部访问函数内部分配的数组 - 意外结果

python - 如何获得 Numpy 矩阵的整数特征向量?

python on-the-fly md5 作为一个读取流

python - 如何通过将另外两个 tf.feature_column 相乘来创建 tf.feature_column?

python - 如何渲染同一列表中的多个多边形

python - 来自任意级别嵌套字典的 numpy 结构化数组