Python 有没有更快的方法添加两个二维numpy数组
假设我有两个尺寸相同的大型二维numpy数组(比如2000x2000)。我想按元素对它们求和。我想知道是否有比np.add()更快的方法 编辑:我正在添加一个类似的示例,说明我现在使用的是什么。有没有办法加快速度Python 有没有更快的方法添加两个二维numpy数组,python,performance,python-2.7,numpy,optimization,Python,Performance,Python 2.7,Numpy,Optimization,假设我有两个尺寸相同的大型二维numpy数组(比如2000x2000)。我想按元素对它们求和。我想知道是否有比np.add()更快的方法 编辑:我正在添加一个类似的示例,说明我现在使用的是什么。有没有办法加快速度 #a and b are the two matrices I already have.Dimension is 2000x2000 #shift is also a list that is previously known for j in range(100000):
#a and b are the two matrices I already have.Dimension is 2000x2000
#shift is also a list that is previously known
for j in range(100000):
b=np.roll(b, shift[j] , axis=0)
a=np.add(a,b)
进近#1(矢量化)
我们可以使用模
来模拟滚动/循环移位
的循环行为,并使用广播索引覆盖所有行,我们将采用完全矢量化的方法,如下所示-
n = b.shape[0]
idx = n-1 - np.mod(shift.cumsum()[:,None]-1 - np.arange(n), n)
a += b[idx].sum(0)
进近#2(环形进近)
冒号符号与使用索引进行切片的比较
这里的想法是,一旦我们进入循环,就要做最少的工作。在进入循环之前,我们将预先计算每个迭代的起始行索引。因此,一旦进入循环,我们需要做的就是使用冒号表示法进行切片,这是数组中的一个视图,并将其相加。这应该比rolling
好得多,后者需要计算所有这些行索引,从而生成昂贵的副本
这里将进一步介绍使用冒号和索引进行切片时的查看和复制概念-
In [11]: a = np.random.randint(0,9,(10))
In [12]: a
Out[12]: array([8, 0, 1, 7, 5, 0, 6, 1, 7, 0])
In [13]: a[3:8]
Out[13]: array([7, 5, 0, 6, 1])
In [14]: a[[3,4,5,6,7]]
Out[14]: array([7, 5, 0, 6, 1])
In [15]: np.may_share_memory(a, a[3:8])
Out[15]: True
In [16]: np.may_share_memory(a, a[[3,4,5,6,7]])
Out[16]: False
运行时测试 函数定义-
def original_loopy_app(a,b):
for j in range(shift.size):
b=np.roll(b, shift[j] , axis=0)
a += b
def vectorized_app(a,b):
n = b.shape[0]
idx = n-1 - np.mod(shift.cumsum()[:,None]-1 - np.arange(n), n)
a += b[idx].sum(0)
def modified_loopy_app(a,b):
n = b.shape[0]
b_ext = np.row_stack((b, b[:-1] ))
start_idx = n-1 - np.mod(shift.cumsum()-1,n)
for j in range(start_idx.size):
a += b_ext[start_idx[j]:start_idx[j]+n]
案例1:
案例2:
因此,我们正在研究改进的循环方法在那里的加速效果 添加2000x2000阵列只需400万个元素,从硬件方面来说,添加非常简单。我认为优化此操作不会显著加快速度。您是否关心代码的性能?这是在临界循环的中间吗?它在一个循环中,加法大约每秒进行200次。仅此添加就消耗了总运行时间的50%以上。有什么建议吗?一种可能的加速方法是在计算数字时将其相加。您是否考虑过使用
线程
或子流程
库?(这些可能不是名称)@AnirbanDutta,您可以通过减少阵列的副本来节省一些时间。例如,x+=y比z=x+y快。加法运算中没有太多优化,考虑到更多的程序上下文,我们可以提供替代方案(如线程),但问题是,我真的不认为有太多要说的。谢谢。它正在工作。我也喜欢这样处理整件事。我的方法太传统了。
def original_loopy_app(a,b):
for j in range(shift.size):
b=np.roll(b, shift[j] , axis=0)
a += b
def vectorized_app(a,b):
n = b.shape[0]
idx = n-1 - np.mod(shift.cumsum()[:,None]-1 - np.arange(n), n)
a += b[idx].sum(0)
def modified_loopy_app(a,b):
n = b.shape[0]
b_ext = np.row_stack((b, b[:-1] ))
start_idx = n-1 - np.mod(shift.cumsum()-1,n)
for j in range(start_idx.size):
a += b_ext[start_idx[j]:start_idx[j]+n]
In [5]: # Setup input arrays
...: N = 200
...: M = 1000
...: a = np.random.randint(11,99,(N,N))
...: b = np.random.randint(11,99,(N,N))
...: shift = np.random.randint(0,N,M)
...:
In [6]: original_loopy_app(a1,b1)
...: vectorized_app(a2,b2)
...: modified_loopy_app(a3,b3)
...:
In [7]: np.allclose(a1, a2) # Verify results
Out[7]: True
In [8]: np.allclose(a1, a3) # Verify results
Out[8]: True
In [9]: %timeit original_loopy_app(a1,b1)
...: %timeit vectorized_app(a2,b2)
...: %timeit modified_loopy_app(a3,b3)
...:
10 loops, best of 3: 107 ms per loop
10 loops, best of 3: 137 ms per loop
10 loops, best of 3: 48.2 ms per loop
In [13]: # Setup input arrays (datasets are exactly 1/10th of original sizes)
...: N = 200
...: M = 10000
...: a = np.random.randint(11,99,(N,N))
...: b = np.random.randint(11,99,(N,N))
...: shift = np.random.randint(0,N,M)
...:
In [14]: %timeit original_loopy_app(a1,b1)
...: %timeit modified_loopy_app(a3,b3)
...:
1 loops, best of 3: 1.11 s per loop
1 loops, best of 3: 481 ms per loop