CBLAS的安裝與使用
ysm
cleverysm@gmail.com
CBLAS是BLAS的C語言介面。BLAS的全稱是Basic Linear Algebra Subprograms,中文大概可以叫做基礎線性代數子程式。主要是用於向量和矩陣計算的高效能數學庫。本身BLAS是用Fortran寫的,為了方便C/C++程式的使用,就有了BLAS的C介面庫CBLAS。BLAS的首頁是http://www.netlib.org/blas/,CBLAS的也可以在這個頁面上找到。
CBLAS安裝需要先裝BLAS,從首頁上下載blas.tgz,解壓,根據系統修改make.inc和Makefile,make,就會產生一個blas_LINUX.a檔案。然後,下載cblas.tgz,解壓,在目錄下將Makefile.*檔案改名或者做一個連結檔案為Makefile.in檔案,比如在linux下就是ln -s Makefile.LINUX Makefile.in,根據具體情況修改Makefile.in檔案,主要是BLAS的庫檔案路徑BLLIB和CBLAS的安裝目錄CBDIR,make help就可以列印出可以使用的make命令,要產生全部檔案就是用make all。在$(CBDIR)目錄下的$(CBLIBDIR)將產生CBLAS的庫檔案$(CBLIB),cblas_LINUX.a。
在CBLAS的安裝目錄$(CBDIR)下的src目錄中有個cblas.h是包括的CBLAS的函數和常量的標頭檔,使用CBLAS的時候就需要這個標頭檔,同時還需要BLAS的庫檔案$(BLLIB )和CBLAS的庫檔案$(CBLIB)。
CBLAS/BLAS分為3個level,level1是用於向量的計算,level2是用於向量和矩陣之間的計算,level3是矩陣之間的計算。比如計算矩陣的乘法就是屬於level3,這裡就用矩陣乘法來學習使用CBLAS。
計算矩陣乘法的函數之一是 cblas_sgemm,使用單精確度實數,另外還有對應雙精確度實數,單精確度複數和雙精確度複數的函數。在此以 cblas_sgemm為例。
函數定義為:
void cblas_sgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const float alpha, const float *A, const int lda, const float *B, const int ldb, const float beta, float *C, const int ldc)
關於此函數的詳細定義可以在http://www.netlib.org/blas/sgemm.f找到,只不過是fortran語言的,這個C語言版的略有差別。
此Function Compute的是 C = alpha*op( A )*op( B ) + beta*C,
const enum CBLAS_ORDER Order,這是指的資料的儲存形式,在CBLAS的函數中無論一維還是二維資料都是用一維數組儲存,這就要涉及是行主序還是列主序,在C語言中數組是用行主序,fortran中是列主序。我還是習慣於是用行主序,所以這個參數是用CblasRowMajor,如果是列主序的話就是CblasColMajor。
const enum CBLAS_TRANSPOSE TransA和const enum CBLAS_TRANSPOSE TransB,這兩個參數影響的是op( A )和op( B),選擇性參數為CblasNoTrans=111, CblasTrans=112, CblasConjTrans=113,其中TransA = CblasNoTrans, op( A ) = A,TransA = CblasTrans, op( A ) = A',TransA = CblasConjTrans, op( A ) = A'。 TransB類似。
const int M,矩陣A的行,矩陣C的行
const int N,矩陣B的列,矩陣C的列
const int K,矩陣A的列,矩陣B的行
const float alpha, const float beta,計算公式中的兩個參數值,如果只是計算C=A*B,則alpha=1,beta=0
const float *A, const float *B, const float *C,矩陣ABC的資料
const int lda, const int ldb, const int ldc,在BLAS的文檔裡,這三個參數分別為ABC的行數,但是實際使用發現,在CBLAS裡應該是列數。
我在這裡計算兩個簡單矩陣的乘法。
A:
1,2,3
4,5,6
7,8,9
8,7,6
B:
5,4
3,2
1,0
程式碼:
//因為程式是C++,而CBLAS是C語言寫的,所以在此處用extern關鍵字extern"C"{ #include<cblas.h> } #include<iostream>usingnamespace std;int main(void) { constenum CBLAS_ORDER Order=CblasRowMajor; constenum CBLAS_TRANSPOSE TransA=CblasNoTrans; constenum CBLAS_TRANSPOSE TransB=CblasNoTrans; constint M=4;//A的行數,C的行數 constint N=2;//B的列數,C的列數 constint K=3;//A的列數,B的行數 constfloat alpha=1; constfloat beta=0; constint lda=K;//A的列 constint ldb=N;//B的列 constint ldc=N;//C的列 constfloat A[K*M]={1,2,3,4,5,6,7,8,9,8,7,6}; constfloat 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;}
在編譯的時候需要帶上cblas_LINUX.a和blas_LINUX.a,比如,
g++ main.cpp cblas_LINUX.a blas_LINUX.a -o main
當然,這裡假定是這兩個.a檔案是放在可以直接存取的位置,或者寫全路徑也可以。
這種做法在CentOS.5下順利通過,但是在我的Ubuntu.7.10下出了問題,blas_LINUX.a正常編譯產生,但在連結的時候出了錯誤,所以只好從源裡安裝了atlas,sudo apt-get install atlas3-base,在/usr/lib/atlas/目錄下就會有libblas.*和liblapack.*庫檔案,只需要在連結的時候用這裡的blas庫檔案替換上文安裝的BLAS就可以正常編譯通過。
另外,在GSL下也有BLAS和CBLAS,在boost裡有ublas也提供CBLAS/BLAS的功能,有時間也拿來研究研究。