OpenBlas庫----cblas_dgemm()函數

    在Caffe的源碼中有不少地方使用OpenBlas庫進行矩陣運算,今天就簡單講一下我在使用cblas_dgemm()函數的使用時遇到的問題。html

    在網上查到的資料不少都是簡單的說了下cblas_dgemm()函數的參數和功能,具體怎麼用沒有給出相應的代碼,並且我對裏面的轉置也是很迷惑。先給你們幾個博客地址:ios

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

很棒的以一個例子,我根據這個搞定的:http://blog.sina.com.cn/s/blog_4a03c0100101ethf.htmlgithub

這個也不錯:http://blog.csdn.net/g_spider/article/details/6054990數組

    在看下面的內容以前,請先仔細閱讀函數參數。ide

    好了言歸正傳,講講幾個你們不太熟悉的參數。函數

    第一個參數是選擇行主序仍是列主序。那什麼是行主序?什麼又是列主序呢?以下所示spa

    數組A[1,2,3,4,5,6,7,8,9].net

    若是咱們想將A按照行主序(CblasRowMajor)展開成一個3*3的矩陣結果以下:code

    [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 <stdio.h>
#include<iostream>
extern "C"
{  
    #include <cblas.h>       // <strong>因爲cblas.h文件已經拷貝到工做目錄中,只需用雙引號 </strong>   
}  
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 };
	/*按列主序展開*/
	//一、都無轉置
	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");
 
	/*按行主序展開*/
	//一、都無轉置
	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");
 
	//二、矩陣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是怎樣展開成矩陣的。

一、按列主序展開,都無轉置

矩陣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也是按列主序展開,(這個地方有點問題,一直沒找到緣由,你們注意)

二、按列主序展開,矩陣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按行主序展開

三、按行主序展開,都無轉置

矩陣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按行主序展開

四、按行主序展開,矩陣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>       // <strong>因爲cblas.h文件已經拷貝到工做目錄中,只需用雙引號 </strong>   
}  
#include <cstdlib>  
#include <iostream>  
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<M;i++)  
    {  
       for(int j=0;j<N;j++)  
       {  
           cout<<C[i*N+j]<<"/t";  
       }  
       cout<<endl;  
    }  
     
    return EXIT_SUCCESS;  
}
相關文章
相關標籤/搜索