gpt4 book ai didi

python - np.empty、np.zeros 和 np.ones 的性能

转载 作者:太空狗 更新时间:2023-10-30 01:24:46 28 4
gpt4 key购买 nike

我很好奇使用 np.empty 到底有多大不同?而不是 np.zeros ,以及关于 np.ones 的区别.我运行这个小脚本来对每个创建大型数组所花费的时间进行基准测试:

import numpy as np
from timeit import timeit

N = 10_000_000
dtypes = [np.int8, np.int16, np.int32, np.int64,
np.uint8, np.uint16, np.uint32, np.uint64,
np.float16, np.float32, np.float64]
rep= 100
print(f'{"DType":8s} {"Empty":>10s} {"Zeros":>10s} {"Ones":>10s}')
for dtype in dtypes:
name = dtype.__name__
time_empty = timeit(lambda: np.empty(N, dtype=dtype), number=rep) / rep
time_zeros = timeit(lambda: np.zeros(N, dtype=dtype), number=rep) / rep
time_ones = timeit(lambda: np.ones(N, dtype=dtype), number=rep) / rep
print(f'{name:8s} {time_empty:10.2e} {time_zeros:10.2e} {time_ones:10.2e}')

并得到下表结果:

DType         Empty      Zeros       Ones
int8 1.39e-04 1.76e-04 5.27e-03
int16 3.72e-04 3.59e-04 1.09e-02
int32 5.85e-04 5.81e-04 2.16e-02
int64 1.28e-03 1.13e-03 3.98e-02
uint8 1.66e-04 1.62e-04 5.22e-03
uint16 2.79e-04 2.82e-04 9.49e-03
uint32 5.65e-04 5.20e-04 1.99e-02
uint64 1.16e-03 1.24e-03 4.18e-02
float16 3.21e-04 2.95e-04 1.06e-02
float32 6.31e-04 6.06e-04 2.32e-02
float64 1.18e-03 1.16e-03 4.85e-02

从中我得出两个有点令人惊讶的结论:

  • np.empty 的性能几乎没有差异。和 np.zeros ,也许除了 int8 的一些差异。我不明白为什么会这样。创建一个空数组应该会更快,实际上我已经看到了这方面的报道(例如 Speed of np.empty vs np.zeros )。
  • np.zeros之间有很大区别和 np.ones .我怀疑这与内存归零的高性能方法有关,这种方法不适用于用常量填充内存区域,但我真的不知道它是如何工作的或在什么级别工作。

这些结果的解释是什么?

我在 Windows 10(带有 MKL)上使用 NumPy 1.15.4 和 Python 3.6 Anaconda,并且我有一个 Intel Core i7-7700K CPU。

编辑:根据评论中的建议,我尝试在每个单独的试验中交错运行基准测试并在最后取平均值,但我看不出结果有显着差异。不过,在相关说明中,我不知道 NumPy 中是否有任何机制可以重用刚刚删除的数组的内存,这会使这些措施变得不切实际(尽管时间似乎确实随着数据类型的大小而增加对于空数组)。

最佳答案

这真的应该是一个评论,但它不适合。这是您的脚本的一个小扩展。 zerosones 的一些“手工制作”版本。

import numpy as np
from timeit import timeit

N = 10_000_000
dtypes = [np.int8, np.int16, np.int32, np.int64,
np.uint8, np.uint16, np.uint32, np.uint64,
np.float16, np.float32, np.float64]
rep= 100
print(f'{"DType":8s} {"Empty":>10s} {"Zeros":>10s} {"Ones":>10s}')
for dtype in dtypes:
name = dtype.__name__
time_empty = timeit(lambda: np.empty(N, dtype=dtype), number=rep) / rep
time_zeros = timeit(lambda: np.zeros(N, dtype=dtype), number=rep) / rep
time_ones = timeit(lambda: np.ones(N, dtype=dtype), number=rep) / rep
time_full_zeros = timeit(lambda: np.full(N, 0, dtype=dtype), number=rep) / rep
time_full_ones = timeit(lambda: np.full(N, 1, dtype=dtype), number=rep) / rep
time_empty_zeros = timeit(lambda: np.copyto(np.empty(N, dtype=dtype), 0), number=rep) / rep
time_empty_ones = timeit(lambda: np.copyto(np.empty(N, dtype=dtype), 1), number=rep) / rep
print(f'{name:8s} {time_empty:10.2e} {time_zeros:10.2e} {time_ones:10.2e} {time_full_zeros:10.2e} {time_full_ones:10.2e} {time_empty_zeros:10.2e} {time_empty_ones:10.2e} ')

时间安排具有启发性。

DType         Empty      Zeros       Ones
int8 1.37e-06 6.33e-04 5.73e-04 5.76e-04 5.73e-04 6.05e-04 5.82e-04
int16 1.61e-06 1.55e-03 3.54e-03 3.54e-03 3.56e-03 3.54e-03 3.54e-03
int32 7.22e-06 6.99e-06 1.24e-02 1.20e-02 1.25e-02 1.19e-02 1.21e-02
int64 8.26e-06 8.06e-06 2.62e-02 2.64e-02 2.61e-02 2.62e-02 2.62e-02
uint8 1.32e-06 6.30e-04 5.85e-04 5.86e-04 5.77e-04 5.70e-04 5.83e-04
uint16 1.32e-06 1.63e-03 3.61e-03 3.65e-03 4.08e-03 4.08e-03 3.58e-03
uint32 7.08e-06 7.20e-06 1.48e-02 1.41e-02 1.63e-02 1.44e-02 1.32e-02
uint64 7.14e-06 7.13e-06 2.69e-02 2.67e-02 2.82e-02 2.68e-02 2.72e-02
float16 1.31e-06 1.55e-03 3.56e-03 3.79e-03 3.54e-03 3.53e-03 3.55e-03
float32 7.11e-06 6.95e-06 1.36e-02 1.35e-02 1.37e-02 1.35e-02 1.37e-02
float64 7.27e-06 7.33e-06 3.13e-02 3.00e-02 2.75e-02 2.80e-02 2.75e-02

Re zeros being faster than ones 我似乎记得评论中建议 zeros 确实使用了 calloc 作为一个系统例程,其唯一目的是分配零 block ,这可能很擅长。

关于python - np.empty、np.zeros 和 np.ones 的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55145592/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com