首页 > 解决方案 > 为什么矢量化 Pinv 比未矢量化慢?

问题描述

我有十个6000 x 784矩阵。如果我运行 np.cov 然后在它们每个上运行 pinv,总时间是:

%timeit for n in range(10): pinv(np.cov(A,rowvar = False))
1.64 s ± 78.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

如果我改为循环 np.cov 并计算 3D 堆栈的 pinv,我得到:

%timeit for n in range(10): dd[n] = np.cov(A,rowvar = False)
485 ms ± 18 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit pinv(dd)
4.59 s ± 369 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

为什么 3D 上的 pinv 这么慢?

我该怎么做才能计算堆栈的 np.cov 和相应的 pinv?

标签: pythonnumpyvectorization

解决方案


这是由于实施。限制步骤是 numpy matmul。首先,我认为 SVD 是限制步骤,但这会线性扩展(每次迭代约 130 毫秒,十个一组为 1.3 秒)。

以下是分析的一些部分:

1 个电话(您的第一个片段)

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.131    0.131    0.131    0.131 linalg.py:1299(svd)
    1    0.011    0.011    0.011    0.011 {built-in method numpy.core.multiarray.matmul}
    1    0.003    0.003    0.144    0.144 <ipython-input-76-2a63f1c84429>:1(pinv)

一包 10 个的 1 个电话(您的第二个片段)

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    2.952    2.952    2.952    2.952 {built-in method numpy.core.multiarray.matmul}
    1    1.265    1.265    1.265    1.265 linalg.py:1299(svd)
    1    0.026    0.026    4.266    4.266 <ipython-input-76-2a63f1c84429>:1(pinv)

可能存在 C 排序的内部问题(但最近的 numpy 版本应该处理它),或者在这种情况下效率低下......尝试使用scipy 实现直接更改为 BLAS 接口,但这仅适用于二维矩阵。这些问题(matmul 很慢)实际上已在其他地方提出。

底线,做非矢量化或尝试使用其他实现。有时矩阵乘法的最快方法是使用eigen函数,但我从未在多维问题中尝试过。


推荐阅读