docker容器访问GPU资源的使用指南

 更新时间:2024年02月27日 09:06:16   作者:墨鸦_Cormorant  
nvidia-docker 和 nvidia-container-runtime 是用于在 NVIDIA GPU 上运行 Docker 容器的两个相关工具,它们的作用是提供 Docker 容器与 GPU 加速硬件的集成支持,本文给大家介绍了docker容器访问GPU资源的使用指南,需要的朋友可以参考下

概述

nvidia-dockernvidia-container-runtime 是用于在 NVIDIA GPU 上运行 Docker 容器的两个相关工具。它们的作用是提供 Docker 容器与 GPU 加速硬件的集成支持,使容器中的应用程序能够充分利用 GPU 资源。

nvidia-docker

为了提高 Nvidia GPU 在 docker 中的易用性, Nvidia 通过对原生 docker 的封装提供了 nvidia-docker 工具

nvidia-docker 是一个 Docker 插件,用于在 Docker 容器中启用 NVIDIA GPU 支持。

该工具提供了一个命令行界面,允许在运行容器时通过简单的命令来指定容器是否应该访问主机上的 NVIDIA GPU 资源。

当在容器中运行需要 GPU 加速的应用程序时,可以使用 nvidia-docker 来确保容器能够访问 GPU。

# 示例命令
nvidia-docker run -it --rm nvidia/cuda:11.0-base nvidia-smi

上述命令使用 nvidia-docker 在容器中运行 NVIDIA 的 CUDA 基础镜像,并在容器中执行 nvidia-smi 命令以查看 GPU 信息

nvidia-container-runtime

nvidia-container-runtime 是 NVIDIA 的容器运行时,它与 Docker 和其他容器运行时(如 containerd)集成,以便容器可以透明地访问 NVIDIA GPU 资源。

与 nvidia-docker 不同,nvidia-container-runtime 不是 Docker 插件,而是一种更通用的容器运行时,可与多个容器管理工具集成。

nvidia-dockernvidia-container-runtime 都是用于使 Docker 容器能够访问 NVIDIA GPU 资源的工具。可以根据自己的需求选择其中一个来配置容器以利用 GPU 加速。

需要注意的是,最新的 NVIDIA Docker 支持通常建议使用 nvidia-container-runtime,因为它提供了更灵活和通用的 GPU 支持,而不仅仅是为 Docker 定制的解决方案。

# 示例命令
docker run --runtime=nvidia -it --rm nvidia/cuda:11.0-base nvidia-smi

上述命令使用 Docker 运行容器,通过 --runtime=nvidia 参数指定使用 nvidia-container-runtime 运行时,并在容器中执行 nvidia-smi 命令。

原生 docker 通过设备挂载和磁盘挂载的方式支持访问 GPU 资源

docker 本身并不原生支持 GPU,但使用 docker 的现有功能可以对 GPU 的使用进行支持

# 示例命令
docker run \
--device /dev/nvidia0:/dev/nvidia0 \
--device /dev/nvidiactl:/dev/nvidiactl \
--device /dev/nvidia-uvm:/dev/nvidia-uvm \
-v /usr/local/nvidia:/usr/local/nvidia \
-it --privileged nvidia/cuda

通过 --device 来指定挂载的 GPU 设备,通过 -v 来将宿主机上的 nvidia gpu 的命令行工具和相关的依赖库挂载到容器。这样,在容器中就可以看到和使用宿主机上的 GPU 设备了。

注意:这种方式对于 GPU 的可用性(哪些 GPU 是空闲的等)需要人为的判断,效率很低

nvidia-docker 详解

结构图及各组件说明

nvidia-docker 对于使用 GPU 资源的 docker 容器支持的层次关系:

在这里插入图片描述

Nvidia-docker的原理图以及各个部分的作用解析:

在这里插入图片描述

**libnvidia-container:**提供了一个库和简单的 CLI 工具,以实现在容器当中支持使用 GPU 设备的目标。

nvidia-container-toolkit:

是一个实现了 runC 的 prestart hook 接口的脚本,该脚本在 runC 创建一个容器之后,启动该容器之前调用,其主要作用就是修改与容器相关联的 config.json,注入一些在容器中使用 NVIDIA GPU 设备所需要的一些信息(比如:需要挂载哪些 GPU 设备到容器当中)。

nvidia-container-runtime:

主要用于将容器 runC spec 作为输入,然后将 nvidia-container-toolkit 脚本作为一个 prestart hook 加入到 runC spec 中,再用修改后的 runC spec 调 runc 的 Exec 接口运行容器。

所以在容器启动之前会调用 pre-start hook(nvidia-container-toolkit),这个 hook 会通过 nvidia-container-cli 文件,来调用libnvidia-container 库,最终映射挂载宿主机上的 GPU 设备、nvid 驱动的 so 文件、可执行文件到容器内部。

nvidia-container-runtime 才是真正的核心部分,它在原有的 docker 容器运行时 runc 的基础上增加一个 prestart hook,用于调用 libnvidia-container 库

在这里插入图片描述

RunC

RunC 是一个轻量级的工具,它是用来运行容器的,只用来做这一件事。

可以认为它就是个命令行小工具,可以不用通过 docker 引擎,直接运行容器。也是 docker 默认的容器运行方式。

事实上,runC 是标准化的产物,它根据 OCI 标准来创建和运行容器。而 OCI(Open Container Initiative)组织,旨在围绕容器格式和运行时制定一个开放的工业化标准。

直接使用 RunC 的命令行即可以完成创建一个容器,并提供了简单的交互能力。

容器创建过程

创建一个正常容器(不支持 GPU)的流程:

docker --> dockerd --> containerd–> containerd-shim -->runc --> container-process

docker 客户端将创建容器的请求发送给 dockerd,当 dockerd 收到请求任务之后将请求发送给 containerd,containerd 经过查看校验启动 containerd-shim 或者自己来启动容器进程。

创建一个支持 GPU 的容器的流程:

docker–> dockerd --> containerd --> containerd-shim–> nvidia-container-runtime --> nvidia-container-runtime-hook --> libnvidia-container --> runc – > container-process

基本流程和不支持 GPU 的容器差不多,只是把 docker 默认的运行时替换成了 NVIDIA 封装的 nvidia-container-runtime

这样当 nvidia-container-runtime 创建容器时,先执行 nvidia-container-runtime-hook,这个 hook 去检查容器是否需要使用GPU(通过环境变 NVIDIA_VISIBLE_DEVICES 来判断)。如果需要则调用 libnvidia-container 来暴露 GPU 给容器使用。否则走默认的 runc 逻辑。

NVIDIA Docker 整体工作架构

软硬件基础

  • 硬件,服务器上安装了英伟达 GPU
  • 宿主机,安装了操作系统和 Cuda Driver,以及 Docker 引擎
  • 容器,包含容器 OS 用户空间,Cuda Toolkit,以及用户应用程序

注意:

  • 宿主机上需要安装 cuda driver,容器内需要安装 cuda toolkit。容器内无需安装 cuda driver
  • NVIDIA 提供了一些官方镜像,其中已经安装好了 cuda toolkit,但还是需要在宿主机安装 cuda driver。

API 结构

NVIDIA 提供了三层 API:

  • CUDA Driver API

GPU 设备的抽象层,通过提供一系列接口来操作 GPU 设备,性能最好,但编程难度高,一般不会使用该方式开发应用程序

  • CUDA Runtime API:

对 CUDA Driver API 进行了一定的封装,调用该类 API 可简化编程过程,降低开发难度

  • CUDA Libraries:

是对 CUDA Runtime API 更高一层的封装,通常是一些成熟的高效函数库,开发者也可以自己封装一些函数库便于使用

CUDA 结构图如下:

在这里插入图片描述

CUDA 调用关系:

应用程序可调用 CUDA Libraries 或者 CUDA Runtime API 来实现功能,当调用 CUDA Libraries 时,CUDA Libraries 会调用相应的 CUDA Runtime API,CUDA Runtime API 再调用 CUDA Driver API,CUDA Driver API 再操作 GPU 设备。

CUDA 的容器化

目标:让应用程序可以在容器内调用 CUDA API 来操作 GPU

因此需要实现:

  • 在容器内应用程序可调用 CUDA Runtime API 和 CUDA Libraries
  • 在容器内能使用 CUDA Driver 相关库。因为 CUDA Runtime API 其实就是 CUDA Driver API 的封装,底层还是要调用到 CUDA Driver API
  • 在容器内可操作 GPU 设备

因此容器中访问 GPU 资源过程为:

  • 要在容器内操作 GPU 设备,需要将 GPU 设备挂载到容器里
    • Docker 可通过 --device 挂载需要操作的设备,或者直接使用特权模式(不推荐)。
    • NVIDIA Docker 是通过注入一个 prestart 的 hook 到容器中,在容器自定义命令启动前就将GPU设备挂载到容器中。
    • 至于要挂载哪些GPU,可通过 NVIDIA_VISIBLE_DEVICES 环境变量控制。
  • 挂载 GPU 设备到容器后,还要在容器内可调用 CUDA API
    • CUDA Runtime API 和 CUDA Libraries 通常跟应用程序一起打包到镜像里
    • CUDA Driver API 是在宿主机里,需要将其挂载到容器里才能被使用。
    • NVIDIA Docker 挂载 CUDA Driver 库文件到容器的方式和挂载 GPU 设备一样,都是在 runtime hook 里实现的。

注意:

该方案也有一些问题,即容器内的 CUDA Runtime 同宿主机的 CUDA driver 可能存在版本不兼容的问题。

CUDA Libraries 和 CUDA Runtime API 是和应用程序一起打包到镜像中的,而 Driver 库是在创建容器时从宿主机挂载到容器中的,需要保证 CUDA Driver 的版本不低于 CUDA Runtime 版本。

NVIDIA Docker 2.0(nvidia-container-runtime)

实现机制

  • nvidia-docker2.0 是一个简单的包,它主要通过修改 docker 的配置文件 /etc/docker/daemon.json,将默认的 Runtime 修改为 nvidia-container-runtime,可实现将 GPU 设备,CUDA Driver 库挂载到容器中。
cat /etc/docker/daemon.json 
{
    "default-runtime": "nvidia",
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}

Debug日志

修改 nvidia runc 的默认配置文件 /etc/nvidia-container-runtime/config.toml ,打开 hook 的 debug 日志选项,可以看到宿主机挂载 nvidia 驱动、设备到容器内部的详细过程。

在这里插入图片描述

以上就是docker容器访问GPU资源的使用指南的详细内容,更多关于docker访问GPU资源的资料请关注脚本之家其它相关文章!

相关文章

  • 如何使用docker部署Dashdot工具箱

    如何使用docker部署Dashdot工具箱

    dashdot是一个简洁清晰的服务器数据仪表板,基于React实现 ,主要是显示操作系统、进程、存储、内存、网络这五个的数据,这篇文章主要介绍了如何使用docker部署Dashdot工具箱,需要的朋友可以参考下
    2024-02-02
  • 使用dockercompose搭建springboot-mysql-nginx应用

    使用dockercompose搭建springboot-mysql-nginx应用

    这篇文章主要介绍了使用dockercompose搭建springboot-mysql-nginx应用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • 详解docker pull 下来的镜像都存到了哪里

    详解docker pull 下来的镜像都存到了哪里

    这篇文章主要介绍了详解docker pull 下来的镜像都存到了哪里,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • 使用Docker搭建Vsftpd 的 FTP 服务的详细过程

    使用Docker搭建Vsftpd 的 FTP 服务的详细过程

    FTP 基础FTP 需要两个端口,一个是数据端口,一个是控制端口,这篇文章主要介绍了使用Docker搭建Vsftpd的FTP服务,需要的朋友可以参考下
    2022-08-08
  • 使用Docker快速安装grafana的基本步骤

    使用Docker快速安装grafana的基本步骤

    Grafana 是一个强大的开源监控和数据分析平台,它能够与各种数据源集成,并提供灵活的可视化和仪表盘功能,下面给大家分享Docker 中安装 Grafana 的基本步骤,感兴趣的朋友一起看看吧
    2024-01-01
  • 快速使用docker-compose部署clickhouse的教程

    快速使用docker-compose部署clickhouse的教程

    ClickHouse 的工作速度比传统方法快 100-1000 倍。它适用于大数据、业务分析和时间序列数据。在这个小教程中,我将向您展示如何以最少的设置安装 ClickHouse,感兴趣的朋友一起看看吧
    2021-11-11
  • 一文快速入门Docker推荐

    一文快速入门Docker推荐

    这篇文章主要介绍了一文快速入门Docker推荐,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-06-06
  • Docker删除已存在的镜像的实现

    Docker删除已存在的镜像的实现

    本文主要介绍了Docker删除已存在的镜像的实现,删除已存在的 Docker 镜像,可以使用 docker rmi 命令,下面就来详细的介绍一下使用步骤,感兴趣的可以了解一下
    2023-08-08
  • Docker 镜像国内加速的方法汇总(收藏版)

    Docker 镜像国内加速的方法汇总(收藏版)

    本文介绍了在国内使用Docker时遇到的加速和优化方法,针对国内下载速度慢和断线问题,可以使用国内可用的DockerRegistryMirrors或自建DockerRegistryMirror/Proxy,针对没有公共镜像库账号导致的限流问题,可以注册各个镜像库账号并登录,感兴趣的朋友跟随小编一起看看吧
    2025-01-01
  • 解决Docker中的error during connect异常情况

    解决Docker中的error during connect异常情况

    这篇文章主要介绍了解决Docker中的error during connect异常情况,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11

最新评论