Kot*_*ori 14 python random numpy
我做了一些实验,发现了一些python的标准random和math库比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)
numpy实际上,这只是对大数据块的性能改进。如果数组不算大,确保将内存块正确ndarray排入C编译numpy函数之前的开销通常会淹没任何时间的收益。这就是为什么这么多numpy问题基本上都是“我如何获取此循环代码并使之快速运行”,以及为什么它被视为此标签中的一个有效问题,几乎所有其他标签都会在您超过标题之前将您扔到代码审查中。
因此,是的,您的观察是可概括的。向量化是的重点numpy。 numpy未向量化的代码总是比裸python代码慢,并且可以说与用手提钻破解单个胡桃木一样“错误”。找到合适的工具或获取更多的螺母。
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. 因此,有在差异如何随机数推导和可用的功能。出于测试或其他目的,您可能希望能够生成一致的“随机”数字。