2016-11-18 95 views
0

我有许多矩阵要添加。假设矩阵是[M1,M2 ...,M_n]。然后,一个简单的办法就是numpy矩阵加法的有效方法

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

在操作上,X + = M,并Python中创建一个新的内存X每次+ =执行?如果是这样的话,那似乎是低效的。在没有为X创建新内存的情况下进行就地操作有什么方法吗?

+0

你究竟做了什么:'[M1,M2 ...,M_n]'?它是一个数组列表吗?添加一个样本? – Divakar

+0

@Divakar我认为这是一个矩阵列表。 – TuanDT

+0

@Divakar,M是np.ndarray。 – DSKim

回答

1

这工作,但不是我的机器上更快:

numpy.sum(matrices, axis=0) 
0

除非你得到的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.sum情况下给我的MemoryError如果我使用range(1000)。我没有足够的内存来存放(1000,1000,1000)数组。 add.reduce相同,从列表中构建一个数组。

+=什么+=在掩护下通常是隐藏的,并且我们通常不关心。但对于下盖峰看ufunc.athttps://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.at.html#numpy.ufunc.at

上执行操作到位操作无缓冲“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