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的矩阵
lda: 原矩阵a主行元素数量
transa=CblasNoTrans transa=CblasTrans
Layout=CblasColMajor max(1,m) max(1,k)
Layout=CblasRowMajor max(1,k) max(1,m)
b:
transa=CblasNoTrans transa=CblasTrans
Layout=CblasColMajor ldb*n的矩阵 ldb*k的矩阵
Layout=CblasRowMajor ldb*k的矩阵 ldb*n的矩阵
ldb: 原矩阵b主行元素数量
transa=CblasNoTrans transa=CblasTrans
Layout=CblasColMajor max(1,k) max(1,n)
Layout=CblasRowMajor max(1,n) max(1,k)
beta: 标量
C:
Layout=CblasColMajor ldc*n的矩阵
Layout=CblasRowMajor ldc*m的矩阵
ldc:
Layout=CblasColMajor max(1,m)
Layout=CblasRowMajor max(1,n)
输出参数: c 调用方法: 行主序:
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文档

    推荐阅读