zoukankan      html  css  js  c++  java
  • CentOS7系统上的LAPACK源码安装

    参考链接:linux下安装blas和lapack

    BLAS 和 LAPACK 这两个数学库是很多 Linux 科学计算软件需要调用的,所以经常会用到。

    LAPACK,其名为Linear Algebra PACKage的缩写,是一以Fortran编程语言编写,用于数值计算的函式集。LAPACK提供了丰富的工具函式,可用于诸如解多元线性方程式、线性系统方程组的最小平方解、计算特征向量、用于计算矩阵QR分解的Householder转换、以及奇异值分解等问题。

    LAPACK的源码可以从http://www.netlib.org/lapack/处下载,BLAS也包含在其中。

    BLAS,全称Basic Linear AlgebraSubprograms,即基础线性代数子程序库,里面拥有大量已经编写好的关于线性代数运算的程序。

    BLAS的源码可以从 http://www.netlib.org/blas/ 下载,但实际上LAPACK中已经包含了BLAS。

    0. 写在前面的:

    之前采用gfortran来编译生成了lapack的库文件,但是在后续采用pgf90命令(pgf90 -llapack)来编译其它文件时,产生了以下的类似错误:

    [She@she-centos7 TEC_She]$ make
    pgf90  -g -fast -c  m_bern.f90
    pgf90  -g -fast -c  d_inpkey.f90
    pgf90  -g -fast -c  p_menaux.f90
    ...
    pgf90  -g -fast -o main_igsTec  -L/usr/local/lib m_bern.o d_inpkey.o ... -llapack -lblas
    /usr/local/lib/liblapack.a(dormlq.o):在函数‘dormlq_’中:
    dormlq.f:(.text+0x32b):对‘_gfortran_concat_string’未定义的引用
    dormlq.f:(.text+0x887):对‘_gfortran_concat_string’未定义的引用
    /usr/local/lib/liblapack.a(dormqr.o):在函数‘dormqr_’中:
    dormqr.f:(.text+0x2f8):对‘_gfortran_concat_string’未定义的引用
    dormqr.f:(.text+0x81c):对‘_gfortran_concat_string’未定义的引用
    /usr/local/lib/liblapack.a(ilaenv.o):在函数‘ilaenv_’中:
    ilaenv.f:(.text+0x58):对‘_gfortran_compare_string’未定义的引用
    ilaenv.f:(.text+0x287):对‘_gfortran_compare_string’未定义的引用
    ilaenv.f:(.text+0x2b4):对‘_gfortran_compare_string’未定义的引用
    ilaenv.f:(.text+0x2d5):对‘_gfortran_compare_string’未定义的引用
    ilaenv.f:(.text+0x2f4):对‘_gfortran_compare_string’未定义的引用
    /usr/local/lib/liblapack.a(ilaenv.o):ilaenv.f:(.text+0x313): more undefined references to `_gfortran_compare_string' follow
    /usr/local/lib/liblapack.a(xerbla.o):在函数‘xerbla_’中:
    xerbla.f:(.text+0x49):对‘_gfortran_st_write’未定义的引用
    xerbla.f:(.text+0x54):对‘_gfortran_string_len_trim’未定义的引用
    xerbla.f:(.text+0x66):对‘_gfortran_transfer_character_write’未定义的引用
    xerbla.f:(.text+0x76):对‘_gfortran_transfer_integer_write’未定义的引用
    xerbla.f:(.text+0x7e):对‘_gfortran_st_write_done’未定义的引用
    xerbla.f:(.text+0x87):对‘_gfortran_stop_string’未定义的引用
    /usr/local/lib/liblapack.a(iparmq.o):在函数‘iparmq_’中:
    iparmq.f:(.text+0x150):对‘_gfortran_compare_string’未定义的引用
    iparmq.f:(.text+0x16f):对‘_gfortran_compare_string’未定义的引用
    iparmq.f:(.text+0x18f):对‘_gfortran_compare_string’未定义的引用
    iparmq.f:(.text+0x273):对‘_gfortran_compare_string’未定义的引用
    iparmq.f:(.text+0x28e):对‘_gfortran_compare_string’未定义的引用
    /usr/local/lib/liblapack.a(iparam2stage.o):iparam2stage.F:(.text+0x263): more undefined references to `_gfortran_compare_string' follow
    make: *** [all] 错误 2

    这是由于gfortran和pgf90编译命令不同导致的,因而本文以PGI编译器来执行lapack源代码的编译,即,Fortran程序采用pgf90命令,C程序采用pgcc命令来编译,相应的具体过程及参数记录如下。

    1. 确保机器上安装了PGI gfortran编译器。如果没有安装的话,手动安装:

     sudo yum install gfortran 

    PGI编译器需要去官网下载,具体安装过程参见我的另一篇博客《CentOS 7上安装PGI 2017编译器》。 

    2. 下载blas, cblas, lapack 源代码, 这些源码都可以在http://www.netlib.org 上找到,下载并解压。

    我下载的版本是lapack-3.7.1.tgz,解压之后会有一个文件夹,lapack-3.7.1,它含有BLAS,CBLAS,LAPACKE等文件夹,其中BLAS是BLAS的源码,CBLAS是BLAS的C语言接口。

    3. 这里就是具体的编译步骤

    (0) 复制lapack目录下的make.in.example文件,并修改其中的内容

    首先进入lapack-3.7.1文件夹,然后根据平台的特点,将该目录下对应的 make.inc.example 文件另存为 make.inc

    cd ..
    
    cp make.inc.example make.inc
    
    vi make.inc
    
    ####################################################################
    #  LAPACK make include file.                                       #
    #  LAPACK, Version 3.7.1                                           #
    #  June 2017                                                       #
    ####################################################################
    
    SHELL = /bin/sh
    
    #  CC is the C compiler, normally invoked with options CFLAGS.
    #
    CC     = pgcc # gcc
    CFLAGS = -O3
    
    #  Modify the FORTRAN and OPTS definitions to refer to the compiler
    #  and desired compiler options for your machine.  NOOPT refers to
    #  the compiler options desired when NO OPTIMIZATION is selected.
    #
    #  Note: During a regular execution, LAPACK might create NaN and Inf
    #  and handle these quantities appropriately. As a consequence, one
    #  should not compile LAPACK with flags such as -ffpe-trap=overflow.
    #
    FORTRAN = pgf90 # gfortran
    OPTS    = -O2 -Mrecursive # -frecursive
    DRVOPTS = $(OPTS)
    NOOPT   = -O0 -Mrecursive # -frecursive
    
    #  Define LOADER and LOADOPTS to refer to the loader and desired
    #  load options for your machine.
    #
    LOADER   = pgf90 # gfortran
    LOADOPTS =
    
    #  The archiver and the flag(s) to use when building an archive
    #  (library).  If your system has no ranlib, set RANLIB = echo.
    #
    ARCH      = ar
    ARCHFLAGS = cr
    RANLIB    = ranlib
    
    #  Timer for the SECOND and DSECND routines
    #
    #  Default:  SECOND and DSECND will use a call to the
    #  EXTERNAL FUNCTION ETIME
    #TIMER = EXT_ETIME
    #  For RS6K:  SECOND and DSECND will use a call to the
    #  EXTERNAL FUNCTION ETIME_
    #TIMER = EXT_ETIME_
    #  For gfortran compiler:  SECOND and DSECND will use a call to the
    #  INTERNAL FUNCTION ETIME
    #TIMER = INT_ETIME
    #  If your Fortran compiler does not provide etime (like Nag Fortran
    #  Compiler, etc...) SECOND and DSECND will use a call to the
    #  INTERNAL FUNCTION CPU_TIME
    TIMER = INT_CPU_TIME
    #  If none of these work, you can use the NONE value.
    #  In that case, SECOND and DSECND will always return 0.
    #TIMER = NONE
    
    #  Uncomment the following line to include deprecated routines in
    #  the LAPACK library.
    #
    #BUILD_DEPRECATED = Yes
    
    #  LAPACKE has the interface to some routines from tmglib.
    #  If LAPACKE_WITH_TMG is defined, add those routines to LAPACKE.
    #
    #LAPACKE_WITH_TMG = Yes
    
    #  Location of the extended-precision BLAS (XBLAS) Fortran library
    #  used for building and testing extended-precision routines.  The
    #  relevant routines will be compiled and XBLAS will be linked only
    #  if USEXBLAS is defined.
    #
    #USEXBLAS = Yes
    #XBLASLIB = -lxblas
    
    #  The location of the libraries to which you will link.  (The
    #  machine-specific, optimized BLAS library should be used whenever
    #  possible.)
    #
    BLASLIB      = ../../librefblas.a
    CBLASLIB     = ../../libcblas.a
    LAPACKLIB    = liblapack.a
    TMGLIB       = libtmglib.a
    LAPACKELIB   = liblapacke.a

    (1) 编译blas

    进入 BLAS/SRC 文件夹,执行以下几条命令

    cd BLAS/SRC
    # gfortran -c -O3 *.f # 编译所有的 .f 文件,生成 .o文件,这里采用PGI编译器的pgf90命令来编译 pgf90
    -c -O3 *.f # 编译所有的 .f 文件,生成 .o文件,这个pgf90编译命令与~/lapack*/make.inc保持一致 ar rv libblas.a *.o # 链接所有的 .o文件,生成.a 文件 sudo cp libblas.a /usr/local/lib #将库文件复制到系统库目录
    sudo cp
    libblas.a /usr/lib

    (2) 编译cblas

    进入CBLAS 文件夹,首先根据你自己的计算机平台,将目录下某个 Makefile.XXX复制为 Makefile.in , XXX表示计算机的平台,如果是linux,那么就将Makefile.LINUX 复制为Makefile.in,然后执行以下命令

    cd .. && cd ../CBLAS
    cp ../BLAS/SRC/libblas.a ./testing/ # 将上一步编译成功的 libblas.a复制到 CBLAS目录下的testing子目录 make # 编译所有的目录 sudo cp ../libcblas.a /usr/local/lib #将库文件复制到系统库目录下
    sudo cp
    ../libcblas.a /usr/lib

     

    (3) 编译 lapack 以及 lapacke

    这一步比较麻烦,首先进入lapack-3.7.1文件夹,根据平台的特点,编辑 Makefile,编译 lapack 和 lapacke 文件,并将 lapacke 目录下的头文件、lapack 目录下生成的 *.a 文件拷贝到系统目录(/usr/local/lib, /usr/lib)下。

    cd ..
    
    vi Makefile # 修改 lapack-3.7.1/Makefile 文件,因为 lapack 依赖于 blas 库 # 旧版本
    lib: lapacklib tmglib #lib: blaslib variants lapacklib tmglib # 新版本
    #lib: lapacklib tmglib
    lib: blaslib variants lapacklib tmglib



    make # 编译所有的lapack文件 cd LAPACKE # 进入LAPACKE 文件夹,这个文件夹包含lapack的C语言接口文件
    make # 编译lapacke
    sudo
    cp include/*.h /usr/local/include #将lapacke的头文件复制到系统头文件目录,
    # 包括: lapacke.h, lapacke_config.h, lapacke_mangling.h,lapacke_mangling_with_flags.h lapacke_utils.h
    cd .. # 返回到 lapack-3.7.1 目录
    sudo cp *.a /usr/local/lib  # 将生成的所有库文件复制到系统库目录,
    # 包括:liblapack.a, liblapacke.a, librefblas.a,libtmglib.a。

    sudo cp
    *.a /usr/lib

    Ques: 事实上,编译 lapack 时生成的 librefblas.a 文件与编译 BLAS 时生成的 libblas.a 文件大小基本一样,这里生成了两次,是否可以省去第(1)-(2)步?

     至此blas,cblas 和 lapack 就成功安装到你的电脑上了。

    4. lapack子程序测试

    测试程序  Console.f 

    ! 测试程序来自:http://blog.sina.com.cn/s/blog_5f350c9601014ejc.html
          program Console1
          external dgesv
          integer n, lda, nrhs, ldb
          parameter (n=2,lda=2,nrhs=1,ldb=2)
          double precision A(lda,n)
          double precision b(ldb,nrhs)
          character byebye
          integer ipiv(n), info, i, j
          A(1,1)=1
          A(1,2)=2
          A(2,1)=3
          A(2,2)=4
          B(1,1)=5
          B(2,1)=6
          write(*,*) 'Hello World'
          call dgesv(n,nrhs,A,lda,ipiv,b,ldb,info)
          write(*,*) 'INFO =', info
          write(*,*) ((A(i,j),i=1,lda),j=1,n)
          write(*,*) ((B(i,j),i=1,ldb),j=1,nrhs)
          write(*,*) "END OF PROGRAM..."
          end program Console1

    使用pgf90来编译该程序,可以得到预期的结果,而使用 gfortran 来编译则会报错:

    [She@she-centos7 LSQtest]$ pgf90 Console1.f  -lblas -llapack # 编译及运行正常
    [She@she-centos7 LSQtest]$ ./a.out
     Hello World
     INFO =            0
        3.000000000000000        0.3333333333333333         4.000000000000000      
       0.6666666666666667     
       -3.999999999999999         4.499999999999999     
     END OF PROGRAM...
    [She@she-centos7 LSQtest]$ 
    [She@she-centos7 LSQtest]$ 
    [She@she-centos7 LSQtest]$ 
    [She@she-centos7 LSQtest]$ gfortran Console1.f  -lblas -llapack # 编译报错
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(dgesv.o):在函数‘.C1_322’中:
    dgesv.f:(.data+0x18):对‘f90_compiled’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(dgetrf.o):在函数‘dgetrf_’中:
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./dgetrf.f:206:对‘dtrsm_’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./dgetrf.f:213:对‘dgemm_’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(dgetrf.o):在函数‘.C1_331’中:
    dgetrf.f:(.data+0x38):对‘f90_compiled’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(dgetrs.o):在函数‘dgetrs_’中:
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./dgetrs.f:191:对‘dtrsm_’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./dgetrs.f:191:对‘dtrsm_’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./dgetrs.f:202:对‘dtrsm_’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./dgetrs.f:202:对‘dtrsm_’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(dgetrs.o):在函数‘.C1_292’中:
    dgetrs.f:(.data+0x48):对‘f90_compiled’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(dlaswp.o):(.data+0x0):对‘f90_compiled’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(ilaenv.o):在函数‘ilaenv_’中:
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./ilaenv.f:703:对‘pgf90_str_copy’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./ilaenv.f:261:对‘pgf90_strcmp’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./ilaenv.f:274:对‘pgf90_strcmp’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./ilaenv.f:687:对‘pgf90_strcmp’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./ilaenv.f:353:对‘pgf90_strcmp’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./ilaenv.f:479:对‘pgf90_strcmp’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(ilaenv.o):/home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./ilaenv.f:485: more undefined references to `pgf90_strcmp' follow
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(ilaenv.o):在函数‘.STATICS1’中:
    ilaenv.f:(.data+0x128):对‘f90_compiled’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(ieeeck.o):在函数‘.C1_352’中:
    ieeeck.f:(.data+0x10):对‘f90_compiled’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(xerbla.o):在函数‘xerbla_’中:
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./xerbla.f:90:对‘pgf90io_src_info03’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./xerbla.f:90:对‘pgf90io_fmtw_init’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./xerbla.f:90:对‘pgf90_lentrim’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./xerbla.f:90:对‘pgf90io_fmt_write’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./xerbla.f:90:对‘pgf90io_sc_i_fmt_write’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./xerbla.f:90:对‘pgf90io_fmtw_end’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./xerbla.f:90:对‘pgf90_stop08’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(xerbla.o):在函数‘.STATICS1’中:
    xerbla.f:(.data+0xa0):对‘f90_compiled’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(iparmq.o):在函数‘iparmq_’中:
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparmq.f:265:对‘__gss_log’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparmq.f:265:对‘__gss_log’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparmq.f:265:对‘__mth_i_nint’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparmq.f:321:对‘pgf90_str_copy’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparmq.f:336:对‘pgf90_strcmp’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparmq.f:369:对‘pgf90_strcmp’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparmq.f:387:对‘pgf90_strcmp’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparmq.f:379:对‘pgf90_strcmp’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparmq.f:379:对‘pgf90_strcmp’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(iparmq.o):在函数‘.C1_289’中:
    iparmq.f:(.data+0x20):对‘f90_compiled’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(iparam2stage.o):在函数‘iparam2stage_’中:
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparam2stage.F:207:对‘pgf90_str_copy’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparam2stage.F:341:对‘pgf90_strcmp’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparam2stage.F:350:对‘pgf90_strcmp’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparam2stage.F:359:对‘pgf90_strcmp’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparam2stage.F:360:对‘pgf90_strcmp’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparam2stage.F:378:对‘pgf90_strcmp’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(iparam2stage.o):/home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./iparam2stage.F:378: more undefined references to `pgf90_strcmp' follow
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(iparam2stage.o):在函数‘.C1_327’中:
    iparam2stage.F:(.data+0x48):对‘f90_compiled’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(lsame.o):(.data+0x0):对‘f90_compiled’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(dgetrf2.o):在函数‘dgetrf2_’中:
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./dgetrf2.f:242:对‘dtrsm_’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./dgetrf2.f:247:对‘dgemm_’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./dgetrf2.f:192:对‘idamax_’未定义的引用
    /home/She/Software/Fortran/Lapack/lapack-3.7.1/SRC/./dgetrf2.f:207:对‘dscal_’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(dgetrf2.o):在函数‘.C1_292’中:
    dgetrf2.f:(.data+0x40):对‘f90_compiled’未定义的引用
    /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../liblapack.a(dlamch.o):在函数‘.C1_291’中:
    dlamch.f:(.data+0x68):对‘f90_compiled’未定义的引用
    collect2: 错误:ld 返回 1

    测试完毕。

    5. 结论和心得

    在同一台电脑上,最好对Fortran程序和C程序使用一致的编译命令,库文件和源代码都遵循这样的做法,可以避免不必要的奇怪bug。

    如果一组程序中,某些文件采用了gfortran 来编译,而一些文件采用了 pgf90 命令来编译,则链接时容易产生一些难以检查的错误,浪费生命!

     

     
  • 相关阅读:
    C++ 多线程
    C++ 信号处理
    首页流量监控代码
    macro-name replacement-text 宏 调试开关可以使用一个宏来实现 do { } while(0)
    color depth 色彩深度 像素深度
    数据更新 数据同步 起始点 幂等同步历史数据
    获取当前调用函数名 方法名
    版本号风格为 Major.Minor.Patch
    query_string查询支持全部的Apache Lucene查询语法 低频词划分依据 模糊查询 Disjunction Max
    Cutoff frequency
  • 原文地址:https://www.cnblogs.com/snake553/p/7151787.html
Copyright © 2011-2022 走看看