【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

松散耦合深度学习 Serving 的优势和部署案例

  • 2021-08-06
  • 本文字数:5286 字

    阅读完需:约 17 分钟

松散耦合深度学习Serving的优势和部署案例
本文要点
  • 随着深度网络变得更加专业化,对资源的需求也越来越大,对于初创公司和规模化扩张的企业而言,在预算紧张的环境中为这些运行在加速硬件上的网络提供服务(serving)也变得越来越困难。

  • 松散耦合的架构可能是更好的选项,因为它们在为深度网络提供服务时具有高度可控性、易适应性、透明可观察性和自动缩放性(成本效益较高)。

  • 任何规模的公司都可以利用各种托管云组件(例如函数、消息服务和 API 网关),使用相同的服务基础架构来处理公共和内部请求。

  • 托管消息代理带来了轻松的可维护性,无需专门的团队负责维护工作。

  • 适应无服务器和松散耦合组件后,深度学习解决方案的开发和交付速度也可能会提升。


随着深度学习在许多行业的应用范围不断扩大,深度网络的规模和特异性也在增加。大型网络需要更多资源,并且由于它们的任务特定性(如定制的函数/层),将它们从急切执行(eager execution)编译为运行在 CPU 或 FPGA 后端上的优化计算图可能是无法做到的。因此,这种模型在运行时可能需要显式 GPU 加速和自定义配置。然而,深度网络都是在资源有限的约束环境中运行的,环境中云 GPU 的价格颇为昂贵,且低优先级(即竞价、抢占式)实例相当稀缺。


由于调用者和 API 处理者之间的紧密时间耦合,使用常见的机器学习服务框架将这些网络投入生产,可能会给机器学习工程师和架构师带来很多麻烦。这种情况是非常有可能出现的,特别是对于采用深度学习的初创公司和规模化扩张的公司来说更是如此。从 GPU 内存管理到缩放,他们在服务深度网络时可能会面临多个问题。


在本文中,我将重点介绍一种部署深度网络的替代方法的优势,这种方法会暴露基于消息的中介。这会放松我们在 REST/RPC API 服务中看到的紧密时间耦合,并带来异步运行的深度学习架构,在初创和扩张公司工作的工程师会更喜爱这种架构。


我将使用四大指标来对比这个服务架构与 REST 框架:可控性适应性可观察性自动缩放性。我将进一步展示如何使用一系列现代云组件轻松地将 REST 端点添加到面向消息的系统中。本文将要讨论的所有想法都是云和语言无关的。它们也可以用在本地服务器上托管的场景中。

服务深度网络的挑战

深度网络是由一些高度级联的非线性函数组成的,这些函数形成应用于数据的计算图。在训练阶段,网络使用选定的输入/输出对以最小化选定目标的方式来调整这些图的参数。在推理时,输入数据简单地流过这个优化图。正如上述介绍所示,任何深度网络都要面对的一个明显的挑战就是它的计算密集度。知道了这一点后,你可能会惊讶地发现,基于紧密时间耦合的 REST/RPC API 调用是服务深度网络的最常见方式。


只要构成深度网络的图可以通过层的融合、量化或剪枝进行优化,基于 API 的服务就不会引发任何问题。然而,这种优化并不总能得到保证,尤其是在将研究网络转移到生产环境时往往会出现优化不足的问题。研发阶段产生的大多数想法都具有特异性,为优化计算图而创建的通用框架可能不适用于这种网络(例如,Pytorch/ONNX JIT 无法编译具有Swish激活函数的层)。


在这种情况下,由 REST API 带来的紧密耦合是不理想的。提高推理速度的另一种方法是将图编译到专用硬件上运行,这种专用硬件设计为能够很好地并行化图中执行的计算(例如 FPGA、ASIC)。但同样,由于自定义函数需要通过硬件描述语言(如 Verilog、VHDL)集成到 FPGA 中,因此特异性问题是没办法用这种方式来处理的。


考虑到深度网络还将继续扩大规模,并根据行业需求变得越来越专业化,预计在不久的将来推理时也会用上显式 GPU 加速了。因此,分离调用者和服务函数之间的同步接口,并允许高度可控的基于拉取的推理,在许多层面上都更具优势。

打破紧密的时间耦合

我们可以向系统添加额外的中间件服务来放松时间耦合。在某种程度上,这更像是通过电子邮件服务提供商与你的邻居交流,而不是在邻居家窗外喊话。使用消息中间件(例如 RabbitMQ、Azure 服务总线、AWS SQS、GCP Pub/Sub、Kafka、Apache Pulsar、Redis)后,目标现在可以完全灵活地处理调用者的请求(就像邻居可能会忽略你的电子邮件,直到他/她吃完晚餐为止)。这是特别有利的,因为从工程师的角度来看,它实现了高度可控。考虑在具有 8Gb 内存的 GPU 上部署 2 个深度网络(在推理时需要 3Gb 和 6Gb 内存)的情况。


在基于 REST 的系统中,可能需要事先采取预防措施来确保这两种模型的 worker 不会过度使用 GPU 内存,否则由于直接调用,某些请求将失败。另一方面,如果使用一个队列,worker 可能会选择推迟工作,等到稍后有内存可用时再处理。由于这是异步处理的,因而调用者不会被阻塞并且可以继续执行其工作。这种场景尤其适合公司内部的请求,例如时间约束相对宽松的请求,但这种队列也可以使用云组件(例如无服务器函数)实时处理客户端或合作伙伴的 API 请求,如下一节所述。


选择消息中介的 DL 服务的另一个令人信服的理由是其简单的适应性。如果想要充分利用 Web 框架和库的潜力,我们就一定要面对它们的学习曲线,即便是 Flask 这样的微框架也不例外。另一方面,我们并不需要了解消息中间件的内部结构,而且所有主流云供应商都提供自己的托管消息服务,于是工程师就用不着再管维护工作了。这在可观察性方面也有很多优势。由于消息传输通过显式接口与主要的深度学习 worker 分离,因此可以独立聚合日志和指标。在云上,这甚至可能都用不着了,因为托管消息传递平台会使用仪表板和警报等附加服务自动处理日志记录。这样的队列机制本身也适合自动缩放。


由于高可观察性,队列带来了选择如何自动缩放 worker 的自由。在下一节中,我们将使用KEDA(Kubernetes 事件驱动的自动缩放)展示 DL 模型的可自动缩放容器部署。它是一个开源的基于事件的自动缩放服务,旨在简化 K8s pod 的自动管理。它目前是一个云原生计算基金会(Cloud Native Computing Foundation)沙箱项目,支持多达 30 个缩放器,从 Apache Kafka 到 Azure 服务总线(Azure Service Bus)、AWS SQS 和 GCP Pub/Sub 都在支持之列。KEDA 的参数让我们可以根据传入的数据量(例如等待消息的数量、持续时间和负载大小)自由地优化缩放机制。

一个部署示例

在本节中,我们将使用 Pytorch worker 容器和 Azure 上的 Kubernetes 展示一个模板部署示例。除了网络权重、输入和可能的输出图像等大型工件外,数据通信将由 Azure 服务总线处理。它们应该存储在 blob 存储中,并使用用于 blob 的 Azure Python SDK 从容器下载/上传。该架构的高级概述见下图 1。



图 1:所提议架构的高级概述。对于每个块,括号中给出了相应的 Azure 服务。它可以处理使用无服务器函数的外部 REST API 请求和直接来自队列的内部请求。


我们将使用 Azure 服务总线队列和 KEDA 实现一个可自动缩放的竞争消费者模式服务器。要启用请求-回复模式来处理 REST 请求,可以使用Azure Durable Function外部事件。在示例架构中,我们假设一个持久函数已准备就绪,并通过服务总线队列将反馈事件回复 URL 传输到 worker 线程,Azure 文档中解释了设置此服务的细节。KEDA 允许我们使用队列长度设置缩放规则,这样 K8s 中的 worker pod 数量将根据负载自动更新。我们还将一个 worker 容器(或在我们的例子中的多个容器)绑定到一个 GPU 上,这样我们就可以自动缩放任何托管集群,并向我们的系统添加更多 GPU 机器,而不会出现任何麻烦。K8s 自动处理集群的自动缩放以解决资源约束(即由于 GPU 数量不足导致的节点压力)。


可以在这个Github存储库中找到描述如何为常规 ResNet 分类器提供服务的详细模板。文中将显示每个块的缩短版本。第一步,我们来创建我们的深度网络服务函数(network.py)。初始化推理函数的模板类可以写成如下形式,这可以根据手头的任务(例如分割、检测)进行定制:


class Infer(object):    __slots__ = [""]        # 初始化推理函数(例如,从blob下载权重)    def __init__(self, tuned_weights=None):        pass        # 执行推理    @torch.no_grad()    def __call__(self, pil_image):        pass
复制代码


在原始函数中,我们返回前 5 个 ImageNet 类别的类 ID。随后,我们准备编写我们的 worker Python 函数(run.py),这里我们将模型与 Azure 服务总线集成在一起。如下面的片段所示,用于服务总线的 Azure Python SDK 支持对传入的消息队列进行非常简单的管理。PEEK_LOCK 模式允许我们明确控制何时完成或放弃传入请求:


...with servicebus_client:    receiver = servicebus_client.get_queue_receiver(        queue_name=self.bus_queue_name,        receive_mode=ServiceBusReceiveMode.PEEK_LOCK,    )    with receiver:        for message in receiver:            # 使用输入数据执行服务            data = json.loads(str(message))            ...
复制代码


此时我们已经准备好了模板 worker,现在我们来创建容器的 Dockerfile 并将其推送到 Azure 容器注册表(Container Registry)。这里 requirements.txt 包含我们的 worker 的额外 pip 依赖项。通过 exec 运行主进程可以被视为一种确保它作为 PID 1 进程运行的技巧。这让集群能够在发生任何错误时自动重启 pod,而无需在部署 YAML 文件中写入显式活动端点。请注意,指定健康检查仍然是更好的做法:


FROM pytorch/pytorch:1.8.0-cuda11.1-cudnn8-runtimeRUN python -m pip install -r requirements.txtCOPY . /workerWORKDIR /workerCMD exec python run.py
复制代码


NAME= # SETVERSION= # SETACR= # SETsudo docker build -t $ACR.azurecr.io/$NAME:$VERSION -f Dockerfile .sudo docker push $ACR.azurecr.io/$NAME:$VERSION
复制代码


创建 K8s 集群后,不要忘记从门户启用节点自动缩放特性(例如,最小 1,最大 8)。作为最后的准备步骤,我们需要在集群中启用GPU驱动程序(到 gpu-resources 命名空间)并通过官方 YAML 文件部署KEDA服务(到 keda 命名空间)。为方便读者,Keda 和 GPU 驱动程序 YAML 文件已包含在存储库中:


kubectl create ns gpu-resourceskubectl apply -f nvidia-device-plugin-ds.yamlkubectl apply -f keda-2.3.0.yaml
复制代码


下一步,我们可以通过准备好的 shell 脚本部署 worker 容器。首先,我们创建命名空间来部署我们的服务:


kubectl create namespace ml-system
复制代码


请注意,使用 shell 文件而不是普通的 YAML 可以帮助我们轻松更改参数。运行部署脚本(deploy.sh)后,我们就准备就绪了(不要忘记根据你的需要设置参数):


bash deploy.sh
复制代码


由于我们限制每个 pod 使用一个 GPU,因此通过 KEDA 缩放 pod 也将有效地缩放集群节点。这会让整体架构具有很高的成本效益。在某些情况下,你甚至可以将最小节点数设置为零并在 worker 空闲时砍掉 GPU 成本。但是,我们做这种配置时必须非常小心,并考虑好节点的缩放时间。部署脚本中使用的 KEDA 参数的细节可以在官方文档中找到。在部署脚本(deploy.sh)中,如果你仔细查看,你会发现我们将 NVIDIA_VISIBLE_DEVICES 环境变量设置为“all”,来尝试从另一个容器(worker-1)访问 GPU。这个技巧让我们能够同时利用集群缩放和一个 pod 中的多个容器。如果不设置此项,由于 worker-0 的“limit”约束,K8s 将不允许为每个 GPU 添加更多容器。工程师应测量其模型的 GPU 内存使用情况,并根据 GPU 卡的限制添加容器。请注意,为简洁起见,图 1 中指定的 Azure 专属块的细节(示例服务总线接收器除外)没有展示出来。Azure 为每个组件提供了大量文档以及相关的 Python 示例实现。

未来发展方向

如果大家看过了计算技术在 20 世纪的演变过程,那么现在深度学习硬件研究中发生的事情可能会让人感到非常熟悉。一个显然容易实现的成果是翻译器的小型化,我们可以尽量将计算核心的数量控制在单芯片的水平上。最后,行业严重依赖 VLSI 改进而不是算法开发。看到为深度学习定制的硬件增长的速度如此之快,我们可能会期望 21 世纪复刻 20 世纪的历史。另一方面,在云中,无服务器加速的 DL 服务似乎是可以轻松摘取的果实。深度学习部署将进一步抽象化,按用量付费的初创公司将在不久的将来随处可见。由于松散耦合架构带来的灵活性,我们也可以合理预测松散耦合架构将减轻在此类初创公司工作的工程师的负担,因此我们可能会看到许多针对松散耦合架构的新生开源项目。

总结

在这篇文章中,我们描述了消息中介深度学习服务的四大好处:可控性、适应性、可观察性和自动缩放性(成本效益较高)。除此之外,我还提供了一个模板代码,可用于在 Azure 平台上部署文中所描述的架构。应该强调的是,这种服务的灵活性在某些场景中可能是不切实际的,例如物联网和嵌入式设备服务,在这些场景中组件的本地独立性过重。然而,这里提出的想法可以通过多种方式采用,例如我们可以使用低级 C/C+消息代理库在资源约束平台中创建类似的松散耦合架构,而不是使用云消息服务(例如用于自动驾驶、物联网需求)。


想在实践中尝试本文中的概念吗?你可以在Github上找到文章随附的代码

作者介绍

Sabri Bolkar 是机器学习应用科学家和工程师,他对基于学习的系统从研发到部署和持续改进的整个生命周期感兴趣。他在挪威科技大学学习计算机视觉,并在比利时鲁汶大学完成了关于无监督图像分割的硕士论文。在荷兰代尔夫特理工大学攻读博士学位后,他目前正在攻关电子商务行业面临的大规模应用深度学习的挑战。读者可以通过他的网站与他联系。


原文链接:Benefits of Loosely Coupled Deep Learning Serving

公众号推荐:

跳进 AI 的奇妙世界,一起探索未来工作的新风貌!想要深入了解 AI 如何成为产业创新的新引擎?好奇哪些城市正成为 AI 人才的新磁场?《中国生成式 AI 开发者洞察 2024》由 InfoQ 研究中心精心打造,为你深度解锁生成式 AI 领域的最新开发者动态。无论你是资深研发者,还是对生成式 AI 充满好奇的新手,这份报告都是你不可错过的知识宝典。欢迎大家扫码关注「AI前线」公众号,回复「开发者洞察」领取。

2021-08-06 11:444467

评论

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

一个响指,代码生成!华为云CodeArts Snap正式公测

华为云PaaS服务小智

人工智能 华为云

一文深度解读多模态大模型视频检索技术的实现与使用

阿里云视频云

云计算 大模型 视频云

软件测试学习笔记丨Flask定义接口路由和视图函数

测试人

软件测试

苹果电脑实用工具:Unclutter for mac 下拉菜单隐藏工具

南屿

在线视频转Mp3软件4K YouTube to MP3中文直装版

南屿

音频提取工具 音频转换 MP3

做dapp的开发公司有哪些

西安链酷科技

DAPP系统开发

低代码开发业务在AIGC时代的应用

EquatorCoco

人工智能 低代码 AIGC

BRC20铭文跨链系统开发技术

西安链酷科技

BRC-20 铭文币

区块链开发项目:构建去中心化未来的蓝图

区块链软件开发推广运营

dapp开发 区块链开发 链游开发 NFT开发 公链开发

国内首个图计算标准发布,悦数图数据库通过测试

悦数图数据库

图谱

为什么跨境电商成为海外云手机的主要受众群体?

Ogcloud

云手机 海外云手机 跨境电商云手机 云手机海外版

2024年前端会流行什么技术和框架了?

互联网工科生

软件开发 低代码 前端框架 JNPF

数据中心AIOps智能运维标杆 浪潮信息InManage全新升级

财见

软件测试学习笔记丨Flask环境安装

测试人

软件测试

10个适合后端程序员的前端框架

快乐非自愿限量之名

程序员 前端 前端框架

减少文件体积优化性能,你的姿势对了吗?

Yestodorrow

云原生 前端开发 可观测性 用户体验 网站性能

大模型+知识图谱双驱架构:新一代《知识语义框架SPG》白皮书

可信AI进展

知识图谱 大模型

Higress 开源一周年:新版本,新标准,新工具,新征程

阿里巴巴云原生

阿里云 开源 云原生 Higress

苹果电脑mac上好用10款系统优化软件

南屿

苹果mac系统优化 Mac卸载软件

Mac母带制作工具Steinberg WaveLab 12 Pro下载安装

南屿

Steinberg 母带处理软件 WaveLab 12

macOS数据转换工具 Easy Data Transform for mac v1.46.2激活版

南屿

Excel CSV编程文件转换 数据转换工具 Easy Data Transform

otc承兑商支付系统开发 otc承兑商支付模式系统开发

西安链酷科技

下一代软件架构,如何构建微服务核心能力

阿里巴巴云原生

阿里云 Serverless 微服务 云原生

使用云手机运营TikTok,实现更多可能性

Ogcloud

云手机 海外云手机 tiktok云手机 云手机海外版

JetBrains软件怎么设置中文,jetbrains全家桶汉化教程

南屿

编程开发 jetbrains rider破解版 JetBrains全家桶

连续四次登顶!天翼云稳居中国专属云服务市场第一

天翼云开发者社区

云计算 云服务 IDC

正式发布!《ICPMM行业云平台运营管理能力成熟度》系列标准来了!

天翼云开发者社区

云计算 云服务 企业上云

彰显科技硬实力!天翼云论文在国际顶刊JoCCASA发表!

天翼云开发者社区

云计算 混合云 论文

SWAP/DEX去中心化交易所开发

西安链酷科技

swap链游 合约交易所开发

BRC20铭文合约代币系统开发

西安链酷科技

铭文开发

松散耦合深度学习Serving的优势和部署案例_服务革新_Sabri Bolkar_InfoQ精选文章