链接R包取决于RcppEigen与Microsoft R Open中的MKL

时间:2017-12-30 20:31:42

标签: package eigen rcpp intel-mkl microsoft-r

我已经构建了一个自定义包,其中包含一些用RcppEigen编写的函数。我也启用了Microsoft R,并启用了英特尔MKL。如何将R包链接到英特尔MKL功能?

设置1

以下是我尝试将程序包与正常R中的MKL链接但但失败的程序:

The Eigen documents说我需要:

1. #define EIGEN_USE_MKL_ALL
2. link your program to MKL libraries 

the MKL linking advisor

基于2,在我的文件Makevars中

PKG_CXXFLAGS = -I/opt/intel/mkl/include 
PKG_LIBS = ${LAPACK_LIBS} ${BLAS_LIBS} ${FLIBS}  -L/opt/intel/mkl/lib/intel64 -Wl,--no-as-needed -lmkl_intel_lp64 -lmkl_gnu_thread -lmkl_core -lgomp -lpthread -lm -ldl

我在编译软件包时遇到了错误:

Error in dyn.load(dllfile) : 
unable to load shared object '/home/path/RPackageName.so':
libmkl_intel_lp64.so: cannot open shared object file: No such file or directory

根据Ralf的评论进行更新:在Makevars文件中添加选项<, - rpath,'路径'>,错误消失。

PKG_CXXFLAGS = -DMKL_LP64 -m64  -I/opt/intel/mkl/include 
PKG_LIBS =  ${LAPACK_LIBS} ${BLAS_LIBS} ${FLIBS}  -L/opt/intel/mkl/lib/intel64 -Wl,--no-as-needed,-rpath,'/opt/intel/mkl/lib/intel64' -lmkl_intel_lp64 -lmkl_gnu_thread -lmkl_core -lgomp -lpthread -lm -ldl 

包编译成功,但是下面有这些消息,我不明白。

/home/shen/R/x86_64-pc-linux-gnu-
library/3.4/RcppEigen/include/Eigen/src/Core/Assign_MKL.h: In 
instantiation of ‘static void Eigen::internal::Assignment<DstXprType, 
Eigen::CwiseUnaryOp<Eigen::internal::scalar_log_op<double>, 
SrcXprNested>, Eigen::internal::assign_op<double, double>, 
Eigen::internal::Dense2Dense, typename 
Eigen::internal::enable_if<Eigen::internal::vml_assign_traits<Dst, 
Src>::EnableVml>::type>::run(DstXprType&, const SrcXprType&, const 
Eigen::internal::assign_op<double, double>&) [with DstXprType = 
Eigen::Matrix<double, -1, 1>; SrcXprNested = const 
Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, -1> >; 
Eigen::internal::Assignment<DstXprType, 
Eigen::CwiseUnaryOp<Eigen::internal::scalar_log_op<double>, 
SrcXprNested>, Eigen::internal::assign_op<double, double>, 
Eigen::internal::Dense2Dense, typename 
Eigen::internal::enable_if<Eigen::internal::vml_assign_traits<Dst, 
Src>::EnableVml>::type>::SrcXprType = 
Eigen::CwiseUnaryOp<Eigen::internal::scalar_log_op<double>, const 
Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, -1> > >]’:
/home/shen/R/x86_64-pc-linux-gnu-
library/3.4/RcppEigen/include/Eigen/src/Core/AssignEvaluator.h:836:49:   
required from ‘void Eigen::internal::call_assignment_no_alias(Dst&, 
const Src&, const Func&) [with Dst = Eigen::Matrix<double, -1, 1>; Src 
= Eigen::CwiseUnaryOp<Eigen::internal::scalar_log_op<double>, const 
Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, -1> > >; Func = 
Eigen::internal::assign_op<double, double>]’

设置2 我直接在MRO中编译,Makevars文件中没有任何特殊参数,得到以下错误:

/home/shen/R/x86_64-pc-linux-gnu-
library/3.3/RcppEigen/include/Eigen/src/Core/util/MKL_support.h:57:21: 
fatal error: mkl.h: No such file or directory
PS:我对Microsoft R open的经验是,他们可以在没有做任何事情的情况下加速Armadillo中的正常R脚本和功能。只需在Microsoft R Open中正常运行它们。

1 个答案:

答案 0 :(得分:0)

记录我的发现的部分答案。也许其他人可以在此基础上继续发展。

Linux与R链接MKL

对于此设置,我使用了安装了R 3.5.0的Debian稳定机器。我通过this script安装了MKL。对于编译,我使用了一个add-hoc插件,其中包含更新的问题中提供的编译标记以及-Wno-ignored-attributessilence some unrelated warnings

library(Rcpp)

registerPlugin(
  name = "mkl",
  plugin = function(x) {
    list(
      includes = "#define EIGEN_USE_MKL_ALL",
      env = list(PKG_CXXFLAGS = "-DMKL_LP64 -m64  -I/opt/intel/mkl/include -Wno-ignored-attributes",
                 PKG_LIBS = "${LAPACK_LIBS} ${BLAS_LIBS} ${FLIBS}  -L/opt/intel/mkl/lib/intel64 -Wl,--no-as-needed,-rpath,'/opt/intel/mkl/lib/intel64' -lmkl_intel_lp64 -lmkl_gnu_thread -lmkl_core -lgomp -lpthread -lm -ldl")
    )
  }
)

cppFunction('
Eigen::VectorXd mkl_sin(Eigen::VectorXd x) {
  return x.array().sin();
}
', plugins = "mkl", depends = "RcppEigen")
mkl_sin((1:10)/10)
#>  [1] 0.09983342 0.19866933 0.29552021 0.38941834 0.47942554 0.56464247] 0.64421769 0.71735609 0.78332691 0.84147098

这没有任何警告,所以我得出结论,当R与MKL作为外部BLAS / LAPACK链接时,它有效。

Linux with MRO

对于此设置,我使用了基于Ubuntu的Docker镜像:

FROM ubuntu:16.04

RUN apt-get update \
 && apt-get install --yes --no-install-recommends \
    apt-transport-https \
    build-essential \
    ca-certificates \
    curl \
    gfortran \
 && curl -O https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb \
 && dpkg -i packages-microsoft-prod.deb \
 && apt-get update \
 && apt-get install --yes --no-install-recommends \
    microsoft-r-open-foreachiterators-3.4.3 \
    microsoft-r-open-mkl-3.4.3 \
    microsoft-r-open-mro-3.4.3 \
 && Rscript -e 'install.packages("RcppEigen")'

MRO的问题在于它不包含MKL标题而只包含MKL库的一部分:

ls /opt/microsoft/ropen/3.4.3/lib64/R/lib/libmkl_*
/opt/microsoft/ropen/3.4.3/lib64/R/lib/libmkl_core.so
/opt/microsoft/ropen/3.4.3/lib64/R/lib/libmkl_gf_ilp64.so
/opt/microsoft/ropen/3.4.3/lib64/R/lib/libmkl_gf_lp64.so
/opt/microsoft/ropen/3.4.3/lib64/R/lib/libmkl_gnu_thread.so
/opt/microsoft/ropen/3.4.3/lib64/R/lib/libmkl_vml_def.so
/opt/microsoft/ropen/3.4.3/lib64/R/lib/libmkl_vml_mc3.so

特别是在上面的链接命令中请求的libmkl_intel_lp64.so缺失。因此,不可能将上述配方与MRO一起使用。除了MRO之外,它可能会安装MKL并与之相关联,但我还没有对此进行测试。

然而,只要Eigen回归到BLAS / LAPACK方法,就会使用MKL。与使用引用BLAS / LAPACK(Windows的默认值)的R版本相比,这将加快操作。