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:https://www.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 属地重庆