硬核干货——《中小企业 AI 实战指南》免费下载! 了解详情
写点什么

复杂场景下的深度学习模型部署

  • 2023-08-07
    北京
  • 本文字数:3236 字

    阅读完需:约 11 分钟

复杂场景下的深度学习模型部署

背景


深度学习是一种使用神经网络的机器学习,正迅速成为解决从文本分类到推荐系统等许多不同问题的有效工具。然而,将训练好的神经网络模型部署到应用程序和服务中可能给算法从业人员带来不小的挑战。算法框架的不同、计算资源稀缺和缺乏标准实现等挑战都可能导致模型部署的失败。


作业帮的业务体量较大,需要部署大量的深度学习模型应对不同的任务。为满足实际使用,我们部署的模型服务需要具有以下特点:


  1. 高并发

  2. 低时延

  3. 模型多

  4. 更新快

  5. 业务方多


结合任务特点与实际应用场景,我们还面临以下问题:


  1. 数据预处理模块与模型版本强耦合,部署时需保持同步。

  2. 多个版本的预处理模块相互之间易冲突。

  3. 模型太多,如果全部加载至 GPU 浪费资源。


因此,本文将以上述场景作为对象,阐述三种不同的解决方案,并对比它们的性能指标。最终目标是找到一个适合作业帮任务的模型部署方案,在合理占用资源的情况下,满足不同业务方的需求。

模型部署方案

1. Gunicorn + Flask + Transformers


Transformers 是一个十分方便的自然语言处理库,它的宗旨是让最先进的 NLP 技术人人易用。通过 Transformers 可以轻松地实现模型的训练、加载和推理。此外,使用 Flask 框架部署深度学习模型是最简单快捷的方式。但是 Flask 自带的 Web 服务性能极不稳定,无法满足高并发、低延迟的需求。因此,我们通过 Gunicorn 框架提供的 WSGI 服务来部署 Flask 的接口,也就是将 Flask 代码部署在 Gunicorn 提供的 WSGI 服务上,可以显著提升服务的并发能力和稳定性。


本部署方式的整体框架如下图所示:



  1. 利用 Transformers 加载所需模型,但通过 LRU 机制控制加载在内存中的模型数量最大为 8,防止内存多大。

  2. 通过 Flask Web 框架构建模型预测服务,包括数据的预处理、模型预测和结果后处理等步骤。

  3. 最后用 Gunicorn 启动 Flask 服务,设置 worker 数量支持异步处理请求,提高并发能力。


Flask 服务的构建十分简单,具体如下图所示。实现一个模型预测函数,并将其与’predict’接口绑定即可。另外,需注意的是线上服务需要实现’ready’接口返回 200 和’ok’以执行健康检查。



采用 Gunicorn+Flask+Transformers 部署深度学习服务的初衷是,该方式与我们的训练框架较为耦合,实现起来比较简单。但在使用线上服务的实际场景中,遇到了以下问题:


  1. 在每个 worker 中,执行模型的预测会有 100+线程,导致资源的挤兑。

  2. Gunicorn 确实提高了 Flask 服务的并发能力,但在并发请求较多时,并不能解决健康检查超时的问题,使得 pod 摘流并增加预测时延。

  3. Transformers 模型推理方式的时延较长。

  4. LRU 机制的存在使得模型需要重新加载,而模型加载比较慢导致预测时延增加。


最后,这种通过这种部署方式部署至 serverless,共 6 个 pod,每个 pod 的资源是 16 核 16G 的情况下,能达到 150QPS。

2. Tornado + PyTorch


    Tornado 是使用 Python 编写的一个强大的、可扩展的 Web 服务器。它在处理严峻的网络流量时表现得足够强健,在创建和编写时又足够轻量,并能够被用在大量的应用和工具中。Tornado 在设计之初就考虑到了性能因素,支持异步非阻塞,可以接受多个用户的并发请求。本方案采用 Tornado 代替 Flask 以实现更好的异步通信。


    本部署方案直接采用PyTorch模型预测的方式代替 Transformers,避免 Transformers 内 Trainer 的冗余操作以减少预测时间。此外,将每个模型分开部署至子服务,取消模型的动态加载机制,避免模型切换造成的耗时。同时,这种方式也避免了模型过多导致的资源挤占问题。


本部署方式的整体框架如下图所示:



  1. 每个模型通过 Tornado 包装成子服务,包含数据预处理,模型预测和结果后处理。

  2. 分发服务负责接收所有请求,并根据数据类别将其分发至对应的模型预测服务进行预测。

  3. 子服务的预测结果返回至分发服务,由分发服务返回所有数据的预测结果。

  4. Tornado 部署 Web 服务同样十分便捷,同时可通过’async’和’await’关键字轻松实现异步。


采用 Tornado+PyTorch 的方案部署模型的原因是,组里同事有 Tornado 的踩坑经验,方便实现性能上的优化(如异步)。此外,本方式仍与训练框架有联系,从训练到部署的链路仍比较完整。然而在上线测试后,发现本部署方式仍有以下问题:


  1. PyTorch 预测时启动大量线程的问题仍未解决。

  2. 模型多的情况下,需要申请大量模块并部署,管理太繁杂。

  3. 没有动态 Batching 功能,无法更好地发挥机器性能。

3. 单模型性能测试


为更方便地进行性能测试,我们采用单个模型进行性能的测试。通过不同部署方式在单模型上的性能进行对比,以挑选最优的部署方案。本节中,我们采用了 ONNX 和 TorchScript 两种模型格式,并分别用 Tornado 和 Triton Inference Server 进行部署。


ONNX (Open Neural Network Exchange)是一种针对机器学习所设计的开放式文件格式,用于存储训练好的模型。它使得不同的人工智能框架可以采用相同格式存储模型数据并交互。对于我们的场景,其优势在于可以控制线程数防止资源挤占。


Triton 是英伟达等公司推出的开源推理框架,为用户提供在深度学习模型部署的解决方案。其主要职责和服务紧密相关,服务中常见的需求需要它做处理。比如 Batching,Sequence,Pipeline 和模型仓库的管理等

我们将各个服务部署在 Docker 中,限定 CPU 核数为 16 来模拟线上模块的资源。通过 Locust 工具进行压测,具体结果如下表所示:


部署方式

QPS

时延中位数 (ms)

95%分位时延 (ms)

CPU利用率

Tornado + ONNX

100

300

500

1300%

Tornado + TorchScript

60

1600

1800

1600%

Triton + ONNX

100

340

530

1300%

Triton + TorchScript

100

50

150

800%

集成预处理的Triton + TorchScript

25

200

300

1600%


在不考虑预处理的情况下,Triton + TorchScript 的部署方式是最优的。Triton 的动态 Batching 功能极大地提升了并行预测的功能。但是在我们的场景中,数据预处理与模型预测强耦合。于是,尝试利用 Python Backend 将预处理部分同样集成在 Triton 中,实现完整的模型预测服务。但在实际测试过程中,发现集成预处理的 Triton 服务效果并不理想,怀疑是预处理的串行使得模型预测时无法进行动态 Batching。因此,我们最终决定将部署方式确定为 Tornado Web 服务和 Triton Inference Server。


本节对 ONNX 的处理比较粗糙,可能并没有发挥其优势。但 Triton + TorchScript 的方式已经满足业务需求,并没有对 ONNX 的实验进行深究。

4. Tornado + Triton


本节介绍最终确定的模型部署方式:Tornado + Triton。通过将不同版本的预处理模块打包成不同的 Python 模块解决版本冲突问题。另外,针对业务方多且需求不一致的问题,我们通过写多个接口的方式解决。比如,’/category_predict’支持单条预测,’/category_predict_nlp’支持批量预测。于是,本部署方式如下图所示:



其中,Tornado Web 服务接收应用方的请求,对数据进行预处理,然后异步调用 Triton 进行模型预测,最后对预测结果进行后处理并返回结果。


    本节中通过题型预测任务对新的部署方式进行测试,将对应的 21 个模型部署至限定 16 核的 Triton Inference Server。产生随机数据模拟线上请求并用 Locust 工具进行压测,具体结果如下:


部署方式

QPS

时延中位数 (ms)

95%分位时延 (ms)

CPU利用率

Web服务+Triton

100

270

600

800%


通过结果可以发现,将数据预处理和结果后处理集成在 Web 服务中并通过 Triton 进行模型部署的方案在我们复杂的业务场景下是最优的。这种方式不仅通过动态 Batching 的方式增加并发降低时延,并且方便了模型的管理与更新。其唯一的缺陷是无法解决预处理模块和模型版本强耦合的问题,在部署时需保持同步,且时间点最好是在服务低谷期。

总结与展望


本文涉及的场景比较复杂,主要有以下几个问题:


  1. 模型多,不同任务的模型总数接近 100 个,且更新频率随业务节奏变更。

  2. 易冲突,数据预处理和模型版本强耦合,且不同版本预处理模块易冲突。

  3. 性能要求高,任务面向用户,在部署至 CPU 环境下要求高并发和低时延。


因此,本文从实际应用场景触发,设计并尝试了多种部署方式,对比其在线上使用过程中的表现。经过几次实验后,找到了一种适用于我们复杂场景的深度学习模型部署方式,在不依赖 GPU 资源的情况下满足业务方的需求,并为后续的模型部署提供了一种可行的部署方案。


然而,由于业务节奏,本文在实验过程中仍忽略了一些问题。比如,ONNX 格式的模型部署在 Triton 中的性能为何不如部署在 Tornado Web 服务中,或许是 ONNX 在 Triton 中需要一些特殊的配置。另外,数据预处理和模型版本强耦合的问题仍未得到合理的解决方案,目前的处理方式仍有版本对不齐的风险。本文未对这些问题进行深入研究,留待后续探讨。

2023-08-07 15:074498

评论

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

架构实战营-模块一作业

氢原子

#架构实战营

2022-12-07:删除重复的电子邮箱。删除重复数据后,id=3的数据被删除。请问sql语句如何写? DROP TABLE IF EXISTS `person`; CREATE TABLE `per

福大大架构师每日一题

数据库 福大大

设计原则 — 基于接口而非实现编程

Lemoon Can

面向对象设计原则 设计原则

Verilog 设计方法

芯动大师

流程 Verilog 设计方法

架构实战营-模块1-作业

zealot0317

如何通过“推送文案的千人千面”有效提升用户转化和留存

极光GPTBots-极光推送

极光推送 用户运营

模块一:课程作业

peter

#架构实战营

架构实战营-模块一作业

落叶挂云霄

ChatGPT中文版杀疯了,已登录AI模型市场

felix

架构实战模块一:架构图

小飞同学

#架构实战营

架构训练营模块一作业

现在不学习马上变垃圾

#架构实战营

全面进化!Apache Doris 1.2.0 Release 版本正式发布|版本通告

SelectDB

数据库 大数据 开源 数据分析 Doris

FL Studio21正式版本发布更新附送85款主题下载

茶色酒

FL Studio 21 FL Studio21

FL Studio2023新版本功能爆料将引入4款全新插件!创作力UP!

茶色酒

FL Studio

十大开源测试工具和框架

FunTester

超详细FL Studio水果2023新版更新功能讲解!80项更新与改进!

茶色酒

FL Studio FL Studio 21 FL Studio21

从汽车之家效能平台建设看汽车行业研发数字化之路

之家技术

数字化 汽车 构架 效能度量 效能

微信业务架构图 & 学生管理系统

chinandy

架构设计

MySQL执行计划之explain详解

@下一站

程序 MySQL优化 dba 11月日更 11月月更

从观察者模式到Java事件处理机制(下)

老农小江

设计模式 java 编程 事件机制

架构实战营(第10期)模块一作业

Geek_e5f2e5

从观察者模式到Java事件处理机制(上)

老农小江

设计模式 java 编程 事件机制

架构实战营模块一_作业

原城

架构实战营 #架构实战营 架构师实战营 「架构实战营」

模块一作业

陈天境

设计原则 — 多用组合,少用继承

Lemoon Can

面向对象设计原则 设计原则

王者荣耀商城异地多活设计

π

模块七-王者荣耀商城异地多活架构设计

Geek_b35d92

商城 构架 王者荣耀

API安全中的数据隐私保护步骤

穿过生命散发芬芳

API安全 12月月更

模块一作业提交

Geek_7d539e

架构实战营模块一作业

周烨

ChatGPT 加图数据库 NebulaGraph 预测 2022 世界杯冠军球队

NebulaGraph

图数据库 世界杯 AI预测

复杂场景下的深度学习模型部署_机器学习/深度学习_作业帮技术团队_InfoQ精选文章