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 整体工作架构

软硬件基础

  1. 硬件,服务器上安装了英伟达 GPU

  2. 宿主机,安装了操作系统和 Cuda Driver,以及 Docker 引擎

  3. 容器,包含容器 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

因此需要实现:

  1. 在容器内应用程序可调用 CUDA Runtime API 和 CUDA Libraries

  2. 在容器内能使用 CUDA Driver 相关库。因为 CUDA Runtime API 其实就是 CUDA Driver API 的封装,底层还是要调用到 CUDA Driver API

  3. 在容器内可操作 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 驱动、设备到容器内部的详细过程。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/703298.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全球冰川均衡调整(GIA)数据下载链接汇总(续)

前一专栏我们介绍了一些常用的GIA模型和对应的下载地址,但是不少数据是提供的球谐数据,对于部分用户使用不方便,这里分享NASA发布的几个格网的GIA(PGR)模型产品,其下载地址为:Files (nasa.gov) …

迅速了解Ascii、GBK、Unicode、UTF-8、BCD各种编码格式的由来及关系!

《嵌入式工程师自我修养/C语言》系列——迅速了解Ascii、GBK、Unicode、UTF-8、BCD各种编码格式的由来及关系 一、Ascii编码二、GBK编码三、Unicode编码四、UTF-8编码五、BCD编码六、其他网友的总结 快速学习嵌入式开发其他基础知识?>>>>>>>&g…

什么是代码签名证书中的“硬证书”?

代码签名证书是用于验证和签名软件程序的一种数字证书。使用代码签名证书,可以保护代码完整性、防止非法篡改,标识软件发行商的身份并确保软件来源可信。按不同验证级别,代码签名证书分为扩展验证型EV代码签名证书、企业验证型OV代码签名证书…

5.2 Ajax 数据爬取实战

目录 1. 实战内容 2、Ajax 分析 3、爬取内容 4、存入MySQL 数据库 4.1 创建相关表 4.2 数据插入表中 5、总代码与结果 1. 实战内容 爬取Scrape | Movie的所有电影详情页的电影名、类别、时长、上映地及时间、简介、评分,并将这些内容存入MySQL数据库中。 2、…

智慧城市与数字孪生:共创未来城市新篇章

一、引言 随着科技的飞速发展,智慧城市与数字孪生已成为现代城市建设的核心议题。智慧城市注重利用先进的信息通信技术,提升城市治理水平,改善市民生活品质。而数字孪生则通过建立物理城市与数字模型之间的连接,为城市管理、规划…

SpringBoot自带的tomcat的最大连接数和最大的并发数

先说结果:springboot自带的tomcat的最大并发数是200, 最大连接数是:max-connectionsaccept-count的值 再说一下和连接数相关的几个配置: 以下都是默认值: server.tomcat.threads.min-spare10 server.tomcat.threa…

【Python笔记-设计模式】组合模式

一、说明 组合模式是一种结构型设计模式, 你可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们。 (一) 解决问题 处理树形结构:可以很好地处理树形结构的数据,使得用户可以统一对待单个对象和对象组合。统一接…

17.openEuler操作系统启动管理

openEuler OECA认证辅导,标红的文字为学习重点和考点。 如果需要做实验,建议安装麒麟信安、银河麒麟、统信等具有图形化的操作系统,其安装与openeuler基本一致。 1.系统启动流程介绍 Linux系统启动流程: POST->Bios->Grub->kernel+initrd->systemd(init)->…

【计算机网络】1.4 接入网和物理媒体

1.4 接入网和物理媒体 问题:怎样将端系统和边缘路由器连接? 答:有线方式(住宅接入网络、单位接入网络等)或无线方式(无线接入网络)。 有线接入方式 光纤同轴混合网是基于已有的有线电视网开发的…

《Docker 简易速速上手小册》第9章 Docker 与持续集成(2024 最新版)

文章目录 9.1 持续集成的基本概念9.1.1 重点基础知识9.1.2 重点案例:Python Web 应用的 CI 流程9.1.3 拓展案例 1:Python 数据分析项目的 CI9.1.4 拓展案例 2:Python 微服务的 CI/CD 9.2 Docker 在 CI/CD 中的应用9.2.1 重点基础知识9.2.2 重…

关于使用Mxnet GPU版本运行DeepAR报错解决方案

1.引言 我们经常使用GPU来训练和部署神经网络,因为与CPU相比,它提供了更多的计算能力。在本教程中,我们将介绍如何将GPU与MXNet GluonTS一起使用。 首先,确保您的机器中至少有一个Nvidia GPU,并正确安装了CUDA以及CUDN…

C++动态链接库;C++链接库链接到C#上

1.在创建项目中选择动态链接库,如果没有可以从右侧搜索,如果还没有重新安装安装包点击修复增加相应功能 2.点击下一步,可以修改项目名称和目录位置点击创建完成项目创建 3.在新建项目内添加新的头文件(.h),…

modbus-tcp协议详解

本文参考:Modbus协议中文版【完整版】.pdf,加上自己的理解的记录,该文章主要讲modbus-TCP协议。(文档下载链接:【免费】modbus协议中文详细解释文档资源-CSDN文库) 本系列文章分为三章: 1.mod…

Cubase学习:Cubase 12常用快捷键

按键盘上的上下箭头就可以让选中的音符向上或向下移动 数字0键: 停止 Ctrl+数字 0 键: 新建视图层 Alt+数字0 键: 重新设置视图层 小数点键: 播放指针回零点 数字1 键: 左定位指针 数字 2 键: 右定位指针 数字3 键--数字9键: 分别控制 3--9 的7个定位标志 Alt+数字1 键--数字9键…

HuggingFists系统功能介绍(5)--环境资源

模型库 模型库用于管理由HuggingFists系统自己生成的或者外部导入的各种模型。如:HuggingFace网站提供的各类模型可导入该模块进行统一管理及部署。该功能目前在HuggingFists的社区版中并未提供。 环境管理 环境管理-工作节点 环境管理-服务配置 环境管理主要用于与…

protobuf简单使用(二)

介绍 上一节中,我们介绍了protobuf,简单来说,它是一种消息数据格式,其作用类似于json,但是比json的使用效率要高。 除此以外,我们介绍了protobuf的简单使用,也就是如何可以像使用json一样&…

2627. 函数防抖

说在前面 🎈不知道大家对于算法的学习是一个怎样的心态呢?为了面试还是因为兴趣?不管是出于什么原因,算法学习需要持续保持。 题目描述 请你编写一个函数,接收参数为另一个函数和一个以毫秒为单位的时间 t &#xff0…

Linux之vim的使用详细解析

个人主页:点我进入主页 专栏分类:C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 算法 欢迎大家点赞,评论,收藏。 一起努力,一起奔赴大厂 目录 一.vim简介 二.vim的基本概念 三.vim的基本操作 3.1准备 …

状态空间模型(SSM)

论文:A new approach to linear filtering and prediction problems http://160.78.24.2/Public/Kalman/Kalman1960.pdf 状态空间模型介绍 术语状态空间模型具有非常广泛的含义,它简单地表示任何具有潜在状态的循环过程的概念。 它已被用来指代不同学科…

MySQL数据库进阶第四篇(视图/存储过程/触发器)

文章目录 一、视图简单介绍与基础语法二、视图的检查选项三、视图的更新四、视图的作用五、存储过程的概念与特点六、存储过程的 创建,调用,查看,删除七、存储过程 — 系统变量八、存储过程 — 用户定义变量九、存储过程 — 局部变量十、存储…