预分配NumPy数组的首选方式是什么?

jjjwad0x  于 2023-05-22  发布在  其他
关注(0)|答案(3)|浏览(168)

我是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-preferred”的方法是什么?

tktrz96b

tktrz96b1#

预分配会在一次调用中错误分配您所需的所有内存,而调整数组大小(通过调用append、insert、concatenate或resize)可能需要将数组复制到更大的内存块。所以你是对的,预分配比调整大小更好(而且应该更快)。
根据您想要创建的内容,有许多预分配numpy数组的“首选”方法。有np.zerosnp.onesnp.emptynp.zeros_likenp.ones_likenp.empty_like,以及许多其他创建有用数组的数组,如np.linspacenp.arange
所以呢

ar0 = np.linspace(10, 20, 16).reshape(4, 4)

如果这最接近您想要的ar0,则可以。
但是,要使最后一列都是1,我认为首选的方法是说

ar0[:,-1]=1

由于ar0[:,-1]的形状是(4,),因此1是broadcasted以匹配此形状。

oyjwcjzk

oyjwcjzk2#

在性能很重要的情况下,**np.emptynp.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
v8wbuo2f

v8wbuo2f3#

根据我的经验,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  # Much faster
1 loop, best of 3: 273 ms per loop
1 loop, best of 3: 272 ms per loop

相关问题