NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

Bert 语义在 360 搜索中的探索实践 - 工程优化

  • 2021-03-10
  • 本文字数:3141 字

    阅读完需:约 10 分钟

Bert语义在360搜索中的探索实践-工程优化

Bert 模型网络结构较深,参数量庞大,将 Bert 模型部署成在线服务在实时性和吞吐上面临巨大挑战。本文主要介绍 360 搜索将 Bert 模型部署成在线服务的过程中碰到的一些困难以及做的工程方面的优化。

背景

在 360 搜索场景下对在线 Bert 服务的延迟和吞吐有极高的要求。经过前期的调研探索和试验,将 Bert 模型做成在线服务主要有以下 3 个挑战:


  1. 模型参数量巨大。12 层 Bert 模型有超过 1 亿参数量,相比于其他语义模型计算量高很多。

  2. 推理时间长。经验证,12 层 Bert 模型在 CPU 上延迟约为 200ms,在 GPU 上未经优化的推理延迟为 80ms,在搜索这个场景下如此性能是不可接受的。

  3. 推理计算量大,需要的资源多。经过压测验证,单个机房需要几百张 GPU 卡才能承接全部的线上流量,投入的成本远高于预期收益。


基于以上几个困难点,我们前期调研了 TF-Serving、OnnxRuntime、TorchJIT、TensorRT 等几个热门的推理框架,在比较了是否支持量化、是否需要预处理、是否支持变长、稳定性和性能以及社区活跃度等几个维度后,最终选用了 Nvidia 开源的 TensorRT。确定了框架选型之后,我们针对 Bert 在线服务做了几个不同层面的优化。

Bert 在线服务优化

框架层面提供的优化

TensorRT 推理框架本身提供的优化有:


  1. 层间融合和张量融合。本质是通过减少核函数调用次数来提高 GPU 利用率。

  2. Kernel 自动调优。TensorRT 会在目标 GPU 卡上选择最优的层和并行优化算法,保证最优性能。

  3. 多流执行。通过共享权重的方式并行处理多条任务流,优化显存。

  4. 动态申请 Tensor 显存。当 Tensor 使用时再真正申请显存,显著提高显存利用率。

  5. 模型量化。在保证精度的情况下大幅提升模型的吞吐,同时降低推理延迟。

知识蒸馏

12 层 Bert 模型的线上延迟不能满足性能要求,我们将其蒸馏至 6 层的轻量级小模型。做完知识蒸馏后,在降低计算量的同时也保证了预测效果,6 层模型可以达到 12 层模型精度的 99%。经过试验验证,Bert 模型层数和在线服务的性能呈正相关的关系,6 层模型 TP99 指标相对于 12 层模型性能提升 1 倍。

FP16 量化

在 Bert 模型结构中,大部分 Tensor 都是 fp32 精度,但是在推理时不需要反向传播,此时可以降低精度,在保证模型效果的基础上大幅提高模型的吞吐。经过 FP16 量化之后,模型推理延迟变为原先 1/3 的同时,吞吐提升为原先的 3 倍,此时显存占用也为原先模型的 1/2。但是相比较原先模型,fp16 量化后的模型在万分位后有损失,在 360 搜索的场景下经过验证,量化后的模型对最终效果几乎无影响。权衡之下,量化后的收益远大于损失。

流水优化

开发完在线服务后压测过程中,观察到一种现象:无论压测请求压到多高,GPU 利用率会达到一个瓶颈,维持在 80%左右。此时继续增大压力,GPU 利用率依然没有升高,延迟反而不断增大。



上图中 H2D 和 D2H 分别表示从内存往显存中拷贝数据和从显存往内存中拷贝数据,Kernel 表示正在执行核函数。线上请求推理时所做的三个动作为首先将请求数据由内存拷贝至显存,然后 GPU 发起核函数调用做推理计算,最后将计算结果由显存拷贝至内存。GPU 真正执行计算的部分是执行核函数的部分(上图中蓝色部分),数据拷贝时 GPU 是空闲的(上图中白色部分),此时无论压测压力多大 GPU 都会有空闲时间,因此利用率不会压满。


解决上述问题的一个方法是增加一条 Stream,使得两条 Stream 的核函数计算部分可以交替执行,增加 GPU 有效工作时间占比,GPU 利用率可以压到 98%以上。Stream 可以理解为任务队列,H2D 可以理解为一次任务,多增加一条 Stream 不会增加额外的显存占用,多条 Stream 是共享模型权重的。

运行架构



上图描述了一个占有 2 张 GPU 卡的单个 Bert 服务进程的运行架构。从左至右依次解释出现的名词,task 表示待处理的预测请求,context 用来存储这条请求的上下文信息,stream 表示任务流,profile 描述了模型输入的限制(比如限制输入的最大 batch size),engine 是 TensorRT 将原始模型编译优化后的模型。每张 GPU 卡上加载一个模型,每个模型会有 2 条 Stream 共享模型权重对外提供预测服务。


每当 Bert 服务收到来自客户端的预测请求,这个请求将会被放入任务队列。上图线程池中的 4 个工作线程每当空闲时会从任务队列中取出一条预测任务,保存好上下文信息后便将请求数据通过 Stream 拷贝到显存,GPU 调用核函数做完推理后再将结果通过 Stream 传回到内存,此时工作线程将结果存入指定位置后通知上层,一条完整的请求预测流程就完成了。

缓存优化

在搜索场景下,当天的搜索内容会有一部分热词出现,加上缓存可以有效减轻一部分计算量。在搜索系统加入请求级别的缓存之后,平均缓存命中率可达 35%,极大地缓解了 Bert 在线服务的压力。

动态 sequence length

最开始的在线服务是采用输入维度固定的方式,即输入 shape 的最后一个维度为离线统计出现过的最大 sequence 长度,经过线上小流量验证并且统计线上请求之后,发现线上请求长度超过 70 的 sequence 占比不到 10%。于是我们采取了动态 sequence 长度的优化方式,即采用一个请求 batch 中长度最长的 sequence 为输入长度,对其余的 sequence 做补零操作,经过这一优化线上性能提升 7%。

Bert 在线服务探索

做完上述优化后在测试以及小流量验证的过程中,我们也碰到了一些问题,分享给大家。

模型动态加载导致延迟升高

在搜索场景下,有一个多版本模型热加载的需求。开发完上线后观测到一个现象,在热加载新模型的时候,会出现 TP99 升高的现象,后来经过定位分析找到了原因。

在 Bert 在线服务做预测的时候,会有一个将模型输入数据从内存拷贝到显存的操作。而 Bert 服务动态加载模型的时候,也会有一个将模型权重数据从内存拷贝到显存的动作,拷贝模型到显存的时候占据了 PCI 总线,这时候预测请求数据从内存拷贝到显存就会受到影响,从而 TP99 就会升高。模型权重拷贝持续约几秒的时间,此时 TP95 正常,经统计仅有几条请求会有延迟升高,对业务基本无影响。

精度震荡

在前期开发过程中,我们观测到相同的 sequence 输入模型,在不同的 batch size 下返回的结果总是不尽相同,而是在某一固定的区间内震荡,例如返回的结果总是介于 0.93-0.95 之间且不固定。这个现象在 TensorRT 7.1.3.4 下稳定复现,后与 Nvidia 的同事沟通反馈,在 7.2.2.3 这个版本下已经修复。

显存占用

单个 Bert 模型仅占用几百 MB 的显存,但是上了多版本模型的功能后,Bert 在线服务有可能加载 5-8 个模型,如果处理不好有可能会出现 OOM 的问题。目前我们的处理手段是如果因显存不够而无法正常加载模型,仅仅会提示模型加载失败不会影响正常服务。加载一个新的模型的显存占用量是可以提前判断出来的,主要依据有 3 个:


  1. 模型本身的权重。模型本身的权重是需要占用显存的,占用显存的大小约等于模型在磁盘上的文件大小。

  2. 模型推理时需要的一些上下文信息。此部分显存占用分为两部分,一部分是保存上下文的持久化信息,包括输入输出数据占用的显存。另一部分是推理时占用的中间信息,中间信息显存占用一般不会超过模型权重大小。

  3. CUDA 运行时也耗费一些显存,但这些显存占用是固定的。

总结与展望

经过前期框架调研验证,模型优化,工程架构优化以及部署探索过程后,最终 Bert 在线服务在 360 搜索场景下正式上线了。目前经过优化后的 6 层模型单张 T4 卡每秒可计算 1500 条 qt,线上高峰期 TP99 为 13ms。工程方面 Bert 在线服务稳定性和性能得到了保障的基础上,业务效果上相较于 baseline 也取得了可观的收益。


我们后续会持续探索推进 Bert 在 360 的应用落地,目前在搜索场景下工程方面还有一些亟需优化点:


  1. 目前 Bert 服务还是物理机部署,存在升级扩容困难、容灾差以及资源浪费的问题,我们正在推进 Bert K8S 化部署进程。

  2. 当前 Bert 的训练、蒸馏、数据和模型管理以及部署各个工作模块比较分散,我们在做的一个工作是把这些模块慢慢集成到公司内部的机器学习平台中,做到模型训练,数据管理,模型管理,服务部署升级,AB 实验的平台化和流程化,缩短上线周期,提高工作效率。


本文转载自:360 技术(ID:qihoo_tech)

原文链接:Bert语义在360搜索中的探索实践-工程优化

公众号推荐:

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

2021-03-10 13:001699

评论

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

软件测试丨ChatGPT的火爆对测试人员来说,是机遇还是挑战?

测试人

软件测试 ChatGPT

【直播回顾】数字化转型成为银行业发展的关键(上)

易观分析

金融 银行 经济

Redis管道

京茶吉鹿

nosql redis pipeline

从零学习SDK(4)使用SDK创建一个简单的应用程序

MobTech袤博科技

浅析云原生时代的服务架构演进

华为云开发者联盟

后端 开发 华为云 华为云开发者联盟 企业号 4 月 PK 榜

扯下@EventListener这个注解的神秘面纱。

why技术

Java 源码

ZBC 荣登OKX涨幅榜前列,生态持续发力是关键

EOSdreamer111

GitHub登顶的 Java 面试八股文(2023最新)附答案详解

采菊东篱下

Java 编程

你知道什么是“XY Problem”吗?-【避坑指南】

炜娓道来程序人生

架构 职场 沟通 工作哲学 思维

软件测试丨河南工业大学“火焰杯”软件测试开发选拔赛颁奖仪式

测试人

OpenTiny 跨端、跨框架组件库升级TypeScript,10万行代码重获新生

华为云开发者联盟

Vue 前端 华为云 华为云开发者联盟 企业号 4 月 PK 榜

Docker教程:如何将Helix QAC创建为一个容器并运行?

龙智—DevSecOps解决方案

Docker 容器 Helix QAC 静态代码扫描

ZBC 荣登OKX涨幅榜前列,月内涨幅逾六成

股市老人

你的 Kubernetes 安全吗?最新benchmark的重要趋势解读

HummerCloud

Kubernetes k8s

GreatSQL社区月报 | 2023.03

GreatSQL

greatsql greatsql社区

4月飞桨国赛火热报名中!产业级赛题和免费硬件,等你来拿

飞桨PaddlePaddle

飞桨

聊聊ChatGPT

炜娓道来程序人生

AI ChatGPT

OpenHarmony标准系统开机时长优化

OpenHarmony开发者

OpenHarmony

【四大分主题,九次干货分享】去哪儿网“云原生”系列分享即将开讲!!

Qunar技术沙龙

云原生 去哪儿网

火山引擎云原生数据仓库ByteHouse技术白皮书V1.0(上)

字节跳动数据平台

大数据 数据仓库 云原生 实时数仓 企业号 4 月 PK 榜

从 OSPO 角度思考开源治理问题——蚂蚁集团开源办公室负责人边思康

开源雨林

阿里P8架构师3年心血终成的453页神级Java系统分析与架构设计文档

Java你猿哥

Java ssm 架构师 面经 Java系统性能

Apache IoTDB v1.1.0 发布|增加多种分段方式与实用函数,引入 pipeline 执行引擎进一步提升查询速度

Apache IoTDB

科学的演变:从笛卡尔到生成式人工智能

Baihai IDP

人工智能 AIGC 企业号 4 月 PK 榜

极光笔记 | 如何在Shopify中使用EngageLab (下)

极光JIGUANG

市场营销 用户运营

穿云鉴智 - HashiCorp 创始人对于 AI 大模型的思考

Bytebase

人工智能 DevOps

用友开发者中心应用构建实践指引(二):如何实现入职申请单功能?

YonBuilder低代码开发平台

绝了!阿里大佬的"Redis深度核心笔记",从基础到源码,全是精华

Java你猿哥

Java redis 面试 面经 春招

期盼已久的“库权限”来了

NineData

数据库 安全 数据 开发 权限管理

使用 App Store Connect API v2.3 管理 App Store 新定价机制

37手游iOS技术运营团队

ios iap In App Purchase App Store Connect API app store

低至200元/月,火山引擎DataLeap帮你搭建企业级数据中台

字节跳动数据平台

数据中台 数据集成 促销 数字化建设 企业号 4 月 PK 榜

Bert语义在360搜索中的探索实践-工程优化_语言 & 开发_360技术_InfoQ精选文章