我在Ipython中的计时是(使用更简单的timeit接口):
In [57]: timeit np.zeros_like(x)1 loops, best of 3: 420 ms per loopIn [58]: timeit np.zeros((12488, 7588, 3), np.uint8)100000 loops, best of 3: 15.1 µs per loop
当我使用IPython(
np.zeros_like??)查看代码时,我看到:
res = empty_like(a, dtype=dtype, order=order, subok=subok)multiarray.copyto(res, 0, casting='unsafe')
而
np.zeros黑匣子-纯编译代码。
的时间
empty是:
In [63]: timeit np.empty_like(x)100000 loops, best of 3: 13.6 µs per loopIn [64]: timeit np.empty((12488, 7588, 3), np.uint8)100000 loops, best of 3: 14.9 µs per loop
因此,额外的时间
zeros_like就在其中
copy。
在我的测试中,分配时间(
x[]=1)的差异可以忽略不计。
我的猜测是
zeros,
ones,
empty都是早期编译作品。
empty_like为方便起见添加了此功能,只是从输入中绘制形状和类型信息。
zeros_like撰写本书时,
empty_like比起速度,更多的是着眼于轻松进行编程维护(重用)。
np.ones并
np.full使用该
np.empty ... copyto序列,并显示相似的时间。
https://github.com/numpy/numpy/blob/master/numpy/core/src/multiarray/array_assign_scalar.c
似乎是将标量(例如
0)复制到数组的文件。我看不到使用
memset。
https://github.com/numpy/numpy/blob/master/numpy/core/src/multiarray/alloc.c调用了
malloc和
calloc。
https://github.com/numpy/numpy/blob/master/numpy/core/src/multiarray/ctors.c-
zeros和的来源
empty。两者都通话
PyArray_NewFromDescr_int,但是一个最终使用
npy_alloc_cache_zero另一个
npy_alloc_cache。
npy_alloc_cache在
alloc.c通话中
alloc。
npy_alloc_cache_zero呼叫
npy_alloc_cache后跟一个
memset。输入的代码
alloc.c进一步与THREAD选项混淆。
关于
callocv
malloc+memset差异的更多信息: 为什么malloc +
memset比calloc慢?
但是对于缓存和垃圾回收,我想知道这种
calloc/memset区别是否适用。
这与简单的测试
memory_profile包支持声称
zeros和
empty分配“上即时”内存,而
zeros_like分配一切前面:
N = (1000, 1000) M = (slice(None, 500, None), slice(500, None, None))Line # Mem usage Increment Line Contents================================================ 2 17.699 MiB 0.000 MiB @profile 3 def test1(N, M): 4 17.699 MiB 0.000 MiB print(N, M) 5 17.699 MiB 0.000 MiB x = np.zeros(N) # no memory jump 6 17.699 MiB 0.000 MiB y = np.empty(N) 7 25.230 MiB 7.531 MiB z = np.zeros_like(x) # initial jump 8 29.098 MiB 3.867 MiB x[M] = 1 # jump on usage 9 32.965 MiB 3.867 MiB y[M] = 1 10 32.965 MiB 0.000 MiB z[M] = 1 11 32.965 MiB 0.000 MiB return x,y,z



