【问题标题】:Speed up numpy array assignment via list comprehension or mapping?通过列表理解或映射加速 numpy 数组分配?
【发布时间】:2019-03-02 07:59:58
【问题描述】:

我正在尝试将一个小的 2D numpy 数组(“source”)的值添加到一个更大的 2D numpy 数组(“frame”)中,从帧数组中的特定位置开始(“pos_x”,“铭文”)。现在,我有两个 for 循环将源值添加到每个位置的帧值:

for i in range(x):
    for j in range(y):
        frame[pos_x+i][pos_y+j] += source[i][j]

(“x”和“y”是源数组的形状)

但是,阵列非常大(框架阵列形状:5000x8000,源阵列形状:1000x5000)。所以这个过程需要很长时间(大约 15 秒)。

有什么方法可以加快这个过程,无论是通过列表理解、映射还是其他方式?

我已经用多个语句和赋值尝试了这样的列表理解:

frame = [[frame[pos_x+i][pos_y+j] + source[i][j] for j in range(y)] for i in range(x)]

(改编自线程:How can I do assignments in a list comprehension?Multiple statements in list compherensions in Python?

但它需要的时间与原来的 for 循环一样长。

另一个想法是只允许循环使用if source[i][j] != 0 的非零值。但是当我尝试这样做时,它花费了三倍多的时间(潜在的子问题:知道为什么吗?)。

【问题讨论】:

  • 我认为您发布的代码中有错字,在第二个代码块中,第二个范围应该是range(x)而不是range(xs),对吧?
  • 真的,谢谢(那些是我在较大程序中的旧变量名)。

标签: python python-3.x multidimensional-array mapping list-comprehension


【解决方案1】:

切片在numpy 中是可变的;因此您可以执行以下操作:

import numpy as np

A = np.zeros((10,10), int)
B = np.zeros((5,5), int) + 5

A[2:7,2:7] += B

print(A)

【讨论】:

    【解决方案2】:

    您可以在此处利用 numpy 矢量化而不是循环来获得巨大的加速。这只是计算索引并检查是否超出范围的问题。

    height, width = source.shape
    pos_x2 = pos_x + width
    pos_y2 = pos_y + height
    #check for possible index out of range
    fheight, fwidth = frame.shape
    if pos_x2 > fwidth or pos_y2 > fheight:
        print('source out of frame bounds')
    else:
        #add `source` to our slice of `frame`
        frame[pos_y:pos_y2, pos_x:pos_x2] += source
    

    虽然从技术上讲,这将具有相同的时间复杂度,但 numpy 使用高效的编译 C 代码,可以利用硬件矢量化等功能,并且没有 python 解释器的所有开销。

    【讨论】:

    • 非常感谢!现在效果好多了!是否有任何书籍或网站或您知道的任何东西,我可以在其中了解更多关于以这样的方式优化代码(尤其是关于内存分配、使用 c 扩展等)?
    • @YohanneSaurus 你永远不必明确地担心内存分配或任何类似的事情,因为 numpy(和其他类似的库)会为你处理它。 Python 经常因为速度慢而声名狼藉,因为它有很多开销。您可以编写相当快的代码,但有时需要了解幕后实际发生的事情才能理解为什么有些事情比其他事情慢。我没有“灵丹妙药”教程或书籍,但我通常从不担心只运行一次的代码,但如果有一个大循环(或嵌套循环),我会尝试找到一个更快的库。
    猜你喜欢
    • 1970-01-01
    • 2017-05-19
    • 2018-10-16
    • 2013-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多