关于美团:外卖广告大规模深度学习模型工程实践-美团外卖广告工程实践专题连载

在外卖广告CTR场景下,深度学习模型正在从简略DNN小模型过渡到千亿参数简单模型。基于该背景,本文将重点针对大规模深度模型在全链路带来的挑战,从在线时延、离线效率两个方面开展,论述外卖广告在大规模深度模型上的工程实践经验,心愿能为读者提供思路上的借鉴。

导语

随着美团外卖业务一直倒退,外卖广告引擎团队在多个畛域进行了工程上的摸索和实际,也获得了一些成绩。咱们将以连载的形式进行分享,内容次要包含:① 业务平台化的实际;② 大规模深度学习模型工程实际;③ 近线计算的摸索与实际;④ 大规模索引构建与在线检索服务实际;⑤ 机制工程平台化实际。

不久前,咱们已发表过业务平台化的实际(详情请参阅《美团外卖广告平台化的摸索与实际》一文)。本文为连载文章的第二篇,咱们将重点针对大规模深度模型在全链路层面带来的挑战,从在线时延、离线效率两个方面进行开展,论述广告在大规模深度模型上的工程实际,心愿能为大家带来一些帮忙或者启发。

1 背景

在搜寻、举荐、广告(下简称搜推广)等互联网外围业务场景下,对用户行为进行数据挖掘及趣味建模,为用户提供优质的服务,曾经成为改善用户体验、晋升营收的要害因素。近几年,针对搜推广业务,深度学习模型凭借数据红利和硬件技术红利,在业界得以宽泛落地,同时在CTR场景,业界逐渐从简略DNN小模型过渡到数万亿参数的Embedding大模型甚至超大模型。

外卖广告业务线次要经验了“LR浅层模型(树模型)” -> “深度学习模型” -> “大规模深度学习模型”的演化过程。整个演变趋势从以人工特色为主的简略模型,逐渐向以数据为外围的简单深度学习模型进行过渡。而大模型的应用,大幅提高了模型的表达能力,更精准地实现了供需侧的匹配,为后续业务倒退提供了更多的可能性。但随着模型、数据规模的一直变大,咱们发现效率跟它们存在如下的关系:

依据上图所示,在数据规模、模型规模增长的状况下,所对应的“时长”变得会越来越长。这个“时长”对应到离线层面,体现在效率上;对应到在线层面,就体现在Latency上。而咱们的工作就是围绕这个“时长”的优化来发展。

2 剖析

相比一般小模型,大模型的外围问题在于:随着数据量、模型规模减少数十倍甚至百倍,整体链路上的存储、通信、计算等都将面临新的挑战,进而影响算法离线的迭代效率。如何冲破在线时延束缚等一系列问题?咱们先从全链路进行剖析,如下所示:

“时长”变长,次要会体现在以下几个方面:

  • 在线时延:特色层面,在线申请不变的状况下,特色量的减少,带来的IO、特色计算耗时减少等问题尤为突出,须要在特色算子解析编译、特色抽取外部任务调度、网络I/O传等方面重塑。在模型层面,模型历经百M/G到几百G的变动,在存储上带来了2个数量级的回升。此外,单模型的计算量也呈现了数量级的上涨(FLOPs从百万到当初千万),单纯的靠CPU,解决不了微小算力的需要,建设CPU+GPU+Hierarchical Cache推理架构来撑持大规模深度学习推理势在必行。
  • 离线效率:随着样本、特色的数倍减少,样本构建,模型训练的工夫会被大大拉长,甚至会变得不可承受。如何在无限的资源下,解决海量样本构建、模型训练是零碎的首要问题。在数据层面,业界个别从两个层面去解决,一方面一直优化批处理过程中掣肘的点,另一方面把数据“化批为流”,由集中式转到摊派式,极大晋升数据的就绪工夫。在训练层面,通过硬件GPU并联合架构层面的优化,来达到减速目标。其次,算法翻新往往都是通过人来驱动,新数据如何疾速匹配模型,新模型如何疾速被其余业务利用,如果说将N集体放在N条业务线上独立地做同一个优化,演变成一个人在一个业务线的优化,同时播送适配到N个业务线,将会有N-1个人力释放出来做新的翻新,这将会极大地缩短翻新的周期,尤其是在整个模型规模变大后,不可避免地会减少人工迭代的老本,实现从“人找特色/模型” 到“特色/模型找人”的深度转换,缩小“反复翻新”,从而达到模型、数据智能化的匹配。
  • Pipeline其余问题:机器学习Pipeline并不是在大规模深度学习模型链路里才有,但随着大模型的铺开,将会有新的挑战,比方:①零碎流程如何反对全量、增量上线部署;②模型的回滚时长,把事件做正确的时长,以及事件做错后的复原时长。简而言之,会在开发、测试、部署、监测、回滚等方面产生新的诉求。

本文重点从在线时延(模型推理、特色服务)、离线效率(样本构建、数据筹备)等两个方面来开展,逐渐论述广告在大规模深度模型上的工程实际。如何去优化“时长”等相干问题,咱们会在后续篇章介进行分享,敬请期待。

3 模型推理

在模型推理层面,外卖广告历经了三个版本,从1.0时代,反对小众规模的DNN模型为代表,到2.0时代,高效、低代码反对多业务迭代,再到现在的3.0时代,逐渐面向深度学习DNN算力以及大规模存储的需要。次要演进趋势如下图所示:

面向大模型推理场景,3.0架构解决的两个外围问题是:“存储问题”和“性能问题”。当然,面向N个百G+模型如何迭代,运算量数十倍减少时在线稳定性如何保障,Pipeline如何加固等等,也是工程面临的挑战。上面咱们将重点介绍模型推理3.0架构是如何通过“分布式”来解决大模型存储问题,以及如何通过CPU/GPU减速来解决性能、吞吐问题。

3.1 分布式

大模型的参数次要分为两局部:Sparse参数和Dense参数。

  • Sparse参数:参数量级很大,个别在亿级别,甚至十亿/百亿级别,这会导致存储空间占用较大,通常在百G级别,甚至T级别。其特点:① 单机加载艰难:在单机模式下,Sparse参数需全副加载到机器内存中,导致内存重大吃紧,影响稳定性和迭代效率;② 读取稠密:每次推理计算,只需读取局部参数,比方User全量参数在2亿级别,但每次推理申请只需读取1个User参数。
  • Dense参数:参数规模不大,模型全连贯个别在2~3层,参数量级在百万/千万级别。特点:① 单机可加载:Dense参数占用在几十兆左右,单机内存可失常加载,比方:输出层为2000,全连贯层为[1024, 512, 256],总参数为:2000 1024 + 1024 512 + 512 * 256 + 256 = 2703616,共270w个参数,内存占用在百兆内;②全量读取:每次推理计算,须要读取全量参数。

因而,解决大模型参数规模增长的要害是将Sparse参数由单机存储革新为分布式存储,革新的形式包含两局部:① 模型网络结构转换;② Sparse参数导出。

3.1.1 模型网络结构转换

业界对于分布式参数的获取形式大抵分为两种:内部服务提前获取参数并传给预估服务;预估服务外部通过革新TF(TensorFlow)算子来从分布式存储获取参数。为了缩小架构革新老本和升高对现有模型构造的侵入性,咱们抉择通过革新TF算子的形式来获取分布式参数。

失常状况下,TF模型会应用原生算子进行Sparse参数的读取,其中外围算子是GatherV2算子,算子的输出次要有两局部:1)须要查问的ID列表;2)存储Sparse参数的Embedding表。算子的作用是从Embedding表中读取ID列表索引对应的Embedding数据并返回,实质上是一个Hash查问的过程。其中,Embedding表存储的Sparse参数,其在单机模型中全副存储在单机内存中。

革新TF算子实质上是对模型网络结构的革新,革新的外围点次要包含两局部:① 网络图重构;② 自定义分布式算子。

1. 网络图重构:革新模型网络结构,将原生TF算子替换为自定义分布式算子,同时进行原生Embedding表的固化。

  • 分布式算子替换:遍历模型网络,将须要替换的GatherV2算子替换为自定义分布式算子MtGatherV2,同时批改上下游节点的Input/Output。
  • 原生Embedding表固化:原生Embedding表固化为占位符,既能保留模型网络结构残缺,又能防止Sparse参数对单机内存的占用。

2. 自定义分布式算子:革新依据ID列表查问Embedding流程,从本地Embedding表中查问,革新为从分布式KV中查问。

  • 申请查问:将输出ID进行去重以升高查问量,并通过分片的形式并发查问二级缓存(本地Cache + 远端KV)获取Embedding向量。
  • 模型治理:保护对模型Embedding Meta注册、卸载流程,以及对Cache的创立、销毁性能。
  • 模型部署:触发模型资源信息的加载,以及对Embedding数据并行导入KV的流程。

3.1.2 Sparse参数导出

  • 分片并行导出:解析模型的Checkpoint文件,获取Embedding表对应的Part信息,并依据Part进行划分,将每个Part文件通过多个Worker节点并行导出到HDFS上。
  • 导入KV:提前预调配多个Bucket,Bucket会存储模型版本等信息,便于在线路由查问。同时模型的Embedding数据也会存储到Bucket中,按分片并行形式导入到KV中。

整体流程如下图所示,咱们通过离线分布式模型构造转换、近线数据一致性保障、在线热点数据缓存等伎俩,保障了百G大模型的失常迭代需要。

能够看到,分布式借助的存储是内部KV能力,后续会替换为更加高效、灵便、易治理的Embedding Service。

3.2 CPU减速

抛开模型自身的优化伎俩外,常见的CPU减速伎俩次要有两种:① 指令集优化,比方应用AVX2、AVX512指令集;② 应用减速库(TVM、OpenVINO)。

  1. 指令集优化:如果应用TensorFlow模型,在编译TensorFlow框架代码时,间接在编译选项里退出指令集优化项即可。实践证明引入AVX2、AVX512指令集优化成果显著,在线推理服务吞吐晋升30%+。
  2. 减速库优化:减速库通过对网络模型构造进行优化交融,以达到推理减速成果。业界罕用的减速库有TVM、OpenVINO等,其中TVM反对跨平台,通用性较好。OpenVINO面向Intel厂商硬件进行针对性优化,通用性个别,但减速成果较好。

上面,将会重点介绍咱们应用OpenVINO进行CPU减速的一些实践经验。OpenVINO是Intel推出的一套基于深度学习的计算减速优化框架,反对机器学习模型的压缩优化、减速计算等性能。OpenVINO的减速原理简略概括为两局部:线性算子交融和数据精度校准。

  1. 线性算子交融:OpenVINO通过模型优化器,将模型网络中的多层算子进行对立线性交融,以升高算子调度开销和算子间的数据访存开销,比方将Conv+BN+Relu三个算子合并成一个CBR构造算子。
  2. 数据精度校准:模型通过离线训练后,因为在推理的过程中不须要反向流传,齐全能够适当升高数据精度,比方降为FP16或INT8的精度,从而使得内存占用更小,推理提早更低。

CPU减速通常是针对固定Batch的候选队列进行减速推理,但在搜推广场景中,候选队列往往都是动静的。这就意味着在模型推理之前,须要减少Batch匹配的操作,行将申请的动静Batch候选队列映射到一个离它最近的Batch模型上,但这需构建N个匹配模型,导致N倍的内存占用。而以后模型体积已达百G规模,内存重大吃紧。因而,选取正当的网络结构用于减速是须要思考的重点问题。下图是整体的运行架构:

  1. 网络散布:CTR模型网络结构整体形象为三局部:Embedding层、Attention层和MLP层,其中Embedding层用于数据获取,Attention层蕴含较多逻辑运算和轻量级的网络计算,MLP层则为密集网络计算。
  2. 减速网络抉择:OpenVINO针对纯网络计算的减速成果较好,能够很好地利用于MLP层。另外,模型大部分数据存储在Embedding层中,MLP层占内存只有几十兆左右。如果针对MLP层网络划分出多个Batch,模型内存占用在优化前(Embedding+Attention+MLP)≈ 优化后(Embedding+Attention+MLP×Batch个数),对于内存占用的影响较小。因而,咱们最终选取MLP层网络作为模型减速网络。

目前,基于OpenVINO的CPU减速计划曾经在生产环境获得不错成果:CPU与基线持平时,服务吞吐晋升40%,均匀时延降落15%。如果大家想在CPU层面做些减速的话,OpenVINO是个不错的抉择。

3.3 GPU减速

一方面,随着业务的倒退,业务状态越来越丰盛,流量越来越高,模型变宽变深,算力的耗费急剧减少;另一方面,广告场景次要应用DNN模型,波及大量稠密特色Embedding和神经网络浮点运算。作为访存和计算密集型的线上服务,在保障可用性的前提下,还要满足低提早、高吞吐的要求,对单机算力也是一种挑战。这些算力资源需要和空间的矛盾,如果解决不好,会极大限度业务的倒退:在模型加宽加深前,纯CPU 推理服务可能提供可观的吞吐,然而在模型加宽加深后,计算复杂度回升,为了保障高可用性,须要耗费大量机器资源,导致大模型无奈大规模利用于线上。

目前,业界比拟通用的解决办法是利用GPU来解决这个问题,GPU自身比拟实用于计算密集型工作。应用GPU须要解决如下挑战:如何在保障可用性、低提早的前提下,尽可能做到高吞吐,同时还须要思考易用性和通用性。为此,咱们也在GPU上做了大量实际工作,比方TensorFlow-GPU、TensorFlow-TensorRT、TensorRT等,为了兼顾TF的灵活性以及TensorRT的减速成果,咱们采纳TensorFlow+TensorRT独立两阶段的架构设计。

3.3.1 减速剖析

  • 异构计算:咱们的思路跟CPU减速比拟统一,200G的深度学习CTR模型不能间接全放入到GPU里,访存密集型算子实用(比方Embedding相干操作)CPU,计算密集型算子(比方MLP)实用GPU。
  • GPU应用须要关注的几个点:① 内存与显存的频繁交互;② 时延与吞吐;③ 扩展性与性能优化的Trade Off;④ GPU Utilization 。
  • 推理引擎的抉择:业界罕用推理减速引擎有TensorRT、TVM、XLA、ONNXRuntime等,因为TensorRT在算子优化相比其余引擎更加深刻,同时能够通过自定义plugin的形式实现任意算子,具备很强的扩展性。而且TensorRT反对常见学习平台(Caffe、PyTorch、TensorFlow等)的模型,其周边越来越欠缺(模型转换工具onnx-tensorrt、性能剖析工具nsys等),因而在GPU侧的减速引擎应用TensorRT。
  • 模型剖析:CTR模型网络结构整体形象为三局部:Embedding层、Attention层和MLP层,其中Embedding层用于数据获取,适宜CPU;Attention层蕴含较多逻辑运算和轻量级的网络计算,MLP层则重网络计算,而这些计算能够并行进行,适宜GPU,能够充分利用GPU Core(Cuda Core、Tensor Core),进步并行度。

3.3.2 优化指标

深度学习推理阶段对算力和时延具备很高的要求,如果将训练好的神经网络间接部署到推理端,很有可能呈现算力有余无奈运行或者推理工夫较长等问题。因而,咱们须要对训练好的神经网络进行肯定的优化。业界神经网络模型优化的个别思路,能够从模型压缩、不同网络层合并、稠密化、采纳低精度数据类型等不同方面进行优化,甚至还须要依据硬件个性进行针对性优化。为此,咱们次要围绕以下两个指标进行优化:

  1. 延时和资源束缚下的吞吐:当register、Cache等共享资源不须要竞争时,进步并发可无效进步资源利用率(CPU、GPU等利用率),但随之可能带来申请延时的上涨。因为在线零碎的延时限度十分刻薄,所以不能只通过资源利用率这一指标简略换算在线零碎的吞吐下限,须要在延时束缚下联合资源下限进行综合评估。当零碎延时较低,资源(Memory/CPU/GPU等)利用率是制约因素时,可通过模型优化升高资源利用率;当系统资源利用率均较低,延时是制约因素时,可通过交融优化和引擎优化来升高延时。通过联合以上各种优化伎俩可无效晋升零碎服务的综合能力,进而达到晋升零碎吞吐的目标。
  2. 计算量束缚下的计算密度:CPU/GPU异构零碎下,模型推理性能次要受数据拷贝效率和计算效率影响,它们别离由访存密集型算子和计算密集型算子决定,而数据拷贝效率受PCIe数据传输、CPU/GPU内存读写等效率的影响,计算效率受各种计算单元CPU Core、CUDA Core、Tensor Core等计算效率的影响。随着GPU等硬件的疾速倒退,计算密集型算子的解决能力同步疾速进步,导致访存密集型算子妨碍零碎服务能力晋升的景象越来越突出,因而缩小访存密集型算子,晋升计算密度对系统服务能力也变得越来越重要,即在模型计算量变动不大的状况下,缩小数据拷贝和kernel launch等。比方通过模型优化和交融优化来缩小算子变换(比方Cast/Unsqueeze/Concat等算子)的应用,应用CUDA Graph缩小kernel launch等。

上面将围绕以上两个指标,具体介绍咱们在模型优化交融优化引擎优化所做的一些工作。

3.3.3 模型优化

  1. 计算与传输去重:推理时同一Batch只蕴含一个用户信息,因而在进行inference之前能够将用户信息从Batch Size降为1,真正须要inference时再进行开展,升高数据的传输拷贝以及反复计算开销。如下图,inference前能够只查问一次User类特色信息,并在只有用户相干的子网络中进行裁剪,待须要计算关联时再开展。

    • 自动化过程:找到反复计算的结点(红色结点),如果该结点的所有叶子结点都是反复计算结点,则该结点也是反复计算结点,由叶子结点逐层向上查找所有反复结点,直到结点遍历查找完,找到所有红白结点的连接线,插入User特色扩大结点,对User特色进行开展。

  1. 数据精度优化:因为模型训练时须要反向流传更新梯度,对数据精度要求较高;而模型推理时,只进行前向推理不须要更新梯度,所以在保障成果的前提下,应用FP16或混合精度进行优化,节俭内存空间,缩小传输开销,晋升推理性能和吞吐。
  2. 计算下推:CTR模型构造次要由Embedding、Attention和MLP三层形成,Embedding层偏数据获取,Attention有局部偏逻辑,局部偏计算,为了充沛压迫GPU的后劲,将CTR模型构造中Attention和MLP大部分计算逻辑由CPU下沉到GPU进行计算,整体吞吐失去大幅晋升。

3.3.4 交融优化

在线模型inference时,每一层的运算操作都是由GPU实现,实际上是CPU通过启动不同的CUDA kernel来实现计算,CUDA kernel计算张量的速度十分快,然而往往大量的工夫是节约在CUDA kernel的启动和对每一层输出/输入张量的读写操作上,这造成了内存带宽的瓶颈和GPU资源的节约。这里咱们将次要介绍TensorRT局部主动优化以及手工优化两块工作。

1. 主动优化:TensorRT是一个高性能的深度学习inference优化器,能够为深度学习利用提供低提早、高吞吐的推理部署。TensorRT可用于对超大规模模型、嵌入式平台或主动驾驶平台进行推理减速。TensorRT现已能反对TensorFlow、Caffe、MXNet、PyTorch等简直所有的深度学习框架,将TensorRT和NVIDIA的GPU联合起来,能在简直所有的框架中进行疾速和高效的部署推理。而且有些优化不须要用户过多参加,比方局部Layer Fusion、Kernel Auto-Tuning等。

  • Layer Fusion:TensorRT通过对层间的横向或纵向合并,使网络层的数量大大减少,简略说就是通过交融一些计算op或者去掉一些多余op,来缩小数据流通次数、显存的频繁应用以及调度的开销。比方常见网络结构Convolution And ElementWise Operation交融、CBR交融等,下图是整个网络结构中的局部子图交融前后结构图,FusedNewOP在交融过程中可能会波及多种Tactic,比方CudnnMLPFC、CudnnMLPMM、CudaMLP等,最终会依据时长抉择一个最优的Tactic作为交融后的构造。通过交融操作,使得网络层数缩小、数据通道变短;雷同构造合并,使数据通道变宽;达到更加高效利用GPU资源的目标。

  • Kernel Auto-Tuning:网络模型在inference时,是调用GPU的CUDA kernel进行计算。TensorRT能够针对不同的网络模型、显卡构造、SM数量、内核频率等进行CUDA kernel调整,抉择不同的优化策略和计算形式,寻找适宜以后的最优计算形式,以保障以后模型在特定平台上取得最优的性能。上图是优化次要思维,每一个op会有多种kernel优化策略(cuDNN、cuBLAS等),依据以后架构从所有优化策略中过滤低效kernel,同时抉择最优kernel,最终造成新的Network。

2. 手工优化:家喻户晓,GPU适宜计算密集型的算子,对于其余类型算子(轻量级计算算子,逻辑运算算子等)不太敌对。应用GPU计算时,每次运算个别要通过几个流程:CPU在GPU上调配显存 -> CPU把数据发送给GPU -> CPU启动CUDA kernel -> CPU把数据取回 -> CPU开释GPU显存。为了缩小调度、kernel launch以及访存等开销,须要进行网络交融。因为CTR大模型构造灵便多变,网络交融伎俩很难对立,只能具体问题具体分析。比方在垂直方向,Cast、Unsqueeze和Less交融,TensorRT外部Conv、BN和Relu交融;在程度方向,同维度的输出算子进行交融。为此,咱们基于线上理论业务场景,应用NVIDIA相干性能剖析工具(NVIDIA Nsight Systems、NVIDIA Nsight Compute等)进行具体问题的剖析。把这些性能剖析工具集成到线上inference环境中,取得inference过程中的GPU Profing文件。通过Profing文件,咱们能够清晰的看到inference过程,咱们发现整个inference中局部算子kernel launch bound景象重大,而且局部算子之间gap间隙较大,存在优化空间,如下图所示:

为此,基于性能剖析工具和转换后的模型对整个Network剖析,找出TensorRT曾经优化的局部,而后对Network中其余能够优化的子结构进行网络交融,同时还要保障这样的子结构在整个Network占有肯定的比例,保障交融后计算密度可能有肯定水平的回升。至于采纳什么样的网络交融伎俩,依据具体的场景进行灵活运用即可,如下图是咱们交融前后的子结构图比照:

3.3.5 引擎优化

  1. 多模型:因为外卖广告中用户申请规模不确定,广告时多时少,为此加载多个模型,每个模型对应不同输出的Batch,将输出规模分桶归类划分,并将其padding到多个固定Batch,同时对应到相应的模型进行inference。
  2. Multi-contexts和Multi-streams:对每一个Batch的模型,应用多context和多stream,不仅能够防止模型期待同一context的开销,而且能够充分利用多stream的并发性,实现stream间的overlap,同时为了更好的解决资源竞争的问题,引入CAS。如下图所示,单stream变成多stream:

  1. Dynamic Shape:为了应答输出Batch不定场景下,不必要的数据padding,同时缩小模型数量升高显存等资源的节约,引入Dynamic Shape,模型依据理论输出数据进行inference,缩小数据padding和不必要的计算资源节约,最终达到性能优化和吞吐晋升的目标。
  2. CUDA Graph:古代GPU每个operation(kernel运行等)所破费的工夫至多是微秒级别,而且,将每个operation提交给GPU也会产生一些开销(微秒级别)。理论inference时,常常须要执行大量的kernel operation,这些operation每一个都独自提交到GPU并独立计算,如果能够把所有提交启动的开销汇总到一起,应该会带来性能的整体晋升。CUDA Graph能够实现这样的性能,它将整个计算流程定义为一个图而不是单个操作的列表,而后通过提供一种由单个CPU操作来启动图上的多个GPU操作的办法缩小kernel提交启动的开销。CUDA Graph核心思想是缩小kernel launch的次数,通过在推理前后capture graph,依据推理的须要进行update graph,后续推理时不再须要一次一次的kernel launch,只须要graph launch,最终达到缩小kernel launch次数的目标。如下图所示,一次inference执行4次kernel相干操作,通过应用CUDA Graph能够清晰看到优化成果。

  1. 多级PS:为了进一步开掘GPU减速引擎性能,对Embedding数据的查问操作可通过多级PS的形式进行:GPU显存Cache->CPU内存Cache->本地SSD/分布式KV。其中,热点数据可缓存在GPU显存中,并通过数据热点的迁徙、降职和淘汰等机制对缓存数据进行动静更新,充沛开掘GPU的并行算力和访存能力进行高效查问。经离线测试,GPU Cache查问性能相比CPU Cache晋升10倍+;对于GPU Cache未命中数据,可通过拜访CPU Cache进行查问,两级Cache可满足90%+的数据拜访;对于长尾申请,则须要通过拜访分布式KV进行数据获取。具体构造如下:

3.3.6 Pipeline

模型从离线训练到最终在线加载,整个流程繁琐易出错,而且模型在不同GPU卡、不同TensorRT和CUDA版本上无奈通用,这给模型转换带来了更多出错的可能性。因而,为了晋升模型迭代的整体效率,咱们在Pipeline方面进行了相干能力建设,如下图所示:

Pipeline建设包含两局部:离线侧模型拆分转换流程,以及在线侧模型部署流程:

  1. 离线侧:只需提供模型拆分节点,平台会主动将原始TF模型拆分成Embedding子模型和计算图子模型,其中Embedding子模型通过分布式转换器进行分布式算子替换和Embedding导入工作;计算图子模型则依据抉择的硬件环境(GPU型号、TensorRT版本、CUDA版本)进行TensorRT模型的转换和编译优化工作,最终将两个子模型的转换后果存储到S3中,用于后续的模型部署上线。整个流程都是平台主动实现,无需应用方感知执行细节。
  2. 在线测:只需抉择模型部署硬件环境(与模型转换的环境保持一致),平台会依据环境配置,进行模型的自适应推送加载,一键实现模型的部署上线。

Pipeline通过配置化、一键化能力的建设,极大晋升了模型迭代效率,帮忙算法和工程同学可能更加专一的做好本职工作。下图是在GPU实际中相比纯CPU推理获得的整体收益:

4 特色服务CodeGen优化

特色抽取是模型计算的前置阶段,无论是传统的LR模型还是日趋风行的深度学习模型,都须要通过特色抽取来失去输出。在之前的博客美团外卖特色平台的建设与实际中,形容了咱们基于模型特色自描述MFDL,将特色计算流程配置化,尽量保障了在线预估和离线训练时样本的一致性。随着业务疾速迭代,模型特色数量一直减少,特地是大模型引入了大量的离散特色,导致计算量有了成倍的增长。为此,咱们对特色抽取层做了一些优化,在吞吐和耗时上都获得了显著的收益。

4.1 全流程CodeGen优化

DSL是对特色解决逻辑的形容。在晚期的特色计算实现中,每个模型配置的DSL都会被解释执行。解释执行的长处是实现简略,通过良好的设计便能取得较好的实现,比方罕用的迭代器模式;毛病是执行性能较低,在实现层面为了通用性防止不了增加很多的分支跳转和类型转换等。实际上,对于一个固定版本的模型配置来说,它所有的模型特色转换规则都是固定的,不会随申请而变动。极其状况下,基于这些已知的信息,能够对每个模型特色各自进行Hard Code,从而达到最极致的性能。

显然,模型特色配置变幻无穷,不可能针对每个模型去人工编码。于是便有了CodeGen的想法,在编译期为每一个配置主动生成一套专有的代码。CodeGen并不是一项具体的技术或框架,而是一种思维,实现从形象描述语言到具体执行语言的转换过程。其实在业界,计算密集型场景下应用CodeGen来减速计算已是罕用做法。如Apache Spark通过CodeGen来优化SparkSql执行性能,从1.x的ExpressionCodeGen减速表达式运算到2.x引入的WholeStageCodeGen进行全阶段的减速,都获得了非常明显的性能收益。在机器学习畛域,一些TF模型减速框架,如TensorFlow XLA和TVM,也是基于CodeGen思维,将Tensor节点编译成对立的中间层IR,基于IR联合本地环境进行调度优化,从而达到运行时模型计算减速的目标。

借鉴了Spark的WholeStageCodeGen,咱们的指标是将整个特色计算DSL编译造成一个可执行办法,从而缩小代码运行时的性能损耗。整个编译过程能够分为:前端(FrontEnd),优化器(Optimizer)和后端(BackEnd)。前端次要负责解析指标DSL,将源码转化为AST或IR;优化器则是在前端的根底上,对失去的中间代码进行优化,使代码更加高效;后端则是将曾经优化的中间代码转化为针对各自平台的本地代码。具体实现如下:

  1. 前端:每个模型对应一张节点DAG图,一一解析每个特色计算DSL,生成AST,并将AST节点增加到图中。
  2. 优化器:针对DAG节点进行优化,比方公共算子提取、常量折叠等。
  3. 后端:将通过优化后的图编译成字节码。

通过优化之后,对节点DAG图的翻译,即后端代码实现,决定了最终的性能。这其中的一个难点,同时也是不能间接应用已有开源表达式引擎的起因:特色计算DSL并非是一个纯计算型表达式。它能够通过读取算子和转换算子的组合来形容特色的获取和处理过程:

  1. 读取算子:从存储系统获取特色的过程,是个IO型工作。比方查问近程KV零碎。
  2. 转换算子:特色获取到本地之后对特色进行转换,是个计算密集型工作。比方对特征值做Hash。

所以在理论实现中,须要思考不同类型工作的调度,尽可能进步机器资源利用率,优化流程整体耗时。联合对业界的调研以及本身实际,进行了以下三种实现:

  1. 基于工作类型划分Stage:将整个流程划分成获取和计算两种Stage,Stage外部分片并行处理,上一个Stage实现后再执行下一个Stage。这是咱们晚期应用的计划,实现简略,能够基于不同的工作类型抉择不同的分片大小,比方IO型工作能够应用更大的分片。但毛病也很显著,会造成不同Stage的长尾叠加,每个Stage的长尾都会影响整个流程的耗时。
  2. 基于流水线划分Stage:为了缩小不同Stage的长尾叠加,能够先将数据分片,为每个特色读取分片增加回调,在IO工作实现后回调计算工作,使整个流程像流水线一样平滑。分片调度能够让上一个Stage就绪更早的分片提前进入下一个Stage,缩小等待时间,从而缩小整体申请耗时长尾。但毛病就是对立的分片大小不能充沛进步每个Stage的利用率,较小的分片会给IO型工作带来更多的网络耗费,较大的分片会加剧计算型工作的耗时。
  3. 基于SEDA(Staged Event-Driven Architecture)形式:阶段式事件驱动形式应用队列来隔离获取Stage和计算Stage,每个Stage调配有独立的线程池和批处理解决队列,每次生产N(batching factor)个元素。这样既可能实现每个Stage独自抉择分片大小,同时事件驱动模型也能够让流程放弃平滑。这是咱们目前正在摸索的形式。

CodeGen计划也并非完满,动静生成的代码升高了代码可读性,减少了调试老本,但以CodeGen作为适配层,也为更深刻的优化关上了空间。基于CodeGen和异步非阻塞的实现,在线上取到了不错的收益,一方面缩小了特色计算的耗时,另一方面也显著的升高了CPU负载,进步了零碎吞吐。将来咱们会持续施展CodeGen的劣势,在后端编译过程中进行针对性的优化,如摸索联合硬件指令(如SIMD)或异构计算(如GPU)来做更深层次的优化。

4.2 传输优化

在线预估服务整体上是双层架构,特色抽取层负责模型路由和特色计算,模型计算层负责模型计算。原有的零碎流程是将特色计算后的后果拼接成M(预测的Batch Size) × N(样本宽度)的矩阵,再通过序列化传输到计算层。之所以这么做,一方面出于历史起因,晚期很多非DNN的简略模型的输出格局是个矩阵,通过路由层拼接后,计算层能够间接应用,无需转换;另一方面,数组格局比拟紧凑,能够节俭网络传输耗时。

然而随着模型迭代倒退,DNN模型逐步成为支流,基于矩阵传输的弊病也非常明显:

  1. 扩展性差:数据格式对立,不兼容非数值类型的特征值。
  2. 传输性能损耗:基于矩阵格局,须要对特色做对齐,比方Query/User维度须要被拷贝对齐到每个Item上,增大了申请计算层的网络传输数据量。

为了解决以上问题,优化后的流程在传输层之上退出一层转换层,用来依据MDFL的配置将计算的模型特色转换成须要的格局,比方Tensor、矩阵或离线应用的CSV格局等。

理论线上大多数模型都是TF模型,为了进一步节俭传输耗费,平台设计了Tensor Sequence格局来存储每个Tensor矩阵:其中,r_flag用来标记是否是item类特色,length示意item特色的长度,值为M(Item个数)× NF(特色长度),data用来存储理论的特征值,对于Item特色将M个特征值扁平化存储,对于申请类特色则间接填充。基于紧凑型Tensor Sequence格局使数据结构更加紧凑,缩小网络传输数据量。优化后的传输格局在线上也获得不错的成果,路由层调用计算层的申请大小降落了50%+,网络传输耗时显著降落。

4.3 高维ID特色编码

离散特色和序列特色能够对立为Sparse特色,特色解决阶段会把原始特色通过Hash解决,变为ID类特色。在面对千亿级别维度的特色,基于字符串拼接再Hash的过程,在表白空间和性能上,都无奈满足要求。基于对业界的调研,咱们设计和利用了基于Slot编码的形式特色编码格局:

其中,feature_hash为原始特征值通过Hash后的值。整型特色能够间接填充,非整型特色或穿插特色先通过Hash后再填充,超过44位则截断。基于Slot编码方案上线后,不仅晋升了在线特色计算的性能,同时也为模型成果的带来了显著晋升。

5 样本构建

5.1 流式样本

业界为了解决线上线下一致性的问题,个别都会在线dump实时打分应用的特色数据,称为特色快照;而不是通过简略离线Label拼接,特色回填的形式来构建样本,因为这种形式会带来较大的数据不统一。

架构原始的形式如下图所示:

这种计划随着特色规模越来越大、迭代场景越来越简单,突出的问题就是在线特色抽取服务压力大,其次是整个数据流收集老本太高。此样本收集计划存在以下问题:

  1. 就绪工夫长:在现有资源限度下,跑那么大数据简直要在T + 2能力将样本数据就绪,影响算法模型迭代。
  2. 资源消耗大:现有样本收集形式是将所有申请计算特色后与曝光、点击进行拼接,因为对未曝光Item进行了特色计算、数据落表,导致存储的数据量较大,消耗大量资源。

5.1.1 常见的计划

为了解决下面的问题,业界常见有两个计划:① Flink实时流解决;② KV缓存二次解决。具体流程如下图所示:

  1. 流式拼接计划:借助流式解决框架(Flink、Storm等)低提早的流解决能力,间接读取曝光/点击实时流,与特色快照流数据在内存中进行关联(Join)解决;学生成流式训练样本,再转存为模型离线训练样本。其中流式样本和离线样本别离存储在不同的存储引擎中,反对不同类型的模型训练形式。此计划的问题:在数据流动环节的数据量仍然很大,占用较多的音讯流资源(比方Kafka);Flink资源耗费过大,如果每秒百G的数据量,做窗口Join则须要30分钟×60×100G的内存资源。
  2. KV缓存计划:把特色抽取的所有特色快照写入KV存储(如Redis)缓存N分钟,业务零碎通过音讯机制,把候选队列中的Item传入到实时计算零碎(Flink或者生产利用),此时的Item的量会比之前申请的Item量少很多,这样再将这些Item特色从特色快照缓存中取出,数据通过音讯流输入,反对流式训练。这种办法借助了外存,不论随着特色还是流量减少,Flink资源可控,而且运行更加稳固。但突出的问题还是须要较大的内存来缓存大批量数据。

5.1.2 改良优化

从缩小有效计算的角度登程,申请的数据并不会都曝光。而策略对曝光后的数据有更强的需要,因而将天级解决前置到流解决,能够极大晋升数据就绪工夫。其次,从数据内容登程,特色蕴含申请级变更的数据与天级变更的数据,链路灵便拆散两者解决,能够极大晋升资源的利用,下图是具体的计划:

1. 数据拆分:解决数据传输量大问题(特色快照流大问题),预测的Label与实时数据一一Match,离线数据能够通过回流的时候二次拜访,这样能够极大升高链路数据流的大小。

  • 样本流中只有上下文+实时特色,减少读取数据流稳定性,同时因为只须要存储实时特色,Kafka硬盘存储降落10+倍。

2. 延时生产Join形式:解决占用内存大问题。

  • 曝光流作为支流,写入到HBase中,同时为了后续能让其余流在HBase中Join上曝光,将RowKey写入Redis;后续流通过RowKey写入HBase,曝光与点击、特色的拼接借助外存实现,保障数据量增大后零碎能稳固运行。
  • 样本流延时生产,后盾服务的样本流往往会比曝光流先到,为了能Join上99%+的曝光数据,样本流期待窗口统计至多要N分钟以上;实现形式是将窗口期的数据全副压在Kafka的磁盘上,利用磁盘的程序读性能,省略掉了窗口期内须要缓存数据量的大量内存。

3. 特色补录拼样本:通过Label的Join,此处补录的特色申请量不到在线的20%;样本提早读取,与曝光做拼接后过滤出有曝光模型服务申请(Context+实时特色),再补录全副离线特色,拼成残缺样本数据,写入HBase。

5.2 结构化存储

随着业务迭代,特色快照中的特色数量越来越大,使得整体特色快照在单业务场景下达到几十TB级别/天;从存储上看,多天单业务的特色快照就曾经PB级别,快达到广告算法存储阈值,存储压力大;从计算角度上看,应用原有的计算流程,因为计算引擎(Spark)的资源限度(应用到了shuffle,shuffle write阶段数据会落盘,如果分配内存有余,会呈现屡次落盘和外排序),须要与本身数据等大小的内存和较多的计算CU能力无效的实现计算,占用内存高。样本构建流程外围流程如下图所示:

在补录特色时,存在以下问题:

  1. 数据冗余:补录特色的离线表个别为全量数据,条数在亿级别,样本构建用到的条数约为当日DAU的数量即千万级别,因而补录的特色表数据在参加计算时存在冗余数据。
  2. Join程序:补录特色的计算过程即维度特色补全,存在屡次Join计算,因而Join计算的性能和Join的表的程序有很大关系,如上图所示,如果左表为几十TB级别的大表,那么之后的shuffle计算过程都会产生大量的网络IO、磁盘IO。

为了解决样本构建效率慢的问题,短期先从数据结构化治理,具体过程如下图所示:

  1. 结构化拆分:数据拆分成Context数据和结构化存储的维度数据代替混合存储。解决Label样本拼接新特色过程中携带大量冗余数据问题;并且做结构化存储后,针对离线特色,失去了很大的存储压缩。
  2. 高效过滤前置。数据过滤提前到Join前,缩小参加特色计算的数据量,能够无效升高网络IO。在拼接过程中,补录特色的Hive表一般来说是全量表,数据条数个别为月活量,而理论拼接过程中应用的数据条数约为日活量,因而存在较大的数据冗余,有效的数据会带来额定的IO和计算。优化形式为预计算应用的维度Key,并生成相应的布隆过滤器,在数据读取的时候应用布隆过滤器进行过滤,能够极大升高补录过程中冗余数据传输和冗余计算。
  3. 高性能Join。应用高效的策略去编排Join程序,晋升特色补录环节的效率和资源占用。在特色拼接过程中,会存在多张表的Join操作,Join的先后顺序也会极大影响拼接性能。如上图所示,如果拼接的左表数据量较大时,那么整体性能就会差。能够应用哈夫曼算法的思维,把每个表看作一个节点,对应的数据量量看成是他的权重,表之间的Join计算量能够简略类比两个节点的权重相加。因而,能够将此问题形象成结构哈夫曼树,哈夫曼树的结构过程即为最优的Join程序。

数据离线存储资源节俭达80%+,样本构建效率晋升200%+,以后整个样本数据也正在进行基于数据湖的实际,进一步晋升数据效率。

6 数据筹备

平台积攒了大量的特色、样本和模型等有价值的内容,心愿通过对这些数据资产进行复用,帮忙策略人员更好的进行业务迭代,获得更好的业务收益。特色优化占了算法人员晋升模型成果的所有办法中40%的工夫,但传统的特色开掘的工作形式存在着破费工夫长、开掘效率低、特色反复开掘等问题,所以平台心愿在特色维度赋能业务。

如果有自动化的试验流程去验证任意特色的成果,并将最终成果指标举荐给用户,无疑会帮忙策略同学节俭大量的工夫。当整个链路建设实现,后续只须要输出不同的特色候选集,即可输入相应成果指标。为此平台建设了特色、样本的“加”、“减”、“乘”、“除”智能机制。

6.1 做“加法”

特色举荐基于模型测试的办法,将特色复用到其余业务线现有模型,结构出新的样本和模型;比照新模型和Base模型的离线成果,获取新特色的收益,主动推送给相干的业务负责人。具体特色举荐流程如下图所示:

  1. 特色感知:通过上线墙或业务间存量形式触发特色举荐,这些特色曾经过肯定验证,能够保障特色举荐的成功率。
  2. 样本生产:样本生产时通过配置文件抽取特色,流程主动将新增特色加到配置文件中,而后进行新样本数据的生产。获取到新特色后,解析这些特色依赖的原始特色、维度、和UDF算子等,将新特色配置和依赖的原始数据交融到基线模型的原有配置文件中,结构出新的特色配置文件。主动进行新样本构建,样本构建时通过特色名称在特色仓库中抽取相干特色,并调用配置好的UDF进行特色计算,样本构建的时间段可配置。
  3. 模型训练:主动对模型构造和样本格局配置进行革新,而后进行模型训练,应用TensorFlow作为模型训练框架,应用tfrecord格局作为样本输出,将新特色依照数值类和ID类别离放到A和B两个组中,ID类特色进行查表操作,而后对立追加到现有特色前面,不须要批改模型构造便可接管新的样本进行模型训练。
  4. 主动配置新模型训练参数:包含训练日期、样本门路、模型超参等,划分出训练集和测试集,主动进行新模型的训练。
  5. 模型评测:调用评估接口失去离线指标,比照新老模型评测后果,并预留单特色评估后果,打散某些特色后,给出单特色贡献度。将评估后果对立发送给用户。

6.2 做“减法”

特色举荐在广告外部落地并获得了肯定收益后,咱们在特色赋能层面做一些新的摸索。随着模型的一直优化,特色收缩的速度十分快,模型服务耗费资源急剧回升,剔除冗余特色,为模型“瘦身”势在必行。因而,平台建设了一套端到端的特色筛选工具。

  1. 特色打分:通过WOE(Weight Of Evidence, 证据权重)等多种评估算法给出模型的所有特色评分,打分较高特色的品质较高,评估准确率高。
  2. 成果验证:训练好模型后,按打分排序,分批次对特色进行剔除。具体通过采纳特色打散的办法,比照原模型和打散后模型评估后果,相差较大低于阈值后完结评估, 给出能够剔除的特色。
  3. 端到端计划:用户配置好试验参数和指标阈值后,无需人为干预,即可给出可删除的特色以及删除特色后模型的离线评估后果。

最终,在外部模型下线40%的特色后,业务指标降落依然管制在正当的阈值内。

6.3 做“乘法”

为了失去更好的模型成果,广告外部曾经开始做一些新的摸索,包含大模型、实时化、特色库等。这些摸索背地都有一个要害指标:须要更多、更好的数据让模型更智能、更高效。从广告现状登程,提出样本库(Data Bank)建设,实现把内部更多品种、更大规模的数据拿进来,利用于现有业务。具体如下图所示:

咱们建设了一套通用的样本共享平台,在这个平台上,能够借用其余业务线来产生增量样本。并且也搭建通用的Embedding共享架构,实现业务的以大带小。上面以广告业务线复用非广告样本为例,具体做法如下:

  1. 扩样本:基于Flink流式解决框架,建设了高扩大样本库DataBank,业务A很不便复用业务B、业务C的曝光、点击等Label数据去做试验。尤其是为小业务线,裁减了大量的价值数据,这种做法相比离线补录Join,一致性会更强,特色平台提供了在线、离线一致性保障。
  2. 做共享:在样本就绪后,一个很典型的利用场景就是迁徙学习。另外,也搭建Embedding共享的数据通路(不强依赖“扩样本”流程),所有业务线能够基于大的Embedding训练,每个业务方也能够update这个Embedding,在线通过建设Embedding版本机制,供多个业务线应用。

举例来说,通过将非广告样本复用到广告内一个业务,使样本数量减少了几倍,联合迁徙学习算法,离线AUC晋升千分之四,上线后CPM晋升百分之一。

此外,咱们也在建设广告样本主题库,将各业务生成的样本数据进行对立治理(对立元数据),面向用户透出对立样本主题分类,疾速注册、查找、复用,面向底层对立存储,节约存储、计算资源,缩小数据Join,进步时效性。

6.4 做“除法”

通过特色“减法”能够剔除一些无正向作用的特色,但通过观察发现模型中还存在很多价值很小的特色。所以更进一步咱们能够通过价值、老本两方面综合思考,在全链路基于老本的束缚下价值最大,筛选出那些投入产出比拟低特色,升高资源耗费。这个在老本束缚上来求解的过程定义为做“除法”,整体流程如下图所示。

在离线维度,咱们建设了一套特色价值评估零碎,给出特色的老本和价值,在线推理时能够通过特色价值信息进行流量降级、特色弹性计算等操作,做“除法”关键步骤如下:

  1. 问题形象:如果咱们能失去每个特色的价值得分,又能够拿到特色的老本(存储、通信、计算加工),那么问题就转换成了在已知模型构造、固定资源老本下,如何让特色的价值最大化。
  2. 老本束缚下的价值评估:基于模型的特色集,平台首先进行老本和价值的统计汇总;老本包含了离线老本和在线老本,基于训练好的评判模型,得出特色的综合排序。
  3. 分场景建模:能够依据不同的资源状况,抉择不同的特色集,进行建模。在无限的资源下,抉择价值最大的模型在线Work。另外,能够针对比拟大的特色集建模,在流量低峰启用,晋升资源利用率的同时给业务带来更大收益。还有一种利用场景是流量降级,推理服务监控在线资源的耗费,一旦资源计算达到瓶颈,切换到降级模型。

7 总结与瞻望

以上是咱们在大规模深度学习工程上的反“增”实际,去助力业务降本提效。将来咱们还会继续在以下方面进行摸索、实际:

  1. 全链路GPU化:在推理层面,通过GPU的切换,撑持更简单业务迭代的同时,整体老本也极大的升高,前面会在样本构建、特色服务上进行GPU化革新,并协同推动离线训练层面的降级。
  2. 样本数据湖:通过数据湖的Schema Evolution、Patch Update等个性构建更大规模的样本仓库,对业务方进行低成本、高价值的数据透出。
  3. Pipeline:算法全生命周期迭代过程中,很多环节的调试,链路信息都不够“串联”,以及离线、在线、成果指标的视角都比拟割裂,基于全链路的标准化、可观测大势所趋,并且这是后续链路智能化弹性调配的根底。当初业界比拟火的MLOps、云原生都有较多的借鉴思路。
  4. 数据、模型智能匹配:上文提到在模型构造固定前提下,主动为模型加、减特色,同理在模型层面,固定肯定特色输出前提下,去主动嵌入一些新的模型构造。以及在将来,咱们也将基于业务畛域,通过平台的特色、模型体系,自动化地实现数据、模型的匹配。

8 本文作者

亚劼、英亮、陈龙、成杰、登峰、东奎、仝晔、思敏、乐彬等,均来自美团外卖技术团队。

9 招聘信息

美团外卖广告工程团队长期招聘后盾高级工程师/技术专家,负责广告多个方向(举荐/搜寻/召回/预估/翻新)的零碎研发工作,坐标北京。欢送感兴趣的同学退出咱们。可投简历至:zouyajie@meituan.com(邮件主题请注明 — 美团外卖广告工程团队)。

浏览美团技术团队更多技术文章合集

前端 | 算法 | 后端 | 数据 | 平安 | 运维 | iOS | Android | 测试

| 在公众号菜单栏对话框回复【2021年货】、【2020年货】、【2019年货】、【2018年货】、【2017年货】等关键词,可查看美团技术团队历年技术文章合集。

| 本文系美团技术团队出品,著作权归属美团。欢送出于分享和交换等非商业目标转载或应用本文内容,敬请注明“内容转载自美团技术团队”。本文未经许可,不得进行商业性转载或者应用。任何商用行为,请发送邮件至tech@meituan.com申请受权。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理