通过列表理解或映射来加速numpy数组分配?

时间:2018-09-26 13:55:17

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

我正在尝试将较小的2D numpy数组(“源”)的值添加到较大的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循环非零值。但是当我尝试这样做时,它花费了三倍的时间(潜在的子问题:为什么知道?)。

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分:1)

您可以在这里利用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解释器的所有开销。