“亿”想天开系列之eBay模型服务性能及资源优化实践

文摘   2024-05-24 11:24   上海  

背景

PART.1

机器学习模型最终通过提供推理能力从而服务业务。随着机器学习尤其是大模型技术的快速发展,模型推理服务作为整个模型生命周期最重要的环节之一,在业务链路中扮演着越来越重要的作用。从平台角度,既要保证模型推理服务能够满足线上不同业务场景苛刻的性能要求,同时又要保证GPU等昂贵硬件得到合理的分配和利用本文将从这两个方面考量出发,介绍eBay在模型服务性能以及资源优化方面的一些工程实践。

“亿”想天开AI系列推文目录:


  • 模型推理平台核心功能和整体架构,及主流框架支持

  • 模型生命周期管理

  • 模型端到端服务优化及资源优化(本篇)

  • 模型特征监控

  • 大模型落地实践



整体服务框架

PART.2

首先,我们来看一下eBay模型推理服务的基础架构:


图1:模型推理基础架构



  • API Gateway: API网关, 这是我们的服务入口。主要提供鉴权、模型路由、AB测试等基础功能。


  • Tracing/Logging: 这里主要提供一些跟踪和日志服务,API网关会异步记录模型服务相关请求,用于问题的诊断以及模型的重训练等等。


  • Model Runtime Service: 实际模型部署的推理服务,我们基于NVIDIA Triton进行了封装,对多种模型框架提供统一的推理接口。

网关服务+模型服务的两层服务架构提供了许多优势。比如标准化的集成接口、特征监控的异步执行以及多模型的切换能力等等。这些在我们系列文章的第一篇(《“亿”想天开AI|eBay 云原生人工智能推理平台:推理智能,推演“亿”生》)中已经提及,这里就不再赘述。


推理运行时框架选择

正如我们的基础框架所示,我们选择了NVIDIA Triton server作为我们的模型运行时基础服务框架。其主要有以下几点优势:


  • 多模型框架支持:支持主流的各种深度学习框架比如PyTorch,ONNX等等。并且直接支持NVIDIA自己的一些加速库,如TensorRT, DALI等。


  • 模型编排能力:Triton可以通过定义模型ensemble规则或直接编写python脚本的方式来进行模型编排,能使我们方便的添加模型前后处理和复杂逻辑。


  • 高性能:Triton对TensorRT的支持,以及dynamic batching等功能都有助于提升推理性能和吞吐量。在我们的一些实际案例中,P99能获得50%以上的提升,吞吐量和GPU使用率也都得到了显著提升。



推理优化

PART.3

整个模型服务通常不仅仅包含模型推理本身,也包含相关的前后处理逻辑。所以,推理优化也主要分为2个方面:模型本身的优化和前后处理的优化。

    模型优化    

01


既然我们已经使用了Triton作为我们的推理框架,我们就要充分利用其与TensorRT的良好集成。TensorRT提供了多种不同的模型优化手段,比如量化、fusion等等,可以帮助我们方便地提升模型性能。



我们主要提供2种配置TensorRT的方式。第一种是直接通过Triton支持的推理服务后端配置参数。这种方式比较便捷,用户只需要在部署时选择开启TensorRT优化即可。但对模型的限制较多,需要符合一定条件才能进行自动的优化。另一种则是用户手动把模型转换成TensorRT格式,我们在Jupyter Notebook环境中集成了TensorRT的工具链,用户调用相关命令行工具即可。当然,这对算法工程师提出了比较高的要求,需要熟悉TensorRT工具链的使用。


下图是我们使用TensorRT量化的一个案例,可以看到响应速度减少了近70%,而资源占用也减少了很多。



    前后处理优化    

02


对于包含前后处理的模型服务,仅仅优化模型本身往往是不够的。如果前后处理包含大量的CPU计算,如果这些CPU操作没有被得到优化,同样会影响整体的服务性能。下图中描述了一个模型服务端到端执行CPU和GPU使用占比,可以看到CPU占用了大概一半的时间。如果我们可以优化这部分CPU执行时间,无疑会大大提升我们模型服务的响应速度。



在这些CPU操作中,最具代表性的应该是图像相关的操作,例如图像解码、变化等操作都非常占用CPU资源。针对这些图像操作,我们利用了NVIDIA Data Loading Library (DALI)来将CPU计算迁移到GPU来执行,从而大大提升了起执行速度。DALI通过NVJPEG/NVDEC硬解模块来提升图像视频的解码速度,同时集成了大量常用的图像变化操作算子。将原来OpenCV或者PIL的图像逻辑转换到DALI其实十分方便。在我们的一个场景中,DALI帮助我们降低了近80%的响应时间。



资源优化

PART.4

GPU作为相当昂贵的硬件资产,我们希望其能得到充分的利用。线上模型服务应该在满足服务SLA的前期下,使用尽可能少的GPU资源并达到较高的GPU使用率。在实际应用中,我们发现有以下这些问题影响了GPU的充分利用:


  • 弹性扩缩容


  • 资源碎片化


  • 小模型


  • CPU瓶颈


下面我们分别解释这些问题以及我们的应对方案。


    弹性扩缩容    

01


通常用户会以峰值流量来估算需要用到的资源,但实际情况是生产流量通常是周期变化的,存在波峰波谷。此时如果我们都是以波峰流量来分配资源,那在波谷的时候就会造成资源的浪费。并且,线上服务的高可用要求使得我们需要给每个数据中心的服务节点给出1.5倍的额外冗余,更是进一步加剧了这种浪费。另一方面,用户的预估跟时间往往存在偏差,从模型上线到接受实际流量可能中间相隔数周甚至数月之久,所以已上线就直接分配大量资源但没有实际流量也会造成大量浪费。



所以,我们需要根据实际的流量和资源利用率来自动伸缩副本数量。我们与eBay的Cloud Infra团队合作,集成了基于KEDA(Kubernetes Event-driven Autoscaling) 的自动伸缩功能。对于我们的模型服务,我们主要配置基于CPU和GPU使用率来触发自动扩缩容。目前我们已经对大多数模型启用了自动伸缩,得到了比较好的效果,整体GPU使用率提升了30%以上


但实际使用中,我们也发现了一些问题。因为扩容需要时间,通常是3分钟左右新的副本才可以接收,自动伸缩只能应对流量变化相对缓慢温和的情况。如果流量增长过快,新增的副本来不及准备好,会造成当前副本的请求积压,影响响应时间。


    资源碎片化   

02


这里主要有几方面的问题导致了资源的碎片化。


一方面,物理节点上对应的CPU,GPU,内存和硬盘等资源是固定的。而用户部署服务、提交任务时可能使用不合理的资源配比,导致某种资源被过量占用。这样即使其他资源还充足,新的部署也无法再调度到这个节点上。因此我们设计了标准的SKU,用户只能使用标准的SKU配置来申请资源。以A100为例,扣除留给节点上一些必要服务的资源,一张A100卡会被分配14核CPU和96G的内存。


另一方面,为了提升整体的GPU使用率,我们需要把模型训练任务和模型推理服务使用的GPU放到一起来看。对于训练任务来说,他需要把任务尽可能调度到相同节点或机架上以保证训练的数据通信效率。但这就导致一个问题,比如同一个节点上的6张卡被一个训练任务占用,剩余的2张卡可能又不够被另外一个任务调度,那这就造成了浪费。这时,我们正好可以利用推理服务的特点来优化资源占用。不同于训练任务,推理服务要求资源分配尽可能分散以满足高可用的要求。那我们就可以利用这一特点,把一些相对低优先级的服务比如NRT/Batch的推理任务调度到空余的训练节点上,填满训练任务造成的一些碎片资源。



    小模型    

03



虽然现在大模型非常流行,但实际生产环境中还是以几百MB到几GB的中小模型为主。他们的问题是难以充分利用整张卡的资源,吞吐量上升以后往往因为大量请求的序列化反序列化而造成CPU上的瓶颈。跟弹性扩缩容类似,高可用的要求更加剧了这个问题,造成了3倍的浪费。


以往,我们的做法是把多个模型放到同一个容器中共享GPU,但这一方案的隔离性不佳,一个模型出现问题可能影响其他模型的推理。并且资源利用率是以容器为单位来统计的,我们难以观察单个模型占用了多少资源。


在NVIDIA推出Multi-Instance GPU(MIG)后,我们充分利用了这一技术。MIG使得一张整卡能被最多切分成7个独立的MIG实例,被单独分配给服务使用,并且提供与整卡无异的隔离性。目前,我们的A100节点主要提供3种不同的配置:整卡,3g40gb (1/2卡),1g10gb(1/7卡)。用户模型并不能随意选择配置,该配置需要配合前一篇文章中提到的性能测试得到。比如用户在使用整卡测试时无法到达需要的GPU使用率要求,但用3g40gb的半张卡,那就需要使用3g40gb来部署模型。



    CPU瓶颈    

04



前文提到我们可以通过DALI加速图像相关的前后处理,把负载从CPU转到GPU上。但DALI只针对图像视频等有此优化,对于其他的前后处理逻辑无能为力。此时,GPU节点有限的CPU性能仍然可能成为瓶颈。


为此,我们应用了Ray Serve。Ray因为OpenAI用它来训练ChatGPT等模型而备受关注,而Ray也可以通过Ray Serve来作为模型推理服务使用。如下图,通过Ray,我们可以把CPU的处理逻辑通过Ray actor放到CPU节点执行。这样GPU节点就只要处理简单的输出输出序列化,其他都是GPU计算,从而大大提高GPU使用率。



在我们的测试中,Ray Serve可以带来3倍的吞吐量提升,GPU使用率也从26%提升到78%。但因为整个流程的cpu负载和gpu负载是在不同节点上完成的,节点间的通信损耗影响了响应时间,P99相比全部在一个容器中慢了不少。所以,Ray Serve这种分布式的推理方式更适合NRT或者batch这类相对来说SLA不敏感的场景,对于SLA敏感的则还是使用纯Triton的方式。



总结展望

PART.5


本文介绍了eBay机器学习推理平台在推理服务性能和资源使用优化方面的一些实践。讨论了如果对模型以及前后处理进行优化,以及如何提高GPU硬件使用率,充分利用硬件资源。在过去的工作中,我们主要着重一些相对传统的深度神经网络模型的优化实践,比如一些CV和NLP的网络模型。但随着大模型的迅速兴起,我们需要更深入地去挖掘针对这些大模型服务的优化方案,提供更完善的平台支持。





eBay技术荟
eBay技术荟,与你分享最卓越的技术,最前沿的讯息,最多元的文化。
 最新文章