numpy.dot具有动态数组和静态数组的效率

问题描述 投票:1回答:2

我必须在数据处理管道中做很多<< >>产品。因此,我正在试验以下两段代码,其中一段代码的效率是最慢的3倍(就运行时而言)。最慢的方法(动态创建数组)

In [33]: %timeit np.dot(np.arange(200000), np.arange(200000, 400000)) 352 µs ± 958 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

最快的方法(带有静态数组)

In [34]: vec1_arr = np.arange(200000) In [35]: vec2_arr = np.arange(200000, 400000) In [36]: %timeit np.dot(vec1_arr, vec2_arr) 121 µs ± 90.3 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

为什么

动态生成

数组的第一种方法比第二种方法慢3倍?是否是因为在第一种方法中,这些额外时间中有很多是花在为元素分配内存上?还是其他一些导致这种降解的因素?
为了获得更多了解,我还用纯Python复制了该设置。令人惊讶的是,尽管它比numpy的实现要慢,这显然是可以预期的,但以一种方式或另一种方式执行,两者之间没有性能差异。

In [42]: %timeit sum(map(operator.mul, range(200000), range(200000, 400000))) 12.5 ms ± 71.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


In [38]: vec1 = range(200000) In [39]: vec2 = range(200000, 400000) In [40]: %timeit sum(map(operator.mul, vec1, vec2)) 12.5 ms ± 27.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
纯Python情况下的行为很明显,因为range函数实际上并未创建所有这些元素。它会进行惰性评估(即即时生成)。

Note

:纯Python隐式表示。只是为了使自己确信数组分配可能是导致拖累的因素。这并不是要与NumPy实现进行比较。我必须在我的数据处理管道中做很多点产品。因此,我正在试验以下两段代码,其中一段代码与...
python performance numpy numpy-ndarray
2个回答
0
投票
纯Python测试是不公平的。因为np.arange(200000)实际上返回数组,而range(200000)仅返回生成器。因此,这两种方法都可以动态创建数组。

import operator %timeit sum(map(operator.mul, range(200000), range(200000, 400000))) # 15.1 ms ± 45.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) vec1 = range(200000) vec2 = range(200000, 400000) %timeit sum(map(operator.mul, vec1, vec2)) # 15.2 ms ± 117 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) vec1 = list(range(200000)) vec2 = list(range(200000, 400000)) %timeit sum(map(operator.mul, vec1, vec2)) # 12.4 ms ± 716 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


0
投票
速度差异是由于在较慢的情况下分配数组。我粘贴了%timeit的输出,该输出考虑了两种情况下数组的分配。 OP的timeit命令仅在较慢的情况下考虑分配,而在较快的情况下不考虑分配。
© www.soinside.com 2019 - 2024. All rights reserved.