python - np.zeros 和 np.full 的内存消耗和性能差异的原因
问题描述
测量内存消耗时np.zeros
:
import psutil
import numpy as np
process = psutil.Process()
N=10**8
start_rss = process.memory_info().rss
a = np.zeros(N, dtype=np.float64)
print("memory for a", process.memory_info().rss - start_rss)
结果是意外8192
字节,即几乎为 0,而 1e8 双打则需要 8e8 字节。
当替换np.zeros(N, dtype=np.float64)
为字节np.full(N, 0.0, dtype=np.float64)
所需的内存a
时。800002048
运行时间也有类似的差异:
import numpy as np
N=10**8
%timeit np.zeros(N, dtype=np.float64)
# 11.8 ms ± 389 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit np.full(N, 0.0, dtype=np.float64)
# 419 ms ± 7.69 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
即np.zeros
对于大尺寸来说,速度提高了 40 倍。
不确定这些差异是否适用于所有架构/操作系统,但我至少在 x86-64 Windows 和 Linux 上观察到了这种差异。
np.zeros
和之间的哪些差异np.full
可以解释不同的内存消耗和不同的运行时间?
解决方案
我不相信psutil
这些内存基准,而且 rss(驻留集大小)可能一开始就不是正确的指标。
使用 stdlib tracemalloc
,您可以获得正确的内存分配数字 - 对于这个 N 和 float64 dtype,它应该是大约 800000000 字节的增量:
>>> import numpy as np
>>> import tracemalloc
>>> N = 10**8
>>> tracemalloc.start()
>>> tracemalloc.get_traced_memory() # current, peak
(159008, 1874350)
>>> a = np.zeros(N, dtype=np.float64)
>>> tracemalloc.get_traced_memory()
(800336637, 802014880)
np.full
对于and之间的时间差异np.zeros
,比较and 的手册页malloc
,calloc
即np.zeros
可以转到一个分配例程,该例程将页面归零。请参阅PyArray_Zeros
--> 调用PyArray_NewFromDescr_int
传入参数1
,zeroed
然后有一个特殊情况可以更快地分配零:
if (zeroed || PyDataType_FLAGCHK(descr, NPY_NEEDS_INIT)) {
data = npy_alloc_cache_zero(nbytes);
}
else {
data = npy_alloc_cache(nbytes);
}
看起来np.full
没有这条快速路径。那里的性能将类似于首先执行 init 然后执行复制O(n):
a = np.empty(N, dtype=np.float64)
a[:] = np.float64(0.0)
numpy
如果填充值为零,开发人员可能已经添加了一条快速路径np.full
,但是为什么还要添加另一种方法来做同样的事情 - 用户可以np.zeros
首先使用。
推荐阅读
- google-contacts-api - 您无法删除此项目,因为它与 Dialogflow 代理相关联
- types - Haxe:如何检查变量是否为函数
- html - 将样式应用于类而不影响导航 LI 中的其他类?
- javascript - 复选框上的 html5 验证
- swiftui - 在 init() 中初始化 2 个变量:在初始化所有存储的属性之前使用“self”
- javascript - 将 PDF 中的特定单词/数字保存到 Google 电子表格。(应用程序脚本)
- azure - 如何允许任何人通过 MsGraph 创建 Teams 会议
- c++ - 设置成员变量值后,该值在 getter 函数内部发生变化
- php - Laravel Eloquent 3 个表 + 1 个数据透视表
- websocket - 很多 tcp 窗口更新大小段