链接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的风格,你可以这样做:
-
找出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
-
-
如果你还没有安装ATLAS / MKL / OpenBLAS。 顺便说一下,我肯定会推荐OpenBLAS over ATLAS – 看看这个答案 (虽然基准数据现在可能已经过时了)。
-
使用
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.3
和liblapack.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差异。