CBLAS的安装与使用

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 语言版的略有差别。
此函数计算的是  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>
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;
}
在编译的时候需要带上 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 的功能,有时间也拿来研究研究。

另附GNU上的一个例子:

The following program computes the product of two matrices using the Level-3 BLAS function SGEMM,

[ 0.11 0.12 0.13 ]  [ 1011 1012 ]     [ 367.76 368.12 ]
[ 0.21 0.22 0.23 ]  [ 1021 1022 ]  =  [ 674.06 674.72 ]
                              [ 1031 1032 ]
The matrices are stored in row major order but could be stored in column major order if the first argument of the call to cblas_sgemm was changed to CblasColMajor.

#include <stdio.h>
#include <gsl/gsl_cblas.h>

int
main (void)
{
  int lda = 3;

  float A[] = { 0.11, 0.12, 0.13,
                0.21, 0.22, 0.23 };

  int ldb = 2;
  
  float B[] = { 1011, 1012,
                1021, 1022,
                1031, 1032 };

  int ldc = 2;

  float C[] = { 0.00, 0.00,
                0.00, 0.00 };

  /* Compute C = A B */

  cblas_sgemm (CblasRowMajor, 
               CblasNoTrans, CblasNoTrans, 2, 2, 3,
               1.0, A, lda, B, ldb, 0.0, C, ldc);

  printf ("[ %g, %g\n", C[0], C[1]);
  printf ("  %g, %g ]\n", C[2], C[3]);

  return 0;  
}
To compile the program use the following command line,

$ gcc -Wall demo.c -lgslcblas
There is no need to link with the main library -lgsl in this case as the CBLAS library is an independent unit. Here is the output from the program,

$ ./a.out
[ 367.76, 368.12
  674.06, 674.72 ]


你可能感兴趣的:(CBLAS的安装与使用)