【问题标题】:Why is a.dot(b) faster than a@b although Numpy recommends a@b为什么 a.dot(b) 比 a@b 快,尽管 Numpy 推荐 a@b
【发布时间】:2019-02-03 08:38:57
【问题描述】:

根据questionnumpy 的答案,与a.dot(b) 相比,二维数组的矩阵乘法最好通过a @ bnumpy.matmul(a,b) 完成。

如果 a 和 b 都是二维数组,则为矩阵乘法,但使用 首选 matmul 或 a @ b。

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

问题:我的基准测试有问题吗?如果不是,为什么 Numpy 比 a@bnumpy.matmul(a,b) 快时不推荐 a.dot(b)

基准测试使用 python 3.5 numpy 1.15.0。

$ pip3 list | grep numpy
numpy                         1.15.0
$ python3 --version
Python 3.5.2

基准代码:

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) )

结果:

test  : 0.11132473500038031
test1 : 0.10812476599676302
test2 : 0.06115105600474635

添加结果:

>>> 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]])

【问题讨论】:

  • 因为这里它已经“假定”它是一个矩阵乘法?此外,最好运行 batch 个测试(不仅仅是 100 个)。
  • @WillemVanOnsem 如果将其增加到 number=1000,或者运行脚本几次,您将观察到类似的发现。
  • 例如,通过运行这些测试,矩阵乘法算法被缓存(在程序缓存中)可能,从而促进第二次调用。
  • matmul@ 没有显着差异。 dotmatmul 甚至不做同样的事情。

标签: python arrays performance numpy matrix


【解决方案1】:

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

使用 Python 3.60 / NumPy 1.11.3,您会发现,正如 here 所解释的那样,@ 调用 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

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

【讨论】:

  • 我添加了结果以显示我的基准测试是在 python 3.5.2 和 numpy 1.15.0 上执行的。目前,基准是 4x4 矩阵。
  • @SunBear,好吧,试试更大的阵列。您不希望函数调用使无关紧要的计算相形见绌。
  • 谢谢。有趣的是:我发现a.dot(b) 在 na.dot(b) 仍然有好处。我的基准测试是针对二维数组的,而不是针对高阶类型的。请在您的最后一句话中添加限定词,例如通过在末尾添加“但不适用于二维数组”,此后我将接受您的回答。干杯。
【解决方案2】:

matmuldot 不做同样的事情。它们对 3D 数组和标量的行为不同。文档可能会说matmul 是首选,因为它更“清晰”和通用,不一定是出于性能原因。如果文档能更清楚地说明为什么一个人比另一个人更受欢迎,那就太好了。

正如@jpp 所指出的,matmul 的性能实际上并不一定更差。

【讨论】:

    猜你喜欢
    • 2015-01-18
    • 2014-03-29
    • 2021-10-06
    • 2010-12-08
    • 2016-06-02
    • 1970-01-01
    • 2015-06-15
    • 2011-05-30
    • 1970-01-01
    相关资源
    最近更新 更多