docker - 如何在 gitlab-ci docker executor 中使用 cuda
问题描述
我们正在使用 gitlab 持续集成来构建和测试我们的项目。最近,其中一个项目增加了对 CUDA 启用 GPU 加速的要求。我不想改变我们的管道(docker 和 gitlab-ci 对我们来说工作得很好),所以我想以某种方式让 docker 能够与 nvidia GPU 对话。
额外细节:
- 在我们的构建服务器上安装 nvidia GPU 很好 - 我们有一些备用 GPU 可用于此目的
- 我们没有使用ubuntu或者centOS,所以不能直接使用nvidia的cuda容器
- 您无法将
--runtime
参数提供给 gitlab CI,因此您无法使用 nvidia 建议的 docker 调用。[编辑:实际上,你现在可以。见https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/764 ]
解决方案
现在--gpu
gitlab runner 版本 >13.9 上有标志。你应该使用那些 insetad。如果坚持使用旧版本,请继续阅读。
有多个步骤:
- 在主机 PC 上安装 nvidia 驱动程序
- 安装 nvidia-docker2
- 使用 CUDA 构建 docker 镜像
- 让它在 gitlab CI 中工作
请注意,如果您只想编译 CUDA 代码而不需要运行它,则无需使用 nvidia-docker2,在主机 PC 上安装 nvidia 驱动程序,并且无需特殊步骤即可使其工作gitlab CI。(即您只需执行第 3 步)
恐怕我对 docker 不太熟悉,所以如果我混合了容器和图像,我深表歉意。如果有更多知识的人想要修复有关 docker 的任何拼写错误,将不胜感激。
步骤 1:在主机 PC 上安装 nvidia 驱动程序
您在这里有两个选择。您可以使用主机操作系统推荐的程序。这很容易,但意味着不同构建服务器的环境可能不同。另一种选择是直接从 nVidia 下载安装程序(即https://www.nvidia.com/object/unix.html),以便您可以将其与 docker 容器一起分发。
第 2 步:安装 nvidia-docker2
我当前的测试 PC 是 archlinux,所以这是从 AUR 使用它的一个案例。nVidia 为多个操作系统提供存储库,因此请参阅nvidia-docker github 页面上的快速入门指南。
您应该按照快速入门指南测试您的 nvidia-docker 安装。从您的主机 PC 运行命令:
docker run --runtime=nvidia --rm nvidia/cuda:9.0-base nvidia-smi
应该运行并输出如下内容:
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 415.18 Driver Version: 415.18 CUDA Version: 10.0 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 GeForce GTX 106... Off | 00000000:02:00.0 On | N/A |
| 28% 39C P0 24W / 120W | 350MiB / 6071MiB | 3% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
+-----------------------------------------------------------------------------+
请注意,虽然我指定了 9.0-base 映像,但 nvidia-smi 报告 Cuda 10。我认为这是因为 Cuda 10 安装在主机 PC 上。nvidia-docker 文档说它将使用 docker 映像中的 cuda,所以这应该不是问题。
第 3 步:使用 CUDA 构建 docker 映像
您应该直接使用 Nvidia dockerhub docker 映像,除非您有充分的理由不这样做。就我而言,我想使用基于 Debian 的 docker 镜像,但 Nvidia 只为 Ubuntu 和 CentOS 提供镜像。幸运的是,Nvidia 为他们的图像发布了 dockerfile,所以你可以从他们那里复制他们的 dockerfile 的相关部分。我基于https://gitlab.com/nvidia/cuda/blob/ubuntu16.04/9.2/base/Dockerfile
dockerfile 的神奇部分包括:
# Install cuda manually
RUN wget https://developer.nvidia.com/compute/cuda/9.2/Prod2/local_installers/cuda_9.2.148_396.37_linux
COPY install_cuda.exp install_cuda.exp
RUN mv cuda_* cuda_install_bin && \
chmod +x cuda_install_bin && \
expect install_cuda.exp && \
rm cuda_*
# Magic copied from nvidia's cuda9.2 dockerfile at
# https://gitlab.com/nvidia/cuda/blob/ubuntu16.04/9.2/base/Dockerfile
ENV CUDA_VERSION 9.2.148
LABEL com.nvidia.volumes.needed="nvidia_driver"
LABEL com.nvidia.cuda.version="${CUDA_VERSION}"
RUN echo "/usr/local/nvidia/lib" >> /etc/ld.so.conf.d/nvidia.conf && \
echo "/usr/local/nvidia/lib64" >> /etc/ld.so.conf.d/nvidia.conf
ENV PATH /usr/local/nvidia/bin:/usr/local/cuda/bin:${PATH}
ENV LD_LIBRARY_PATH /usr/local/nvidia/lib:/usr/local/nvidia/lib64
# nvidia-container-runtime
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility
ENV NVIDIA_REQUIRE_CUDA "cuda>=9.2"
“expect”命令将允许您编写脚本以自动接受许可协议等。发布文件对我来说可能不是一个好主意install_cuda.exp
(因为我不能接受你的协议),但就我而言,我接受了 eula,同意将其安装在不受支持的操作系统上,没有安装图形驱动程序,确实安装了 cuda,使用了默认路径,安装了指向 usr/local/cuda 的符号链接并且没有安装示例。有关 expect 的更多信息,请参阅手册页[此处的在线手册页]。检查文件主要由以下行组成expect -- "(y)es/(n)o/(q)uit:" { send "y\r" }
您应该检查是否可以使用您自己的容器为 nvidia-smi 运行 nvidia-smi 测试命令。(即docker run --runtime=nvidia -it your_image_here /bin/sh
)
第 4 步:让它在 gitlab-ci 中运行。
在网络上进行研究时,大多数消息来源都告诉您,您无法--runtime
从 gitlab 运行器配置中提供标志。实际上,根据这个合并请求,您可以。为此,您必须编辑/etc/gitlab-runner/config.toml
并添加runtime = "nvidia"
到正确的位置。例如,我的运行器配置如下所示:
[[runners]]
name = "docker-runner-test"
url = "<<REDACTED>>"
token = "<<REDACTED>>"
executor = "docker"
[runners.docker]
tls_verify = false
image = "build_machine"
privileged = false
disable_cache = false
runtime = "nvidia"
volumes = ["/cache"]
pull_policy = "never"
shm_size = 0
[runners.cache]
推荐阅读
- c - GCC 中的嵌套函数现在安全吗?GNU C 中的类定义
- r - 如何将列表元素名称分配给 sheetName
- python - t-SNE算法中如何选择维数
- java - 用于查找表的 Spring data Jpa 与 Spring Jdbc
- javascript - 如何检查 DOM 元素是否正确嵌套
- c++ - C++ 类设计问题。将类与其他类和数量相关联
- django - Django 从名称列表中查询值
- xcode - SwiftUI 预览:如果自定义按钮样式在其他文件中,则预览失败
- jinja2 - 如果 Jinja 中的值为空,则隐藏属性定义?
- r - Cox PH 模型的生存曲线。检查我对绘制它们的理解