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中。那么修改它能解决我的问题吗?如果是,你能告诉我怎么做吗
假设您运行的是某种风格的linux,以下是一种方法:
-
使用
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的组件。如果使用pip
安装numpy而不手动指定BLAS库,则经常会发生这种情况(请参见下文)。如果你想链接到外部BLAS库,恐怕你别无选择,只能重建numpy。
-
对于numpy v1.10及更新版本:
_dotblas.so
已从最近版本的numpy中删除,但您应该能够检查multiarray.so
的依赖关系:$ ldd /<path_to_site-packages>/numpy/core/multiarray.so
-
-
如果你还没有安装ATLAS/MKL/OpenBLAS。顺便说一句,我肯定会推荐OpenBLAS而不是ATLAS——看看这个答案(尽管基准数据现在可能有点过时)。
-
使用
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
时,我可以在以下三个库中进行选择: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
中放置一个配置文件,可以使pip
尊重numpy的特定配置——有关更多详细信息,请参阅此答案。
我个人的偏好是手动配置和构建numpy。这并不是特别困难,而且它可以让您更好地控制numpy的配置。
答案取决于NumPy最初是如何构建的。如果它是针对BLAS和LAPACK构建的,那么至少没有办法在不重建的情况下强制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/CBAS(作为官方包)构建NumPy,则_dotblas.so
(提供了numpy.dot
的BLAS版本)将无法构建(在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=464784.也许有人可以深入源代码来制作补丁。。。无论如何,这只是一个受影响的函数(numpy.dot
),现在您可以使用更快的OpenBLAS轻松地重建整个NumPy,所以可能根本没什么大不了的。
结论:您可以稍后链接到ATLAS/MKL/OpenBLAS,而无需重建,但如果NumPy最初不是针对ATLAS/MHL/OpenBLAS构建的,则numpy.dot
仍然会非常慢(因为numpy.dot
最初根本没有使用任何BLAS,编译完成后您对此无能为力)。
更新:实际上,您可以强制numpy构建_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
来测试差异。