【问题标题】:Do I need nvidia-container-runtime, and why? [closed]我需要 nvidia-container-runtime,为什么? [关闭]
【发布时间】:2020-09-25 15:57:40
【问题描述】:

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

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

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

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

所以,问题:

  • 我错过了什么?
  • 我能否使用库存的 Docker(或 podman)运行时访问我的 NVIDIA GPU?
  • 如果没有,为什么不呢?

【问题讨论】:

    标签: docker containers gpu nvidia-docker podman


    【解决方案1】:

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

    NVIDIA GPU 驱动程序包含在user space 中运行的组件以及在内核空间中运行的其他组件。这些组件协同工作,必须协调一致。这意味着驱动程序 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 代码存在的兼容性策略(“向前”),以及在谈论特定驱动程序和 @987654324 时存在的兼容性策略(“向后”) @。我也不打算提供有关使用 nvidia-container-toolkit 的说明,该说明已记录在案,并且关于它的许多问题/答案也已经存在。

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

    【讨论】:

    • 这个答案是完全不够的。我正在无根运行这些容器并且它正在工作。根据定义,无根运行的代码不是“驱动程序”。我想更多地了解它实际上在做什么,但是由于您对这种糟糕的设计的防御是可以理解的,我想我会从源头上弄清楚。感谢您的宝贵时间。
    • 如果您想查看源代码,您可以了解here 我提到的一些驱动程序“用户空间组件”,它们被安装在容器中,位于挂载时间。
    【解决方案2】:

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

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

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

    HPC 社区在不久前就发现了这一点并使其发挥作用。 Here are some old instructions 用于创建可移植的 Singularity GPU 容器,该容器在容器运行时注入所需的 NVIDIA 共享库。您可以轻松地按照类似的过程来创建可移植的 OCI 或 Docker GPU 容器。

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-06
      • 2011-05-27
      • 1970-01-01
      • 1970-01-01
      • 2020-08-28
      • 1970-01-01
      • 2012-08-26
      • 2014-09-24
      相关资源
      最近更新 更多