速度比较.numpy vs python标准

Kot*_*ori 14 python random numpy

我做了一些实验,发现了一些python的标准randommath库比numpy对应的更快的情况.

我认为python的标准库有一个趋势,即小规模操作的速度快10倍,而numpy大规模(矢量)操作的速度要快得多.我的猜测是,numpy有一些开销会成为小案件的主导.

我的问题是:我的直觉是否正确?通常建议使用标准库而不是numpy小型(通常是标量)操作吗?

示例如下.

import math
import random
import numpy as np
Run Code Online (Sandbox Code Playgroud)

记录和指数

%timeit math.log(10)
# 158 ns ± 6.16 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

%timeit np.log(10)
# 1.64 µs ± 93.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit math.exp(3)
# 146 ns ± 8.57 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

%timeit np.exp(3)
# 1.72 µs ± 78.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Run Code Online (Sandbox Code Playgroud)

生成正态分布

%timeit random.gauss(0, 1)
# 809 ns ± 12.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit np.random.normal()
# 2.57 µs ± 14.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Run Code Online (Sandbox Code Playgroud)

选择一个随机元素

%timeit random.choices([1,2,3], k=1)
# 1.56 µs ± 55.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit np.random.choice([1,2,3], size=1)
# 23.1 µs ± 1.04 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Run Code Online (Sandbox Code Playgroud)

与numpy数组相同

arr = np.array([1,2,3])

%timeit random.choices(arr, k=1)
# 1.72 µs ± 33.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit np.random.choice(arr, size=1)
# 18.4 µs ± 502 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Run Code Online (Sandbox Code Playgroud)

随着大阵列

arr = np.arange(10000)

%timeit random.choices(arr, k=1000)
# 401 µs ± 6.16 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit np.random.choice(arr, size=1000)
# 41.7 µs ± 1.39 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Run Code Online (Sandbox Code Playgroud)

Dan*_*l F 7

numpy实际上,这只是对大数据块的性能改进。如果数组不算大,确保将内存块正确ndarray排入C编译numpy函数之前的开销通常会淹没任何时间的收益。这就是为什么这么多numpy问题基本上都是“我如何获取此循环代码并使之快速运行”,以及为什么它被视为此标签中的一个有效问题,几乎所有其他标签都会在您超过标题之前将您扔到代码审查中

因此,是的,您的观察是可概括的。向量化是的重点numpynumpy未向量化的代码总是比裸python代码慢,并且可以说与用手提钻破解单个胡桃木一样“错误”。找到合适的工具或获取更多的螺母。

  • @PaulPanzer更像是程序员,是创建隐喻的错误工具。 (6认同)
  • 因此,只要您有足够的手提钻,就可以用开凿机将核桃开裂?;-) (4认同)

jpp*_*jpp 5

NumPy 主要用于数组的性能。这依赖于使用连续内存块和更有效的低级迭代。在标量上应用 NumPy 数学函数或计算随机数不是可矢量化的操作。这解释了您所看到的行为。

另请参阅NumPy 相对于常规 Python 列表的优势是什么?

对于小型(通常是标量)操作,通常建议使用标准库而不是 NumPy 吗?

程序的瓶颈很少由标量操作引起。在实践中,差异可以忽略不计。所以无论哪种方式都很好。如果您已经在使用 NumPy,那么继续对标量使用 NumPy 操作并没有什么坏处。

值得做一个计算随机数的特例。正如您所料,通过randomvs NumPy选择的随机数可能不同:

assert random.gauss(0, 1) == np.random.normal()  # AssertionError
assert random.choices(arr, k=1)[0] == np.random.choice(arr, size=1)[0]  # AssertionError
Run Code Online (Sandbox Code Playgroud)

您在 NumPy 中有额外的功能可以使随机数“可预测”。例如,重复运行以下脚本只会产生相同的结果:

np.random.seed(0)
np.random.normal()
Run Code Online (Sandbox Code Playgroud)

这同样适用于np.random.choice. 因此,有在差异如何随机数推导和可用的功能。出于测试或其他目的,您可能希望能够生成一致的“随机”数字。