k8s环境部署gpu以及CUDA兼容性分析

news2024/10/7 12:29:26

本文记录和学习在实用gpu搭建k8s支持上层应用时的功能实践和遇到的问题。

1. 基础概念

CUDA本质上就是NVIDIA专为通用高性能并行计算设计的一套计算平台和编程模型,换句话使用GPU并行编程的规范方法,所以CUDA在软件层面包含了众多库, 那这里我们用一张图来简单阐述CUDA的各类运行时以及库的关系。

从最底层开始CUDA Driver(也就是常说的GPU驱动):可以认为是最底层的操作GPU的接口,作为直接与GPU设备打交道,其变成难度很大,但是性能更好。而CUDA Runtime(也就是常说的CUDA库):更多是面向CUDA应用开发人员,其API更加简化,可编程性更高,而基于CUDA Runtime接口再向上封装了更多的面向专用计算场景的库,例如专用于深度学习的cuDNN库等。最后,应用层可以使用CUDA Library或者直接使用CUDA Runtime API实现其功能。

我们都知道想要使用GPU训练程序,那么必须要从nividia官方选择安装对应GPU机型的驱动文件。而官方提供的是一个叫做CUDA toolkit打包的东西,这个本质上是CUDA相关库和工具的集合,例如你如果选择 runfile方式安装 ,从官方下载下来的run文件(eg:cuda_11.0.3_450.51.06_linux.run),本身其中包括了CUDA Runtime(CUDA库),CUDA Driver (GPU驱动),还有样例代码,用户可以通过命令选择,需要安装CUDA库还是GPU驱动,还是说两者都安装。

另外nvidia-smi本质上是直接使用CUDA driver库,所以说和系统中安装的CUDA Runtime(即CUDA版本)无关.

1.1 CUDA Version/Driver Version/兼容原则

nvidia-smi中显示的CUDA Version本质上是DRIVER API COMPATIBILITY VERSION,换句话理解就是根据机器上当前GPU的Driver驱动版本,CUDA Version显示的是与驱动匹配的最高兼容的CUDA Runtime版本(下文都我们简称CUDA Runtime为CUDA,简单理解就是你可以在机器中安装的cuda动态/静态链接库的最高版本,CUDA driver简称为driver或驱动)。

下面从源码/二进制/cubin三个角度具体说说兼容性,这有助于更好的排查“为什么我的训练代码在这台机器上跑不起来”的问题。

1.1.1 兼容性原则一:源码级别不兼容性

所谓源码不兼容很好理解,例如用户的代码是基于cuda 10.1这一特定版本对应的API库构建的,那么如果用户升级到cuda11.0的对应API库,则可能无法正常运行。需要用户根据cuda11.0对应的API文档修改代码再进行编译构建。

所以我们可以看到pytorch,针对不同的cuda版本,都有对应不同的编译后的库,例如下面两个就是分别基于cuda11.1(torch-1.10.1%2Bcu113-cp37-cp37m-linux_x86_64.whl)和cuda11.3(torch-1.10.0%2Bcu111-cp36-cp36m-linux_x86_64.whl)不同的cuda版本构建的。

1.1.2. 兼容原则二:后向兼容

        后向兼容的意思是:如果一个程序使用的CUDA版本可以在某一Driver版本下运行,那么在升级了Driver后,此程序在保持原CUDA版本的情况下,仍然可以在新的更高版本的驱动下运行。换句话说,某一具体的cuda版本存在与之对应的最小驱动版本。而对于cuda11和cuda10这两个主版本下,兼容的情况也有细微的却别。兼容性对照表可以查看。

1. 对于cuda11主版本(cuda版本是X.Y.X三段式,其中X为主版本号,Y为次版本号),那么对于以11开头的所有CUDA版本来说,只要driver版本>=450.80.02*, 则即可满足所有的CUDA11.0,11.1,11.2等以11.x开头的CUDA运行时版本。这种兼容模式称作为为次版本兼容(Minor Version Compatibility)。当然这种兼容是“limited feature-set”,换句话说满足在保持驱动不变下,升级cuda版本后,运行不出错,但是对于一些高版本的cuda的特性,如果要更好的使用或者性能,也需要升级driver驱动。比如对于cuda11.2,官方的cuda toolkit包中推荐安装的driver是>=460.00。

我们用的devcloud GPU是一个vGPU实例,把Tesla T4 从一个GPU虚拟化出两个vGPU分配给两台虚拟机,nvidia-smi显示Driver Version为450.102.04,而CUDA Version显示的是11.0,通过上文的说明,可以发现此虚拟机支持包括11.x在内的所有cuda11版本,而CUDA Version显示的可以认为是最高兼容的CUDA“主版本”。这里验证的方法也很简单,可以在devcloud GPU机器中安装任意的cuda10.x/cuda11.x,通过编译cuda sampler示例中的deviceQuery程序验证。

2. 对于cuda10这主版本,每一个cuda10.x的版本都有与之对应的最小驱动版本号,例如下图是截取自CUDA Compatibility :: NVIDIA Data Center GPU Driver Documentation 。可以看到cuda10.0/10.1/10.2对应的最小满足的版本号均不一样,不同于cuda11.x,可以在驱动不变的情况下升级cuda,cuda10.x,想要升级从10.1升级到10.2,那么驱动版本必须要大于等于440.33。

安装cuda11.2,则显而易见编译后运行上文的deviceQuery程序会返回错误。

而对于devcloud GPU来说,虚拟机中的驱动都是450.102.04,因此可以支持任意cuda11及以下的CUDA Runtime。

1.1.3. 兼容原则三:有限的前向兼容

后向兼容是需要在cuda升级后,驱动也需要根据要求进行升级(或者不变)。而前向兼容的意思就是,在cuda升级后,driver不需要对内核态相关包进行升级,而只需要变更相关用户态文件即可。目的就是可以在老旧驱动上基于新的cuda版本编译程序,从而获取到最新的cuda特性。 而为什么说是有限的兼容,主要表现在两点限制:1. 限制了GPU卡的类型,只有NVIDIA Data Center/Tesla 系列(和小部分特殊的RTX)的GPU卡. 2. 前向兼容的能力理论上只有在需要跨cuda主版本的时使用,例如本来最高只支持cuda版本10.1的Driver418,可以通过安装正确的Compat Package,使其在不更新内核态驱动的情况,支持cuda10.1~cuda11.6。具体可以参考官方文档的前向兼容矩阵,来下载安装对应的兼容包。CUDA Compatibility :: NVIDIA Data Center GPU Driver Documentation

1.1.4. 兼容性原则四:cuda应用程序编译产物与不同GPU架构间的兼容

这部分的兼容性原则理解起来,需要涉及到cuda应用程序编译的相关知识。一个写好的cuda程序,通过nvcc编译后的产物可以包含两种形式,一个是二进制的cubin对象,另一个是PTX(Parallel Thread Execution)汇编代码。

cubin是特定于指定的GPU架构的,cubin二进制对象对于GPU架构的计算能力(计算能力只是代表一个GPU的能力特性与性能高低无关)是一个向后兼容的,并且对GPU计算能力也是类似Minor Version Compatibility,换句话说,为计算能力为X.y的GPU生成的cubin对象,只能在计算能力为X.z且z>=y的GPU上运行。举个例子:为7.0计算能力生成的cubin,可以在7计算能力为7.5的GPU上执行,但是无法在计算能力为8.0的GPU上执行。

那对于编译成PTX形式的产物,在cuda应用程序运行加载时,会先由设备驱动程序进一步把PTX通过JIT技术(即时编译)编译成对应GPU架构或者计算能力的cubin,这也就意味着此PTX可以在计算能力高于当前生成的此PTX计算能力的GPU上运行。关于更多JIT的内容可以参考:Programming Guide :: CUDA Toolkit Documentation

因此,如果一个cuda应用程序在编译时选择包含PTX相关产物,“理论上”可以更好的保证在GPU架构升级后,代码仍然可以兼容运行,换句话说,理论上一个原先使用cuda10.x编译且可以在Volta架构V100上运行的应用,选择选择生成PTX二进制代码,那么可以在Ampere架构的A100上运行。

但是回到一个具体的案例,事实上对于pytorch,由于受制于使用的cuDNN与GPU架构升级的兼容的原因(cuDNN7与Ampere架构不兼容),以及pytorch使用pip wheel安装或者conda安装(pytorch在编译过程根据不同的安装方式会选择不同的编译模式,例如conda安装会选择使用包含PTX的二进制版本,而pip wheel安装可能不会包含),想要使用A100机器训练,必须升级到cuda11且cuDNN8以上版本的pytorch来可以使用。

换句话说,GPU的架构在一定程度上限制了cuda的版本(注:计算能力只是代表一个GPU的能力特性与性能高低无关)关于更多关于编译链接的内容,可以参考官网文档:NVCC :: CUDA Toolkit Documentation

1.2. 归根还是容器中"挂载"宿主机的"文件"

我们的devcloud GPU 带有的docker,事实上是把原来底层用来通过操作系统调用创建运行容器的“runc”组件替换为nvidia-container-runtime组件(关于runC的一些概念,可以参考从kubernetes中容器生态窥探设计模式的哲学),当然nvidia-contianer-runtime本质上是一个做了修改后的runc组件,区别是它增加了一个自定义的prestart hook,目的是在创建容器后,在启动容器前,调用这个hook,而这个hook本身做的就是一些类似将宿主机的device/driver文件等挂载进容器中。下图为NVIDIA官网介绍NVIDIA Container的大致架构组件图。

那到底具体将宿主机的哪些设备文件挂载进了容器呢。我们可以打开nvidia-container-runtime的debug功能,详细在其日志中查看所有文件设备挂载列表,具体为修改/etc/nvidia-container-runtime/config.toml文件

[nvidia-container-cli]
environment = []
debug = "/var/log/nvidia-container-toolkit.log"
load-kmods = true
ldconfig = "@/sbin/ldconfig"
[nvidia-container-runtime]
debug = "/var/log/nvidia-container-runtime.log"

打开debug功能后,我们重新通过docker 启动一个容器

docker run  --rm --gpus '"device=0"' --net host  -it mirrors.tencent.com/shadow_test_xiaobaihe/test_for_light:torch_ptx /bin/bash

启动成功后,我们发现可以使用nvidia-smi命令查看挂载进容器的GPU情况。明明我的镜像中没有nvidia-smi这个二进制程序,为什么启动后文件就可以直接使用呢?那么秘密事实上就在nvidia-container-toolkit这个prehook内帮我们完成了。打开上方的/var/log/nvidia-container-toolkit.log文件,可以详细的查询到整个hook过程。

其中我们发现,hook过程中向容器中注入了包括宿主机的二进制工具,例如nivida-smi/nvida-debugdump等,宿主机的上的库,例如很重要的CUDA Driver API库libcuda.so。另外还有很重要的是在宿主机中通过mknod创建所需的nvidia相关的设备文件,并将宿主机的文件设备文件注入到容器中。

# 注入宿主机的二进制程序
I0311 03:09:13.228302 19802 nvc_mount.c:112] mounting /usr/bin/nvidia-smi at /data/dockerimages/overlay2/05f25c9dde0a3cad98c5ec03e78fbd25ce10eb4ac52aeccac393d6645220770f/merged/usr/bin/nvidia-smi
I0311 03:09:13.228326 19802 nvc_mount.c:112] mounting /usr/bin/nvidia-debugdump at /data/dockerimages/overlay2/05f25c9dde0a3cad98c5ec03e78fbd25ce10eb4ac52aeccac393d6645220770f/merged/usr/bin/nvidia-debugdump
# 注入宿主机的CUDA Driver库
I0311 03:09:13.228463 19802 nvc_mount.c:112] mounting /usr/lib64/libcuda.so.450.102.04 at /data/dockerimages/overlay2/05f25c9dde0a3cad98c5ec03e78fbd25ce10eb4ac52aeccac393d6645220770f/merged/usr/lib64/libcuda.so.450.102.04
I0311 03:09:13.228484 19802 nvc_mount.c:112] mounting /usr/lib64/libnvidia-opencl.so.450.102.04 at /data/dockerimages/overlay2/05f25c9dde0a3cad98c5ec03e78fbd25ce10eb4ac52aeccac393d6645220770f/merged/usr/lib64/libnvidia-opencl.so.450.102.04
# 创建设备文件,并将宿主机设备文件注入到容器中
I0311 03:09:13.207136 19807 nvc.c:282] running mknod for /dev/nvidia0
I0311 03:09:13.228019 19802 nvc_info.c:705] listing device /dev/nvidia0 (GPU-40143293-c4ff-11eb-ba91-04c440212a27 at 000000    00:00:09.0)
I0311 03:09:13.280933 19802 nvc_mount.c:208] mounting /dev/nvidia0 at /data/dockerimages/overlay2/05f25c9dde0a3cad98c5ec03e    78fbd25ce10eb4ac52aeccac393d6645220770f/merged/dev/nvidia0

由此可以看到在使用nvidia-contiainer-runtime这种容器使用GPU的解决方案方案下,容器中使用CUDA Driver还有nvidia-smi都是来自于宿主机的,不需要在镜像中安装CUDA Driver。而如果在镜像中包含了CUDA driver库,可能会导致容器在hook过程中,在建立libcuda.so软链时,使用镜像中的driver库,从而可能触发上文说的"前向兼容"流程(即有可能镜像中使用的用户态的driver驱动高于宿主机的内核态的启动,从而使得GPU认为应该用前向兼容),而往往前向兼容是比较有限的,受制于GPU机型,还有驱动版本等,从而导致报错,例如可能出现forwoard compatibilty报错。

2. GPU(离线)训练任务

使用k8s中的Operator来定制我们训练任务的多机多卡Pod以及网络的等组合方式,太极平台使用kubeflow/mpi-operator方式,来创建满足all-reduce方式的通用任务。通过mpi-operator通过自定义资源定义(CRD--custom resource definition)引用MPIJob这个新的对象类型,换句话说太极平台的调度是通过Operator对CRD(例如对于通用任务来说是MPIJob这个自定义资源)进行调度,而资源的真实创建是通过virtual kubelet下方到星辰算力来完成。

3. 疑问

3.1. nvidia-smi命令中返回的CUDA Version和Driver Version的关系,以及和我运行机器/镜像中的安装的cuda库版本之间的关系?

3.2. 在docker容器中通过GPU训练,容器镜像到底需要安装什么?镜像中需要安装GPU驱动吗?

我认为很多的由于训练环境导致的训练异常,都可以从这两个问题的回答中找到原因,进而更快的定位异常点。下面我围绕这两个问题,详细的做一个回答。

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

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

相关文章

《QT实用小工具·五十一》带动画的 CheckBox

1、概述 源码放在文章末尾 该项目实现了带动画效果的多选框&#xff0c;鼠标放在上面或者选中都会呈现炫酷的动画效果&#xff0c;demo演示如下&#xff1a; 项目部分代码如下所示&#xff1a; #ifndef LINEARCHECKBOX_H #define LINEARCHECKBOX_H#include <QCheckBox> …

图像处理1,灰度,data,for循环批处理图片,图片属性查看,图片单通道查看,椒盐噪声的生成,滤波处理,图像分割

图像处理1 灰度处理data库的使用for循环批处理图像对图像属性的查看图片类型图片尺寸图片宽度图像高度通道数总像素个数最大像素值最小像素值&#xff0c;像素平均值图像点像素值 for循环分别显示图像rgb通道椒盐噪声的生成中值滤波处理高斯模糊处理图像切割 灰度处理 from sk…

多国语言免费在线客服系统源码,网站在线客服系统,网页在线客服软件在线聊天通讯平台

详情介绍 多国语言免费在线客服系统源码,网站在线客服系统,网页在线客服软件在线聊天通讯平台 新款在线客服系统全开源无加密:多商户、国际化多语言、智能机器人、自动回复、语音聊天、 文件发送、系统强力防黑加固、不限坐席、国际外贸、超多功能 支持手机移动端和PC网页…

如何从Mac电脑恢复任何删除的视频

Microsoft Office是包括Mac用户在内的人们在世界各地创建文档时使用的最佳软件之一。该软件允许您创建任何类型的文件&#xff0c;如演示文稿、帐户文件和书面文件。您可以使用 MS Office 来完成。所有Microsoft文档都可以在Mac上使用。大多数情况下&#xff0c;您处理文档&…

私有开源LLM实例的三个考虑因素

原文地址&#xff1a;three-considerations-for-private-open-source-llm-instances 2024 年 4 月 29 日 在生产应用中使用商业 LLM APIs 会带来明确且经过充分研究的风险。因此&#xff0c;企业越来越多地转向利用开源的私有托管LLM实例&#xff0c;并通过RAG技术进行增强。 介…

RCE学习

从最近的xyctf中&#xff0c;最大的感受就是自己的rce基础并不牢固&#xff0c;所以马上来恶补一下 漏洞成因 php和其他语言有很多能够执行系统命令或执行其他php代码的函数&#xff0c;因为开发者的使用不当&#xff0c;使得用户能够控制传递给执行命令的函数的参数&#xf…

【C++题解】1300. 小明暑假的零花钱

问题&#xff1a;1300. 小明暑假的零花钱 类型&#xff1a;多分支结构 题目描述&#xff1a; 小明同学的妈妈在期末考试之后决定根据小明的考试成绩奖励小明不同的暑假零花钱&#xff0c;如果考试成绩在90 分以上&#xff08;包括 90 分&#xff09;&#xff0c;零花钱是成绩…

clang:在 Win10 上编译 MIDI 音乐程序

先从 Microsoft C Build Tools - Visual Studio 下载 1.73GB 安装 "Microsoft C Build Tools“ 访问 Swift.org - Download Swift 找到 Windows 10&#xff1a;x86_64 下载 swift-5.10-RELEASE-windows10.exe 大约490MB 建议安装在 D:\Swift\ &#xff0c;安装后大约占…

【Linux系统编程】32.线程同步、锁的使用、互斥锁管理

目录 线程同步 锁的使用 注意事项 pthread_mutex_init 注意 参数mutex 参数attr 返回值 动态初始化 静态初始化 pthread_mutex_destroy 参数mutex 返回值 pthread_mutex_lock 参数mutex 返回值 pthread_mutex_unlock 参数mutex 返回值 pthread_mutex_trylo…

JAVA面试之MQ

如何保证消息的可靠传输&#xff1f;如果消息丢了怎么办 数据的丢失问题&#xff0c;可能出现在生产者、MQ、消费者中。 &#xff08;1&#xff09;生产者发送消息时丢失&#xff1a; ①生产者发送消息时连接MQ失败 ②生产者发送消息到达MQ后未找到Exchange(交换机) ③生产者发…

Python | Leetcode Python题解之第64题最小路径和

题目&#xff1a; 题解&#xff1a; class Solution:def minPathSum(self, grid: List[List[int]]) -> int:if not grid or not grid[0]:return 0rows, columns len(grid), len(grid[0])dp [[0] * columns for _ in range(rows)]dp[0][0] grid[0][0]for i in range(1, r…

WPF基础应用

WPF参考原文 MVVM介绍 1.常用布局控件 1.1 布局控件 WPF&#xff08;Windows Presentation Foundation&#xff09;提供了多种布局容器来帮助开发者设计用户界面&#xff0c;以下是一些常用的布局&#xff1a; Grid: Grid是最常用的布局容器之一&#xff0c;它允许你通过定…

计算机网络-408考研

后续更新发布在B站账号&#xff1a;谭同学很nice http://【计算机408备考-什么是计算机网络&#xff0c;有什么特点&#xff1f;】 https://www.bilibili.com/video/BV1qZ421J7As/?share_sourcecopy_web&vd_source58c2a80f8de74ae56281305624c60b13http://【计算机408备考…

【论文阅读笔记】TS2Vec: Towards Universal Representation of Time Series

【论文阅读笔记】TS2Vec: Towards Universal Representation of Time Series 摘要 这段文字介绍了一个名为TS2Vec的通用框架&#xff0c;用于学习时间序列数据的表示&#xff0c;可以在任意语义层次上进行。与现有方法不同&#xff0c;TS2Vec通过对增强的上下文视图进行层次化…

C语言指针进阶_字符指针、指针数组、数组指针、函数指针等的介绍

文章目录 前言一、字符指针二、指针数组三、 数组指针1. 数组名和 & 数组名2. 数组指针3. 数组指针解引用 四、数组指针的使用二维数组的传参说明数组指针使用小测验 五、数组传参和指针传参1. 一维数组传参总结2. 二维数组传参总结3. 一级指针传参4. 二级指针传参 六、函数…

React Context

Context https://juejin.cn/post/7244838033454727227?searchId202404012120436CD549D66BBD6C542177 context 提供了一个无需为每层组件手动添加 props, 就能在组件树间进行数据传递的方法 React 中数据通过 props 属性自上而下(由父及子)进行传递&#xff0c;但此种用法对…

Git使用指北

目录 创建一个Git仓库本地仓库添加文件文件提交到本地仓库缓冲区添加远程仓库地址本地仓库推送到远程仓库创建新的分支拉取代码同步删除缓冲区的文件&#xff0c;远程仓库的文件.gitignore文件 创建一个Git仓库 Git仓库分为远程和本地两种&#xff0c;远程仓库如Githu上创建的…

每天五分钟深度学习框架pytorch:如何创建多维Tensor张量元素?

本文重点 上节课程我们学习了如何创建Tensor标量,我们使用torch.tensor。本节课程我们学习如何创建Tensor向量,我们即可以使用torch.Tensor又可以使用torch.tensor,下面我们看一下二者的共同点和不同点。 Tensor张量 tensor张量是一个多维数组,零维就是一个点(就是上一…

Java零基础入门到精通_Day 9

1.ArrayList 编程的时候如果要存储多个数据&#xff0c;使用长度固定的数组存储格式&#xff0c;不一定满足我们的需求&#xff0c;更适应不了变化的需求&#xff0c;那么&#xff0c;此时该如何选择呢? 集 合 集合类的特点:提供一种存储空间可变的存储模型&#xff0c;存储的…

EMP.DLL是什么东西?游戏提示EMP.DLL文件缺失怎么解决

emp.dll文件是Windows操作系统中的一种动态链接库文件&#xff0c;它被设计为可以被多个程序共享使用的模块化文件。这种设计旨在提高系统效率&#xff0c;减少内存消耗&#xff0c;并简化软件的维护和更新。DLL文件通常包含了一系列相关的函数和变量&#xff0c;这些函数和变量…