我终于在代码中发现了性能瓶颈,但是对于原因是很困惑的。为了解决这个问题,我将所有对的调用都numpy.zeros_like
改为使用numpy.zeros
。但是为什么zeros_like
太慢了?
例如(注意e-05
在zeros
电话):
>>> timeit.timeit('np.zeros((12488, 7588, 3), np.uint8)', 'import numpy as np', number = 10)
5.2928924560546875e-05
>>> timeit.timeit('np.zeros_like(x)', 'import numpy as np; x = np.zeros((12488, 7588, 3), np.uint8)', number = 10)
1.4402990341186523
但是奇怪的是,写入使用创建的数组zeros
要慢于使用创建的数组zeros_like
:
>>> timeit.timeit('x[100:-100, 100:-100] = 1', 'import numpy as np; x = np.zeros((12488, 7588, 3), np.uint8)', number = 10)
0.4310588836669922
>>> timeit.timeit('x[100:-100, 100:-100] = 1', 'import numpy as np; x = np.zeros_like(np.zeros((12488, 7588, 3), np.uint8))', number = 10)
0.33325695991516113
我的猜测是zeros
使用一些CPU技巧,而不是实际写入内存来分配它。写入时可以即时完成。但这仍不能解释数组创建时间的巨大差异。
我正在使用当前的numpy版本运行Mac OS X Yosemite:
>>> numpy.__version__
'1.9.1'
我在Ipython中的计时是(使用更简单的timeit接口):
In [57]: timeit np.zeros_like(x)
1 loops, best of 3: 420 ms per loop
In [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 loop
In [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选项混淆。
关于calloc
vmalloc+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
问题内容: 我正在计算稀疏自动编码器的算法。我已经使用和在python中实现了它。代码几乎相同,但是性能却大不相同。matlab完成任务所需的时间为0.252454秒,而numpy为0.973672151566,几乎是原来的四倍。在最小化问题中,我将在以后多次调用此代码,因此这种差异会导致实现之间的延迟几分钟。这是正常行为吗?如何提高numpy的性能? numpy实现: Sparse.rho是调整
是的,这是一个老话题,但我还是有些困惑。 在爪哇,人们说: LinkedList的插入速度比ArrayList快。这里插入是什么意思?如果这意味着向后移动一些元素,然后将元素放在中间的空点,那么ArrayList应该比LinkedList慢。如果插入只意味着添加(对象)操作,这怎么会慢呢?
问题内容: 我想知道为什么numpy.zeros占用这么小的空间? 这不会占用任何内存, 占用约1.5GB。numpy.zeros是否创建一个空指针数组?如果是这样,是否可以在cython中更改指针后将其设置为空?如果我使用: 内存使用率上升。有没有办法更改一个值,然后将其更改回numpy.zeros的格式,最初是在python或cython中使用的? 问题答案: 您在使用Linux吗?Linux
是的,这是一个老话题,但我仍然有一些困惑。 在Java,人们说: > 如果我随机访问它的元素,ArrayList比LinkedList快。我认为随机存取意味着“给我第n个元素”。为什么ArrayList更快? LinkedList的删除速度比ArrayList快。我理解这一点。ArrayList速度较慢,因为需要重新分配内部备份阵列。代码说明: LinkedList的插入速度比ArrayList快
我想知道使用子句和之间的性能差异。我从他们两个那里得到了不同的时间。假设我有10个组,我想让一个用户可以访问5个组,同时排除5个组。因此,我有两种使用查询的方式: 我可以在布尔查询中使用子句,并执行。我可以再次在布尔查询中使用子句,并执行。 我在这里没有提供很多细节,因为我只是想更多地了解使用这两个术语的性能差异。我在ES文档中读到了Boolean查询,它说在子句中忽略评分,尽管我还不明白在Luc
使用AtomicLong.IncrementAndGet方法测试JDK7和JDK8的性能差异,测试数据表明JDK7的性能优于JDK8。为什么JDK7的性能比JDK8好?是什么导致JDK8中的性能差? 系统环境: CPU:Intel(R)至强(R)CPU E5620@2.40 GHz 2.40 GHz(双处理器) 内存:8.00 GB set jvm_opt=-xms1024m-xmx1024m-x