我刚刚修改了正在编写的程序,将我的数据存储为numpy数组,因为我遇到了性能问题,结果差异惊人。原本需要30分钟才能运行完毕,现在只需要2.5秒!
我很好奇它是如何做到的。我认为这是因为它消除了对for
循环的需求,但除此之外,我感到困惑。
我刚刚修改了正在编写的程序,将我的数据存储为numpy数组,因为我遇到了性能问题,结果差异惊人。原本需要30分钟才能运行完毕,现在只需要2.5秒!
我很好奇它是如何做到的。我认为这是因为它消除了对for
循环的需求,但除此之外,我感到困惑。
Numpy数组是一种密集的同类型数组。相比之下,Python列表是对象指针的数组,即使它们都是相同类型的。因此,您可以获得引用局部性的好处。
此外,许多Numpy操作都是用C实现的,避免了Python循环的一般成本、指针间接和每个元素的动态类型检查。加速取决于您执行的操作,但在数字计算程序中,几个数量级的加速并不罕见。
NumPy数组是专门的数据结构。这意味着您不仅可以获得高效的内存表示方式,还可以获得高效的专用实现。
例如,如果您正在对两个数组进行求和,则会使用专用CPU矢量操作执行加法,而不是在循环中调用Python整数加法的实现。
考虑以下代码:
import numpy as np
import time
a = np.random.rand(1000000)
b = np.random.rand(1000000)
tic = time.time()
c = np.dot(a, b)
toc = time.time()
print("Vectorised version: " + str(1000*(toc-tic)) + "ms")
c = 0
tic = time.time()
for i in range(1000000):
c += a[i] * b[i]
toc = time.time()
print("For loop: " + str(1000*(toc-tic)) + "ms")
输出:
Vectorised version: 2.011537551879883ms
For loop: 539.8685932159424ms
Numpy在这里更快,因为它利用了并行性(即单指令多数据(SIMD)),而传统的for循环无法利用这一点。
dot
操作中使用它)。主要速度差异是由编译循环和解释循环引起的。 - hpaulj你仍然可以使用for循环,但是它们是用c语言完成的。Numpy基于Atlas,这是一个线性代数操作库。
面对大量的计算,我们会使用几个实现来运行测试,以找出当前计算机上哪一个是最快的。使用一些 numpy 构建,计算可能会在多个 CPU 上并行化处理。因此,您将得到高度优化的 C 代码,其运行在连续的内存块上。