美团视觉面向本地生活服务,在众多场景上落地应用了文字识别、图像质量评价、视频理解等视觉AI技术。此前,在线推理服务使用的GPU资源不断增加,但服务GPU利用率普遍较低,浪费大量计算资源,增加了视觉AI应用成本,这是美团也是很多企业亟需解决的问题。
美团视觉智能部通过实验分析发现,造成视觉推理服务GPU利用率低下的一个重要原因是模型结构问题:模型中预处理或者后处理部分CPU运算速度慢,导致推理主干网络无法充分发挥GPU运算性能。基于此,视觉研发团队通过模型结构拆分和微服务化,提出一种通用高效的部署架构,解决这种常见的性能瓶颈问题。
目前,该解决方案已经在多个核心服务上成功应用。以“图像检测+分类”服务为例,优化后的服务压测性能指标GPU利用率由40%提升至100%,QPS提升超过3倍。本文将会重点介绍推理服务部署架构优化的工程实践,希望对从事相关工作的同学们有所帮助或启发。
随着越来越多的AI应用进入生产应用阶段,推理服务所需要的GPU资源也在迅速增加。调研数据表明,国内AI相关行业推理服务的资源使用量占比已经超过55%,且比例未来还会持续升高。但很多公司面临的实际问题是,线上推理服务GPU利用率普遍较低,还具备很大的提升空间。
而造成服务GPU利用率低的重要原因之一是:推理服务本身存在性能瓶颈,在极限压力情况下也无法充分利用GPU资源。在这种背景下,“优化推理服务性能、提高GPU资源使用效率、降低资源使用成本”具有非常重要的意义。本文主要介绍如何通过架构部署优化,在保证准确率、推理时延等指标的前提下,提升推理服务的性能和GPU利用率。
近年来,深度学习方法在计算机视觉任务上取得显著进展,已经成为主流方法。视觉模型在结构上具有一些特殊性,如果使用现有推理框架部署,服务在性能和GPU利用率方面可能无法满足要求。
深度学习模型部署前通常会使用优化工具进行优化,常见的优化工具包括TensorRT、TF-TRT、TVM和OpenVINO等。这些工具通过算子融合、动态显存分配和精度校准等方法提高模型运行速度。模型部署是生产应用的最后一环,它将深度学习模型推理过程封装成服务,内部实现模型加载、模型版本管理、批处理以及服务接口封装等功能,对外提供RPC/HTTP接口。业界主流的部署框架有以下几种:
在实际部署中,无论选择哪种框架,需要同时考虑模型格式、优化工具、框架功能特点等多种因素。
与传统方法不同, 深度学习是一种端到端的方法,不需要单独设计特征提取、分类器等模块,用单个模型取代传统方法多模块任务。深度学习模型在分类、检测、分割、识别等视觉任务上呈现出巨大优势,做到了传统方法无法达到的精度。常用的视觉分类模型(如ResNet、GoogleNet等)和检测模型(如YOLO、R-FCN等)具有如下特点:
由于视觉模型存在的上述特点,导致模型在部署和优化上存在2个问题:
这两点常见的模型部署问题,导致视觉推理服务存在性能瓶颈、GPU利用率低,即便Triton这种高性能部署框架也难以解决。
通用部署框架重点关注的是“通信方式、批处理、多实例”等服务托管方面的性能问题,但如果模型本身中间某个部分(如图像预处理或后处理)存在瓶颈,优化工具也无法优化,就会出现“木桶效应”,导致整个推理过程性能变差。因此,如何优化推理服务中的模型性能瓶颈,仍然是一件重要且具有挑战性的工作。
分类和检测是两种最基础的视觉模型,常应用在图像审核、图像标签分类和人脸检测等场景。下面以两个典型服务为案例,单个分类模型和“分类+检测”多模型组合的使用情况,来介绍具体性能的优化过程。
美团每天有千万量级的图片需要审核过滤有风险内容,人工审核成本太高,需要借助图像分类技术实现机器自动审核。常用的分类模型结构如图1,其中预处理部分主要包括“解码、缩放、裁切”等操作,主干网络是ResNet-50。预处理部分接收图像二进制流,生成主干网络需要的矩阵数据Nx3x224x224(分别代表图片数量、通道数、图像高度和图像宽度 ),主干网络预测输出图片分类结果。
模型经过TF-TRT优化后的实际结构如下图2所示,主干网络ResNet被优化为一个Engine,但预处理部分的算子不支持优化,所以整个预处理部分仍然保持原始状态。
模型经过TF-TRT优化后使用TF-Serving框架部署,服务压测GPU利用率只有42%,QPS与Nvidia官方公布的数据差距较大。排除TF-TRT和Tensorflow框架等可能影响的因素,最终聚焦在预处理部分。Nvidia进行性能测试的模型没有预处理,直接输入Nx3x224x224矩阵数据。但这里的线上服务包含了预处理部分,压测指标CPU利用率偏高。查看模型中各个算子的运行设备,发现模型预处理大部分是CPU运算,主干网路是GPU运算(具体细节参见图1)。
如下图3所示,通过NVIDIA Nsight System(nsys)工具查看模型运行时的CPU/GPU执行情况,可以发现GPU运行有明显间隔,需要等待CPU数据准备完成并拷贝到GPU上,才能执行主干网络推理运算,CPU处理速度慢导致GPU处于饥饿状态。结合服务压测的CPU/GPU利用率数据可以看出:预处理部分CPU消耗高、处理速度慢,是推理服务的性能瓶颈。
如下图4所示,针对预处理CPU消耗过高影响推理服务性能的问题,提出几种优化方法:
如下图5所示,我们利用NVIDIA Nsight System,对比上述几种方法优化后的模型运行情况。增加CPU和前置预处理的方法都可以缩短CPU预处理时间,减少GPU数据等待时间,提升GPU利用率。但相较而言,分离预处理的方法优化更加彻底,CPU到GPU的数据拷贝时间最短,GPU利用最为充分。
各种方法优化后的线上服务压测性能结果见下图6(其中前置预处理和分离预处理中的CPU预处理服务额外使用16个CPU),机器配置的CPU型号是Intel® Xeon® Gold 5218 [email protected]、GPU型号是Tesla T4。从压测结果可以看出:
nvidia-smi
命令获取的GPU-Util指标)提升超过1倍,GPU利用率提升至88%;增加CPU并不能完全解决服务性能瓶颈问题,虽然GPU利用率达到88%,但是CPU-GPU数据传输时间占比较大,QPS提升有限。前置预处理方法也没有完全解决预处理性能瓶颈问题,优化并不彻底。相较而言,分离预处理方法充分发挥了GPU运算性能,在QPS和GPU利用率指标上都取得了更好的优化效果。
在一些复杂任务场景下(如人脸检测识别、图像文字识别等),通常是检测、分割、分类等多个模型组合实现功能。本节介绍的模型便是由“检测+分类”串接而成,模型结构如下图7所示,主要包括以下几个部分:
其中检测和分类两个子模型是单独训练的,推理时合并成单个模型,部署框架采用TF-Serving,优化工具采用TF-TRT。
模型中预处理和检测后处理大部分是CPU运算,检测和分类模型主干网络是GPU运算,单次推理过程中需要进行多次CPU-GPU之间数据交换。同样地,CPU运算速度慢会导致GPU利用率低,推理服务存在性能瓶颈。
实际线上服务压测GPU利用率68%,QPS也存在较大优化空间。服务配置为1GPU+8CPU(机器CPU型号是Intel® Xeon® Gold 5218 [email protected],GPU型号是Tesla T4)。
仍然采用模型拆分的思路,将CPU和GPU运算部分单独部署微服务。如下图8所示,我们将原始模型拆分为4个部分,预处理和检测后处理部署成CPU微服务(可根据流量大小动态扩容),检测模型和分类模型部署成GPU微服务(同一张GPU卡上)。为了保持调用方式简单,上层采用调度服务串接各个微服务,提供统一调用接口,对上游屏蔽调用差异。拆分后的检测模型和分类模型经过TensorRT优化后采用Triton部署。
如下图9所示,除了原始服务和微服务拆分,另外还对比了增加CPU和Triton Ensemble两种方式的性能测试结果。Triton Ensmeble方式将所有子模型(包括预处理和后处理)部署在一个机器上,实现多模型流水线调度。对比可以看出:
增加CPU的方法对服务GPU利用率提升较大、QPS提升不明显,原因在于CPU预处理和后处理时间缩短,但CPU-GPU数据传输时间在整个推理过程中仍然占比较大,GPU运算时间较少。
将模型拆分使用Triton Ensmeble方式部署实现多模型调度流水线,效率并不比模型拆分前高。因为多模型流水线是在同一台机器上,CPU和GPU相互影响的问题并没有解决,GPU处理效率受CPU制约。模型拆分微服务部署方式在服务层面实现了调用流水线,CPU预处理和后处理微服务可以根据流量动态增加资源,满足GPU模型微服务吞吐需求,实现了GPU/CPU处理解耦,避免了CPU处理成为瓶颈。
总而言之,拆分微服务的方式充分发挥了GPU运算性能,在QPS和GPU利用率指标上都取得了更好的效果。
除了上述两个具有代表性的推理服务优化案例,视觉其它很多服务也采用了这种优化方式。这种优化方式具有一个核心思想:在CPU运算是瓶颈的推理服务中,将模型的CPU和GPU运算部分拆分,单独部署成CPU/GPU微服务。
根据这种思想,我们提出一种通用高效的推理服务部署架构。如下图10所示,底层使用通用的部署框架(TF-Serving/Triton等),将模型中CPU运算部分如预处理、后处理拆分单独部署成CPU微服务,主干网络模型部署成GPU服务,上层调度服务串联模型微服务实现整体功能逻辑。
这里需要解释一个重要问题,为什么这种部署架构是高效的?
首先在宏观层面,模型拆分部署成微服务,通过调度服务实现了子模型流水线处理。拆分的子模型CPU微服务可以根据流量和处理能力动态扩容,避免模型预处理或后处理CPU运算能力不足成为性能瓶颈,满足了GPU模型微服务的吞吐需求。
其次在微观层面,如果模型包含多个CPU/GPU运算部分,那么GPU运算之间会存在间隔。如下图11所示,单次推理过程中两次GPU运算之间需要等待CPU后处理部分完成,CPU预处理也会影响GPU运算。模型拆分后,预处理和后处理部分独立部署成CPU服务,GPU服务中推理过程仅包含两个子模型运算部分,并且子模型间运算相互独立无数据关联,CPU-GPU数据传输部分可以与GPU运算过程并行,理论上GPU可以达到100%运行效率。
另外,在时延方面,拆分微服务的部署方式增加了RPC通信和数据拷贝时间开销,但从实践来看这部分时间占比很小,对端到端的延迟没有显著影响。例如对于上面3.1节中的分类模型,优化前服务的平均耗时是42ms,优化后微服务形式(RPC通信协议为Thrift)的服务整体平均耗时是45ms。对于大部分视觉服务应用场景而言,这种级别的延迟增加通常并不敏感。
本文以两个典型的视觉推理服务为案例,介绍了针对模型存在性能瓶颈、GPU利用率不高的问题进行的优化实践,优化后服务推理性能提升3倍左右,GPU利用率接近100%。根据优化实践,本文提出了一种通用高效的推理服务部署架构,这种架构并不局限于视觉模型服务,其它领域的GPU服务也可参考应用。
当然,这种优化方案也存在一些不足,比如优化过程中模型如何拆分比较依赖人工经验或者实验测试,没有实现优化流程的自动化与标准化。后续我们计划建设模型性能分析工具,自动诊断模型瓶颈问题,支持自动拆分优化全流程。
| 张旭、赵铮、岸青、林园、志良、楚怡等,来自基础研发平台视觉智能部。 | 晓鹏、駃飞、松山、书豪、王新等,来自基础研发平台数据科学与平台部。