简介
- 本案例中,vivo 人工智能推荐算法组自研的推荐服务平台,使用阿里巴巴开源大规模稀疏模型训练和预测引擎 DeepRec,在稀疏模型训练(稀疏功能、I/O优化)和高性能推理框架层面,实现其搜广推各类业务场景下,算法开发和上线的全链路优化。
- 其中,在 GPU 线上推理服务优化上,vivo 使用 DeepRec 提供的 Device Placement Optimization,以及 NVIDIA CUDA multi-stream,MPS (Multi-Process Service) / Multi-context 和 NVIDIA GPU 计算专家团队在multi-stream 基础上开发的 MergeStream 功能,显著提升了线上推理服务的 GPU 有效利用率。
Case Introduction
vivo significantly increased the GPU utilization of online inference service by Device Placement Optimization function of DeepRec, NVIDIA CUDA multi-stream, MPS (Multi-Process Service) / Multi-context, and the customized function MergeStream developed by NVIDIA DevTech team based on multi-stream.
客户简介及应用背景
vivo 人工智能推荐算法组的业务包含了信息流、视频、音乐、广告等搜索/广告/推荐各类业务,基本涵盖了搜广推各类型的业务。
为了支撑上述场景的算法开发上线,vivo 自研了集特征数据、模型开发、模型推理等流程于一体的推荐服务平台。通过成熟、规范的推荐组件及服务,该平台为 vivo 内各推荐业务(广告、信息流等)提供一站式的推荐解决方案,便于业务快速构建推荐服务及算法策略高效迭代。
图片来源于 vivo
vivo人工智能推荐算法组在深耕业务同时,在积极探索适用于搜索/广告/推荐大规模性稀疏性算法训练框架。分别探索了TensorNet/XDL/TFRA等框架及组件,这些框架组件在分布式、稀疏性功能上做了扩展,能够弥补 TensorFlow 在搜索/广告/推荐大规模性稀疏性场景不足,但是在通用性、易用性以及功能特点上,这些框架存在各种不足。
作为 DeepRec 最早的一批社区用户,vivo 在 DeepRec 还是内部项目时,就与 DeepRec 开发者保持密切的合作。经过一年积累与打磨,vivo 见证了 DeepRec 从内部项目到开源再到后续多个 release 版本的发布。在合作中,DeepRec 赋能 vivo 各个业务增长,vivo 也作为 DeepRec 深度用户,将业务中的需求以及使用中的问题积极回馈到 DeepRec 开源社区。
DeepRec (https://github.com/alibaba/DeepRec) 是阿里巴巴集团提供的针对搜索、推荐、广告场景模型的训练/预测引擎,在分布式、图优化、算子、Runtime 等方面对稀疏模型进行了深度性能优化,提供了丰富的高维稀疏特征功能的支持。基于 DeepRec 进行模型迭代不仅能带来更好的业务效果,同时在Training/Inference 性能有明显的性能提升。
图片来源于阿里巴巴
通过业务实践,在稀疏模型训练层面,vivo 使用 DeepRec 提供的基于 Embedding Variable (官方文档链接) 的动态 Embedding 功能和特征准入 (官方文档链接)/淘汰功能(官方文档链接),解决了使用 TensorFlow 原生 Embedding Layer 的三个痛点,包括可拓展性差,hash 冲突导致模型训练有损,无法处理冗余的稀疏特征;并在内部尝试对训练数据存储格式做 I/O 优化。
使用动态 Embedding 和特征准入/淘汰功能实现的收益如下:
- 静态 Embedding 升级到动态 Embedding:使用 DeepRec 的动态 Embedding 替换 TensorFlow 的静态 Embedding 后,保证所有特征 Embedding 无冲突,离线 AUC 提升 0.5%,线上点击率提升 1.2%,同时模型体积缩小 20%。
- ID 特征的利用:在使用 TensorFlow 时,vivo 尝试过对 ID 特征进行 hash 处理输入模型,实验表明这种操作对比基线具有负收益。这是由于 ID 特征过于稀疏,同时 ID 具有唯一指示性,hash 处理会带来大量的 Embedding 冲突。基于动态 Embedding,使用 ID 特征离线 AUC 提升0.4%,线上点击率提升 0.6%。同时配合 global step 特征淘汰,离线 AUC 提升 0.1%,线上点击率提升 0.5%。
在 I/O 优化上,目前 vivo 内部使用的是 TFRecord 数据格式存储训练数据,存在占用存储空间大,非明文存储的两个缺陷。而 DeepRec 的 Parquet 是一种列式存储的数据格式,能够节省存储资源,加快数据读取速度。使用 Parquet Dataset 支持读取 Parquet 文件,开箱即用,无需额外安装第三库,使用简单方便。同时,Parquet Dataset 能够加快数据读取速度,提高模型训练的 I/O 性能。
vivo 内部尝试使用 Parquet Dataset 来替换现有 TFRecord,提高训练速度 30%,减少样本存储成本 38%,降低带宽成本。同时,vivo 内部支持 hive 查询 Parquet 文件,算法工程师能够高效快捷地分析样本数据。
在高性能推理框架层面,由于在业务逐渐发展过程中,广告召回量增长 3.5 倍,同时目标预估数增加两倍,推理计算复杂度增加,超时率超过 5%,严重影响线上服务可用性以及业务指标。因此,vivo 尝试探索升级改造现有推理服务,保证业务可持续发展。vivo 借助 DeepRec 开源的诸多推理优化功能,在CPU 推理改造以及 GPU 推理升级方面进行探索,并取得一定收益。
客户挑战
在 CPU 推理优化层面,vivo 在使用 DeepRec 提供的基于 ShareNothing 架构的 SessionGroup 后,明显缓解了直接使用 TensorFlow 的 C++ 接口调用 Session::Run 而导致的 CPU 使用率低的问题,在保证 latency 的前提下极大提高了 QPS,单机 QPS 提升高达 80%,单机 CPU 利用率提升 75%。
但是经过 SessionGroup 的优化,虽然 CPU 推理性能得到改善,超时率依旧无法得到缓解。鉴于多目标模型目标塔数较多、模型中使用 Attention、LayerNorm、GateNet 等复杂结构、特征多,存在大量稀疏特征三点原因,vivo 尝试探索 GPU 推理来优化线上性能。
应用方案
Device Placement Optimization
通常,对于稀疏特征的处理一般是将其 Embedding 化,由于模型中存在大量的稀疏特征,因此 vivo 的广告模型使用大量的 Embedding 算子。从推理的 timeline 可以看出,Embedding 算子分散在 timeline 的各个阶段,导致大量的 GPU kernel launch 以及数据拷贝,因此图计算非常耗时。
图片来源于阿里巴巴
Device Placement Optimization 完全将 Embedding Layer placed 到 CPU 上,解决了Embedding layer 内部存在的 CPU 和 GPU 之间大量数据拷贝的问题。
图片来源于阿里巴巴
Device Placement Optimization性能优化明显,CPU 算子(主要是Embedding Layer)的计算集中在 timeline 的最开端,之后 GPU 主要负责网络层的计算。相较于 CPU 推理,Device Placement Optimization P99 降低 35%。
NVIDIA CUDA Multi-Stream 功能
在推理过程中,vivo 发现单流执行导致 GPU 的利用率不高,无法充分挖掘 GPU 算力。DeepRec 支持用户使用 multi-stream 功能,多 stream 并发计算,提升 GPU 利用率。多线程并发 launch kernel 时,存在较大的锁开销,极大影响了 kernel launch 的效率,这里的锁与 CUDA Driver 中 的Context 相关。因此可以通过使用 MPS/Multi-context 来避免 launch 过程中锁开销,从而进一步提升 GPU 的有效利用率。
图片来源于阿里巴巴
此外,模型中存在大量的 H2D 以及 D2H 的数据拷贝,在原生代码中,计算 stream 和拷贝 stream 是独立的,这会导致 stream 之间存在大量同步开销,同时对于在 Recv 算子之后的计算算子,必须等到MemCopy 完成之后才能被 launch 执行,MemCopy 和 launch 难以 overlap 执行。基于以上问题,NVIDIA GPU 计算专家团队在 multi-stream 功能基础上进一步优化,开发了 MergeStream 功能,允许 MemCopy 和计算使用相同的 stream,从而减少上述的同步开销以及允许 Recv 之后计算算子 launch 开销被 overlap。
图片来源于阿里巴巴
vivo 在线上推理服务中使用了 multi-stream 功能,P99 降低 18%。更进一步地,在使用 MergeStream 功能后,P99 降低 11%。
编译优化 – BladeDISC
BladeDISC(https://github.com/alibaba/BladeDISC)是阿里集团自主研发的、原生支持存在动态尺寸模型的深度学习编译器。DeepRec中 集成了 BladeDISC,通过使用 BladeDISC 内置的 aStitch 大尺度算子融合技术对于存在较多访存密集型算子的模型有显著的效果。利用 BladeDISC 对模型进行编译优化,推理性能得到大幅度提升。
BladeDISC 将大量访存密集型算子编译成一个大的融合算子,可以大大减少框架调度和 kernel launch的开销。区别于其他深度学习编译器的是,BladeDISC 还会通过优化 GPU 不同层次存储(特别是 SharedMemory)的使用来提升了访存操作和 Op 间数据交换的性能。图中可以看到,绿色是 Blade DISC优化合并的算子替代了原图中大量的算子。
图片来源于阿里巴巴
图片来源于阿里巴巴
另外,由于线上模型比较复杂,为了进一步减少编译耗时、提升部署效率,vivo 启用了 BladeDISC 的编译缓存功能。开启此功能时,BladeDISC 仅会在新旧版本模型的 Graph 结构发生改变时触发编译,如果新旧模型仅有权重变更则复用之前的编译结果。经过验证,编译缓存在保证正确性的同时,几乎掩盖了编译模型的开销,模型更新速度与之前几乎相同。在使用 BladeDISC 功能后,线上服务 P99 降低 21%。
使用效果及影响
DeepRec 提供大量的解决方案可以帮助用户快速实施 GPU 推理。经过一系列优化,相较于 CPU 推理,GPU 推理 P99 降低 50%,GPU 利用率平均在 60% 以上。此外,线上一张 NVIDIA T4 Tensor Core GPU 的推理性能超过两台 Xeon 6330 112Core 的 CPU 机器,节省了大量的机器资源。
基于 CPU 的分布式异步训练存在两个问题:一是异步训练会损失训练精度,模型难以收敛到最佳;二是随着模型结构逐渐复杂,训练性能会急剧下降。未来,vivo 打算尝试基于 GPU 的同步训练来加速复杂模型训练。DeepRec 支持两种 GPU 同步框架:NVIDIA Merlin Sparse Operation Kit (SOK) 和HybridBackend。后续 vivo 将尝试这两种 GPU 同步训练来加速模型训练。
NVIDIA 计算专家团队也与 DeepRec 技术团队深入合作,为在稀疏功能层面的 Embedding Variable GPU 支持、在同步训练层面的 Merlin SOK 集成,以及图优化层面的 Embedding 子图 Fusion 功能开发提供技术支持。
Embedding Variable GPU 支持介绍 (官方文档链接)
DeepRec 设计并提供了一套支持动态 Embedding 语义的 Embedding Variable,在特征无损训练的同时以最经济的方式使用内存资源,使得超大规模特征的模型更容易增量上线。进一步地,因为 GPU 具有强大的并行计算能力,对于 Embedding Variable 底层的 Hash Table 查找、插入等操作也具有明显的加速作用。同时,对于模型计算部分若使用 GPU,则使用 GPU 上的 Embedding Variable 也可避免 Host 和Device 上的数据拷贝,提高整体性能。因此增加了 Embedding Variable 的 GPU 支持。
GPU 版本的 Embedding Variable 通过 NVIDIA cuCollection 作为底层 Hash Table 的实现,可以明显加速 Embedding 相关的操作,而且使用方便,在具有 NVIDIA GPU 的环境中会自动启用,也可以手动放置在合适的 GPU 设备上。性能测试显示 GPU 版本相比于 CPU 版本,Embedding 部分会有 2倍 以上的加速。
分布式训练集成 Merlin SOK 介绍 (官方文档链接)
DeepMerlin SOK 是 NVIDIA Merlin 团队基于 Merlin SOK 提供的针对神经网络中稀疏操作的加速插件库,使用 DeepMerlin SOK 可对 DeepRec 中相关的 Embedding 操作进行加速和分布式训练的支持。
该 SOK 的设计理念就是希望同时兼容灵活性和高性能。在灵活性方面,使用 SOK 不会对用户使用 DeepRec 本身的功能有影响,可以和 DeepRec 提供的 Embedding Variable 完全兼容,也会集成到 DeepRec 的高级接口方便用户的使用。在高性能方面,SOK 主要从两方面去考虑,一方面,在算法设计上,通过 reduce 操作来减少搬运的数据量,另一方面,在实现上,主要通过算子融合技术,融合多表的查询和通信,提供稀疏操作的性能。性能测试显示 SOK 能够提供接近于线性的扩展能力,在 8 GPU 下相比 1 GPU 能够达到 6.5 倍的加速效果。
Embedding 子图 Fusion 功能介绍 (官方文档链接)
DeepRec 及 TensorFlow 原生的 embedding lookup 相关 API,如 safe_embedding_lookup_sparse,会创建比较多细碎的算子,且部分算子只有 CPU 实现。因此在 GPU 上执行时容易出现 kernel launch bound 的问题以及额外H2D & D2H 拷贝,造成低 GPU 利用率,降低执行速度。
针对此场景,NVIDIA 计算专家团队与 DeepRec 合作,共同定制开发了支持在 NVIDIA GPU 上执行的 Embedding 子图 Fusion 功能,并对 GPU 高算力高吞吐的特点进行了针对性优化:提供一组接口以及相关 Fusion 算子,通过算子融合,减少需要 launch 的 kernel 数量,优化访存,提供高性能的实现,达到加速执行的目的。
Embedding Fusion 功能易用,从 Python 层面提供接口及开关,用户无需修改代码即可快速使用。加速效果方面,单独从 Embedding 模块看,GPU Embedding Fusion 可以提供 2 倍左右的加速。从整体模型来看,加速效果取决于 Embedding 模块的耗时占比。在几个测试模型上,此功能可以提供 1.2 倍左右的整体性能加速。