链接ATLAS / MKL到已安装的Numpy

TL; DR如何在不重build的情况下将ATLAS / MKL链接到现有的Numpy。

我用Numpy来计算大matrix,我发现它很慢,因为Numpy只使用1个核心来进行计算。 做了很多search之后,我发现我的Numpy没有链接到像ATLAS / MKL这样的优化库。 这是我的numpy的configuration:

>>>import numpy as np >>>np.__config__.show() blas_info: libraries = ['blas'] library_dirs = ['/usr/lib'] language = f77 lapack_info: libraries = ['lapack'] library_dirs = ['/usr/lib'] language = f77 atlas_threads_info: NOT AVAILABLE blas_opt_info: libraries = ['blas'] library_dirs = ['/usr/lib'] language = f77 define_macros = [('NO_ATLAS_INFO', 1)] atlas_blas_threads_info: NOT AVAILABLE openblas_info: NOT AVAILABLE lapack_opt_info: libraries = ['lapack', 'blas'] library_dirs = ['/usr/lib'] language = f77 define_macros = [('NO_ATLAS_INFO', 1)] atlas_info: NOT AVAILABLE lapack_mkl_info: NOT AVAILABLE blas_mkl_info: NOT AVAILABLE atlas_blas_info: NOT AVAILABLE mkl_info: NOT AVAILABLE 

为此,我想链接ATLAS / MKL到Numpy。 不过,我的Numpy是从PIP安装的,所以我不想手动安装,因为我想使用最新版本。 我已经做了一些search,但他们只是从头开始build设。 出于这个原因,我的问题是:

  • 有没有办法将ATLAS / MKL链接到Numpy,而无需再次重build?
  • 我发现configuration信息保存在安装的Numpy文件夹的_ config _.py中。 那么修改它会解决我的问题吗? 如果是,请告诉我怎么样?

假设你正在运行一些linux的风格,你可以这样做:

  1. 找出BLAS库numpy当前使用ldd链接的内容。

    • 对于v1.10之前版本的numpy:

       $ ldd /<path_to_site-packages>/numpy/core/_dotblas.so 

      例如,如果我通过apt-get安装numpy,它链接到

       ... libblas.so.3 => /usr/lib/libblas.so.3 (0x00007fed81de8000) ... 

      如果_dotblas.so不存在 ,这可能意味着numpy在最初安装时未能检测到任何BLAS库,在这种情况下,它不会构build任何BLAS相关组件。 如果您使用pip安装numpy而无需手动指定BLAS库(如下所示),则通常会发生这种情况。 如果你想链接到一个外部的BLAS库,恐怕你别无select,只能重buildnumpy。


    • 对于numpy v1.10和更新:

      _dotblas.so已经从numpy的最新版本中删除 ,但你应该能够检查multiarray.so的依赖:

       $ ldd /<path_to_site-packages>/numpy/core/multiarray.so 
  2. 如果你还没有安装ATLAS / MKL / OpenBLAS。 顺便说一下,我肯定会推荐OpenBLAS over ATLAS – 看看这个答案 (虽然基准数据现在可能已经过时了)。

  3. 使用update-alternatives来创build符合您所select的新BLAS库的符号链接。 例如,如果您将libopenblas.so安装到/opt/OpenBLAS/lib ,您将执行以下操作:

     $ sudo update-alternatives --install /usr/lib/libblas.so.3 \ libblas.so.3 \ /opt/OpenBLAS/lib/libopenblas.so \ 50 

    您可以为单个目标库configuration多个符号链接,允许您在多个已安装的BLAS库之间手动切换。

    例如,当我打电话给$ sudo update-alternatives --config libblas.so.3 ,我可以select3个库之一:

      Selection Path Priority Status ------------------------------------------------------------ 0 /opt/OpenBLAS/lib/libopenblas.so 40 auto mode 1 /opt/OpenBLAS/lib/libopenblas.so 40 manual mode 2 /usr/lib/atlas-base/atlas/libblas.so.3 35 manual mode * 3 /usr/lib/libblas/libblas.so.3 10 manual mode 

如果你真的想要“最新”版本的numpy,你也可以看看我的答案,从OpenBLAS集成源码编译numpy 。

用pip安装BLAS支持numpy

正如在注释中提到的@tndoan,通过在~/.numpy-site.cfg放置一个configuration文件,可以让pip尊重numpy的特定configuration – 请参阅此答案以获取更多详细信息。

我个人的喜好是手工configuration和build立numpy。 这并不是特别困难,它让你更好地控制numpy的configuration。

答案取决于最初如何build立NumPy。 如果它是针对BLAS和LAPACK构build的,那么至less在没有重build的情况下,无法强制numpy.dot使用ATLAS / MKL。 其他函数不使用numpy.dot ,您可以使用update-alternatives来更改符号链接libblas.so.3liblapack.so.3的目标。 这是因为numpy.dot需要ATLAS样式的CBLAS或OpenBLAS / MKL,而不是netlib中的BLAS / CBLAS和LAPACK。

我使用的是openSUSE,我已经从netlib安装了标准的cblas-devel。 但是,强制NumPy使用运行的cblas / cblas-devel似乎是不可能的。 也就是说,如果你用netlib BLAS / LAPACK / CBLAS(作为官方软件包)构build了NumPy,那么_dotblas.so (它提供了numpy.dot的BLAS版本)不能build立(在1.10之前),或者multiarray.so (1.10以后)根本就没有链接到libblas.so.3 。 请参阅github上的问题: https : //github.com/numpy/numpy/issues/1265和引用的Debian错误报告: https ://bugs.debian.org/cgi-bin/bugreport.cgi ? bug = 468784 。 也许有人可以潜入源代码来创build一个补丁…无论如何,这只是一个受影响的函数( numpy.dot ),你现在可以使用更快的OpenBLAS轻松地重build整个NumPy,所以可能没有什么大不了的所有。

结论:你可以在不重build的情况下链接到ATLAS / MKL / OpenBLAS,但是如果NumPy最初并不是针对ATLAS / MKL / OpenBLAS构build的, numpy.dot仍然会非常慢(因为numpy.dot根本没有使用任何 BLAS第一个地方,一旦编译完成,你无能为力)。

更新:其实你可以强制numpy来build立_dotblas.so 。 我为numpy-1.9.2做了一个补丁:

 diff -Npru numpy-1.9.2.orig/numpy/core/setup.py numpy-1.9.2/numpy/core/setup.py --- numpy-1.9.2.orig/numpy/core/setup.py 2015-02-01 11:38:25.000000000 -0500 +++ numpy-1.9.2/numpy/core/setup.py 2016-03-28 01:31:12.948885383 -0400 @@ -953,8 +953,8 @@ def configuration(parent_package='',top_ #blas_info = {} def get_dotblas_sources(ext, build_dir): if blas_info: - if ('NO_ATLAS_INFO', 1) in blas_info.get('define_macros', []): - return None # dotblas needs ATLAS, Fortran compiled blas will not be sufficient. + #if ('NO_ATLAS_INFO', 1) in blas_info.get('define_macros', []): + # return None # dotblas needs ATLAS, Fortran compiled blas will not be sufficient. return ext.depends[:3] return None # no extension module will be built 

既然_dotblas.so链接到libblas.so.3 ,您可以使用update-alternatives来testing差异。