【发布时间】:2018-05-29 06:15:29
【问题描述】:
我正在阅读在高性能 Python 中介绍 numpy 的章节,并在我自己的计算机上使用了代码。意外地,我用 for 循环运行了 numpy 版本,发现与原生 python 循环相比,结果出奇地慢。
代码的简化版本如下,我定义了一个二维数组 X 为 0,另一个二维数组 Y 为 1,然后将 Y 重复添加到 X,概念上是 X += Y。
import time
import numpy as np
grid_shape = (1024, 1024)
def simple_loop_comparison():
xmax, ymax = grid_shape
py_grid = [[0]*ymax for x in range(xmax)]
py_ones = [[1]*ymax for x in range(xmax)]
np_grid = np.zeros(grid_shape)
np_ones = np.ones(grid_shape)
def add_with_loop(grid, add_grid, xmax, ymax):
for x in range(xmax):
for y in range(ymax):
grid[x][y] += add_grid[x][y]
repeat = 20
start = time.time()
for i in range(repeat):
# native python: loop over 2D array
add_with_loop(py_grid, py_ones, xmax, ymax)
print('for loop with native list=', time.time()-start)
start = time.time()
for i in range(repeat):
# numpy: loop over 2D array
add_with_loop(np_grid, np_ones, xmax, ymax)
print('for loop with numpy array=', time.time()-start)
start = time.time()
for i in range(repeat):
# vectorized numpy operation
np_grid += np_ones
print('numpy vectorization=', time.time()-start)
if __name__ == "__main__":
simple_loop_comparison()
结果如下:
# when repeat=10
for loop with native list= 2.545672655105591
for loop with numpy array= 11.622980833053589
numpy vectorization= 0.020279645919799805
# when repeat=20
for loop with native list= 5.195128440856934
for loop with numpy array= 23.241904258728027
numpy vectorization= 0.04613637924194336
我完全期望 numpy 向量化操作优于其他两个,但我惊讶地发现在 numpy 数组上使用 for 循环的结果明显慢于原生 python 列表。我的理解是,至少缓存应该相对填满 numpy 数组,即使使用 for 循环,它也应该优于没有矢量化的列表。
关于 numpy 或 CPU/缓存/内存如何在低级别工作,我不了解吗?非常感谢。
编辑:更改标题
【问题讨论】:
-
这不是
numpy循环,而只是带有numpy数组的普通python循环。 -
编辑了标题。不管怎么称呼它,问题是为什么存在性能差距。
-
三件事:1.) 双索引:对于列表列表,您只是引用现有列表和元素,对于二维数组,您正在为行和元素创建一个新对象。 2.) numpy
__getitem__/__setitem__处理比它们的列表计数器部分更多和更复杂的参数类型 3.) (我不完全理解其中的区别,但它就在那里)list.__getitem__是一个内置数组。@987654327 @ 是一个方法包装器 -
所以你认为非本地的东西会胜过本地的东西?在本地人擅长的事情上? ...好吧,缓存参数很不错,但我认为与每个值的工作量相比,它的影响很小。
标签: python performance numpy for-loop memory