在Python中实现大型ndarray乘法的最快方法

时间:2016-11-07 10:14:19

标签: python anaconda matrix-multiplication intel-mkl

我目前正在研究耦合HMM的Python实现,它涉及元素乘法,点积和维数的维数(50,50,40,40,40)和维数的ndarray( 40,40,40,40)。也就是说,非常大......第二个ndarray或多或少稀疏,约有70%的零。

到目前为止,我一直在使用numpy.einsum,它给了我很慢的结果(算法运行大约需要3小时)。现在的问题是我需要为我的HMM优化一些参数,这意味着我必须至少进行10000次运行,因此我需要一个至少1000倍的速度增加才能保持合理

我一直在四处寻找在Python中进行大型数组操作的最佳方法,现在我完全迷失了所有我读过的内容。所以我有几个问题。在询问他们之前,我只想说明我在使用OSX,intel处理器和nvidia GPU的机器上使用最新的带有Python 3的anaconda发行版。此外,我相信我可以压扁我的ndarray以简化我的问题到一个简单的矩阵矩阵问题。

1)似乎BLAS / MKL库可以提供相当好的增加。当使用带有OSX的Ananaconda时,似乎MKL本身与Python链接。因此,直到现在我一直在使用MKL而不知道吗? np。 config .show()给我这样的东西:

openblas_lapack_info:
  NOT AVAILABLE
blas_opt_info:
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
    include_dirs = ['//anaconda/include']
    libraries = ['mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']
    library_dirs = ['//anaconda/lib']
lapack_opt_info:
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
    include_dirs = ['//anaconda/include']
    libraries = ['mkl_lapack95_lp64', 'mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']
    library_dirs = ['//anaconda/lib']
lapack_mkl_info:
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
    include_dirs = ['//anaconda/include']
    libraries = ['mkl_lapack95_lp64', 'mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']
    library_dirs = ['//anaconda/lib']
blas_mkl_info:
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
    include_dirs = ['//anaconda/include']
    libraries = ['mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']
    library_dirs = ['//anaconda/lib']
mkl_info:
    define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
    include_dirs = ['//anaconda/include']
    libraries = ['mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']
    library_dirs = ['//anaconda/lib']

这真的能提高einsum功能的速度吗?如果没有,我怎样才能设法从Python获取MKL的gemm函数?

2)这些Python库中的任何一个对我的问题是否有用:Theanos,Numba,Cupy?或者只是简单的Anaconda Accelerate?来自Anaconda Accelerate的cuBlas会对我来说是最好的选择吗(即我愿意使用单精度或半浮动精度)?

3)例如,在C或C ++中重新编码我的算法是否有用?

4)我尝试使用稀疏矩阵(scipy.sparse.csc_matrix)实现我的算法,但它使我的程序慢了很多。这是可以预料的还是我犯了错误?

我知道这提出了很多问题,但这是我第一次遇到这种问题而互联网并不是那么明确......

非常感谢!

1 个答案:

答案 0 :(得分:0)

好的,因为我在最后几天花了很多时间来调查我的问题,我或许可以给像我这样迷失的人一些答案。所以:

1)是的,默认情况下,MKL本身安装了anaconda(虽然这种情况并非如此)。但是,np.einsum并没有从中获益,因为它没有使用BLAS优化的dot numpy功能。因此,尝试从mkl手动访问gemm函数是没用的(即使由于库anaconda加速,这实际上非常容易)。使用np.tensordot,np.multiply和其他人来重写np.einsum的操作更容易。

2)我没有时间去探索我询问过的所有库,但是一个数字的Theanos操作显然不比简单的np.tensordot快。同样,几年前情况并非如此,因为np.tensordot操作并未使用BLAS进行多维数组。关于所有cuda库,看起来它们与MKL相比实际上并不那么好,除非你有一个非常强大的CGU(参见例如https://larsjuhljensen.wordpress.com/2011/01/28/commentary-the-gpu-computing-fallacy/

3)将用MKL优化的一些Python代码重写为C ++并没有带来太大的增长(参见Benchmarking (python vs. c++ using BLAS) and (numpy)

4)仍然不知道为什么我的稀疏矩阵实现比密集矩阵慢。我很可能犯错了。