写点什么

GPU 虚拟机创建时间深度优化

  • 2020-09-02
  • 本文字数:2626 字

    阅读完需:约 9 分钟

GPU虚拟机创建时间深度优化

从公有云服务商那里购买过虚拟主机的资深用户,一般会发现这么个规律:创建一台 CPU 虚拟主机是比较快的,但是要创建一台包含 GPU 卡的虚拟主机通常需要等比较长的时间,整个创建过程短则数十秒钟,长则数分钟。对于绝大多少的用户来说,虚拟主机的创建时间长一点对他们影响并不大,因为创建虚拟机属于相对低频操作。但是也会有一些特定的用户由于其业务场景交互性比较强,会对虚拟主机的创建时间有相对苛刻的要求,因为过长的创建时间会导致其业务用户体验很差。本文将从虚拟化的角度来介绍 GPU 虚拟主机创建时间长背后的原因,以及相关的优化方法。


通过分析 Libvirt, QEMU 以及 Guest 内的相关日志及对应的时间戳,可以获取 GPU 虚拟主机在创建过程中的耗时情况,这里我们主要关心几个关键的时间点: a) Libvirt 开始创建 QEMU 进程;b) Libvirt 执行 Resume 启动 VCPU ; c) Guest kernel 打印第一条日志. 在本文中,我们把 a 和 b 之间的时间间隔称为 QEMU 初始化时间, 把 b 和 c 之间的时间间隔称为 BIOS 执行时间。以下数据是在滴滴云的线上环境中采集到的创建一台包含 8 个 CPU 核虚拟机实例的相关数据:



从上面的数据可以看到,对于规格相同的虚拟机实例,带 1 块 P40 卡的 GPU 实例相比同规格的 CPU 实例在 QEMU 初始化及 BIOS 执行部分的时间都明显要长, 在带 4 块 P40 卡以及更大内存规格的场景下,需要的时间会进一步拉长。通过实验我们发现在主机配置和 GPU 卡型号确定的前提下,GPU 实例的创建时间长短主要取决于两个因素:虚拟机的内存大小和 GPU 卡的数量。


为什么 GPU 实例的创建过程要比 CPU 实例的创建过程耗时长?多消耗的时间到底花在哪里?要搞清楚原因需要深入的分析,比较直观的办法就是通过 perf 采样来生成火焰图,以此来分析虚拟机在创建过程中的热点函数。下图是在滴滴云环境里抓取到的 GPU 虚拟机启动过程中 QEMU 进程的火焰图。



通过对代码调用关系的分析,可以得知热点发生在系统分配内存和对内存页面清零的过程中,是由 QEMU 中的 vfio_dma_map 函数在执行 VFIO_IOMMU_MAP_DMA ioctl 系统调用所触发,该调用会 Pin 住所有分配给 VM 当做 RAM 使用的内存。在 Pin 内存的过程中,如果虚拟内存对应的物理页面尚未分配,会先进行物理内存分配并对内存页面内容进行清零。在 Linux kernel 中,对分配给应用程序的内存进行清零主要是基于安全方面的考虑,避免 Host 内存中的内容泄漏给用户空间的应用程序。这里之所以要将内存 Pin 住,目的是为了保证 IOMMU IO 页表和 host HVA->HPA 映射的一致性,否则 Guest 内设备的 DMA 操作可能会访问到错误的内存页面。


VFIO DMA 映射处理慢可以在一定程度上解释为什么内存的大小和 GPU 卡的数量会影响到 GPU 实例的创建时间。虚拟机实例内存规格越大,需要映射和 Pin 住的内存量也就越大,相关处理的耗时和内存量成正比。另外 GPU 卡上通常会包含一块比较大的 MMIO 区域,对 MMIO 的映射也会耗费较多的时间,卡的数量越多,耗时就会越长。相比之下,CPU 实例的创建过程没有 VFIO DMA 映射的相关处理流程,因此会比较快。


针对以上的热点,有什么办法可以消除或者缓解呢?已经有业内的同行们提到过这个问题并给出了对应的解决方案,其思路是对分配给 VM 用作 RAM 使用的内存区域做一个标记,在内核中跳过对标记的内存页面进行清零,而将清零的动作留给 QEMU 来做,在 QEMU 中可以利用多线程以及更高效的指令进行清零动作,从而加速 Pin 内存的过程。该方案的缺陷主要有两点: 一是存在安全性风险,其他应用程序可以利用设定的标记来窥探 host 内存中的信息;二是在 VM 实例的 VCPU 个数比较少的情况下,优化效果不是很好。


我们采用了另外一种方案,通过修改 Host kernel 的内存管理部分, 我们实现了一种对 Host 上空闲物理内存提前进行清零的机制,清零动作可以在系统空闲的时候进行,当某个内存页面被清零后,将其对应的 struct page 进行标记,这样在需要对内存进行清零的时候,可以通过检查该标记来判断是否要执行清零动作,如果清零的标记已经被设置,就可以跳过清零的步骤。该方案避免了上述方案中的两个主要问题,同时还有其它方面的好处,主要包括以下几点:a.可以提高缺页异常处理效率,尤其是透明大页的缺页异常处理效率;b. 可以加速需要 Pin 内存及需要通过 mlock 来锁住内存的应用场景,例如使用 RDMA, QAT 硬件加速等场合;c. 可以加速内核中其他需要对内存进行清零的场景。相关补丁的 RFC 版本,我们已经提交到了 Linux kernel 社区。


另一个加速 Pin 内存的有效方法是采用大页,通过开启透明大页可以显著减少缺页处理的调用次数并加速 Pin 内存的过程。下图展示了开启透明大页以及启用空闲内存预清零机制对 GPU 实例创创建时间的影响。



以上的数据表明,在开启透明大页以及空闲内存预清零功能后,可以显著的的优化 QEMU 的初始化时间,但是 BIOS 部分的耗时依然偏长。通过进一步的分析我们发现主要的时间消耗还是在 VFIO 映射 DMA 的处理过程当中,主要有几个方面的原因:a. 映射 DMA Pin 内存需要逐页查询页表,开销较大;b. QEMU 存在对部分 IOVA 区域的反复映射及解除映射的操作。于是我们尝试在这两个方向上进行优化,通过采用批量处理的方法减少查询页表的开销,另外在 QEMU 中加入 VFIO DMA 映射区域的管理,有效的规避了效率低下的反复映射及解除映射操作,最终大幅度降低了 VFIO DMA 映射的时间消耗。


在解决完上述问题后我们并没有止步,对虚拟机实例创建过程中的可优化的其它地方,我们也做了相关的处理,例如关闭 BIOS boot menu ,优化 VFIO PCI 设备 reset 的流程,去掉对 GPU 实例来说不必要的操作,最终将 GPU 实例创建过程中虚拟化部分的时间开销减少了 90%以上,下面这张图展示了单卡小内存规格实例优化前后的耗时对比:



大内存规格和多 GPU 卡的效果更加显著,时间减少了 95%以上,相关数据如下图:



经过上述的优化,目前在滴滴云上创建一个 GPU 实例的速度比优化前显著加快,甚至比优化前创建一个 CPU 实例的速度还要快,如果用户对 GPU 实例的创建速度有比较强的需求,欢迎到滴滴云上进行体验。 除此之外,滴滴云 GPU 产品现已开通企业 0 元体验,请在滴滴技术公众号后台回复「GPU」立即获取。


作者介绍


李亮,滴滴高级专家工程师


专注于系统虚拟化研究,负责解决滴滴云底层虚拟化相关技术问题。曾就职于 Intel 开源软件中心虚拟化组,具备丰富的底层系统软件开发经验。


本文转载自公众号滴滴技术(ID:didi_tech)。


原文链接


GPU虚拟机创建时间深度优化


2020-09-02 14:031511

评论

发布
暂无评论
发现更多内容

.NET6 引入Autofac

面向对象的猫

.net6 快速上手.net6

请说说RPC的一个请求的流程是怎么样的?

热爱java的分享家

Java 架构 程序人生 编程语言 经验分享

快速剪辑-助力度咔智能剪辑提效实践

百度Geek说

架构 后端

低代码——不应该只是玩具

行云创新

云原生 低代码 开发 高效

一周信创舆情观察(11.8~11.14)

统小信uos

更改Apollo数据库为oracle

小鲍侃java

11月日更

SCTL 涅槃重生:投入 RAL 的怀抱

SphereEx

Java 数据库 大前端 ShardingSphere SCTL

制作 Flask 程序容器镜像

wong

Python flask k8s Dockerfile

dart系列之:元世界pubspec.yaml文件详解

程序那些事

flutter dart 程序那些事 11月日更

如何用EasyRecovery恢复中毒U盘中丢失的文件

淋雨

EasyRecovery

Python量化数据仓库搭建系列1:数据库安装与操作

恒生LIGHT云社区

量化投资

uniapp+若依 开发租房小程序

詹Sir

大前端

轻松搞懂MySQL的执行计划,再也不怕SQL优化了

华为云开发者联盟

MySQL 数据库 sql 执行计划 检索

基于MySQL binlog日志,实现Elasticsearch近实时同步实践

热爱java的分享家

Java 架构 程序人生 编程语言 经验分享

有一说一,阿里内部SpringBoot王者晋级之路全彩小册开源,让我开了眼

热爱java的分享家

Java 架构 面试 程序人生 编程语言

教你用SQL进行数据分析

华为云开发者联盟

Python sql 数据分析 数据 BI 分析工具

问题也许没有看上去那么简单

神策技术社区

神策数据

“阿里巴巴”再次出手,这份Github新开源303页Spring全家桶高级笔记,让你打开眼界

热爱java的分享家

Java 架构 面试 程序人生 编程语言

鱼龙混杂的低代码市场,企业选型需关注哪些重点?

优秀

低代码 企业数字化转型

肝!Spring JDBC持久化层框架“全家桶”教程

热爱java的分享家

Java 架构 程序人生 编程语言 架构师

HBase shell get命令从二进制还原真实值

WindFlying

【等保】等保3.0是什么意思?有等保3.0吗?

行云管家

网络安全 等保 等级保护 等保2.0

​Qt全球峰会2021中国站深入解读最新Qt 6.2长周期版本,助力企业数字化转型

元数据管理在数据仓库的实践应用

大数据技术指南

11月日更

SpringBoot+WebSocket实时监控异常

热爱java的分享家

Java spring 架构 程序人生 编程语言

论文解读丨LayoutLM: 面向文档理解的文本与版面预训练

华为云开发者联盟

CV 预训练 LayoutLM模型 无标注 文档理解

一文读懂Hive数据存储格式

五分钟学大数据

11月日更

【混合云小知识】混合云四种形式简单说明

行云管家

云计算 公有云 私有云 混合云 云管理

熵简技术谈 | 熵简科技在资管数据中台的探索与实践

熵简科技

数据挖掘 数据库 大数据 数据中台 数据分析

想一个问题,在高并发中,如何部署奇数个节点?

热爱java的分享家

Java 架构 程序人生 编程语言 经验分享

【高并发】从源码角度深度解析线程池是如何实现优雅退出的

冰河

Java 并发编程 多线程 高并发 异步编程

GPU虚拟机创建时间深度优化_安全_滴滴技术_InfoQ精选文章