C/C++|mkl行主序、列主序转换——以cblas_sgemm为例
本文 以mkl中的cblas_sgemm为例演示行主序、列主序调用方式以及相互调用。 cblas_sgemm接口:
void cblas_sgemm (const CBLAS_LAYOUT Layout, const CBLAS_TRANSPOSE transa, const
CBLAS_TRANSPOSE transb, const MKL_INT m, const MKL_INT n, const MKL_INT k, const float
alpha, const float *a, const MKL_INT lda, const float *b, const MKL_INT ldb, const
float beta, float *c, const MKL_INT ldc);
功能描述: C = alpha*op(A)op(B) + betaC 其中: op(X)=X或者op(X)=X’; alpha、beta均为标量; A、B、C均为矩阵; op(A)是形状为m x k的矩阵; op(B)是形状为k x n的矩阵; C是形状为m x n的矩阵; 输入参数: layout: 行主序(CblasRowMajor)
列主序(CblasColMajor)
transa: 矩阵A非转置(CblasNoTrans),即op(A)=A
矩阵A转置(CblasTrans),即op(A)=A’
transb: 矩阵B非转置(CblasNoTrans),即op(B)=B
矩阵B转置(CblasTrans),即op(B)=B’
m: 矩阵op(A)与矩阵C的行数
n: 矩阵op(B)与矩阵C的列数
k: 矩阵op(A)的列数与矩阵op(B)的行数
alpha: 标量
a:
transa=CblasNoTrans | transa=CblasTrans | |
---|---|---|
Layout=CblasColMajor | lda*k的矩阵 | lda*m的矩阵 |
Layout=CblasRowMajor | lda*m的矩阵 | lda*k的矩阵 |
transa=CblasNoTrans | transa=CblasTrans | |
---|---|---|
Layout=CblasColMajor | max(1,m) | max(1,k) |
Layout=CblasRowMajor | max(1,k) | max(1,m) |
transa=CblasNoTrans | transa=CblasTrans | |
---|---|---|
Layout=CblasColMajor | ldb*n的矩阵 | ldb*k的矩阵 |
Layout=CblasRowMajor | ldb*k的矩阵 | ldb*n的矩阵 |
transa=CblasNoTrans | transa=CblasTrans | |
---|---|---|
Layout=CblasColMajor | max(1,k) | max(1,n) |
Layout=CblasRowMajor | max(1,n) | max(1,k) |
C:
Layout=CblasColMajor | ldc*n的矩阵 |
---|---|
Layout=CblasRowMajor | ldc*m的矩阵 |
Layout=CblasColMajor | max(1,m) |
---|---|
Layout=CblasRowMajor | max(1,n) |
void ABC_row(const CBLAS_TRANSPOSE transa,const CBLAS_TRANSPOSE transb,
const int m, const int n, const int k,
const float alpha, const float* a,
const float* b,
const float beta, float* c)
{
/*一般都是行主序调用*/
cblas_sgemm(CblasRowMajor, transa, transb,
m, n, k,
alpha, a,
/*op(a)为mxk,且为行主序:
如果矩阵a不用转置,则:op(a)=a,lda为k(原矩阵a(mxk)的每行有k个元素)
如果矩阵a需要转置,则:op(a)=a',lda为m(原矩阵a(kxm)的每行有m个元素)
*/
(CblasNoTrans == transa)?k:m,
b,
/*op(b)为kxn,且为行主序:
如果矩阵b不用转置,则:op(b)=b,ldb为n(原矩阵b(kxn)的每行有n个元素)
如果矩阵b需要转置,则:op(b)=b',ldb为k(原矩阵b(nxk)的每行有k个元素)
*/
(CblasNoTrans == transb)?n:k,
beta, c,
n);
//矩阵c为mxn,且为行主序
}
列主序:
void ABC_col(const CBLAS_TRANSPOSE transa,const CBLAS_TRANSPOSE transb,
const int m, const int n, const int k,
const float alpha, const float* a,
const float* b,
const float beta, float* c)
{
cblas_sgemm(CblasColMajor, transa, transb,
m, n, k,
alpha, a,
/*op(a)为mxk,且为列主序:
如果矩阵a不用转置,则:op(a)=a,lda为m(原矩阵a(mxk)的每列有m个元素)
如果矩阵a需要转置,则:op(a)=a',lda为k(原矩阵a(kxm)的每列有k个元素)
*/
(CblasNoTrans == transa)?m:k,
b,
/*op(b)为kxn,且为列主序:
如果矩阵b不用转置,则:op(b)=b,ldb为k(原矩阵b(kxn)的每列有k个元素)
如果矩阵b需要转置,则:op(b)=b',ldb为n(原矩阵b(nxk)的每列有n个元素)
*/
(CblasNoTrans == transb)?k:n,
beta, c,
m);
//矩阵c为mxn,且为列主序
}
行主序调用列主序: 可以采用该方式统一MKL或openblas与cublas的接口一致性,因为cublas采用的是列主序。
void ABC_row(const CBLAS_TRANSPOSE transa,const CBLAS_TRANSPOSE transb,
const int m, const int n, const int k,
const float alpha, const float* a,
const float* b,
const float beta, float* c)
{
/* C = alpha * A * B + beta * C --> C' = alpha * B' * A' + beta * C' */
ABC_col(transb, transa,
n, m, k,
alpha, b, a,
beta, c);
}
列主序调用行主序: (一般不会这样使用)
void ABC_col(const CBLAS_TRANSPOSE transa,const CBLAS_TRANSPOSE transb,
const int m, const int n, const int k,
const float alpha, const float* a,
const float* b,
const float beta, float* c)
{
/* C = alpha * A * B + beta * C --> C' = alpha * B' * A' + beta * C' */
ABC_row(transb, transa,
n, m, k,
alpha, b, a,
beta, c);
}
相关文献 1、OpenBlas官网 2、MKL文档
推荐阅读
- opencv|opencv C++模板匹配的简单实现
- C语言学习|第十一届蓝桥杯省赛 大学B组 C/C++ 第一场
- c++基础概念笔记
- 牛逼!C++开发的穿越丛林真人游戏,游戏未上线就有百万人气
- C++Primer之|C++Primer之 函数探幽
- c/c++|有感 Visual Studio 2015 RTM 简介 - 八年后回归 Dot Net,终于迎来了 Mvc 时代,盼走了 Web 窗体时代...
- QML基础信息
- C++-类型转换
- MongoDB|MongoDB - 简介
- C++面试题目总结