我注意到numpy中的matmul
函数在乘以数组视图时的性能明显比dot
函数差。在这种情况下,我的数组视图是复杂数组的真实的部分。下面是一些代码,重现了这个问题:
import numpy as np
from timeit import timeit
N = 1300
xx = np.random.randn(N, N) + 1j
yy = np.random.randn(N, N) + 1J
x = np.real(xx)
y = np.real(yy)
assert np.shares_memory(x, xx)
assert np.shares_memory(y, yy)
dot = timeit('np.dot(x,y)', number = 10, globals = globals())
matmul = timeit('np.matmul(x,y)', number = 10, globals = globals())
print('time for np.matmul: ', matmul)
print('time for np.dot: ', dot)
在我的机器上,输出如下:
time for np.matmul: 23.023062199994456
time for np.dot: 0.2706864000065252
这显然与共享内存有关,因为用np.real(xx).copy()
替换np.real(xx)
可以消除性能差异。
trolling numpy docs并不是特别有用,因为列出的差异并没有讨论处理内存视图时的实现细节。
1条答案
按热度按时间8qgya5xd1#
这些时序表示
dot
正在执行copy
与real
的操作:将其应用于
matmul
产生几乎相同的时间:同样,
matmul
和real
采用了一些缓慢的路线。当使用int
阵列时,matmul/dot
的性能都较差,尽管没有matmul real
的速度慢。matmul/dot
也可以处理object
数据类型,但速度更慢。因此,作为python级别的用户,我们看不到(也没有文档记录)有很多隐藏的东西。
编辑
我很想把标题改为关注复数实数,但决定检查另一个
view
浮点数组的一个片段同样很明显,
dot
正在使用视图的copies
。matmul
没有:但对于副本,时间与点相同:
因此,我的猜测是,如果
dot
不能将数组直接发送到BLAS例程,它通常会生成copy
。编辑
虽然
dot
和matmul
处理2d数组的方式相似,但它们处理3+d数组的方式却截然不同。实际上,添加@
的主要原因是为矩阵乘法提供一个方便的“批处理”概念。坚持使用大型复杂数组,让我们将一个大3倍:
matmul
刚刚将时间增加了3;我可以探索更多的东西,但不是在分钟范围内的时间。