为什么矩阵减法比numpy中的点积慢得多?

时间:2017-12-07 06:21:35

标签: python numpy

我们说我们有一个向量和一个矩阵:

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

如何像点积一样快速地进行减法?

3 个答案:

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

使用np.subtract(X,Y)几乎将执行时间减半。它比X-Y快,但速度低于点积。可以帮助enter image description here