1. 软件版本信息
2 KLU 编译
KLU是针对线性方程组中系数矩阵的LU分解的一类快速求解方法。源文件为C文件,理论上是可以直接在Visual Studio中直接使用的,可参见KLU使用说明。不过,大部分编程的人,尤其是高校研究生更熟悉Matlab。因此,若想在Matlab中使用KLU,则需进行额外的处理,即采用mex指令进行编译,不过KLU的编译是比较麻烦的。尽管如此,但是开发此代码的作者Tim Davis已以脚本文件完成编译部分,更加便捷,具体安装可参见KLU编译链接。
2.1 KLU来源
From: http://faculty.cse.tamu.edu/davis/suitesparse.html,网页界面如下所示:
下载后,文件内容大致如下所示:
值得注意两点:
其一,因为使用到LU分解,而该算法的快速性很大程度上依赖于减少Fill-in,因此Factorize之前需要进行排序以在Factorize之前减少注入元,提升计算效率。而用于排序的排序算法中,KLU算法包中自带有AMD, ColAMD,默认为AMD;除此之外, KLU也支持第三方库中排序算法,如Metis, 如性能较优的CHOLMOD。此外,下载链接为SuiteSparse(功能很强大,QR、Cholesky分解),而我们仅需要其中的一部分KLU, 因此下载时不要误认为链接有所问题。又回到Metis的补加上,因为SuiteSparse4.4.4,没有Metis,因此需要额外进行下载,下载链接为Metis下载链接,下载选项如下所示。下载后,将Metis文件复制粘贴在SuiteSparse4.4.4文件安装目录下,具体可参见下图。
其二,SuiteSparse5.0以上,里面已经集成Metis包(版本为5.1),这是其一大好处,不过编译总是无法正常安装KLU,还不清楚原因。鉴于无法正常安装,笔者也就仅以正常安装测试成功的SuiteSparse4.4.4为例。如果有朋友测试成功更高版本的SuiteSparse,如5.0以上,还请分享,谢谢!
2.2 Matlab环境编译
安装请记住两点:其一,进入SuiteSparse4.4.4安装目录;其二,Matlab命令窗口敲入此指令(SuiteSparse_install),然后一路回车安装即可。为便于大家,此处也附上安装过程图片。
3. 代码部分
3.1 Matlab 部分
3.1.1 图片
3.1.2 代码
function [rst] = CallKLUInCPlusPlus()
try
load A.mat;
load b.mat;
S = sparse (A) ;
fprintf('KLU Time (Sparse and Double)\n');
tic, LU=klu(S);x0=klu(LU,'\',b); toc;% klu sparse
fprintf('Matlab Double and Dense\n');
tic, x1 = A\b ; toc
fprintf('Matlab Double and Sparse\n');
tic, x2 = S\b ; toc
sA=single(A);
fprintf('Matlab Single and Dense\n');
tic, x3 = sA\b; toc;
x=[x0 x1 x2 x3];
rst=0;% Normal State
return;
catch ME
switch ME.identifier
case 'MATLAB:UndefinedFunction'
warning('Function is undefined. Assigning a value of NaN.');
a = NaN;
case 'MATLAB:scriptNotAFunction'
warning(['Attempting to execute script as function. '...
'Running script and assigning output a value of 0.']);
notaFunction;
a = 0;
otherwise
rethrow(ME)
end
rst=1;% Error Occurs
return;
end
end
3.1.3 数据
3.1.2代码中的数据,即load A.mat和load b.mat, 可以当作一个线性方程组的左端系数矩阵和右端向量矩阵理解。因此,生成这样的矩阵是比较方便的。但是此处,数据源于研究相关,不便透露,仅以图片形式直观展示系数矩阵A。不过为便于大家,也简单写了一个生成数据的函数(简称getData()函数),调用形式为[A,b]=getData(100,'double')。
function [A,b] = getData(n,clz)
fprintf('Creating a matrix of size %d-by-%d.\n', n, n);
A = rand(n, n,clz) + 100*eye(n, n,clz);
b = rand(n, 1);
end
3.2 C++部分
3.2.1 图片
3.2.2 代码
#include "stdafx.h"
#include "CallKLUInCPlusPlus.h"
#include
#include
int main()
{
// Set up the application state for the MATLAB Runtime instance created in the application.
if (!mclInitializeApplication(NULL, 0)) {
std::cerr << "could not initialize the application properly"
<< std::endl;
return -1;
}
// Load the required MATLAB code into the MATLAB Runtime.
if (!CallKLUInCPlusPlusInitialize()) {
std::cerr << "could not initialize the library properly"
<< std::endl;
return -1;
}
// Declare one variable using mxArray format
mwArray out(1, 1, mxDOUBLE_CLASS);
double *rst = new double[1];
// Invoke CallKLUInCPlusPlus() method
CallKLUInCPlusPlus(1, out);
out.GetData(rst, 1);
// Free all related resources occupied by current program
CallKLUInCPlusPlusTerminate();
mclTerminateApplication();
getchar();
return 0;
}
4. C++配置
C++与Matlab混编,总是涉及较多库文件,包含目录、Matlab的extern包含文件设置,很琐碎但也非常关键。此部分,可详见笔者此前关于C++&Matlab混合编程-动态链接库形式的博客的链接。此处,也回顾性的以图片形式说明配置过程。
5. 测试结果
5.1 Matlab Result:
5.1.1 正确性:
5.1.2 运行时间
5.2 C++
所需时间:
6. 有用链接