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 命令來編譯,則鏈接時容易產生一些難以檢查的錯誤,浪費生命!

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM