Numpy 括号引起的矩阵乘法执行时间差

Numpy 括号引起的矩阵乘法执行时间差,numpy,python-3.6,parentheses,Numpy,Python 3.6,Parentheses,给定两个1Dnumpy数组a和b,使用 N = 100000 a = np.randn(N) b = np.randn(N) 为什么以下两个表达式之间的执行时间相差很大: # expression 1 c = a @ a * b @ b # expression 2 c = (a @ a) * (b @ b) 使用Jupyter笔记本电脑的%timeit魔力,我得到以下结果: %timeit a@a*b@b 每个回路223µs±6.97µs(7次运行的平均值±标准偏差,每个1000个回路)

给定两个1D
numpy
数组
a
b
,使用

N = 100000
a = np.randn(N)
b = np.randn(N)
为什么以下两个表达式之间的执行时间相差很大:

# expression 1
c = a @ a * b @ b

# expression 2
c = (a @ a) * (b @ b)
使用Jupyter笔记本电脑的
%timeit
魔力,我得到以下结果:

%timeit a@a*b@b

每个回路223µs±6.97µs(7次运行的平均值±标准偏差,每个1000个回路)

%timeit(a@a)*(b@b)

每个回路17.4µs±27.3 ns(7次运行的平均值±标准偏差,每个100000个回路)


在这两个版本中,都要做长度为N的向量的两个点积。然而,除此之外,第一个解执行N次乘法,而第二个解只需要一次

a@a*b@b
等同于
((a@a)*b)@b

aa = a @ a  # N multiplications and additions -> scalar
aab = aa * b  # N multiplications -> vector
aabb = aab @ b  # N multiplications and additions -> scalar
(a@a)*(b@b)
相当于

aa = a @ a  # N multiplications and additions -> scalar
bb = b @ b  # N multiplications and additions -> scalar
aabb = aa * bb  # 1 multiplication -> scalar
众所周知,矩阵乘法的性能取决于如何设置括号。存在利用这一事实进行优化的算法

更新:正如我刚刚了解到的,numpy具有优化多个矩阵乘法的功能: