Python列表与NumPy数组效率实验出现意外结果
为什么NumPy数组循环赋值比Python列表append还慢?
你做的这个实验结果看似反常,但其实是因为你没有用到NumPy的核心优势——向量化操作,反而用了最不适合NumPy的Python循环逐个赋值的方式,具体原因如下:
你的实验代码
import numpy as np import time length = 1000000 a = np.random.rand(length) l = [] tic = time.time() for i in range(length): a[i] = np.random.rand() toc = time.time() print("Numpy array: "+str(1000*(toc-tic))+"ms") tic = time.time() for i in range(length): l.append(np.random.rand()) toc = time.time() print("List: "+str(1000*(toc-tic))+"ms")
实验输出
Numpy array: 618.1871891021729ms List: 524.2352485656738ms
原因解释
- Python循环抵消了NumPy的优势:NumPy的效率优势来自于C层面的批量操作(向量化),而你用Python循环逐个给NumPy数组赋值时,每次循环都要做:Python到C的上下文切换(调用
np.random.rand())、将生成的Python float对象转换为NumPy的float64类型、对数组元素的内存访问校验,这些额外开销累加起来就比列表append大。 - 列表append的高度优化:Python列表的
append是经过底层优化的操作,扩容策略(按倍数预分配内存)让百万级别的append几乎没有额外的内存分配开销,只是简单地把生成的对象添加到列表中,相比NumPy的循环赋值,少了类型转换和数组访问的额外步骤。 - 错误的使用方式:你当前的NumPy写法完全违背了它的设计初衷,正确的高效用法应该是直接生成整个数组,而不是循环逐个赋值。
正确的效率对比代码
如果用NumPy的向量化方式生成数组,就能体现出它的速度优势:
import numpy as np import time length = 1000000 # NumPy向量化生成数组 tic = time.time() a = np.random.rand(length) toc = time.time() print("Numpy vectorized: "+str(1000*(toc-tic))+"ms") # 列表append方式 tic = time.time() l = [] for i in range(length): l.append(np.random.rand()) toc = time.time() print("List append: "+str(1000*(toc-tic))+"ms")
运行后你会发现,NumPy向量化的速度会远快于列表append,这才是它真正的效率体现。
内容的提问来源于stack exchange,提问作者Sanyo Mn
相关产品推荐
相关产品推荐

