numpy 数组赋值比 python 列表慢

numpy array assignment is slower than python list

numpy-

arr = np.array([[1, 2, 3, 4]])
row = np.array([1, 2, 3, 4])
%timeit arr[0] = row
466 ns ± 12.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

python 列表 -

arr = [[1, 2, 3, 4]]
row = [1, 2, 3, 4]
%timeit arr[0] = row
59.3 ns ± 2.94 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each

numpy 不应该是这里更快的版本吗?


这是我要完成的目标 -

arr = np.empty((150, 4))

while True:
     row = get_row_from_api() 
     arr[-1] = row

是的,以这种方式使用 python 列表肯定会更快,因为当您将某些内容分配给 python 列表元素时,它不会被复制,只是一些引用被重新分配(https://developers.google.com/edu/python/lists). Numpy 而是将所有元素从源容器复制到目标容器。我不确定你在这里是否需要 numpy 数组,因为它们的创建不是免费的,而且 python 列表在创建时并不那么慢(正如我们在赋值时看到的那样)。

这两个操作的底层语义非常不同。 Python 列表是引用数组。 Numpy 数组是数据本身的数组。

row = get_row_from_api() 表示已经分配了一个新列表。

分配给列表 lst[-1] = row 只是将地址写入 lst。这通常是 4 或 8 个字节。

在数组中放置 arr[i] = row 是复制数据。这是 arr[i, :] = row 的 shorthand。 row 的每个元素都被复制到 arr 的缓冲区。如果 row 是一个列表,那么从 python 对象转换为本机数字类型会产生额外的开销。

请记住,过早的优化是没有意义的。与另一种方法相比,您为一种方法节省的时间可能可以忽略不计。同时,如果您以后无论如何都需要一个数组,那么 pre-allocate 可能会更快,并且速度会稍有下降,而不是在最终列表上调用 np.array 。在前一种情况下,您分配一个预定大小和数据类型的缓冲区。在后者中,您只是推迟了复制数据的开销,但也招致了必须计算数组大小和 dtype 的开销。