我的印象是numpy对于列表操作会更快,但以下示例似乎表明不是这样:
import numpy as np
import time
def ver1():
a = [i for i in range(40)]
b = [0 for i in range(40)]
for i in range(1000000):
for j in range(40):
b[j]=a[j]
def ver2():
a = np.array([i for i in range(40)])
b = np.array([0 for i in range(40)])
for i in range(1000000):
for j in range(40):
b[j]=a[j]
t0 = time.time()
ver1()
t1 = time.time()
ver2()
t2 = time.time()
print(t1-t0)
print(t2-t1)
输出是:
4.872278928756714
9.120521068572998
(我在Windows 7中运行64位Python 3.4.3,在i7 920上运行)
我知道这不是复制列表的最快方法,但我试图找出我是否错误地使用了numpy。或者说numpy对于这种操作来说速度较慢,而且在更复杂的操作中效率更高?
编辑:
我也试过以下,只是通过b [:] = a直接复制,而numpy仍然是两倍慢:
import numpy as np
import time
def ver6():
a = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
b = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
for i in range(1000000):
b[:] = a
def ver7():
a = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
b = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
for i in range(1000000):
b[:] = a
t0 = time.time()
ver6()
t1 = time.time()
ver7()
t2 = time.time()
print(t1-t0)
print(t2-t1)
输出是:
0.36202096939086914
0.6750380992889404
答案 0 :(得分:6)
你使用的NumPy错了。 NumPy的效率依赖于在C级循环中尽可能多地完成工作而不是解释代码。当你这样做
for j in range(40):
b[j]=a[j]
这是一个解释循环,具有所有内在解释器开销和更多,因为NumPy的索引逻辑比列表索引更复杂,并且NumPy需要在每个元素检索上创建一个新的元素包装器对象。当您编写这样的代码时,您无法获得NumPy的任何好处。
您需要以在C:
中完成工作的方式编写代码b[:] = a
这也可以提高列表操作的效率,但对于NumPy来说更为重要。
答案 1 :(得分:1)
您所看到的大部分内容都是使用C本机类型创建Python对象。
Python列表就是一个PyObject
指针数组。当a
和b
都是Python列表时,执行b[i] = a[i]
意味着:
b[i]
,a[i]
和a[i]
中存储的地址复制到b[i]
。但如果a
和b
是NumPy数组,那么事情会更精确,然后需要b[i] = a[i]
:
a[i]
存储的本机C整数类型创建Python整数对象,请参阅this,b[i]
中,请参阅here和因此,差异主要在于创建和处理该中间Python对象,列表不需要这样做。