在numpy中进行矩阵加法的有效方法

时间:2016-11-18 20:59:16

标签: numpy

我要添加很多矩阵。假设矩阵是[M1,M2 ...,M_n]。然后,一个简单的方法是

X = np.zeros()
for M in matrices:
    X += M

在操作中,X + = M,每次执行+ =时,Python是否为X创建新内存?如果是这种情况,那似乎效率低下。有没有办法在不为X创建新内存的情况下进行就地操作?

2 个答案:

答案 0 :(得分:1)

这可行,但在我的机器上速度不快:

numpy.sum(matrices, axis=0)

答案 1 :(得分:1)

除非你得到MemoryError,否则尝试在numpy中猜测内存使用情况是不值得的。把它交给知道编译代码的开发人员。

但是我们可以进行一些时间测试 - 这真的很重要,不是吗?

我会测试100次添加好大小的数组。

In [479]: M=np.ones((1000,1000))

您的迭代方法+ =

In [480]: %%timeit 
     ...: X=np.zeros_like(M)
     ...: for _ in range(100): X+=M
     ...: 
1 loop, best of 3: 627 ms per loop

或制作一个大小(100,1000,1000)的数组,并在第一个轴上应用np.sum

In [481]: timeit np.sum(np.array([M for _ in range(100)]),axis=0)
1 loop, best of 3: 1.54 s per loop

并使用np.add ufunc。使用reduce,我们可以按顺序将其应用于列表中的所有值。

In [482]: timeit np.add.reduce([M for _ in range(100)])
1 loop, best of 3: 1.53 s per loop

如果我使用np.sumrange(1000)案例会给我一个MemoryError。我没有足够的内存来容纳(1000,1000,1000)阵列。 add.reduce也是如此,它从列表中构建一个数组。

封面下的+=通常是隐藏的,通常是我们无关紧要的。但是对于封底下的峰值,请查看ufunc.athttps://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.at.html#numpy.ufunc.at

  

对'indices'指定的元素在操作数'a'上执行无缓冲的就地操作。对于加法ufunc,此方法等效于[indices] + = b,除了为多次索引的元素累积结果。

因此X+=M会将总和写入缓冲区,然后将该缓冲区复制到X。有一个临时缓冲区,但最终内存使用量不会改变。 但是缓冲区的创建和复制是在快速C代码中完成的。

添加了

np.add.at来处理缓冲操作产生一些问题(重复索引)的情况。

因此它避免了临时缓冲 - 但速度相当快。它可能是增加的索引功能,可以减慢它的速度。 (可能会有一个更公平的add.at测试;但在这种情况下它肯定没有帮助。)

In [491]: %%timeit 
     ...: X=np.zeros_like(M)
     ...: for _ in range(100): np.add.at(X,(slice(None),slice(None)),M)
1 loop, best of 3: 19.8 s per loop