预分配NumPy阵列的首选方法是什么?

时间:2010-08-16 09:02:48

标签: python numpy

我是NumPy / SciPy的新手。从文档中,预分配似乎更有效 单个数组而不是调用append / insert / concatenate。

例如,要向数组添加1的列,我认为:

ar0 = np.linspace(10, 20, 16).reshape(4, 4)
ar0[:,-1] = np.ones_like(ar0[:,0])

比这更受欢迎:

ar0 = np.linspace(10, 20, 12).reshape(4, 3)
ar0 = np.insert(ar0, ar0.shape[1], np.ones_like(ar0[:,0]), axis=1)

我的第一个问题是这是否正确(第一个更好),而我的第二个问题是,目前我只是预先分配我的数组(我在SciPy的几个Cookbook示例中注意到了)位点):

np.zeros((8,5))

“NumPy首选”的方式是什么?

3 个答案:

答案 0 :(得分:20)

预分配mallocs在一次调用中需要的所有内存,同时调整数组大小(通过调用append,insert,concatenate或resize)可能需要将数组复制到更大的内存块。所以你是对的,预先分配比调整大小更好(并且应该更快)。

根据您要创建的内容,有许多“首选”方法可以预先分配numpy数组。有np.zerosnp.onesnp.emptynp.zeros_likenp.ones_likenp.empty_like以及其他许多可以创建有用数组的人,例如{{ 1}}和np.linspace

所以

np.arange
如果它最接近你想要的ar0 = np.linspace(10, 20, 16).reshape(4, 4) ,那么

就好了。

但是,为了使最后一列全部为1,我认为首选的方法是说

ar0

由于ar0[:,-1]=1 的形状为ar0[:,-1],因此1为broadcasted以匹配此形状。

答案 1 :(得分:1)

在性能很重要的情况下, np.empty np.zeros 似乎是初始化numpy数组的最快方法。

下面是每种方法的测试结果以及其他一些方法的测试结果。值以秒为单位。

>>> timeit("np.empty(1000000)",number=1000, globals=globals())
0.033749611208094166
>>> timeit("np.zeros(1000000)",number=1000, globals=globals())
0.03421245135849915
>>> timeit("np.arange(0,1000000,1)",number=1000, globals=globals())
1.2212416112155324
>>> timeit("np.ones(1000000)",number=1000, globals=globals())
2.2877375495381145
>>> timeit("np.linspace(0,1000000,1000000)",number=1000, globals=globals())
3.0824269766860652

答案 2 :(得分:0)

根据我的经验,numpy.empty()是预分配HUGE数组的最快方法。我要说的数组具有(80,80,300000)和dtype uint8的形状。

代码如下:

%timeit  np.empty((80,80,300000),dtype='uint8')
%timeit  np.zeros((80,80,300000),dtype='uint8')
%timeit  np.ones((80,80,300000),dtype='uint8')

以及计时结果:

10000 loops, best of 3: 83.7 µs per loop  #Too much faster
1 loop, best of 3: 273 ms per loop
1 loop, best of 3: 272 ms per loop