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文档

你可能感兴趣的:(C/C++,Deep,Learing)