MKL普通矩阵运算示例及函数封装
本示例将介绍MKL中的矩阵乘法和求逆,使用MKL进行此类大型矩阵运算可大量节省计算时间和空间,但由于MKL中的原生API接口繁杂,因此将常用函数封装,便于后续使用,最后在实际例子中调用接口执行想要的矩阵运算。
1 MKL矩阵乘法案例
所用示例如下,矩阵A、B分别为
\[A = {\left[ {\begin{array}{*{20}{c}}{\begin{array}{*{20}{c}}1&{ - 1}\end{array}}&{ - 3}&0&0\\{\begin{array}{*{20}{c}}{ - 2}&5\end{array}}&0&0&0\\{\begin{array}{*{20}{c}}0&0\end{array}}&4&6&4\\{\begin{array}{*{20}{c}}{\begin{array}{*{20}{l}}{ - 4}\\0\\1\end{array}}&{\begin{array}{*{20}{l}}0\\8\\0\end{array}}\end{array}}&{\begin{array}{*{20}{l}}2\\0\\0\end{array}}&{\begin{array}{*{20}{l}}7\\0\\0\end{array}}&{\begin{array}{*{20}{l}}0\\{ - 5}\\0\end{array}}\end{array}} \right]_{6 \times 5}}{\begin{array}{*{20}{c}}{}&{B = \left[ {\begin{array}{*{20}{c}}{\begin{array}{*{20}{c}}1\\{ - 2}\end{array}}&{\begin{array}{*{20}{c}}{ - 1}\\5\end{array}}&{\begin{array}{*{20}{c}}{ - 3}\\0\end{array}}&{\begin{array}{*{20}{c}}0\\0\end{array}}\\0&0&4&6\\{ - 4}&0&2&7\\0&8&0&0\end{array}} \right]}\end{array}_{5 \times 4}}\](1)matlab计算结果
作为标准答案,验证后续调用的正确性。
【资料图】
A=[1,-1,-3,0,0; -2,5,0,0,0; 0,0,4,6,4; -4,0,2,7,0; 0,8,0,0,-5; 1,0,0,0,0];B=[1,-1,-3,0; -2,5,0,0; 0,0,4,6; -4,0,2,7; 0,8,0,0];A*B
输出为:
### (2)MKL矩阵乘法矩阵乘法接口
/*输入:MatrixA 矩阵A数据,类型为float型的二维数组rowA 矩阵A的行数colA 矩阵A的列数MatrixB 矩阵B数据,类型为float型的二维数组colC 矩阵C的列数输出:MatrixC 矩阵A*B数据,类型为float型的二维数组,为矩阵乘法计算结果*/bool MKL_MatrixMul(float **MatrixA, int rowA, int colA, float **MatrixB, int colC, float **MatrixC) ;
函数代码
函数将使用MKL库中的矩阵乘法接口cblas_?gemm
实现,具体用法及参数详解见MKL库矩阵乘法(cblas_?gemm) - GeoFXR - 博客园 (cnblogs.com)
#include "MKL_Matrix_Methods.h"//矩阵乘法bool MKL_MatrixMul(float **MatrixA, int rowsA, int colsA, float **MatrixB, int colsC, float **MatrixC) {if (MatrixA == NULL) {return false;}if (MatrixB == NULL) {return false;}if (MatrixC == NULL) {return false;}int M = rowsA; int N = colsA;int K = colsC;float *A = NULL;float *B = NULL;float *C = NULL;int lda = N;int ldb = K;int ldc = K;//由于mkl的矩阵乘法函数仅支持一维数组,需对输入进行转换A = (float*)mkl_malloc(M*N * sizeof(float), 64);B = (float*)mkl_malloc(N*K * sizeof(float), 64);C = (float*)mkl_malloc(M*K * sizeof(float), 64);if (A == NULL || B == NULL || C == NULL) {mkl_free(A);mkl_free(B);mkl_free(C);return false;}//赋值int i = 0;int j = 0;for (i = 0; i < M; i++) {memcpy(A + i * N, MatrixA[i], N * sizeof(float));}for (i = 0; i < N; i++) {memcpy(B + i * K, MatrixB[i], K * sizeof(float));}cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, M, K, N, 1, A, lda, B, ldb,0, C, ldc);for (i = 0; i < M; i++) {memcpy(MatrixC[i], C + i * K, K * sizeof(float));}mkl_free(A);mkl_free(B);mkl_free(C);return true;}
main函数
#include "MKL_Matrix_Methods.h"#include "alloc.h"#define M 6#define N 5#define K 4// 矩阵乘法int main(){int rowsA = M, colsA = N;int rowsB = N, colsB = K;int rowsC = M, colsC = K;float Atemp[M][N] = {{1,-1,-3,0,0},{-2,5,0,0,0},{0,0,4,6,4},{-4,0,2,7,0},{0,8,0,0,-5},{1,0,0,0,0},};float Btemp[N][K] = {{1,-1,-3,0},{-2,5,0,0},{0,0,4,6},{-4,0,2,7},{0,8,0,0}};//将一般二维数组转换为alloc表示float **matrixA = alloc2float(colsA, rowsA);memset(matrixA[0], 0, rowsA*colsA * sizeof(float));memcpy(matrixA[0], Atemp, rowsA*colsA * sizeof(float));float **matrixB = alloc2float(colsB, rowsB);memset(matrixB[0], 0, rowsB*colsB * sizeof(float));memcpy(matrixB[0], Btemp, rowsB*colsB * sizeof(float));float **matrixC = alloc2float(colsC, rowsC);memset(matrixC[0], 0, rowsC*colsC * sizeof(float));MKL_MatrixMul(matrixA, rowsA, colsA, matrixB, colsC, matrixC);//调用MKL矩阵乘法接口/* 输出结果 */ printf("*************** MKL Matrix Multiply ***************\n ");for (int i = 0; i < rowsC; i++) {for (int j = 0; j < colsC; j++) {printf("%f ", matrixC[i][j]);}printf("\n");}free(matrixA);free(matrixB);free(matrixC);}
结果与matlab一致。2 MKL矩阵求逆案例
(1)matlab计算结果
作为标准答案,验证后续调用的正确性。
A = [1 2 4 0 0; 2 2 0 0 0; 4 0 3 0 0; 0 0 0 4 0; 0 0 0 0 5];A_inv = inv(A)
输出为:
(2)MKL求逆
矩阵求逆接口
/*函数功能:基于MKL库的矩阵求逆输入:Matrix 输入矩阵Matrix,n行n列n 矩阵的行、列数输出:Matrix Matrix 的逆,n行n列*/bool MKL_MatrixInverse(float**Matrix, int n)
函数代码
使用MKL中的LAPACK库计算线性方程组\(AX=B\)的解,当\(B\)为单位阵时,\(X\)即为\(A\)的逆矩阵\(A^{-1}\)。函数使用的接口为LAPACKE_sgesv,具体参数详解见MKL库线性方程组求解(LAPACKE_?gesv) - GeoFXR - 博客园 (cnblogs.com)
bool MKL_MatrixInverse(float**Matrix, int n) {MKL_INT nrhs = n, lda = n, ldb = n;// 创建置换矩阵,长度为n的数组 int *ipiv = (int*)mkl_malloc(n * sizeof(int), 64);if (ipiv == NULL) {return false;}// 创建MKL矩阵 float *matA = (float *)mkl_malloc(n * n * sizeof(float), 64);if (matA == NULL) {return false;}//将二维数组转换为一维MKL数组for (int i = 0; i < n; i++) {memcpy(matA + i * n, Matrix[i], n * sizeof(float));}// 创建一个单位阵Bfloat *matEye = (float *)mkl_malloc(n * n * sizeof(float), 64);if (matEye == NULL) {return false;}for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {matEye[i * n + j] = (i == j) ? 1.0 : 0.0;}}// 调用求解AX=B函数LAPACKE_sgesv(LAPACK_ROW_MAJOR, n, nrhs, matA, lda, ipiv, matEye, ldb);// 将MKL矩阵转换回普通二维数组 for (int i = 0; i < n; i++) {memcpy(Matrix[i], matEye + i * n, n * sizeof(float));}// 释放内存 mkl_free(matA);mkl_free(ipiv);mkl_free(matEye);return true;}
main函数
#include "MKL_Matrix_Methods.h"#include "alloc.h"#define N 5// 矩阵乘法int main(){int rowsA = N, colsA = N;float Atemp[N][N] = {{1,2,4,0,0},{2,2,0,0,0},{4,0,3,0,0},{0,0,0,4,0},{0,0,0,0,5}};//将一般二维数组转换为alloc表示float **matrixA = alloc2float(colsA, rowsA);memset(matrixA[0], 0, rowsA*colsA * sizeof(float));//复制二维数组到二级指针memcpy(matrixA[0], Atemp, rowsA*colsA * sizeof(float));//求逆MKL_MatrixInverse(matrixA, rowsA);/* 输出结果 */ printf("*************** MKL Matrix Inverse ***************\n ");for (int i = 0; i < rowsA; i++) {for (int j = 0; j < colsA; j++) {printf("%f ", matrixA[j][i]);}printf("\n");}free(matrixA);}
结果与matlab一致。
完整代码
Ⅰ MKL_Matrix_Methods.h
#pragma once#include#include#include#include"mkl.h"#include "mkl_types.h"#include"mkl_lapacke.h"bool MKL_MatrixMul(float **MatrixA, int rowA, int colA, float **MatrixB, int colC, float **MatrixC);bool MKL_MatrixInverse(float**Matrix, int n);
Ⅱ MKL_Matrix_Methods.cpp
#include "MKL_Matrix_Methods.h"//矩阵乘法bool MKL_MatrixMul(float **MatrixA, int rowsA, int colsA, float **MatrixB, int colsC, float **MatrixC) {if (MatrixA == NULL) {return false;}if (MatrixB == NULL) {return false;}if (MatrixC == NULL) {return false;}int M = rowsA; int N = colsA;int K = colsC;float *A = NULL;float *B = NULL;float *C = NULL;int lda = N;int ldb = K;int ldc = K;//由于mkl的矩阵乘法函数仅支持一维数组,需对输入进行转换A = (float*)mkl_malloc(M*N * sizeof(float), 64);B = (float*)mkl_malloc(N*K * sizeof(float), 64);C = (float*)mkl_malloc(M*K * sizeof(float), 64);if (A == NULL || B == NULL || C == NULL) {mkl_free(A);mkl_free(B);mkl_free(C);return false;}//赋值int i = 0;int j = 0;for (i = 0; i < M; i++) {memcpy(A + i * N, MatrixA[i], N * sizeof(float));}for (i = 0; i < N; i++) {memcpy(B + i * K, MatrixB[i], K * sizeof(float));}cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, M, K, N, 1, A, lda, B, ldb,0, C, ldc);for (i = 0; i < M; i++) {memcpy(MatrixC[i], C + i * K, K * sizeof(float));}mkl_free(A);mkl_free(B);mkl_free(C);return true;}//矩阵求逆bool MKL_MatrixInverse(float**Matrix, int n) {MKL_INT nrhs = n, lda = n, ldb = n;// 创建置换矩阵,长度为n的数组 int *ipiv = (int*)mkl_malloc(n * sizeof(int), 64);if (ipiv == NULL) {return false;}// 创建MKL矩阵 float *matA = (float *)mkl_malloc(n * n * sizeof(float), 64);if (matA == NULL) {return false;}//将二维数组转换为一维MKL数组for (int i = 0; i < n; i++) {memcpy(matA + i * n, Matrix[i], n * sizeof(float));}// 创建一个单位阵Bfloat *matEye = (float *)mkl_malloc(n * n * sizeof(float), 64);if (matEye == NULL) {return false;}for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {matEye[i * n + j] = (i == j) ? 1.0 : 0.0;}}// 调用求解AX=B函数LAPACKE_sgesv(LAPACK_ROW_MAJOR, n, nrhs, matA, lda, ipiv, matEye, ldb);// 将MKL矩阵转换回普通二维数组 for (int i = 0; i < n; i++) {memcpy(Matrix[i], matEye + i * n, n * sizeof(float));}// 释放内存 mkl_free(matA);mkl_free(ipiv);mkl_free(matEye);return true;}
Ⅲ main.cpp
#include "MKL_Matrix_Methods.h"#include "alloc.h"#define M 6#define N 5#define K 4void MKL_MatrixMul_Demo();void MKL_MatrixInverse_Demo();int main(){MKL_MatrixMul_Demo();//矩阵乘法示例MKL_MatrixInverse_Demo();//矩阵求逆示例}//矩阵乘法void MKL_MatrixMul_Demo() {int rowsA = M, colsA = N;int rowsB = N, colsB = K;int rowsC = M, colsC = K;float Atemp[M][N] = {{1,-1,-3,0,0},{-2,5,0,0,0},{0,0,4,6,4},{-4,0,2,7,0},{0,8,0,0,-5},{1,0,0,0,0},};float Btemp[N][K] = {{1,-1,-3,0},{-2,5,0,0},{0,0,4,6},{-4,0,2,7},{0,8,0,0}};//将一般二维数组转换为alloc表示float **matrixA = alloc2float(colsA, rowsA);memset(matrixA[0], 0, rowsA*colsA * sizeof(float));memcpy(matrixA[0], Atemp, rowsA*colsA * sizeof(float));float **matrixB = alloc2float(colsB, rowsB);memset(matrixB[0], 0, rowsB*colsB * sizeof(float));memcpy(matrixB[0], Btemp, rowsB*colsB * sizeof(float));float **matrixC = alloc2float(colsC, rowsC);memset(matrixC[0], 0, rowsC*colsC * sizeof(float));MKL_MatrixMul(matrixA, rowsA, colsA, matrixB, colsC, matrixC);//调用MKL矩阵乘法接口/* 输出结果 */ printf("*************** MKL Matrix Multiply ***************\n ");for (int i = 0; i < rowsC; i++) {for (int j = 0; j < colsC; j++) {printf("%f ", matrixC[i][j]);}printf("\n");}free(matrixA);free(matrixB);free(matrixC);}// 矩阵求逆void MKL_MatrixInverse_Demo() {int rowsA = N, colsA = N;float Atemp[N][N] = {{1,2,4,0,0},{2,2,0,0,0},{4,0,3,0,0},{0,0,0,4,0},{0,0,0,0,5}};//将一般二维数组转换为alloc表示float **matrixA = alloc2float(colsA, rowsA);memset(matrixA[0], 0, rowsA*colsA * sizeof(float));//复制二维数组到二级指针memcpy(matrixA[0], Atemp, rowsA*colsA * sizeof(float));//求逆MKL_MatrixInverse(matrixA, rowsA);/* 输出结果 */ printf("*************** MKL Matrix Inverse ***************\n ");for (int i = 0; i < rowsA; i++) {for (int j = 0; j < colsA; j++) {printf("%f ", matrixA[j][i]);}printf("\n");}free(matrixA);}
-
MKL普通矩阵运算示例及函数封装本示例将介绍MKL中的矩阵乘法和求逆,使用MKL进行此类大型矩阵运算可大量节省计算时间和空间,但由于MKL中
-
最新快讯!花池初级中学1、宣汉县花池初级中学于1993年3月与小学分设挂牌诞生,教职工编制29人,现有17人(另聘代课教师6人),其
-
当前讯息:农发行韶关市分行:反洗钱专项治理在行动为有效落实监管要求,切实防范洗钱风险,日前,农发行韶关市分行组织开展反洗钱专项治理行动,逐项对照检视
-
湖北省普通高校新一轮本科教育教学审核评估全面启动湖北省普通高校新一轮本科教育教学审核评估全面启动---“我们对高等教育的需要比以往任何时候都更加迫切,
-
插上科学的翅膀飞600字作文六年级 作文在双休日里400字 焦点热门今天来聊聊关于插上科学的翅膀飞600字作文六年级,作文在双休日里400字的文章,现在就为大家来简单介绍下插
-
【速看料】康鹏飞1、康鹏飞,毕业于昆明理工大学,2008年被全国学联、共青团中央联合评选为“中国大学生自强之星”。2、2018
-
最新资讯:法尔克:拜仁随时可能有大事发生;首先面临危机的就是卡恩德甲第29轮,拜仁1-3不敌美因茨,在积分榜上被多特蒙德反超1分。《图片报》主编法尔克在某节目中表示,拜仁
-
全球今热点:小学生一年级肺活量正常范围是多少_一年级学生肺活量标准1、男生--7岁1342ml,8岁1496ml,9岁1972ml,10岁1843ml女生--7岁1213ml,8岁135
-
【环球时快讯】杭州临平区全域放宽限购:外地户籍只需1个月社保即可购房去年11月,临平发布的《临平区关于稳经济促消费补强政策若干意见》显示,支持刚性和改善性住房需求,已落户
-
全球快看:中央保密办(国家保密局)组织开展“人人话保密”主题讲述活动为提高新时代新征程保密工作的责任意识和本领能力,筑牢维护党和国家秘密安全的坚固防线,中央保密办(国家
-
每日热议!今日竖劈叉的正确姿势图片_竖劈叉1、我头晕。2、如果按照美女的方法练,肯定你最轻的是韧带损伤,走路不方便一个多月!一、压腿需要压腿每天
-
世界新消息丨久祺股份:本次提供担保后,公司及公司控股子公司提供担保总额为人民币5.13亿元久祺股份:本次提供担保后,公司及公司控股子公司提供担保总额为人民币5 13亿元
-
公积金的钱可以全部取出来吗 公积金全部提取出来有什么影响?|环球播资讯公积金可以全部取出来吗公积金全部提取出来有什么影响?社保网小编为您整理了最新资讯。日常生活中,职工满
-
特色班列助推旅游业复苏_环球播资讯“去延边打卡啦!”4月15日,G8035次“民俗游”高铁列车上,来自东北大学的一支四人青旅小团队对为期两日的
-
潢川县自来水公司:加强供水管线管理 优化营商环境 世界快播报河南广电·大象新闻记者龚雪通讯员刘功近年来,潢川县自来水公司从为群众服务的根本目的出发,从工作实际出
-
林洋能源:拟约100亿元投建南通20GW高效N型TOPCon光伏电池生产基地及新能源相关产业项目 全球热点林洋能源12月2日公告,公司拟与南通市经济技术开发区管理委员会签订投资协议,投资建设20GW高效N型TOPCon光
-
全球新资讯:张艺谋《满江红》网播定档4月28日:上线腾讯视频/优酷/爱奇艺IT之家4月23日消息,张艺谋导演电影《满江红》今日宣布网播定档4月28日,届时将上线腾讯视频、优酷、爱
-
深圳维明生中医馆郭德尚:胃癌的中医辩证分型中医典籍中无胃癌之病名,按临床表现分析,胃癌属于祖国医学“噎膈”、“反胃”、“胃反”、“翻胃”、“胃
-
焦点关注:中泰证券:给予濮阳惠成买入评级中泰证券股份有限公司孙颖,王鹏近期对濮阳惠成进行研究并发布了研究报告《业绩同比高增,成长动能持续》,
-
“10年内将间谍卫星数量增加4倍” 美军方在太空又有新动作 全球新动态据俄罗斯卫星社、美国《网络中心战杂志》网站4月20日报道,美国国家侦察局(NRO)计划在未来10年内将在轨太
-
缝合线行业市场竞争 2023年中国缝合线行业市场投资价值评估缝合线产业主要集中在京津冀地区、长三角地区、珠三角地区以及华中地区。北京作为中国经济政治中心集聚了大
-
格陆博科技完成C轮融资_当前资讯《科创板日报》23日讯,近日,格陆博科技完成C轮融资,融资总额近4亿,中金资本、深投控资本、清研资本、国信弘盛、励时创盈
-
海口椰城男科医院收费高么?设备齐全,环境优美海口椰城男科医院,为医健服务中心在海南省的定点补贴单位,原价三百多的男性功能全套检查,补贴后19元(共10个检查项目),补贴名额每日限10人
-
ChatGPT 标注指南来了!数据是关键|天天观天下Datawhale干货作者:太子长琴,算法工程师,Datawhale成员前言ChatGPT刚刚出来时,业内人士一致认为高质量的数据是一个非常关键的因素。且不论
-
永丰税务:春和景明“三月三”税收宣传正当时最美人间四月天,携手共赴“春之约”。连日来,永丰县税务局紧扣“税惠千万家共建现代化”主题,结合本地税收工作实际,组织开
-
四部门印发通知要求做好今年国家助学贷款免息及本金延期偿还工作 天天速读本报北京4月20日电(记者王观)财政部等四部门近日印发通知,要求做好2023年国家助学贷款免息及本金延期偿还工作,进一步减轻家庭经济困难高校
-
当前信息:杨睿:扎根戒毒事业一线16年 用温情点燃生命之灯“有困难找杨队,她一定有办法。”这是云南省女子强制隔离戒毒所一大队警察常说的一句话。上面提到的“杨队”是现任一大队党支部
-
yotaphone 官网(yotaphone 2)1、YotaPhone2的手机系统是什么?2、YotaPhone2的手机系统是Android4 4系统。3、系统
-
铁路部门将加大“五一”假期运力投放-速看记者22日从中国国家铁路集团有限公司获悉,针对“五一”小长假运输期间火车票预售情况,铁路部门采取多种措施,进一步加大运力
-
同大股份董秘回复:截止4月20日股东户数为6088户_热讯同大股份(300321)04月23日在投资者关系平台上答复了投资者关心的问题。