首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++ .so的Python包装器只有在将代码复制到坞库映像中时才能使用,而不是在按卷挂载时使用?

C++ .so的Python包装器只有在将代码复制到坞库映像中时才能使用,而不是在按卷挂载时使用?
EN

Stack Overflow用户
提问于 2021-03-14 02:38:54
回答 1查看 336关注 0票数 4

我已经在一定程度上成功地将一个软件储存库(KPConv)进行了对接,我计划使用并扩展以下Dockerfile

代码语言:javascript
复制
FROM tensorflow/tensorflow:1.12.0-devel-gpu-py3

# Install other required python stuff
RUN apt-get update && apt install -y --fix-missing --no-install-recommends\
    python3-setuptools python3-pip python3-tk

RUN pip install --upgrade pip
RUN pip3 install numpy scikit-learn psutil matplotlib pyqt5 laspy 

# Compile the custom operations and CPP wrappers
# For some reason this must be done within container, cannot access libcuda.so during docker build
# Ref: https://stackoverflow.com/questions/66575232
#COPY . /kpconv
#WORKDIR /kpconv/tf_custom_ops
#RUN sh compile_op.sh
#WORKDIR /kpconv/cpp_wrappers
#RUN sh compile_wrappers.sh

# Set the working directory to kpconv
WORKDIR /kpconv

# Set root user password so we can su/sudo later if need be
RUN echo "root:pass" | chpasswd

# Create a user and group akin to the host within the container
ARG USER_ID
ARG GROUP_ID
RUN addgroup --gid $GROUP_ID user
RUN adduser --disabled-password --gecos '' --uid $USER_ID --gid $GROUP_ID user
USER user

#Build
#sudo docker build -t kpconv-test \
#    --build-arg USER_ID=$(id -u) \
#    --build-arg GROUP_ID=$(id -g) \
#    .

在这个Dockerfile的末尾,我遵循了post 在这里发现的,它描述了一种正确设置容器中生成的文件的权限的方法,这样主机/用户就可以访问它们,而不必更改文件权限。

此外,这个软件库使用自定义tensorflow操作 in C++ (运维)和Python用于定制C++代码(包装纸)。KPConv的作者Thomas提供了一个bash脚本,它编译每个脚本以生成各种.so文件。

如果我在构建过程(COPY . /kpconv)期间将存储库放入映像中,启动容器,调用两个编译bash脚本,然后运行代码,然后Python正确地加载C++包装器(生成的.so grid_subsampling.cpython-35m-x86_64-linux-gnu.so),并开始按预期/预期的方式运行软件。

代码语言:javascript
复制
$ sudo docker run -it \
>     -v /<myhostpath>/data_sets:/data \
>     -v /<myhostpath>/_output:/output \
>     --runtime=nvidia kpconv-test /bin/bash
user@eec8553dcb5d:/kpconv$ cd tf_custom_ops 
user@eec8553dcb5d:/kpconv/tf_custom_ops$ sh compile_op.sh 
user@eec8553dcb5d:/kpconv/tf_custom_ops$ cd ..
user@eec8553dcb5d:/kpconv$ cd cpp_wrappers/
user@eec8553dcb5d:/kpconv/cpp_wrappers$ sh compile_wrappers.sh 
running build_ext
building 'grid_subsampling' extension
<Redacted for brevity>
user@eec8553dcb5d:/kpconv/cpp_wrappers$ cd ..
user@eec8553dcb5d:/kpconv$ python training_ModelNet40.py 

Dataset Preparation
*******************

Loading training points
1620.2 MB loaded in 0.6s

Loading test points
411.6 MB loaded in 0.2s
<Redacted for brevity>

这是很好的工作,并允许我运行KPConv软件。

另外,为了以后的工作,.so文件有哈希

代码语言:javascript
复制
user@eec8553dcb5d:/kpconv/cpp_wrappers/cpp_subsampling$ sha1sum grid_subsampling.cpython-35m-x86_64-linux-gnu.so 
a17eef453f6d2370a15bc2a0e6714c978390c5c3  grid_subsampling.cpython-35m-x86_64-linux-gnu.so

它还具有以下权限

代码语言:javascript
复制
user@eec8553dcb5d:/kpconv/cpp_wrappers/cpp_subsampling$ ls -al grid_subsampling.cpython-35m-x86_64-linux-gnu.so 
-rwxr-xr-x 1 user user 561056 Mar 14 02:16 grid_subsampling.cpython-35m-x86_64-linux-gnu.so

虽然它产生了一个难以快速编辑和软件的工作流程,但为了我的目的,并在容器中快速运行它。对代码的每一项更改都需要新的映像构建。因此,我更愿意在运行时将KPConv代码从主机加载/卷到容器中,然后编辑在容器中运行时处于“活动”状态。

这样做,并使用帖子顶部的Dockerfile (不包括COPY . /kpconv)编译映像,执行相同的编译步骤,并运行代码

代码语言:javascript
复制
$ sudo docker run -it \
>     -v /<myhostpath>/data_sets:/data \
>     -v /<myhostpath>/KPConv_Tensorflow:/kpconv \
>     -v /<myhostpath>/_output:/output \
>     --runtime=nvidia kpconv-test /bin/bash
user@a82e2c1af21a:/kpconv$ cd tf_custom_ops/
user@a82e2c1af21a:/kpconv/tf_custom_ops$ sh compile_op.sh 
user@a82e2c1af21a:/kpconv/tf_custom_ops$ cd ..
user@a82e2c1af21a:/kpconv$ cd cpp_wrappers/
user@a82e2c1af21a:/kpconv/cpp_wrappers$ sh compile_wrappers.sh 
running build_ext
building 'grid_subsampling' extension
<Redacted for brevity>
user@a82e2c1af21a:/kpconv/cpp_wrappers$ cd ..
user@a82e2c1af21a:/kpconv$ python training_ModelNet40.py 

我收到下面的Python ImportError

代码语言:javascript
复制
user@a82e2c1af21a:/kpconv$ python training_ModelNet40.py 
Traceback (most recent call last):
  File "training_ModelNet40.py", line 36, in <module>
    from datasets.ModelNet40 import ModelNet40Dataset
  File "/kpconv/datasets/ModelNet40.py", line 40, in <module>
    from datasets.common import Dataset
  File "/kpconv/datasets/common.py", line 29, in <module>
    import cpp_wrappers.cpp_subsampling.grid_subsampling as cpp_subsampling
ImportError: /kpconv/cpp_wrappers/cpp_subsampling/grid_subsampling.cpython-35m-x86_64-linux-gnu.so: failed to map segment from shared object

为什么C++的这个Python包装器只能在将代码复制到坞库映像时使用,而不能通过卷挂载?

.so文件具有与第一次描述的情况相同的哈希和权限。

代码语言:javascript
复制
user@a82e2c1af21a:/kpconv/cpp_wrappers/cpp_subsampling$ sha1sum grid_subsampling.cpython-35m-x86_64-linux-gnu.so 
a17eef453f6d2370a15bc2a0e6714c978390c5c3  grid_subsampling.cpython-35m-x86_64-linux-gnu.so
user@a82e2c1af21a:/kpconv/cpp_wrappers/cpp_subsampling$ ls -al grid_subsampling.cpython-35m-x86_64-linux-gnu.so 
-rwxr-xr-x 1 user user 561056 Mar 14 02:19 grid_subsampling.cpython-35m-x86_64-linux-gnu.so

在我的主机上,该文件具有以下权限(它位于主机上,因为/kpconv是作为卷挂载的)(由于某种原因,容器将来也是如此,请检查时间戳)

代码语言:javascript
复制
$ ls -al grid_subsampling.cpython-35m-x86_64-linux-gnu.so 
-rwxr-xr-x 1 <myusername> <myusername> 561056 Mar 13 21:19 grid_subsampling.cpython-35m-x86_64-linux-gnu.so

在对错误消息进行了一些研究之后,看起来每个结果都是特定于某一情况的。尽管大多数人似乎都提到了错误是某种权限问题的结果。

我认为这个Unix&Linux堆栈回答为实际问题提供了答案。但是,我在大学里和C++一起实习的日子太远了,我不知道如何用它来解决这个问题。但我认为问题在于容器和主机之间以及用户对每个用户之间的权限(即容器上的根,容器上的user (Dockerfile),主机上的根,主机上的<myusername> )。

我还试图首先使用Dockerfile中创建的根密码来提升容器中的权限,然后编译代码并运行软件。但这也导致了同样的问题。我还尝试将代码编译为容器中的user,但将软件作为root运行,同样存在同样的问题。

因此,我发现并提供的另一条线索是,当编译“仅在”容器内(没有.so )和在--volume中编译它时(因此我试图比较文件哈希)时,似乎与--volume有一些不同。所以,可能不是那么多的权限,但是内核是如何在容器中加载.so的,或者它在--volume中的位置如何影响加载过程?

编辑:对于SSCCE,您应该能够将链接的存储库克隆到您的计算机上,并使用相同的文件。您不需要指定/data/output卷,也不需要以任何方式更改代码(它试图在加载数据之前加载.so (这只会导致错误并结束执行))

如果您没有GPU或不想使用nvidia-runtime,您应该能够将Dockerfile基映像更改为tensorflow:1.12.0-devel-py3并在CPU上运行代码。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-03-14 05:36:42

您的问题是由试图动态加载库的链接器造成的。这可能有几个根本原因:

  1. 许可。用户应该拥有加载库的权限,因此当在docker中挂载文件系统时,主机中的所有者id和组id不需要在容器中使用相同的id,尽管它们可能是相同的名称。
  2. 错误的二进制格式。主机操作系统正在以错误的格式编译二进制文件。如果您在(例如) macOS上运行编译并在linux容器中使用它,就会发生这种情况。
  3. 安装错误。例如,使用noexec安装也会阻止加载库。
  4. 两种环境中库的不同。由于编译库的环境不同,您可能缺少一些库,因此使用ldd grid_subsampling.cpython-35m-x86_64-linux-gnu.soldd -r -d -v grid_subsampling.cpython-35m-x86_64-linux-gnu.so检查所有链接的库。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66620589

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档