用于C++的Python包装器,那么当将代码复制到DOCKER图像时,只能使用卷的时候不可用?

2024-09-30 14:17:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经成功地将一个software repository (KPConv)对接,我计划使用它并扩展以下Dockerfile

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 found here,它描述了一种正确设置容器生成的文件的权限的方法,这样主机/用户就可以访问这些文件,而无需更改文件权限

此外,这个软件库利用C++中的^ a3}(KPConv/tf_custom_ops)和Python包装器来定制C++代码(KPConv/cpp_wrappers)。KPConv的作者Thomas Hugues提供了一个bash脚本,它对每个脚本进行编译以生成各种.so文件


如果在构建过程中(^ {CD3>})将库插入到图像中(^ {CD3>}),启动容器,调用编译的BASH脚本,然后运行代码,Python正确加载C++包装(生成的.S.{< CD4>}),并开始运行所期望的/预期的软件。p>

$ 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文件具有哈希

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

它还具有权限

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(noCOPY . /kpconv)编译图像,执行相同的编译步骤,然后运行代码

$ 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

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文件与第一种描述的情况具有相同的哈希和权限

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是作为卷装入的)(出于某些原因,容器将来也会装入,请检查时间戳)

$ 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

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

我认为,这为实际问题提供了答案。但我离我在大学里作为一个实习生工作的日子太远了,必须了解如何使用C++来解决这个问题。但我认为问题在于容器和主机之间以及每个主机上的用户之间的权限(即,容器上的root、容器上的user(Dockerfile)、主机上的root和主机上的<myusername>


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

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


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

如果您没有GPU或不想install ^{},您应该能够将Dockerfile基本映像更改为^{},并在CPU上运行代码


Tags: 代码gnusolinuxshcpythoncpp容器
1条回答
网友
1楼 · 发布于 2024-09-30 14:17:38

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

  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检查链接的所有库

相关问题 更多 >