我们说我们有一个向量和一个矩阵:
X = np.random.random((1, 384)).astype('float32')
Y = np.random.random((500000, 384)).astype('float32')
为什么np.dot(X, Y.T)
比X - Y
快得多?
In [8]: %timeit np.dot(X, Y.T)
10 loops, best of 3: 42.4 ms per loop
In [9]: %timeit X - Y
1 loop, best of 3: 501 ms per loop
如何像点积一样快速地进行减法?
答案 0 :(得分:2)
输出的大小很重要,因为必须将输出写入内存,而写入大型数组需要时间。 dot(X, Y.T)
的形状是(1,500000)。 X-Y的形状是(500000,384)。
在我的测试中,X-Y花费的大部分时间是为输出分配一个数组。比较:
%timeit X - Y
1 loop, best of 3: 449 ms per loop
预先分配的空格Z = np.zeros_like(Y)
,
%timeit np.subtract(X, Y, out=Z)
10 loops, best of 3: 181 ms per loop
因此,如果你必须反复进行这种减法,那么预先分配合适形状和类型的数组将节省超过一半的执行时间。
我不认为你的情况下的减法可以和乘法一样快。要做的算术数量大致相同:X的每个条目在任何一种情况下都满足50个条目的Y.当你进行乘法(求和步骤)时结果组合的事实只有帮助,因为CPU用它已经存在的数字快速完成它,因此它只有一个数字要发回。所以:大约相同的工作量,但对于减法的情况,内存写入量是384倍。
当两个(方形矩阵)的输出大小相同时,以下证明减法 更快:
X = np.random.random((1000, 1000)).astype('float32')
Y = np.random.random((1000, 1000)).astype('float32')
%timeit np.dot(X, Y.T)
100 loops, best of 3: 28.7 ms per loop
%timeit X - Y
1000 loops, best of 3: 579 µs per loop
答案 1 :(得分:0)
这只是一个评论,虽然您已经检查过。
我测试了广播是否是一个原因,但在这种情况下它完全与性能无关。
In [1]: import numpy as np
In [2]: X = np.random.random((1, 384)).astype('float32')
...: Y = np.random.random((500000, 384)).astype('float32')
In [3]: %timeit np.dot(X, Y.T)
...: %timeit X - Y
27.4 ms ± 910 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
324 ms ± 16.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [4]: import numpy.matlib
...: X = np.matlib.repmat(X, 500000, 1)
...: print(X.shape)
...: %timeit X - Y
(500000, 384)
351 ms ± 20.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
请原谅我,我不确定如何改善这种表现。
答案 2 :(得分:-1)