我随机比较了显式for循环和numpy中矢量化实现的计算时间。我进行了100万次迭代,发现了一些惊人的差异。 For循环大约花费 646ms ,而np.exp()
函数在不到20ms的时间内计算出相同的结果。
import time
import math
import numpy as np
iter = 1000000
x = np.zeros((iter,1))
v = np.random.randn(iter,1)
before = time.time()
for i in range(iter):
x[i] = math.exp(v[i])
after = time.time()
print(x)
print("Non vectorized= " + str((after-before)*1000) + "ms")
before = time.time()
x = np.exp(v)
after = time.time()
print(x)
print("Vectorized= " + str((after-before)*1000) + "ms")
我得到的结果:
[[0.9256753 ]
[1.2529006 ]
[3.47384978]
...
[1.14945181]
[0.80263805]
[1.1938528 ]]
Non vectorized= 646.1577415466309ms
[[0.9256753 ]
[1.2529006 ]
[3.47384978]
...
[1.14945181]
[0.80263805]
[1.1938528 ]]
Vectorized= 19.547224044799805ms
我的问题是:
答案 0 :(得分:2)
正在发生的事情是NumPy正在调用非常擅长矢量算法的高质量数值库(例如BLAS)。
我想您可以确切地调用NumPy使用的确切库,但是,NumPy可能最了解使用哪个库。
答案 1 :(得分:1)
NumPy是Python封装的库和用C语言编写的代码。这是NumPy效率的很大一部分。 C代码直接编译为处理器或GPU执行的指令。另一方面,Python代码必须在执行时进行解释。尽管速度不断提高,但我们可以从诸如Just In Time Compilers之类的先进语言中获得解释性语言,但对于某些任务,它们将永远无法达到编译语言的速度。
答案 2 :(得分:1)
可以归结为Python无法直接访问硬件级别。
Python无法使用大多数现代CPU和GPU拥有的SIMD (Single instruction, multiple data)汇编指令。这些SIMD指令允许在硬件级别一次(在一个时钟周期内)一次对数据向量执行一次操作。
另一方面,NumPy具有用C内置的功能,C是一种能够运行SIMD指令的语言。因此,NumPy可以利用处理器中的矢量化硬件。