linux关于blas、lapack的安装和使用

近期在安装和使用blas和lapack时,查阅网上的教程觉得有些繁琐,自己梳理了一下做个记录。

blas提供了一些基本的矩阵和向量运算,lapack提供了更丰富的线性方程求解、二次规划、特征值分解等等的运算。cblas是blas的c接口,lapacke是lapack的c接口,因为要用c进行调用,一并安装。

1. blas、 cblas、lapack、lapacke的安装

我在Ubuntu、CentOS安装成功。

  • 首先没有gfortran编译器的话,需要安装,ubuntu下 sudo apt-get install gfortran。
  • 下载lapack:netlib.org/lapack/。因为lapack的安装包已经包含了blas、cblas、lapacke,所以只需要下载lapack的安装包即可。
  • 将下载的安装包解压,比如我解压后的文件位置为:~/lapack-3.10.1(后面举例均以这个路径为准,不同于这个路径需要自行替代)。
1. cd ~/lapack-3.10.1
2. cp make.inc.example make.inc
3. make blaslib
4. make cblaslib
5. make lapacklib
6. make lapackelib

编译完成。

1. 静态库路径: ~/lapack-3.10.1。

检查下~/lapack-3.10.1下是否有librefblas.a、libcblas.a、liblapack.a、liblapacke.a这几个文件,没有的话重新编译一次。

2. 头文件路径

cblas头文件路径: ~/lapack-3.10.1/CBLAS/include
lapacke头文件路径: ~/lapack-3.10.1/LAPACKE/include

2. 静态库和头文件

为了后续使用时不用每次都指定头文件和静态库的路径,有两种方式处理。

  • 方法1

可以把上述静态库copy到/usr/local/lib,把上述cblas和lapacke的头文件copy到/usr/local/include。

  • 方法2

当然由于我没有root权限,选择在自己用户下在~/.bashrc里添加了

## 这里xxx填自己的存放路径
export LIBRARY_PATH="$LIBRARY_PATH:/xxx/lapack-3.10.1"
export C_INCLUDE_PATH="$C_INCLUDE_PATH:/xxx/lapack-3.10.1/LAPACKE/include:/xxx/lapack-3.10.1/CBLAS/include"

保存后source ~/.bashrc

3. blas使用

  • 新建文件test.c
#include <stdio.h>
#include "cblas.h"

int main()
{
        const int dim=2;
        double a[4]={1.0,1.0,1.0,1.0},b[4]={2.0,2.0,2.0,2.0},c[4];
        int m=dim,n=dim,k=dim,lda=dim,ldb=dim,ldc=dim;
        double al=1.0,be=0.0;
        cblas_dgemm(101,111,111,m,n,k,al,a,lda,b,ldb,be,c,ldc);
        printf("the matrix c is:%f,%f\n%f,%f\n",c[0],c[1],c[2],c[3]);
        return 0;
}
  • 编译

编译时注意,更换静态库的链接顺序,可能会报错,我就是在这里折腾了一会。

gcc test.c -o test -lcblas -lrefblas -lm -lgfortran

编译时若出现错误,如果是头文件和静态库未找到,请参考第2部分。也可以在编译时加路径参数,缺哪个补哪个,如下

gcc test.c -o test -lcblas -lrefblas -lm -lgfortran -I/xxx/lapack-3.10.1/CBLAS/include -L/xxx/lapack-3.10.1 -L/usr/lib/gcc/x86_64-linux-gnu/7
# -I/xxx/lapack-3.10.1/CBLAS/include 用自己的CBLAS头文件路径替代
# -L/xxx/lapack-3.10.1 用自己的lapack静态库路径替代
# -L/usr/lib/gcc/x86_64-linux-gnu/7 用自己的gcc libgfortran.a 所在的路径替代
  • 运行 ./test,预期输出
the matrix c is:4.000000,4.000000
4.000000,4.000000

4. lapack使用

  • 新建文件test.c
/* Calling DGELS using row-major order */

#include <stdio.h>
#include <lapacke.h>

int main (int argc, const char * argv[])
{
   double a[5][3] = {1,1,1,2,3,4,3,5,2,4,2,5,5,4,3};
   double b[5][2] = {-10,-3,12,14,14,12,16,16,18,16};
   lapack_int info,m,n,lda,ldb,nrhs;
   int i,j;

   m = 5;
   n = 3;
   nrhs = 2;
   lda = 3;
   ldb = 2;

   info = LAPACKE_dgels(LAPACK_ROW_MAJOR,'N',m,n,nrhs,*a,lda,*b,ldb);

   for(i=0;i<n;i++)
   {
      for(j=0;j<nrhs;j++)
      {
         printf("%lf ",b[i][j]);
      }
      printf("\n");
   }
   return(info);
}
  • 编译

编译时注意,更换静态库的链接顺序,可能会报错

gcc test.c -o test -llapacke -llapack -lcblas  -lrefblas  -lm -lgfortran
  • 运行 ./test,预期输出
2.000000 1.000000
1.000000 1.000000
1.000000 2.000000

补充

因为我需要用python调用C生成的动态库(.so文件),而C写动态库时会调用lapack的函数,也就是编译动态库时需要链接lapack的静态库(.a文件)。

默认的lapack编译选项不支持上述操作,需要进行修改。打开~/lapack-3.10.1/make.inc文件,在下列几个设置加上-fPIC,然后重新make blaslib、cblaslib 、lapacklib 、lapackelib即可。

CFLAGS = -O3 -fPIC

FFLAGS = -O2 -frecursive -fPIC
FFLAGS_NOOPT = -O0 -frecursive -fPIC

报错

/usr/bin/ld: cannot find xxxx

这种是没有找到库文件,需要找到相应路径并添加到编译选项,百度一下 “编译-L“ 解决

编辑于 2022-12-05 10:23・IP 属地重庆