-2

我想从容器内部访问我的 NVIDIA GPU。我可以在没有 nvidia-container-runtime 的情况下执行此操作吗?

需要一个自定义的 Docker 运行时来与一台设备通信似乎很奇怪。那里有一整套 PCI 设备。为什么这个需要自己的运行时?例如,假设我同时拥有 NVIDIA 和 AMD GPU。我会无法从一个容器内访问两者吗?

我知道 nvidia-container-runtime 让我可以控制哪些 GPU 通过NVIDIA_VISIBLE_DEVICES. 但我不在乎这个。我没有使用容器来隔离设备;我正在使用容器来管理 CUDA/CUDNN/TensorFlow 版本 h*ll。如果我确实想隔离设备,我会使用与永远相同的机制:通过控制对 /dev 中节点的访问。

简而言之,整个“自定义运行时”设计在我看来是有缺陷的。

所以,问题:

  • 我错过了什么?
  • 我可以使用库存的 Docker(或 podman)运行时访问我的 NVIDIA GPU 吗?
  • 如果不是,为什么不呢?
4

2 回答 2

1

我当然无法回答与此相关的所有可能的问题。我会试着做一个总结。我在这里写的一些内容是基于此处此处记录的内容。我这里的讨论也将集中在 linux 和 docker(不是 windows,不是奇异,不是 podman 等)。我也不太可能能够详细解决诸如“为什么其他 PCI 设备不必这样做?”之类的问题。我也不想让我对 docker 工作原理的描述完全准确到该领域的专家。

NVIDIA GPU 驱动程序具有在用户空间中运行的组件以及在内核空间中运行的其他组件。这些组件协同工作,必须协调一致。这意味着驱动程序 XYZ.AB 的内核模式组件只能与驱动程序 XYZ.AB(而不是任何其他版本)中的用户空间组件一起使用,反之亦然。

粗略地说,docker 是一种提供隔离的用户空间 linux 存在的机制,该存在运行在 linux 内核(所有内核空间的东西所在的地方)之上,并与其接口。linux内核位于基础机器中(容器外),大部分/大部分linux用户空间代码位于容器内。这是允许您做类似在 RHEL 内核上运行 ubuntu 容器之类的工作的架构因素之一。

从 NVIDIA 驱动的角度来看,它的一些组件需要安装容器内,一些需要安装在容器

我可以使用库存的 Docker(或 podman)运行时访问我的 NVIDIA GPU 吗?

是的,你可以,这就是人们在 nvidia-docker 或 nvidia-container-toolkit 存在之前所做的。您需要在基础机器和容器中安装完全相同的驱动程序。上次我检查时,这是可行的(尽管我不打算在这里提供说明。)如果您这样做,容器内的驱动程序组件与容器外的驱动程序组件匹配,并且它可以工作。

我错过了什么?

NVIDIA(可能还有其他人)想要一个更灵活的场景。上面的描述意味着如果一个容器是用任何其他驱动程序版本(不是安装在你的基础机器上的那个)构建的,它就不能工作。这很不方便。

nvidia-docker 的最初目的是执行以下操作:在容器加载时,将存在于基础机器中的驱动程序的运行时组件安装到容器中。这协调了事情,虽然它不能解决所有的兼容性场景,但它解决了一堆问题。通过一个简单的规则“将基础机器上的驱动程序更新到最新版本”,它有效地解决了可能由不匹配的驱动程序/CUDA 运行时引起的每种兼容性情况。(CUDA 工具包和任何依赖它的东西,比如 CUDNN,只需要安装在容器中。)

正如您所指出的,随着时间的推移,nvidia-container-toolkit 已经获得了许多其他可能有用的功能。

我不会在这里花很多时间谈论编译的 CUDA 代码存在的兼容性策略(“向前”),以及在谈论特定驱动程序和支持的 CUDA 版本时存在的兼容性策略(“向后”)那个司机。我也不打算提供有关使用 nvidia-container-toolkit 的说明,该说明已经记录在案,并且关于它的许多问题/答案也已经存在。

我将无法回答诸如“为什么要这样设计?”之类的后续问题。或“那不应该是必要的,你为什么不这样做?”

于 2020-09-25T17:32:53.397 回答
0

回答我自己的问题:不,我们不需要 nvidia-container-runtime。

NVIDIA 共享库与驱动程序的每个点版本紧密耦合。NVIDIA 喜欢说“驱动程序具有在用户空间中运行的组件”,但这当然是自相矛盾的。所以对于任何版本的驱动,都需要让这些共享库的对应版本在容器内可以访问。

简要说明为什么这是一个糟糕的设计:除了额外的复杂性之外,NVIDIA 共享库还依赖于系统中的其他共享库,尤其是 C 和 X11。如果 NVIDIA 库的较新版本曾经需要较新的 C 或 X11 库的功能,则运行这些较新库的系统将永远无法托管较旧的容器。(因为容器将无法运行较新的注入库。)在新系统上运行旧容器的能力是容器最重要的特性之一,至少在某些应用程序中是这样。我想我们必须希望这永远不会发生。

HPC 社区在不久前就发现了这一点并使其工作。以下是创建可移植 Singularity GPU 容器的一些旧指令,该容器在容器运行时注入所需的 NVIDIA 共享库。您可以轻松地按照类似的过程来创建可移植的 OCI 或 Docker GPU 容器。

如今,Singularity 支持一个--nv标志来自动注入必要的共享库。它还支持--rocmAMD GPU 的标志。(是的,AMD 选择了同样糟糕的设计。)如果你需要这两个标志,大概可以组合这些标志。

所有这些细节都在Singularity 手册中有很好的记录。

底线:如果您问的问题与我相同,请尝试 Singularity。

于 2020-10-12T15:59:51.053 回答