栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如果没有root用户访问权限,请在将RLAS与参考BLAS链接时使用经过调整的BLAS运行R

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如果没有root用户访问权限,请在将RLAS与参考BLAS链接时使用经过调整的BLAS运行R

为什么我的方法不起作用

首先,UNIX上的共享库旨在模仿存档库的工作方式(首先存在存档库)。特别是这意味着,如果您同时具有

libfoo.so
和和
libbar.so
,这两个定义符号
foo
,则首先加载哪个库才是获胜的:所有对
foo
程序中任何位置(包括from
libbar.so
)的引用都将绑定到的
libfoo.so
s定义
foo

这模仿了如果您将程序与

libfoo.a
和链接时会发生的情况
libbar.a
,并且两个存档库都定义了相同的符号
foo
。有关存档链接的更多信息,请参见此处。

它应该是从上面清楚的是,如果

libblas.so.3
libopenblas.so.0
定义相同的符号集(他们 这样做
),如果
libblas.so.3
被加载到进程,然后再从程序
libopenblas.so.0
永远不会 被调用。

其次,您已经正确地决定了,由于

R
直接链接到
libR.so
,并且由于
libR.so
直接链接到
libblas.so.3
,因此可以确保
libopenblas.so.0
赢得这场战斗。

但是,您 错误地 决定

Rscript
比较好,但它不是:
Rscript
是一个 很小的
二进制文件(我的系统上11K;比较2.4MB的
libR.so
),它也几乎全部是
exec
R
。在
strace
输出中看到这很简单:

strace -e trace=execve /usr/bin/Rscript --default-packages=base --vanilla /dev/nullexecve("/usr/bin/Rscript", ["/usr/bin/Rscript", "--default-packages=base", "--vanilla", "/dev/null"], []) = 0execve("/usr/lib/R/bin/R", ["/usr/lib/R/bin/R", "--slave", "--no-restore", "--vanilla", "--file=/dev/null", "--args"], []) = 0--- SIGCHLD {si_signo=SIGCHLD, si_pre=CLD_EXITED, si_pid=89625, si_status=0, si_utime=0, si_stime=0} ------ SIGCHLD {si_signo=SIGCHLD, si_pre=CLD_EXITED, si_pid=89626, si_status=0, si_utime=0, si_stime=0} ---execve("/usr/lib/R/bin/exec/R", ["/usr/lib/R/bin/exec/R", "--slave", "--no-restore", "--vanilla", "--file=/dev/null", "--args"], []) = 0--- SIGCHLD {si_signo=SIGCHLD, si_pre=CLD_EXITED, si_pid=89630, si_status=0, si_utime=0, si_stime=0} ---+++ exited with 0 +++

这意味着在你的脚本开始执行的时候,

libblas.so.3
已经被加载,
libopenblas.so.0
将被加载的依赖
mmperf.so
不会
真正 被用于任何东西。

是否有可能使其正常工作

大概。我可以想到两种可能的解决方案:

  1. 假装
    libopenblas.so.0
    实际上
    libblas.so.3
  2. R
    针对重建整个软件包
    libopenblas.so

对于#1,您需要

ln -s libopenblas.so.0 libblas.so.3

然后
libblas.so.3
通过
LD_LIBRARY_PATH
适当设置来确保在系统副本之前找到您的副本。

这似乎为我工作:

mkdir /tmp/libblas# pretend that libc.so.6 is really libblas.so.3cp /lib/x86_64-linux-gnu/libc.so.6 /tmp/libblas/libblas.so.3LD_LIBRARY_PATH=/tmp/libblas /usr/bin/Rscript /dev/nullError in dyn.load(file, DLLpath = DLLpath, ...) :  unable to load shared object '/usr/lib/R/library/stats/libs/stats.so':  /usr/lib/liblapack.so.3: undefined symbol: cgemv_During startup - Warning message:package ‘stats’ in options("defaultPackages") was not found

请注意我是如何得到错误的(我的“假装”

libblas.so.3
没有定义期望的符号,因为它实际上是的副本
libc.so.6
)。

您还可以通过以下方式确认

libblas.so.3
要加载的版本:

LD_DEBUG=libs LD_LIBRARY_PATH=/tmp/libblas /usr/bin/Rscript /dev/null |& grep 'libblas.so.3'     91533: find library=libblas.so.3 [0]; searching     91533:   trying file=/usr/lib/R/lib/libblas.so.3     91533:   trying file=/usr/lib/x86_64-linux-gnu/libblas.so.3     91533:   trying file=/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server/libblas.so.3     91533:   trying file=/tmp/libblas/libblas.so.3     91533: calling init: /tmp/libblas/libblas.so.3

对于#2,您说:

我没有要测试的计算机的root访问权限,因此无法实际链接到OpenBLAS。

但这似乎是个虚假的论点:如果可以构建

libopenblas
,那么当然也可以构建自己的
R

更新:

您在一开始提到libblas.so.3和libopenblas.so.0定义了相同的符号,这意味着什么?它们具有不同的SONAME,是否不足以通过系统区分它们?

符号和

SONAME
没有 做对方。

您可以从输出中看到的符号

readelf -Ws libblas.so.3
readelf -Wslibopenblas.so.0
。与之相关的符号
BLAS
,例如
cgemv_
,将出现在两个库中。

SONAME
可能 对Windows
感到困惑。
DLL
Windows上的s设计完全不同。特别是,当
FOO.DLL
进口象征
bar
BAR.DLL
两个 符号(名称
bar

,并
DLL
从该符号是进口的(
BAR.DLL
)被记录在
FOO.DLL
的进口表。

这使得它轻松拥有

R
进口
cgemv_
BLAS.DLL
,而
MMPERF.DLL
进口的相同符号的
OPENBLAS.DLL

但是,这使库插入变得困难,并且与存档库的工作方式(甚至在Windows上)完全不同。

对于哪种设计总体上更好,人们意见不一,但是两种系统都不可能改变其模型。

UNIX有多种方法可以模拟Windows样式的符号绑定:请参见

RTLD_DEEPBIND
dlopen
手册页。当心:这些问题充满危险,可能使UNIX专家困惑,没有被广泛使用,并且可能存在实现错误。

更新2:

您的意思是我编译R并将其安装在主目录下?

是。

然后,当我要调用它时,应该显式地给出我的可执行程序版本的路径,否则可能会调用系统上的路径?或者,我可以将此路径放在环境变量$
PATH的第一个位置以欺骗系统吗?

无论哪种方式都行。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/403213.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号