[转]Numpy使用MKL库提升计算性能

时间:2022-03-17 06:22:21

from:http://unifius.wordpress.com.cn/archives/5

系统:Gentoo Linux (64bit, Kernel 3.7.1)
配置:Intel(R) Core(TM) i7-2670QM
在Gentoo中安装Numpy/Scipy非常简单,直接emerge就可以解决。但是默认链接的blas/lapack库性能非常差,在矩阵计算方面比MATLAB慢了不少。原因在于MATLAB使用的是高度优化的数值计算库Intel math kernel library (MKL)。最新的MKL库在science overlay中有,安装后通过eselect blas/lapack set可以将系统默认链接的库设定为MKL(如mkl64-int64-dynamic-openmp)。设定之后再emerge numpy就可使用链接MKL库的numpy,而且可以发现svd等常用矩阵计算函数的速度大大提升。可问题是scipy无法emerge通过,查看log发现scipy无法检测到-lblas,即它根本没有识别系统默认链接库的设置。science overlay中blas/lapack库及其相关包的安装向来十分纠结,因为这里面似乎还没有完善的链接管理。这些问题持续了至少一年,近来才发现(部分)解决途径。

我们改换策略,手工安装numpy。首先获取最新的numpy包:
git clone git://github.com/numpy/numpy.git numpy
然后进入到根目录。我们需要进行一些配置才能使numpy用上安装好的MKL库。这部分可以参考Intel官网的一个教程:

http://software.intel.com/en-us/articles/numpyscipy-with-intel-mkl

首先在根目录中加入site.cfg文件:

[mkl]
library_dirs = /opt/intel/mkl/composer_xe_2013/lib/intel64
include_dirs = /opt/intel/mkl/include
mkl_libs = mkl_rt
lapack_libs =

这里library_dirs与include_dirs是MKL的相关路径,注意各Linux发行版有细微区别。接下来修改numpy/distutils/intelccompiler.py中的cc_exe:

self.cc_exe = 'icc -O3 -g -fPIC -fp-model strict -fomit-frame-pointer -openmp -xhost'

以及numpy/distutil/fcompiler/intel.py中ifort的参数(最新版numpy里已经设置好了)。最后回到根目录进行编译:

sudo python2.7 setup.py config --compiler=intelem --fcompiler=intelem build_clib --compiler=intelem --fcompiler=intelem build_ext --compiler=intelem --fcompiler=intelem install

因为使用的是64位系统,所以是intelem。由于用到了Intel的c与fortran编译器(这二者也能带来性能的提升),编译前需要预先安装icc以及ifc(直接emerge即可安装)。注意,上述命令只编译了python2.7版本的,而之后系统编译scipy还需要py3k版本,所以还需要用python3.2再编译一次,这样两种版本的numpy就都安装在了系统中。至此我们已经从源码安装了numpy,且让其链接上了最新的MKL库。
现在产生了一个新的问题:使用emerge安装scipy等其他依赖numpy的包时系统会自动安装numpy,覆盖掉我们手工安装的numpy,这样就又回到了之前的老路子。这时Gentoo灵活的配置性就体现出来了,通过
echo "dev-python/numpy-1.7.0" >> /etc/portage/profile/package.provided
我们可以告诉系统numpy的1.7.0版本已经手动安装好了,这样系统之后安装其他依赖包时就不会再动numpy了。当然,隔一段时间后numpy可能会发布新版本,这时更新系统会把已安装的numpy覆盖掉,所以要定期手动升级numpy。

上面这种方法的好处是最大程度保留了系统功能,让系统去自动处理尽量多的任务,留给我们的任务仅仅是每隔一段时间更新Numpy。使用python做普通科学计算,其性能主要由numpy决定,因此保证numpy的最优就足够。当然也可以手动编译所有python数值计算库,只是会在更新时多费些时间和精力。
实际测试中,这种方法安装的numpy的速度稍快于MATLAB,不过numpy与scipy的自带测试并没有全部通过。这并不影响基本使用,因此我还未探究原因何在。