【问题标题】:Is matrix multiplication slower than looping over dot product in numpy?矩阵乘法是否比在numpy中循环点积慢?
【发布时间】:2019-09-22 05:54:51
【问题描述】:

我正在编写 numpy 代码来计算自相关。我正在努力提高我的实施性能。

我尝试了两种方法:数组视图上的矩阵乘法和 for 循环中数组切片上的点积。令我惊讶的是,第一种方法似乎要慢得多。

该函数采用向量x 和最大移位k,并返回向量与每个移位i 的移位向量的点积。

def acorr_aview(x, k):
    return np.dot([x[i:-k+i] for i in range(k)], x[:-k])

def acorr_loop(x, k):
    return np.array([np.dot(x[i:-k+i],x[:-k]) for i in range(k)])

我原以为 acorr_aview 会因为使用矩阵乘法而获得更好的性能,但情况似乎恰恰相反。

x = np.random.randn(10000)
k = 100

%timeit acorr_aview(x,k)
%timeit acorr_loop(x,k)
3.32 ms ± 243 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
753 µs ± 33.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

为什么acorr_loop 快得多?谢谢。

编辑:为了比较:

A = np.random.randn(9900,100)
v = np.random.randn(100)

%timeit np.dot(A,v)
%timeit np.array([np.dot(a,v) for a in A])
1.08 ms ± 10.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
12.4 ms ± 243 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

【问题讨论】:

    标签: arrays performance numpy matrix-multiplication dot-product


    【解决方案1】:

    在第一种情况下,您有一个(100, 9900) 和一个(9900,)。在第二个中,你用(9900,)(9900,) 100 次。

    在第一种情况下的内存管理成本和第二种情况下的迭代成本之间需要权衡。其他 SO 问题已经观察到,对一个大问题进行适度数量的迭代可能比对一个更大问题的计算更快。

    Why is B = numpy.dot(A,x) so much slower looping through doing B[i,:,:] = numpy.dot(A[i,:,:],x) )?

    在您的情况下还有另一件事 - 制作更大的数组所需的时间:

    In [366]: timeit np.array([x[i:-k+i] for i in range(k)])                             
    2.62 ms ± 22.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    In [367]: timeit np.dot(np.array([x[i:-k+i] for i in range(k)]),x[:-k])              
    3.6 ms ± 147 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    In [368]: %%timeit xx = np.array([x[i:-k+i] for i in range(k)]) 
         ...: np.dot(xx, x[:-k])                                                                  
    1.05 ms ± 9.27 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    

    较大的 dot 仍然比 100 个较小的 dot 花费更多的时间,但构建 xx 是一项更大的工作。

    【讨论】:

    • 没有那么简单。请参阅我的编辑进行比较。实际上,acorr_loop 甚至比普通的矩阵乘法还要快,所以幕后肯定有一些优化。此外,acorr_aview 中实际上没有构造数组(没有复制内存),这只是数组视图(切片)的列表。
    • 必须先将切片列表转换为数组,然后 dot 才能使用它(将其传递给 BLAS)。
    • 您的比较案例是在一个较小的点上有更多的循环。
    • 谢谢 在你的例子中,任何解释为什么将切片转换为数组并相乘实际上比单独执行这两个更快?
    猜你喜欢
    • 2018-11-29
    • 1970-01-01
    • 2016-03-17
    • 1970-01-01
    • 1970-01-01
    • 2017-07-20
    • 1970-01-01
    • 2020-07-18
    • 2018-09-14
    相关资源
    最近更新 更多