Eigen3本身自带多种线性方程组的求解器,同时也提供了许多其它库的接口,Intel MKL PARDISO就是其中之一。用PARDISO求解线性方程组的效率非常高。下面我将展示如何在Visual Studio 2017中为Eigen3链接PARDISO库来高效地求解线性方程组。Eigen3目前提供了3个基于PARDISO的求解器:
- Eigen::PardisoLDLT
- Eigen::PardisoLLT
- Eigen::PardisoLU
使用这三个求解器需要先安装Intel MKL并且正确地在Visual Studio中配置项目。
安装Visual Studio 2017
除了VS2017以外,VS2015等版本也可以,更早版本未测试。安装VS的具体流程这里这里不再赘述,不过要注意,Visual Studio的安装应当在Intel MKL之前。
下载Intel Math Kernel Library(MKL)
官网钦定的MKL支持列表包括
- Intel® Xeon Phi™ processor
- Intel® Xeon® processor
- Intel® Core™ processor family
- Intel Atom® processor
这四类,如果你使用的是AMD处理器实际上也可以使用,不过性能会有所折扣(不知道是不是故意而为之)。
你可以尝试从这个直链下载2018.3版本,不过这里无法保证这个直链以后不会失效。你也可以点击这个链接进入官网下载最新版本的MKL。下载本身是免费的,但是需要你注册并登录,如图所示。
提交后,如果你没有注册过Intel的账户,则需要提交额外的信息以完成注册。值得注意的是,牙膏厂对用户密码的要求非常严格,具体要求有:
- 8到15个字符
- 至少一个字母,大小写均可
- 至少一个数字
- 至少一个特殊符号(#$%等)
- 不允许非英文字符
- 不允许和用户名一样
- 不允许使用3个以上重复的字符,如1111或aaa
- 不允许使用注册信息里的其他字段
- 不允许使用之前用过的密码
注册完成后,会直接跳转到下载页面,选择Windows平台,下载Intel Math Kernel Library
安装Intel Math Kernel Library(MKL)
在安装MKL之前,请确认你已经正确安装了Visual Studio 2017或Visual Studio 2015。点击exe解包后,首先是安装选项:
最主要的是Intel MKL core libraries for C/C++,有32位和64位版本可以选择安装。其余选项可以随意。点击Next。
这里会提示你安装IDE插件。在这之前, 你必须已经正确地安装了Visual Studio,否则将导致后续在Eigen中链接MKL的步骤失败。接着点击Install,等待安装完成。
如果你的计算机不是Intel的处理器,这里也会警告兼容性问题,可以选择忽略继续安装。
配置项目
接下来新建一个C++项目,然后右键项目-属性,会发现多了一个Intel Performance Library选项,表明Intel MKL及其Visual Studio插件均已安装成功,然后右边Use Intel MKL由No修改为Parallel,即可在项目自动添加MKL的头文件引用和库链接选项。如图所示。当然,也要注意配置为所有配置、平台为所有平台。
接下来,向项目中添加Eigen的头文件引用,即可通过
#include <Eigen/PardisoSupport>
来使用
- Eigen::PardisoLDLT
- Eigen::PardisoLLT
- Eigen::PardisoLU
这三个求解器求解线性方程组。这三个求解器的使用方法和Eigen中其它求解器的使用基本相似。
性能对比
下面,我们来简单对比以下PARDISO和Eigen3自带求解器的性能。求解问题为三角网格调和映射(Harmonic Mapping)的泊松方程,程序的总体结构为:
Eigen::SparseMatrix<double> A;
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> b;
//Build A
//Build b
Eigen::PardisoLDLT<Eigen::SparseMatrix<double>> solver;
solver.Compute(A);
solver.Solve(b);
测试的模型规模为470K面,对应A为235K*235K的稀疏矩阵。在Intel 6700K @4.20GHZ上,测试的结果如下表所示
模型 | 库 | 求解方法 | Compute | Solve | 总计时间 |
Buddha (470K Faces) | PARDISO | PardisoLLT | 872ms | 157ms | 1029ms |
PardisoLDLT | 882ms | 125ms | 1007ms | ||
PardisoLU | 1211ms | 181ms | 1392ms | ||
EIGEN | SimplicialLLT | 1385ms | 88ms | 1473ms | |
SimplicialLDLT | 1398ms | 95ms | 1493ms | ||
SparseLU | 4773ms | 192ms | 4965ms |
可以看出,Pardiso提供的LLT、LDLT、LU比Eigen自带的性能至少高出了30%。