Python Numpy数组比list慢(er)
我正在使用2d阵列。基本上只是尝试对常量值进行元素相加。 需要加快代码速度,因此尝试使用numpy数组而不是list of list,但查找numpy的速度较慢。知道我做错了什么吗?谢谢 例如:Python Numpy数组比list慢(er),python,numpy,Python,Numpy,我正在使用2d阵列。基本上只是尝试对常量值进行元素相加。 需要加快代码速度,因此尝试使用numpy数组而不是list of list,但查找numpy的速度较慢。知道我做错了什么吗?谢谢 例如: import time import numpy as np my_array_list = [[1,2,3],[4,5,6],[7,8,9]] my_array_np = np.array(my_array_list) n = 100000 s_np = time.time() for a in
import time
import numpy as np
my_array_list = [[1,2,3],[4,5,6],[7,8,9]]
my_array_np = np.array(my_array_list)
n = 100000
s_np = time.time()
for a in range(n):
for i in range(3):
for j in range(3):
my_array_np[i,j] = my_array_np[i,j] + 5
end_np = time.time() - s_np
s_list = time.time()
for a in range(n):
for i in range(3):
for j in range(3):
my_array_list[i][j] = my_array_list[i][j] + 5
end_list = time.time() - s_list
print('my_array_np:', '\n', my_array_np, '\n')
print('my_array_list:', '\n',my_array_list, '\n')
print('time to complete with numpy:', end_np)
print('time to complete with list:', end_list)
输出:
my_array_np:
[[500001 500002 500003]
[500004 500005 500006]
[500007 500008 500009]]
my_array_list:
[[500001, 500002, 500003], [500004, 500005, 500006], [500007, 500008, 500009]]
time to complete with numpy: 0.7831366062164307
time to complete with list: 0.45527076721191406
通过使用列表可以看出,完成测试的时间要快得多,即0.45秒对0.78秒。numpy在这里不应该更快吗?嗯。。。在当前情况下,列表派生似乎更快,但当我添加numba时,np更快
import dis
import time
import numpy as np
from numba import jit
my_array_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
my_array_np = np.array(my_array_list)
n = 1000000
# @jit
def fun1(my_array_np):
# it is inplace option
for a in range(n):
my_array_np += 5
s_np = time.time()
fun1(my_array_np)
end_np = time.time() - s_np
def fuc2(my_array_list):
for a in range(n):
my_array_list = [[i + 5 for i in j] for j in my_array_list]
return my_array_list
s_list = time.time()
my_array_list = fuc2(my_array_list)
end_list = time.time() - s_list
print('my_array_np:', '\n', my_array_np, '\n')
print('my_array_list:', '\n', my_array_list, '\n')
print('time to complete with numpy:', end_np)
print('time to complete with list:', end_list)
my_array_np:
[[500001 500002 500003]
[500004 500005 500006]
[500007 500008 500009]]
my_array_list:
[[500001, 500002, 500003], [500004, 500005, 500006], [500007, 500008, 500009]]
# use numba
time to complete with numpy: 0.27802205085754395
time to complete with list: 1.9161949157714844
# not use numba
time to complete with numpy: 3.4962515830993652
time to complete with list: 1.9761543273925781
[Finished in 3.4s]
假设您想向所有元素添加3的倍数。我们通常使用
掩码
In [355]: x = np.arange(12).reshape(3,4)
In [356]: mask = (x%3)==0
In [357]: mask
Out[357]:
array([[ True, False, False, True],
[False, False, True, False],
[False, True, False, False]])
In [358]: x[mask] += 100
In [359]: x
Out[359]:
array([[100, 1, 2, 103],
[ 4, 5, 106, 7],
[ 8, 109, 10, 11]])
许多操作是ufunc
,它们具有where
参数
In [360]: x = np.arange(12).reshape(3,4)
In [361]: np.add(x,100, where=mask, out=x)
Out[361]:
array([[100, 1, 2, 103],
[ 4, 5, 106, 7],
[ 8, 109, 10, 11]])
Fastnumpy
要求我们从整个阵列的角度进行思考。快速编译的代码在数组或数组块上运行。数组上的Python级迭代非常缓慢,因为您发现列表上的迭代非常缓慢。访问数组的单个值的成本更高
对于这个小示例,这些完整的数组方法比数组迭代快,尽管它们仍然比列表迭代慢。但是数组方法更好。您可以尝试将第一组for循环(在i和j上)替换为
my_array\u np+=5
,然后重新计算基准。您不应该手动在数组上循环。手动循环数组就像用手将车拖到身后一样——速度会很慢,因为你用错了。谢谢@hilberts\u。对于这里介绍的测试用例,是的,这会有所帮助。但是,我实际上需要访问每个元素并检查它(可能是使用if语句),然后根据if语句结果添加一些常量值。是的,直接在numpy.ndarray
对象上迭代并在python解释器级别访问其中的项总是比列表慢。因为numpy.ndarray对象通过使用其内置的矢量化操作来提高速度,这些操作将计算向下推到C层。要在python解释器层中使用它,还必须对对象进行“装箱”,因为通常在数组的基础上有基本类型。所以taht使一切都变得更慢。有一个第三方库,numba
,JIT可以编译这种代码,如果它涉及numpy.ndarray对象,这是非常好的。但是仅仅使用普通的numpy
,这种方法是可以避免的。学习做事的基本方法。或者只使用一个列表。顺便说一句,如果取消对@jit的注释,当前的基准测试将占用编译时间。您可以通过调用fun1(my_array\u np.copy())
在s\u np=time.time()
行上方强制编译。