Python Numpy中零点函数的性能

Python Numpy中零点函数的性能,python,numpy,Python,Numpy,我刚刚注意到numpy的zeros函数有一个奇怪的行为: %timeit np.zeros((1000, 1000)) 1.06 ms ± 29.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) %timeit np.zeros((5000, 5000)) 4 µs ± 66 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 另一方面,one似乎有正常的

我刚刚注意到
numpy
zeros
函数有一个奇怪的行为:

%timeit np.zeros((1000, 1000))
1.06 ms ± 29.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit np.zeros((5000, 5000))
4 µs ± 66 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
另一方面,
one
似乎有正常的行为。 有人知道为什么用
zero
函数初始化一个小numpy数组要比初始化一个大数组花费更多的时间吗


(Python3.5,numpy 1.11)

这看起来像是
calloc
达到了一个阈值,在这个阈值中,它向操作系统请求零内存,而不需要手动初始化。查看源代码,
numpy.zeros
最终获取一个归零内存块,如果与不执行初始化的
numpy.empty
进行比较:

In [15]: %timeit np.zeros((5000, 5000))
The slowest run took 12.65 times longer than the fastest. This could mean that a
n intermediate result is being cached.
100000 loops, best of 3: 10 µs per loop

In [16]: %timeit np.empty((5000, 5000))
The slowest run took 5.05 times longer than the fastest. This could mean that an
 intermediate result is being cached.
100000 loops, best of 3: 10.3 µs per loop
您可以看到,
np.zeros
对于5000x5000数组没有初始化开销

事实上,在您尝试访问内存之前,操作系统甚至不会“真正”分配内存。在没有TB备用空间的计算机上成功请求TB阵列:

In [23]: x = np.zeros(2**40)  # No MemoryError!

那么第二个矩阵是25倍大,但创建只需要4倍长?“这太令人惊讶了!”JamesKPolk再次读了一遍,第二个较大的数组需要4微秒,第一个较小的数组需要1毫秒!我得到了类似的结果,但不太极端。我认为这可能是
calloc
达到了一个阈值,它从操作系统请求调零内存,而不需要实际初始化。当1D数组的大小S从4150000变为4200000时,用
np.zero(S)将其调零的时间
从每个环路5.5毫秒更改为每个环路9.6µs。但是,
%timeit
中的循环数同时从100变为100000。我的猜测是,对于一定大小及以上的阵列,最慢运行和最快运行之间的差异变得足够大,足以触发1000倍以上的循环,这大大提高了测量精度并减少了报告的运行时间。不是因为它更短,而是因为它的测量更精确。@DYZ我使用
timeit.timeit
函数,将数字控制在
1000
,我得到了
0.343710215005558
的(10001000)和
0.00286949446
的(50005000)