首页 > 解决方案 > 如何使用 fortran (MKL) 将静态库中的函数打包到 .so 文件中

问题描述

我正在尝试使用 MKL 在 fortran 中的 blas 实现来加速优化例程。我需要将结果保存在共享库中,以便可以从更大的脚本中访问它。我可以在没有任何警告的情况下编译和链接我的代码,但是生成的.so文件对我试图调用的 blas 例程有一个未定义的引用,即dgemm.

fortran代码的相关部分:

subroutine sumsquares(params, Mx, flen, glen, numr, numcols, g, lambda, res)
 implicit none
 integer, intent(in):: flen, glen, numr, numcols
 real(8), dimension(flen, numcols) :: params
 real(8), dimension(flen, numcols) :: g
 real(8), dimension(flen, numcols) :: gc
 real(8), dimension(flen, glen) :: Mx 

 gc = -g
 call dgemm('N', 'N', flen, glen, numcols, 1, Mx, flen, params, numcols, 1, gc,flen)
 return
end subroutine sumsquares

和相应的makefile

FC=ifort
LD_LIBRARY_PATH=/opt/intel/composerxe-2011.1.107/compiler/lib/intel64:/opt/intel/composerxe-2011.1.107/mkl/lib/intel64
LIBRARY_PATH=/opt/intel/composerxe-2011.1.107/compiler/lib/intel64:/opt/intel/composerxe-2011.1.107/mkl/lib/intel64
INCLUDE=/opt/intel/composerxe-2011.1.107/mkl/include
FPATH=/opt/intel/composerxe-2011.1.107/mkl/include
CPATH=/opt/intel/composerxe-2011.1.107/mkl/include
FFLAGS=-i8 -I$(MKLROOT)/include/intel64/ilp64 -I$(MKLROOT)/include
LDFLAGS= -shared -nofor-main -fPIC
LINKLIBS=-fPIC -shared -L$(MKLROOT)/lib/intel64 $(MKLROOT)/lib/intel64/libmkl_blas95_ilp64.a -lmkl_rt -lpthread -lm

sumsquares: sumsquares.f90
    $(FC) $(FFLAGS) -c -fPIC /opt/intel/composerxe-2011.1.107/mkl/include/blas.f90 -o blas95.o
    $(FC) $(FFLAGS) -nofor-main -c -fPIC sumsquares.f90
    $(FC) $(LDFLAGS) sumsquares.o $(LINKLIBS) sumsquares.o

正如我所说,我可以在make没有任何警告的情况下运行,但是当我运行时,nm sumsquares.so | grep dgemm我看到U dgemm_,当我尝试加载.so文件时,我因段错误而崩溃(在调用不相关的子例程时,所以我认为它与此代码无关)。如何让链接器将相关函数放入so文件中?

更新

so通过调用 R 在 R 脚本中加载文件,dyn.load如下所示:

变体1:

dyn.load("/home/me/path/sumsquares.so")

变体2:

dyn.load("/opt/intel/composerxe-2011.1.107/mkl/lib/intel64/libmkl_rt.so")
dyn.load("/home/me/path/sumsquares.so")

两种变体都导致相同的结果,但有段错误。

更新#2

我应该指出,英特尔 MKL 静态库用标志编译的-fPIC,至少根据文档。我显然不知道自己在做什么,但据我所知,这样的事情应该是可能的。

正如blas在科学计算中广泛使用的那样,我担心与不同版本的冲突。如果我在我的so文件中静态链接,并将该so文件加载到使用不同blas实现的程序中,这会导致冲突,还是我的库会运行良好?

标签: linuxfortranshared-librariesintel-mkl

解决方案


如果库确实是静态的,则不能放入共享库。共享目标代码以不同的方式编译,因此它可以独立于位置工作。-fPIC必须使用不用于静态库的标志。

要么将你的 BLAS 编译dgemm为动态库并在加载自定义库之前加载它(也许 Rdyn.load会自动加载依赖项,我不知道,你可以尝试)或者只是将 DGEMM 的代码包含到你自己的库中并编译一切合二为一。所以。

不要忘记您必须使用 MKL 链接顾问https://software.intel.com/content/www/us/en/develop/articles/intel-mkl-link-line-advisor.html不要与 ILP64 链接图书馆,除非您知道自己在做什么并且有充分的理由这样做。

此外,尽管大多数 MKL 都附带使用 构建的静态库-fPIC,但与 LAPACK 和 BLAS 的 Fortran 95 接口却没有。-fPIC包含接口的源文件,所以如果你想使用它们,你需要自己编译它们。它们位于$MKLROOT/interfaces/blas95$MKLROOT/interfaces/lapack95


推荐阅读