Python 通过列表理解或映射加快numpy数组分配?
我试图将一个小的2D numpy数组(“源”)的值添加到一个较大的2D numpy数组(“帧”)中,从帧数组中的特定位置(“pos_x”、“pos_y”)开始。现在,我有两个for循环,在每个位置将源值添加到帧值:Python 通过列表理解或映射加快numpy数组分配?,python,python-3.x,multidimensional-array,mapping,list-comprehension,Python,Python 3.x,Multidimensional Array,Mapping,List Comprehension,我试图将一个小的2D numpy数组(“源”)的值添加到一个较大的2D numpy数组(“帧”)中,从帧数组中的特定位置(“pos_x”、“pos_y”)开始。现在,我有两个for循环,在每个位置将源值添加到帧值: for i in range(x): for j in range(y): frame[pos_x+i][pos_y+j] += source[i][j] (“x”和“y”是源阵列的形状) 但是,阵列相当大(帧阵列形状:5000x8000,源阵列形状:100
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)]
(改编自螺纹:和)
但循环所需的时间与原始循环所需的时间一样长
另一个想法是,如果source[i][j]!=0。但是当我试着这么做的时候,花了三倍多的时间(潜在的子问题:知道为什么吗?)切片在
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)
您可以在这里利用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解释器的所有开销。我认为您发布的代码中有一个输入错误,在第二个代码块中,第二个范围应该是
range(x)
而不是范围(xs)
,对吗?是的,谢谢(那些是我在更大程序中的旧变量名)。非常感谢!现在效果好多了!你知道有没有什么书、网站或其他东西可以让我通过这样的方式来学习优化代码(特别是关于内存分配、用c扩展等等)?@YohanneSaurus你永远不必像numpy(以及其他类似的库)那样明确地担心内存分配或类似的问题我会帮你处理的。Python经常因为速度慢而名声不佳,因为它有很多开销。您可以编写速度相当快的代码,但有时需要了解引擎盖下实际发生的事情,才能理解为什么有些事情比其他事情慢。我没有“银弹”教程或书,但我通常从不担心只运行一次的代码,但如果有大循环(或嵌套循环),我会尝试找到更快的库。