为什么a.dot(b)比a @ b快,尽管Numpy建议a @ b

Sun*_*ear 4 python arrays performance numpy matrix

根据这个问题的答案,也根据numpy,最好通过a @ bnumpy.matmul(a,b)与进行比较,二维阵列的矩阵乘法a.dot(b)

如果a和b均为二维数组,则为矩阵乘法,但最好使用matmul或a @ b。

我做了以下基准测试,发现相反的结果。

问题:我的基准测试有问题吗?如果不是,为什么Numpy不建议a.dot(b)a@b或快numpy.matmul(a,b)

基准使用python 3.5 numpy 1.15.0。

$ pip3 list | grep numpy
numpy                         1.15.0
$ python3 --version
Python 3.5.2
Run Code Online (Sandbox Code Playgroud)

基准代码:

import timeit

setup = '''
import numpy as np
a = np.arange(16).reshape(4,4)
b = np.arange(16).reshape(4,4)
''' 
test = '''
for i in range(1000):
    a @ b
'''
test1 = '''
for i in range(1000):
    np.matmul(a,b)
'''
test2 = '''
for i in range(1000):
    a.dot(b)
'''

print( timeit.timeit(test, setup, number=100) )
print( timeit.timeit(test1, setup, number=100) )
print( timeit.timeit(test2, setup, number=100) )
Run Code Online (Sandbox Code Playgroud)

结果:

test  : 0.11132473500038031
test1 : 0.10812476599676302
test2 : 0.06115105600474635
Run Code Online (Sandbox Code Playgroud)

附加结果:

>>> a = np.arange(16).reshape(4,4)
>>> b = np.arange(16).reshape(4,4)
>>> a@b
array([[ 56,  62,  68,  74],
       [152, 174, 196, 218],
       [248, 286, 324, 362],
       [344, 398, 452, 506]])
>>> np.matmul(a,b)
array([[ 56,  62,  68,  74],
       [152, 174, 196, 218],
       [248, 286, 324, 362],
       [344, 398, 452, 506]])
>>> a.dot(b)
array([[ 56,  62,  68,  74],
       [152, 174, 196, 218],
       [248, 286, 324, 362],
       [344, 398, 452, 506]])
Run Code Online (Sandbox Code Playgroud)

jpp*_*jpp 6

您的前提不正确。您应该使用较大的矩阵来衡量性能,以避免函数调用使无关紧要的计算相形见war。

使用Python 3.60 / NumPy的1.11.3,你会发现,作为解释在这里,即@通话np.matmul和两个跑赢大盘np.dot

import numpy as np

n = 500
a = np.arange(n**2).reshape(n, n)
b = np.arange(n**2).reshape(n, n)

%timeit a.dot(b)        # 134 ms per loop
%timeit a @ b           # 71 ms per loop
%timeit np.matmul(a,b)  # 70.6 ms per loop
Run Code Online (Sandbox Code Playgroud)

还要注意,如文档中所述,np.dot在功能上不同于@/ np.matmul。特别是,它们在处理尺寸大于2的矩阵方面有所不同。

  • @SunBear,好吧,尝试使用更大的数组。您不希望函数调用使微不足道的计算相形见f。 (3认同)
  • 谢谢。有趣的是:我发现如果 n<=50,`a.dot(b)` 的执行速度确实更快,此后它的表现会更好。因此,在处理小型二维数组的矩阵乘法时,使用 `a.dot(b)` 仍然有好处。我的基准测试特定于 2D 数组,而不是高阶类型。请在您的最后一句话中添加一个限定词,例如在最后添加“但不适用于二维数组”,此后我将接受您的回答。干杯。 (2认同)