本文为《大模型时代的 AI 基础设施——百度 AI 大底座》系列云智公开课“AI 算力构建”模块中第二讲《GPU 容器虚拟化新能力发布和全场景实践》的内容精华,以百度智能云资深工程师王利明的演讲视角进行了整理:
今天给大家分享的主题是百度智能云在「GPU 容器虚拟化」方面的最新进展和全场景实践,希望通过这次分享和大家一起探讨如何在实际业务场景更好的应用 GPU 容器虚拟化技术。
本次分享将首先介绍百度智能云 GPU 容器虚拟化 2.0 的升级变化,然后介绍新版本中的技术实现方法并演示具体功能,最后介绍在各类业务场景的实践和探索。
我们去年发布了业内首个双引擎 GPU 容器虚拟化架构,采用了「用户态」和「内核态」两种引擎,以满足用户对隔离性、性能、效率等多方面不同侧重的需求。
在资源池化层之上是 K8s 统一资源调度层。在调度机制之上,我们会根据不同业务场景,抽象出来多种混布方式,包括共享混布、抢占混布、分时混布、潮汐混布等。
通过以上技术能力支持了各类 AI 业务的落地,包括模型开发、模型训练、在线推理等,大幅提升了 GPU 资源的使用率,减少了 GPU 的使用数量。
1.0 版本很好地满足了 AI 场景的业务需求,不管是厂内还是厂外的业务中,得到了比较广泛的应用。
我们的技术目标就是希望:吃干榨尽所有资源,覆盖所有业务场景,提升业务总体表现。所以 1.0 版本还不够完美,并没有释放 GPU 的全部能力:GPU 上的所有资源在容器虚拟化环境中并没有完全使能,更多的场景是无法使用 GPU 容器虚拟化能力的,所以今年我们继续推出了 2.0 版本。
在 2.0 版本中, 除了对 GPU 的显存和 AI 算力进行隔离之外,还实现了对 GPU 的渲染算力和编的隔离。
基于这些新的能力,在资源调度层面可以提供渲染混布和编解码混布,实现了 AI 算力、渲染算力、编等 GPU 全部资源的统一调度。
同时,2.0 版本可以通过多调度器的方式,支持客户的现有业务平滑融合到我们的架构中,这对客户业务能够快速使用最新的 GPU 容器虚拟化能力,是非常重要的。
在这些新能力的支持下,更多的业务场景,比如自动驾驶仿真、ARM 平台的云游戏等都可以通过这套平台提升资源利用率,将所需 GPU 的使用量明显降低。
除此之外,两个容器虚拟化引擎我们都会随着底层库的更新进行不断迭代,确保用户能够使用业界最新的技术。其中用户态支持最新版本 nvidia driver 和 cuda 12.1,内核态支持 nvidia driver 525/530/535 等最新版本。
在 NVIDIA GPU 上不仅能进行 AI 计算,还可以做图形的渲染计算。AI 负载通过 Cuda 访问 GPU,渲染负载通过 OpenGL/Vulkan 访问 GPU。这两类计算均使用相同的算力资源。
从上往下看,最上层的是 AI APP,它们依赖于底层的 Cuda 系列库,包括 cuda-x,cuda runtime 等,它们给上层 AI APP 提供易于使用的高级 API。再往下就是应用层 driver 库,包括 cuda driver,NVML 等,它们会通过设备文件和内核态的 driver 进行通信,最终达到使用 GPU 的目的。
架构图中灰色的箭头是 AI 程序使用 GPU 的控制流,红色的箭头是 AI 程序使用 GPU 的的数据流。
渲染算力架构,从上往下看,最上层的是 UI/3D APP,比如游戏引擎,它的底层库相比 AI 算力架构要复杂一些,调用底层库主要包括两种方式:通过转发层 GLX 调用 X11 server,或者直接调用 EGL。
最终他们都会调用底层的图形库 OpenGL 或者 Vulkan,这些图形库就相当于 AI 计算中的 Cuda 库。
架构图中灰色的箭头是渲染程序使用 GPU 的控制流,红色的箭头是渲染程序使用 GPU 的数据流。
经过以上分析和对比,我们可以发现 AI 算力架构和渲染算力架构,虽然上层软件不同,但是他们的控制流都是一致的,使用相同的设备文件和内核模块进行通信。
回到我们之前的问题,渲染负载能否在 AI 计算的隔离环境中成功运行?依据这个分析结果预测,渲染应用是可以在 AI 算力的隔离环境中运行。
经过逆向分析发现两个方案的控制命令字存在一些差异,需要将这部分差异在隔离实现中区分开来。通过大量的实验后,最终在内核层面实现了渲染算力的隔离。
因为用户态实现需要拦截的上层库函数多,实现难度高。同时,对用户的软件不透明。所以通过用户态实现渲染算力隔离并不是一个好的工程方案。
接下来我向大家演示 AI 算力和渲染算力的隔离效果。演示的硬件环境为一张 NVIDIA V100 16G。
可以看到在单个 GPU 上,AI 负载和渲染负载都实现了隔离,获得了约一半的算力,得到了预期的性能表现。
用户态的编实例中,编是裸混使用,不支持对编的算力做隔离,每个实例都可以全部编解码算力。
内核态的编实例中,我们实现了对编的隔离,在实例中编码器的权重和 AI 算力、渲染算力的权重共享,做到统一算力分配。
那么内核态和用户态的实现有什么不同呢?用户态在实例中使用的是编的全部算力,而内核态实现了编的算力分配。比如在内核态分配 20% 的算力,那么你就可以在内核态的编解码实例中使用 20% 的编解码能力。
在技术特性对比上,业务层一般会在隔离性能的强弱、延时高低、资源分配颗粒度、多用户支持能力等维度做技术考量,为应用匹配合适的 GPU 容器虚拟化引擎。
比如在线推理,对延时的要求很高,一般就会推荐用户态的方案。离线推理,则两种方案都可以选择。在渲染仿真场景,由于用户态不支持渲染隔离,故只能使用内核态的方案。
这是一个经典的互联网的推荐业务,包含了数据处理、模型开发和在线服务等业务。其中数据处理和模型开发是离线业务,用来支持在线服务,所有业务都使用了大量的 GPU。
在没有使用 GPU 容器虚拟化方案之前,每个业务实例使用一个 GPU,通过大量的监控数据发现,在线推理服务的整体 GPU 使用率并不高,整体在 20%,这是一个业界普遍存在的问题。
因为在线服务对时延要求比较高,我们在这种场景选择部署用户态的方案。在保证业务 SLA 相同的情况下,大幅提升整体 GPU 资源使用率,将整体资源利用率到 35%。
在结合用户态本身支持的抢占混布和分时混布,使得数据处理和模型开发等离线任务,可以和在线推理业务进行在离线混布,当在线业务处于波谷时,离线业务抢占较多 GPU 空闲资源进行业务处理,节省了整体的 GPU 使用数量。
这种场景在厂内和厂外都得到了大量的应。