Python Numpy数组比list慢(er)

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

我正在使用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 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]])
Fast
numpy
要求我们从整个阵列的角度进行思考。快速编译的代码在数组或数组块上运行。数组上的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()
行上方强制编译。