将ATLAS / MKL链接到已安装的Numpy

时间:2014-02-10 07:12:12

标签: python performance numpy linear-algebra blas

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

我使用Numpy用大矩阵计算,我发现它非常慢,因为Numpy只使用1个核心进行计算。经过大量的搜索,我发现我的Numpy没有链接到像ATLAS / MKL这样的优化库。这是我的numpy配置:

>>>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安装的,因此我不想手动安装,因为我想使用最新版本。我做了一些搜索,但它们只是用于从头开始构建。出于这个原因,我的问题是:

  • 有没有办法将ATLAS / MKL链接到Numpy而不重建?
  • 我发现配置信息保存在Numpy的已安装文件夹中的 _ config _。py 中。那么修改它会解决我的问题吗?如果是的话,请你告诉我怎么样?

2 个答案:

答案 0 :(得分:25)

假设你正在运行某种版本的linux,这是你可以做到的一种方式:

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

    • 对于早于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库,在这种情况下它根本不构建任何BLAS库BLAS依赖的组件。如果使用pip安装numpy而不手动指定BLAS库(见下文),则会发生这种情况。如果你想链接外部BLAS库,我恐怕你别无选择,只能重建numpy。


    • 适用于numpy v1.10及更新版本:

      来自numpy最新版本的

      _dotblas.so has been removed,但您应该能够检查multiarray.so的依赖关系:

      $ ldd /<path_to_site-packages>/numpy/core/multiarray.so
      
  2. 如果您还没有安装ATLAS / MKL / OpenBLAS。顺便说一句,我肯定会推荐OpenBLAS而不是ATLAS - 看看this answer(尽管基准测试数据现在可能有点过时了。)

  3. 使用update-alternatives为您选择的新BLAS库创建符号链接。例如,如果您将libopenblas.so安装到/opt/OpenBLAS/lib,则可以执行以下操作:

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

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

    例如,当我调用$ sudo update-alternatives --config libblas.so.3时,我可以选择3个库中的一个:

      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
    
  4. 如果您真的想要numpy的“最新”版本,您还可以查看my answer on compiling numpy from source with OpenBLAS integration

    使用pip

    安装带有BLAS支持的numpy

    正如@tndoan在评论中提到的那样,通过在pip中放置配置文件,可以使~/.numpy-site.cfg尊重numpy的特定配置 - 有关详细信息,请参阅this answer

    我个人的偏好是手动配置和构建numpy。这并不是特别困难,它可以让你更好地控制numpy的配置。

答案 1 :(得分:1)

答案取决于最初如何构建NumPy。如果它是针对BLAS和LAPACK构建的,那么至少在没有重建的情况下,没有办法强制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(作为官方软件包)构建了NumPy,则无法构建_dotblas.so(提供numpy.dot的BLAS版本)(或者在1.10之前),或{ {1}}(1.10及更高版本)根本不会链接到multiarray.so。请参阅github上的问题:https://github.com/numpy/numpy/issues/1265和引用的Debian错误报告:https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=464784。也许有人可以深入研究源代码来制作一个补丁...无论如何,它只是一个受影响的函数(libblas.so.3),你现在可以使用更快的OpenBLAS轻松地重建整个NumPy,所以可能没什么大不了的毕竟是交易。

结论:您可以在不重建的情况下链接到ATLAS / MKL / OpenBLAS,但如果NumPy最初不是针对ATLAS / MKL / OpenBLAS构建的,那么numpy.dot仍然会非常慢(因为numpy.dot首先没有使用任何 BLAS,一旦编译完成,您就无法做任何事情。)

更新:实际上你可以强迫numpy构建numpy.dot。我为numpy-1.9.2制作了一个补丁:

_dotblas.so

现在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来测试差异。