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 的开销。
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 的开销。