OpenBlas库----cblas_dgemm()函数

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

    在Caffe的源码中有很多地方使用OpenBlas库进行矩阵运算,今天就简单讲一下我在使用cblas_dgemm()函数的使用时遇到的问题。

    在网上查到的资料很多都是简单的说了下cblas_dgemm()函数的参数和功能,具体怎么用没有给出相应的代码,而且我对里面的转置也是很迷惑。先给大家几个博客地址:

官方例子:https://github.com/xianyi/OpenBLAS/wiki/User-Manual

很棒的以一个例子,我根据这个搞定的:http://blog.sina.com.cn/s/blog_4a03c0100101ethf.html

这个也不错:http://blog.csdn.net/g_spider/article/details/6054990

    在看下面的内容之前,请先仔细阅读函数参数。

    好了言归正传,讲讲几个大家不太熟悉的参数。

    第一个参数是选择行主序还是列主序。那什么是行主序?什么又是列主序呢?如下所示

    数组A[1,2,3,4,5,6,7,8,9]

    如果我们想将A按照行主序(CblasRowMajor)展开成一个3*3的矩阵结果如下:

    [1,2,3

     4,5,6

     7,8,9]

    如果我们想将A按照列主序(CblasRowMajor)展开成一个3*3的矩阵结果如下:

   [1,4,7

     2,5,8

     3,6,9]

    其实我们发现按照行主序就是按照行遍历矩阵得到数组A,按照列主序就是按照列遍历矩阵得到数组A。

    第二个参数:是不转置(CblasTrans  or  CblasNoTrans)

    开始对这个参数很迷惑,后来发现其实很简单,这个参数是和前面的参数(行或列主序)配合使用的。举例:如果你已经选择CblasRowMajor  如果CblasTrans被选择,那么对数组就按照列展开;如果选择CblasNoTrans被选择,那么对数组就按照行展开。简单的说就CblasRowMajor和CblasColMajor是个总开关,CblasTrans和CblasNoTrans是分开关。

好了,下面贴出代码再仔细讲讲。

//g++ -o demo1 demo1.cpp -I/usr/include/openblas -llapacke -llapack -lblas
#include 
#include
extern "C"
{  
    #include        // 由于cblas.h文件已经拷贝到工作目录中,只需用双引号    
}  
using namespace std; 

int main(){
	int i = 0;
	double A[6] = { 1.0, 2.0, 1.0, -3.0, 4.0, -1.0 };
	double B[6] = { 1.0, 2.0, 1.0, -3.0, 4.0, -1.0 };
	double C[9] = { .5, .5, .5, .5, .5, .5, .5, .5, .5 };
	double D[9] = { .5, .5, .5, .5, .5, .5, .5, .5, .5 };
	double E[9] = { .5, .5, .5, .5, .5, .5, .5, .5, .5 };
	double F[9] = { .5, .5, .5, .5, .5, .5, .5, .5, .5 };
	/*按列主序展开*/
	//1、都无转置
	cout << "按列主序展开,都无转置:" << endl;
	cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, 3, 3, 2, 1, A, 3, B, 2, 1, C, 3);
	for (i = 0; i<9; i++)
		printf("%lf ", C[i]);
	printf("\n");
 
	//2\矩阵B转置
	cout << "按列主序展开,矩阵B转置:" << endl;
	cblas_dgemm(CblasColMajor, CblasNoTrans, CblasTrans, 3, 3, 2, 1, A, 3, B, 3, 1, D, 3);
	for (i = 0; i<9; i++)
		printf("%lf ", D[i]);
	printf("\n");
 
	/*按行主序展开*/
	//1、都无转置
	cout << "按行主序展开,都无转置:" << endl;
	cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 3, 3, 2, 1, A, 2, B, 3, 1, E, 3);
	for (i = 0; i<9; i++)
		printf("%lf ",E[i]);
	printf("\n");
 
	//2、矩阵B转置
	cout << "按行主序展开,矩阵B转置:" << endl;
	cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans, 3, 3, 2, 1, A, 2, B, 2, 1, F, 3);
	for (i = 0; i<9; i++)
		printf("%lf ",F[i]);
	printf("\n");
}

结果:

$ ./demo1 
按列主序展开,都无转置:
-4.500000 10.500000 -0.500000 10.500000 -9.500000 4.500000 7.500000 4.500000 5.500000 
按列主序展开,矩阵B转置:
10.500000 -9.500000 4.500000 -9.500000 20.500000 -1.500000 4.500000 -1.500000 2.500000 
按行主序展开,都无转置:
-4.500000 10.500000 -0.500000 10.500000 -9.500000 4.500000 7.500000 4.500000 5.500000 
按行主序展开,矩阵B转置:
5.500000 -4.500000 2.500000 -4.500000 10.500000 7.500000 2.500000 7.500000 17.500000 

下面我们来分析一下各种模式下数组A和B是怎样展开成矩阵的。

1、按列主序展开,都无转置

矩阵A=[1.0,-3.0                   矩阵B=[1.0,1.0,4.0                        A*B=[-5.0,10.0,7.0

            2.0,4.0                                 2.0,-3.0,-1.0]                              10.0,-10.0,4.0

            1.0,-1.0]                                                                                  -1.0,4.0,5.0]

结果矩阵C也是按列主序展开,(这个地方有点问题,一直没找到原因,大家注意)

2、按列主序展开,矩阵B转置

矩阵A=[1.0,-3.0                   矩阵B=[1.0,2.0,1.0                      A*B=[10.0,-10.0,4.0

            2.0,4.0                                 -3.0,4.0,-1.0]                              -10.0,20.0,-2.0

            1.0,-1.0]                                                                                  4.0,-2.0,2.0]

结果矩阵D按行主序展开

3、按行主序展开,都无转置

矩阵A=[1.0,2.0                  矩阵B=[1.0,2.0,1.0                        A*B=[-5.0,10.0,-1.0

            1.0,-3.0                              -3.0,4.0,-1.0]                              10.0,-10.0,4.0

             4.0,-1.0]                                                                                7.0,4.0,5.0]

结果矩阵E按行主序展开

4、按行主序展开,矩阵B转置

矩阵A=[1.0,2.0                  矩阵B=[1.0,1.0,4.0                         A*B=[5.0,-5.0,2.0

            1.0,-3.0                              2.0,-3.0,-1.0]                               -5.0,10.0,7.0

             4.0,-1.0]                                                                                 2.0,7.0,17.0]

结果矩阵F按行主序展开

注意:如果CblasColMajor 则lda,ldb,ldc是A,B,C的行

如果CblasRowMajor则lda,ldb,ldc是A,B,C的列



//  g++ -o mycblas mycblas.cpp -I/usr/include/openblas -llapacke -llapack -lblas
extern "C"  
{  
    #include        // 由于cblas.h文件已经拷贝到工作目录中,只需用双引号    
}  
#include   
#include   
using namespace std;  
int main(void) {  
    const enum CBLAS_ORDER Order=CblasRowMajor;  
    const enum CBLAS_TRANSPOSE TransA=CblasNoTrans;  
    const enum CBLAS_TRANSPOSE TransB=CblasNoTrans;  
    const int M=4;//A的行数,C的行数  
    const int N=2;//B的列数,C的列数  
    const int K=3;//A的列数,B的行数  
    const float alpha=1;  
    const float beta=0;  
    const int lda=K;//A的列  
    const int ldb=N;//B的列  
    const int ldc=N;//C的列  
    const float A[K*M]={1,2,3,4,5,6,7,8,9,8,7,6};  
    const float B[K*N]={5,4,3,2,1,0};  
    float C[M*N];  
     
    cblas_sgemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc);  
       
    for(int i=0;i

--------------------- 
作者:Sunshine_in_Moon 
来源:CSDN 
原文:https://blog.csdn.net/Sunshine_in_Moon/article/details/51728246 
版权声明:本文为博主原创文章,转载请附上博文链接!

转载于:https://my.oschina.net/u/2245781/blog/3020052

你可能感兴趣的:(OpenBlas库----cblas_dgemm()函数)