LAPACK(Linear Algebra PACKage)库,是用Fortran语言编写的线性代数计算库,包含线性方程组求解(\(AX=B\))、矩阵分解、矩阵求逆、求矩阵特征值、奇异值等。该库用BLAS库做底层运算。

本示例将使用MKL中的LAPACK库计算线性方程组\(AX=B\)的解,并扩展使用此思路求逆矩阵的过程。首先介绍原理部分:

LU分解

引用自 LU分解 - 维基百科

对于方阵\(A\),其\(LU\)分解是将它分解成一个下三角矩阵\(L\)与上三角矩阵\(U\)的乘积,即\(A=LU\),

如一个\(3 \times 3\)的矩阵\(A\) ,其\(LU\)分解会写成下面的形式:

\[{\displaystyle A={\begin{bmatrix}a_{11}&a_{12}&a_{13}\\a_{21}&a_{22}&a_{23}\\a_{31}&a_{32}&a_{33}\\\end{bmatrix}}={\begin{bmatrix}l_{11}&0&0\\l_{21}&l_{22}&0\\l_{31}&l_{32}&l_{33}\\\end{bmatrix}}{\begin{bmatrix}u_{11}&u_{12}&u_{13}\\0&u_{22}&u_{23}\\0&0&u_{33}\\\end{bmatrix}}}{\displaystyle }\\
A\vec x = \vec b \Leftrightarrow (LU)\vec x = \vec b \Leftrightarrow \left\{ {\begin{array}{*{20}{c}}
{L\vec y = \vec b}\\
{U\vec x = \vec y}
\end{array}} \right.
\]

分解之后,由于\(L\)与\(U\)分别为下、上三角矩阵,再去求解\(X\)将变得更加简单。

然而,\(LU\)分解只适用于能用消去法处理的矩阵(比如左上角第一个元素为0时就无法消去)。

而\(PLU\)分解在加入置换矩阵\(P\)进行换行后,便可对任意实矩阵进行\(LU\)分解,此时\(A=P*L*U\)。

LAPACKE_sgesv计算线性方程组\(A*X = B\) 的解,其中 \(A\) 是$ N×N$ 矩阵,\(X\) 和 \(B\) 是 \(N×NRHS\) 矩阵。 将 \(A\) 分解为 \(A = P * L * U\),其中 \(P\) 是置换矩阵,\(L\)是单位下三角矩阵,\(U\)是上三角矩阵。 然后使用\(A\)的分解式来求解方程组\(A * X = B\)。

1 参数详解

lapack_int LAPACKE_sgesv( matrix_layout, 	// (input) 行优先(LAPACK_ROW_MAJOR)或列优先(LAPACK_COL_MAJOR)
n, // (input) 线性方程的个数,n>=0
nrhs, // (input) 矩阵B的列数,即线性方程组右端的项个数,nrhs>=0
a, // (input/output)系数矩阵A,维度为nxn
lda, // (input) A矩阵的第一维
ipiv, // (output) 置换矩阵,ipiv[i]表示矩阵A的第i行与第ipiv[i]行进行了交换
b, // (input/output)B矩阵
ldb // (input) B矩阵的第一维
);

2 定义线性方程组

Intel给出的官方示例为:

\[A = \left[ {\begin{array}{*{20}{r}}
{6.80}&{ - 6.05}&{ - 0.45}&{8.32}&{ - 9.67}\\
{ - 2.11}&{ - 3.30}&{2.58}&{2.71}&{ - 5.14}\\
{5.66}&{5.36}&{ - 2.70}&{4.35}&{ - 7.26}\\
{5.97}&{ - 4.44}&{0.27}&{ - 7.17}&{6.08}\\
{8.23}&{1.08}&{9.04}&{2.14}&{ - 6.87}
\end{array}} \right]~~~~~B = \left[ {\begin{array}{*{20}{r}}
{4.02}&{ - 1.56}&{9.81}\\
{6.19}&{4.00}&{ - 4.09}\\
{ - 8.22}&{ - 8.67}&{ - 4.57}\\
{ - 7.57}&{1.75}&{ - 8.61}\\
{ - 3.03}&{2.86}&{8.99}
\end{array}} \right]
\]

去求解\(AX=B\)的解\(X\)。

#include <stdlib.h>
#include <stdio.h>
#include "mkl_lapacke.h" // 参数
#define N 5
#define NRHS 3
#define LDA N
#define LDB NRHS
MKL_INT n = N, nrhs = NRHS, lda = LDA, ldb = LDB, info;

MKL_INT ipiv[N];
float a[LDA*N] = {
6.80f, -6.05f, -0.45f, 8.32f, -9.67f,
-2.11f, -3.30f, 2.58f, 2.71f, -5.14f,
5.66f, 5.36f, -2.70f, 4.35f, -7.26f,
5.97f, -4.44f, 0.27f, -7.17f, 6.08f,
8.23f, 1.08f, 9.04f, 2.14f, -6.87f
};
float b[LDB*N] = {
4.02f, -1.56f, 9.81f,
6.19f, 4.00f, -4.09f,
-8.22f, -8.67f, -4.57f,
-7.57f, 1.75f, -8.61f,
-3.03f, 2.86f, 8.99f
};

3 执行求解过程

LAPACKE_sgesv( LAPACK_ROW_MAJOR, n, nrhs, a, lda, ipiv, b, ldb );

输出结果为:

完整代码

#include <stdlib.h>
#include <stdio.h>
#include "mkl_lapacke.h" extern void print_matrix(const char* desc, MKL_INT m, MKL_INT n, float* a, MKL_INT lda);
extern void print_int_vector(const char* desc, MKL_INT n, MKL_INT* a); #define N 5
#define NRHS 3
#define LDA N
#define LDB NRHS int main() { MKL_INT n = N, nrhs = NRHS, lda = LDA, ldb = LDB, info; MKL_INT ipiv[N];
float a[LDA * N] = {
6.80f, -6.05f, -0.45f, 8.32f, -9.67f,
-2.11f, -3.30f, 2.58f, 2.71f, -5.14f,
5.66f, 5.36f, -2.70f, 4.35f, -7.26f,
5.97f, -4.44f, 0.27f, -7.17f, 6.08f,
8.23f, 1.08f, 9.04f, 2.14f, -6.87f
};
float b[LDB * N] = {
4.02f, -1.56f, 9.81f,
6.19f, 4.00f, -4.09f,
-8.22f, -8.67f, -4.57f,
-7.57f, 1.75f, -8.61f,
-3.03f, 2.86f, 8.99f
}; printf("LAPACKE_sgesv (row-major, high-level) Example Program Results\n"); info = LAPACKE_sgesv(LAPACK_ROW_MAJOR, n, nrhs, a, lda, ipiv,
b, ldb); if (info > 0) {
printf("The diagonal element of the triangular factor of A,\n");
printf("U(%i,%i) is zero, so that A is singular;\n", info, info);
printf("the solution could not be computed.\n");
exit(1);
} print_matrix("Solution", n, nrhs, b, ldb); print_matrix("Details of LU factorization", n, n, a, lda); print_int_vector("Pivot indices", n, ipiv);
exit(0);
} void print_matrix(const char* desc, MKL_INT m, MKL_INT n, float* a, MKL_INT lda) {
MKL_INT i, j;
printf("\n %s\n", desc);
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) printf(" %6.2f", a[i * lda + j]);
printf("\n");
}
} void print_int_vector(const char* desc, MKL_INT n, MKL_INT* a) {
MKL_INT j;
printf("\n %s\n", desc);
for (j = 0; j < n; j++) printf(" %6i", a[j]);
printf("\n");
}

补充:矩阵求逆

简单来说,在使用以上API计算\(AX=B\),当\(B\)为单位矩阵时,\(X\)即为\(A^{-1}\)。

将上述案例中的

float b[LDB * N] = {
4.02f, -1.56f, 9.81f,
6.19f, 4.00f, -4.09f,
-8.22f, -8.67f, -4.57f,
-7.57f, 1.75f, -8.61f,
-3.03f, 2.86f, 8.99f
};
/**********改为**********/ #define NRHS 5
float b[LDB * N] = {
1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
};

即可求解矩阵\(A\)的逆矩阵,输出为:

对比在Matlab中使用inv()函数求逆:

A = [ 6.80, -6.05, -0.45,  8.32, -9.67;
-2.11, -3.30, 2.58, 2.71, -5.14;
5.66, 5.36, -2.70, 4.35, -7.26;
5.97, -4.44, 0.27, -7.17, 6.08;
8.23, 1.08, 9.04, 2.14, -6.87];
A_inv=inv(A)

结果相同。

MKL库线性方程组求解(LAPACKE_?gesv)的更多相关文章

  1. MKL库奇异值分解(LAPACKE_dgesvd)

    对任意一个\(m\times n\)的实矩阵,总可以按照SVD算法对其进行分解.即: \[A = U\Sigma V^T \] 其中\(U.V\)分别为\(m\times m.n\times n\)的 ...

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

    from:http://unifius.wordpress.com.cn/archives/5 系统:Gentoo Linux (64bit, Kernel 3.7.1)配置:Intel(R) Cor ...

  3. 如何在 code blocks中使用 mkl库

    为了安装caffe, 所以安装了mkl, 现在想在codeblock的项目中使用mkl. 设置mkl环境变量: mkl安装好后默认是在/opt/intel/mkl中,其中/opt/intel/mkl/ ...

  4. Matlab - 线性方程组求解

    常用函数:det 计算矩阵的行列式的值inv 求矩阵的逆阵rank 求矩阵的秩[V D]=eig(A) 求矩阵A的特征值和特征向量poly 求矩阵的特征多项式rref 用初等变换将矩阵化成行阶梯形nu ...

  5. poj 2891 模线性方程组求解

    Strange Way to Express Integers Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 8005   ...

  6. MKL库矩阵乘法

    此示例是利用Intel 的MKL库函数计算矩阵的乘法,目标为:\(C=\alpha*A*B+\beta*C\),由函数cblas_dgemm实现: 其中\(A\)为\(m\times k\)维矩阵,\ ...

  7. 【原创】开源Math.NET基础数学类库使用(06)直接求解线性方程组

                   本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新  开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...

  8. 开源Math.NET基础数学类库使用(06)数值分析之线性方程组直接求解

    原文:[原创]开源Math.NET基础数学类库使用(06)数值分析之线性方程组直接求解 开源Math.NET基础数学类库使用系列文章总目录:   1.开源.NET基础数学计算组件Math.NET(一) ...

  9. python 求解线性方程组

    Python线性方程组求解 求解线性方程组比较简单,只需要用到一个函数(scipy.linalg.solve)就可以了.比如我们要求以下方程的解,这是一个非齐次线性方程组: 3x_1 + x_2 - ...

  10. 科学计算库(BLAS,LAPACK,MKL,EIGEN)

    函数库接口标准:BLAS (Basic Linear Algebra Subprograms)和LAPACK (Linear Algebra PACKage) 1979年,Netlib首先用Fortr ...

随机推荐

  1. Visual Studio 自定义项目模版

    以 Visual Studio 2017 为例. 在 Visual Studio 中用户项目模版就是我们俗称的自定义项目模版. 用户项目模版位置 在Visual Studio中打开[工具-选项-项目和 ...

  2. 一文彻底搞懂 MCP:AI 大模型的标准化工具箱

    MCP 最近在 AI 领域 引发了 广泛关注,特别是在 海外各大社区 中,大家热烈讨论,热度 相当高. 我打开了 Google Trends,这是一个专门用于查看全球热点趋势的网站. 输入关键词后,可 ...

  3. python满足任意一个条件均认为假设有效(执行if内脚本)if any的用法

    下方代码,判断sta内是否包含s数组内的数字,只要包含任意一个输入ok,否则输出no s=['3','8','9'] sta='59' if s[0] in sta or s[1] in sta or ...

  4. 如何在Uniapp项目中引入uni_modules中的依赖?

    在Uniapp项目中引入uni_modules中的依赖分为以下几种情况: 对于通用组件: 如果你已经通过HBuilderX插件市场安装了某个uni_modules组件,通常只需在页面的.vue文件中按 ...

  5. 备份一个http/https请求,用的比较多的POST json数据

    var data = new object[] { new { sn = SN, mac = Mac } }; var jobj = await Task.Run(() => { try { u ...

  6. EFCore 高并发

    EFCore 高并发 有常见的并发场景?如果我们使用EFCore常用的解决方法会出现哪些问题?对应不同的并发场景我们应该选择哪些的处理方式? 参照:事务的四种隔离级别详解_事务隔离级别-CSDN博客 ...

  7. PhpStorm - 本地动态调试-下载配置xdebug扩展

    PhpStorm - 本地动态调试-下载配置xdebug扩展 00x01 查看phpinfo <?php phpinfo(); 00x02下载扩展前查看Architecture 如果Archit ...

  8. 【BUG】.NET项目|未能加载文件或程序集“xxx”,或它的某一个依赖项。系统找不到指定的文件的通解

    出错代码: MSBuildWorkspace workspace = CreateWorkspace(); Solution solution = workspace.OpenSolutionAsyn ...

  9. UnoCSS原子CSS引擎

    UnoCSS是一款原子化的即时按需 CSS 引擎,其中没有核心实用程序,所有功能都是通过预设提供的.默认情况下UnoCSS应用通过预设来实现相关功能. UnoCSS中文文档: https://www. ...

  10. 通过 Nuke 为 Dotnet Core 应用构建自动化流程

    为什么使用Nuke 最开始了解Nuke,是浏览github时,刷到了这个项目,看简介可以通过C# 来定义构建任务和流程,这一点很新颖,对我来讲,c# 显然更容易理解和维护. 再看给出的示例,确实比较清 ...