GPU等专用芯片以较低的老本提供海量算力,曾经成为机器学习畛域的外围利器,在人工智能时代施展着越来越重要的作用。如何利用GPU这一利器赋能业务场景,是很多技术研发者都要面临的问题。本文分享了美团外卖搜寻/举荐业务中模型预估的GPU架构设计及落地的过程,心愿能对从事相干利用研发的同学有所帮忙或启发。

1 前言

近些年,随着机器学习技术的蓬勃发展,以GPU为代表的一系列专用芯片以优越的高性能计算能力和愈发低廉的老本,在机器学习畛域失去宽泛认可和青眼,且与传统的CPU体系一直交融,造成了新的异构硬件生态。

在这种技术浪潮之中,很多技术研发者会面临着这样的问题:在咱们的业务上利用GPU硬件能取得什么?如何疾速、平滑地从传统CPU体系根底上实现切换?站在机器学习算法设计的角度,又会带来什么影响和扭转?在GPU生态下泛滥的技术路线和架构选型中,如何找到一条最适宜本身场景的门路?

美团外卖搜寻举荐团队,也面临着相似的挑战和问题。本文咱们会分享美团外卖搜寻/举荐业务中,模型预估的GPU架构设计与落地过程,并将一些技术细节和测试数据做了详尽的披露,心愿能为宽广的技术同行提供一些有价值的参考。

2 背景

以后,美团外卖次要通过搜寻和举荐两种流量散发形式,满足用户对“万物到家”的需要。除了首页的搜寻、举荐性能外,重点品类会在首页减少独立入口(下文称之为“金刚”),每个金刚入口中都有相似于首页搜寻、举荐的区域,而不同场景入口独特服务于外卖的最终成单。首页、金刚、店内的联动关系如下图所示:

面向点击率(CTR)/转化率(CVR)预估的深度学习,是每一个电商类搜寻/举荐产品中的核心技术,间接决定了产品的用户体验和转化成果,同时也是机器资源耗费的“小户”。而CTR/CVR精排模型的设计和实际,也是美团外卖搜寻举荐(下称搜推)技术团队必须要攻克且一直谋求卓越的必争之地。

从搜推零碎设计的角度上看,不同的搜寻、举荐入口会天然造成独立的调用链路。在传统的模型设计思路下,会对不同入口链路、不同漏斗环节的CTR/CVR/PRICE多个指标独立设计模型,这也是美团外卖搜推过往模型设计的经典形式。而从2021年起,基于多场景全局优化的考量,搜推场景的CTR/CVR预估模型开始逐渐走向多模型对立,综合利用多个入口的数据、联合不同入口本身的业务特点实现多个入口的联动优化,逐渐实现“One Model to Serve All”的指标。

从模型计算实际的角度上看,外卖精排模型的倒退,让模型Dense网络的计算量显著收缩,以CPU为计算主力的软硬件架构曾经难以应答算法的倒退需要,即使老本耗费大幅加剧,算力天花板依然“近在眉睫”。而GPU硬件面向浓密计算的算力劣势,恰好吻合新的模型特点,能够从根本上突破精排模型预估/训练中的算力困局。因而,从2021年开始,美团外卖搜推场景的深度学习体系开始逐渐从纯CPU架构走向CPU+GPU的异构硬件计算平台,以满足美团外卖模型算法演进对算力的新要求。

本文接下来的内容,会从外卖搜推场景的精排模型设计登程,联合美团理论的软硬件特点,为大家具体分享在外卖精排模型预估畛域,从纯CPU架构转型到CPU+GPU异构平台的摸索和实际过程,供宽广技术同行参考。

3 外卖搜推场景下的精排模型

本章节次要介绍在外卖场景下多模型对立的演进思路、模型特点以及在实践中的挑战。本文只对模型设计思路做简略的阐明,引出后续模型计算在GPU落地中的实际思考。

3.1 精排模型的设计思路

如前文所述,在美团外卖多入口联动的场景特点下,经典的单体模型设计存在着以下局限:

  1. 首页举荐与各金刚入口举荐各保护一个精排模型,不仅保护老本高而且训练数据割裂,导致精排模型不能捕捉到用户在所有举荐场景的趣味。
  2. 举荐场景的精排模型只应用举荐场景的训练样本,未利用用户在其余重要入口的训练样本,比方搜寻、订单页,模型只学习到用户在部分场景的偏好信息。
  3. 举荐场景的训练样本中存在Position Bias问题,具体是指用户点击一个商家,有可能只是因为该商家在举荐Feeds中排序地位比拟靠前,而非因为用户对此商家真正感兴趣,此类Bias会引起模型训练有偏。
  4. 多指标之间存在贝叶斯束缚,网络结构中未思考,CXR=CTR × CVR,CXR预估值应比CTR小,模型在验证集上会呈现CXR比CTR还高的景象,预估不精确。

基于此,在2021年,美团外卖搜推场景提出了向超过单体的多模型对立演进、逐渐实现“One Model to Serve All”的思维,这一理念在模型设计中具体体现在:

  1. CTR/CXR多指标的交融,实现多指标预测的模型对立。
  2. 场景专家网络与Attention网络的交融,实现不同流量入口之间的模型泛化和对立。
  3. 畛域专属网络和共享网络的交融,实现举荐场景向搜索场景的迁徙学习。

随着外卖精排模型的倒退和演进,模型Dense网络的参数量显著减少,单次推理的FLOPs达到26M,对CPU计算架构造成了微小压力。另一方面,咱们采纳Float 16压缩、特色主动抉择、网络穿插代替手动穿插特色等技术手段,将模型由100G放大到10G以内,并且过程中通过模型的优化,做到了模型成果无损。

综上,外卖搜推精排模型浓密局部计算简单、稠密局部体积可控,这些良好的个性,为咱们在GPU硬件架构上落地推理计算提供了绝对合适的模型算法根底。接下来,咱们将探讨如何在高吞吐、低耗时的外卖搜寻举荐零碎中,利用GPU硬件无效解决外卖精排模型在线预估中的老本和性能问题,并给出咱们的实际过程和后果。

3.2 模型利用的特点与挑战

在搜寻/举荐技术畛域中,稠密模型预估(CTR/CVR)是决定算法成果的外围因素,模型预估服务是搜寻举荐零碎中必不可少的组成部分,业内各大公司已有很多经典的实现计划。在探讨具体实际之前,先介绍一下咱们的场景特点:

① 需要层面

  • 模型构造:如前文介绍,外卖场景下的精排模型的浓密网络局部绝对简单,单次推理的FLOPs达到26M;而模型的稠密局部通过大量的优化,体积失去了无效的管制,模型规模在10G以内。
  • 服务质量要求:举荐服务作为经典的高性能To C场景,业内大部分同类零碎的超时管制在百毫秒量级,合成到预估服务,超时个别须要管制在十毫秒的量级。

② 软件框架层面

  • 开发框架:模型开发采纳TensorFlow框架[1]。作为支流的深度学习第二代框架,TensorFlow具备弱小的模型表达能力,这也导致其算子粒度比拟小,这一特点无论是对CPU还是GPU架构都会带来很大的额定开销。
  • 在线服务框架:采纳TensorFlow Serving框架[2]。基于此框架,可将离线训练好的机器学习模型部署到线上,并利用rpc对外提供实时预估服务。TensorFlow Serving反对模型热更新及模型版本治理,次要特点是应用灵便,性能较好。

③ 硬件层面

  • 机型个性:美团基于晋升算力密度的考量,在预估服务采纳了GPU BOX机型。绝对于传统的GPU插卡机型,这一类机型每张GPU卡配套的CPU和内存绝对无限,这须要咱们在设计在线服务时,精细化的考量CPU、GPU上的计算和数据分布,达到更好的利用率平衡。
  • GPU固有属性:GPU kernel大体上能够划分为传输数据、kernel启动、kernel计算等几个阶段[3],其中每个kernel的启动须要约10us左右。因而,GPU预估会面临一个普适问题,大量的小算子导致每个kernel的执行工夫很短,kernel启动的耗时占了大部分。相邻的kernel之间须要通过读写显存进行数据的传输,产生大量的访存开销。而GPU的访存吞吐远远低于计算吞吐,导致性能低下,GPU的利用率并不高。

总结而言,与业内其余支流搜推场景绝对比,咱们的CTR模型预估场景有两个显著特点:

  • 浓密网络局部计算复杂度高,绝对的,稠密网络在模型设计环节通过了大量的优化,体积绝对较小。
  • 应用GPU BOX机型,单GPU卡的CPU配额受限,须要针对性优化CPU的计算负荷。

基于这两个特点,咱们在面向GPU的优化实际中就能够更具针对性了。

4 模型服务架构概览

本章节简要介绍美团外卖搜推在线预估服务的整体架构和角色分工,也是外卖搜推精排模型在GPU落地实际的工程零碎根底。

零碎要害角色

  • Dispatch:承当着特色获取和特色计算的职能,如前文所述,美团应用GPU BOX机型搭建预估服务,推理计算的CPU资源自身就非常吃紧,因而天然会思考将在线特色工程局部独立部署,防止CPU资源的抢占。本局部和GPU实际关系不大,不是本文的重点。
  • Engine:承当着模型在线推理的职能,通过RPC的形式输出特色矩阵、输入预估后果。采纳GPU BOX机型(单容器8核+1 NVIDIA Tesla T4),均匀响应工夫需管制在20ms以内,下文所述GPU优化实际次要面向这一模块的特点进行。
  • Booster:在模型更新过程中离线执行的模型优化器,外部以Optimizer插件的形式,混合了手工优化器插件和DL编译优化器插件,是下文所述GPU优化操作的执行者。

5 GPU优化实际

本章节将开展分享精排模型预估计算在GPU架构落地中的优化过程。

与CV、NLP等经典机器学习畛域不同,以CTR模型为代表的稠密模型因为构造多变、蕴含大量业务特化等起因,硬件供应商难以对这一类未收敛的模型构造提供端到端优化工具。因而,在CTR模型大规模利用的畛域中,个别会联合GPU个性,面向应用场景对模型执行Case By Case的优化措施。按模型优化的指标来辨别,能够大抵分类为系统优化和计算优化:

系统优化:个别指通过对计算、存储、传输的调度,使CPU+GPU的异构硬件体系能够更有效率的协同和被应用。典型的系统优化包含:

  • 设施摆放
  • 算子交融
  • GPU并发/流水线优化

计算优化:个别指面向硬件个性,优化模型前向推理网络的结构设计和算子执行逻辑,使模型推理计算在GPU上的计算开销更小,效率更高。典型的计算优化包含:

  • 冗余计算去除
  • 量化计算
  • 高性能库的利用

在本文介绍的优化工作中,咱们对上述常见优化中的大部分思路进行了摸索和实际,下文会逐个进行论述,并给出优化成果和面向理论场景的总结剖析。

5.1 系统优化

5.1.1 设施摆放

TensorFlow会为计算图中每个Node主动设置Runtime Device,计算较重者搁置在GPU,计算较轻者搁置在CPU。在简单计算图中实现一次残缺的inference,数据会在CPU和GPU之间重复传输。因为H2D/D2H传输很重,这会造成数据传输耗时远大于op(operator)外部计算耗时,在GPU下模型一次预估耗时为秒级别,远高于只应用CPU时的耗时。此外,如前所述,咱们所应用的GPU机型上CPU资源受限(一张T4卡仅对应8核CPU),这也是咱们在异构架构设计中须要解决的核心技术挑战。

为解决TensorFlow主动设定Runtime Device不合理的问题,咱们为计算图中每个Node手动Set Runtime Device。思考到CPU资源受限,咱们尽量的将计算较重的子图(包含Attention子图、MLP子图)搁置在GPU计算,计算较轻的子图(次要为Embedding查问子图)搁置在CPU计算。

为进一步缩小设施间数据传输,咱们在CPU和GPU之间减少Concat op和Split op,CPU数据先Concat到一起再传输到GPU,之后再按需Split成多份并传给对应op,将H2D/D2H从上千次升高到数次。如下图所示,设施摆放优化之前,有大量的H2D数据传输;优化之后,H2D缩小为3次,优化成果非常显著。

5.1.2 All On GPU

实现根本的设施摆放优化后,计算较轻的Sparse查问局部在CPU实现,计算较重的Dense计算局部在GPU实现。尽管CPU上计算较轻,但压测发现其仍旧是整体吞吐瓶颈。思考到整体计算图较小(约2G),咱们天然的想到是否能够将整图放在GPU执行,绕开CPU配额的限度,此即All On GPU。为了将原在CPU进行的Saprse查问改为在GPU执行,咱们新增了LookupTable op的GPU实现。如下图所示,HashTable搁置在GPU Global Memory,它的Key与Value对立存储在Bucket中。针对输出的多组Key,利用多个Block的Threads并行查问。

同时,为进步GPU利用效率,升高kernel launch开销,咱们利用TVM对计算图进行编译优化(下文会进行具体介绍)。优化后的All On GPU模型图解决了CPU资源受限带来的瓶颈,整体吞吐晋升显著(qps 55->220,约4倍)。

5.1.3 算子交融

外卖搜推精排模型十分复杂,计算图中蕴含上万个计算Node。GPU上执行计算图时,每个Node都有kernel launch开销,多个Node之间还有拜访显存开销。此外,TensorFlow框架自身在Node执行时会带来肯定开销,每个Node执行时都会创立、销毁Input/Output Tensor,内存管制引入额定老本。因而,计算图中Node过多会重大影响执行效率。为解决这一问题,罕用的办法是进行算子交融,即在计算结果等价的前提下,将多个Node交融成一个Node,尽量升高计算图Node数量,这样既能够将Node之间的拜访显存开销转为拜访寄存器开销,同时也能够缩小计算图中每个Node带来的固定开销。

算子交融次要通过三种形式进行:

  • 特定算子手动交融。例如模型训练阶段中,针对一个Embedding Table会有多个Node拜访,在线预估阶段可将其交融成一个Node,即查问Node和Embedding Table一一对应。尔后可进一步交融算子,一个Node负责查问多个Embeddding Table。
  • 常见算子主动交融,次要是利用TensorFlow Grappler[4]优化器进行算子主动交融。
  • 利用深度学习编译器主动交融,下文会具体进行介绍。

5.2 计算优化

5.2.1 FP16低精度优化

一方面,在CPU架构下,为了升高内存开销,曾经将Embedding Table压缩为FP16[5]存储,然而计算时仍会开展为FP32,这引入了转换开销;另一方面,模型预估仅进行模型图的前向计算,应用低精度计算引入的误差较小。因而,业界广泛应用低精度形式进行模型预估计算。

针对以后的业务场景,咱们尝试了FP16、INT8[6]等低精度计算,FP16半精度计算对模型成果无显著影响,INT8量化则会造成成果衰减。因而,咱们采纳FP16半精度计算的形式,在不影响模型成果的前提下,进一步晋升预估服务的吞吐。

5.2.2 broadcast优化

模型图中的数据能够分为user和item两类。通常状况下,申请中蕴含一个user以及多个item。在模型Sparse局部,user和item别离获取Embedding;在模型Dense局部,两类Embedding组合成矩阵后进行计算。通过深入分析,咱们发现模型图中存在冗余查问和计算。如下图橙色局部所示,在模型Sparse局部,user信息先被broadcast成batchsize大小再去查问Embedding,导致同一个Embedding查问了batchsize次;在模型Dense局部,user信息同样被broadcast成batchsize大小,再进行之后所有计算,实际上在和item穿插之前不用broadcast user,同样存在冗余计算。

针对以上问题,咱们对模型图进行了手工优化,如下图紫色局部所示,在模型Sparse局部,user信息只查问一次Embedding;在模型Dense局部,user信息与item穿插时再broadcast成batchsize大小,即整体上将user信息的broadcast后置。

5.2.3 高性能库利用

应用CPU时,能够利用Intel MKL[7]库对计算进行减速。受限于CPU硬件特点,减速成果无限。应用GPU时,咱们能够利用Tensor Core[8]进行减速计算。每个Tensor Core都是一个矩阵乘累加计算单元,以后应用的NVIDIA T4卡具备320个Tensor Core,在混合精度计算时算力为65 TFLOPS,在单精度计算时算力为8.1 TFLOPS,具备极强的推理性能。在TensorFlow中,可利用cuBLAS[9]调用Tensor Core进行GEMM减速计算,利用cuDNN[10]调用Tensor Core进行CNN、RNN网络减速计算。

5.3 基于DL编译器的主动优化

随着深度学习网络越来越简单(Wider And Deeper),硬件设施越来越多样(CPU、GPU、NPU),神经网络的优化工作也变得越来越艰难。在繁多硬件、繁多框架上的优化会受到优化库限度,很难进一步调优。在不同硬件、不同框架的优化又很难做到通用,优化很难移植。这导致优化神经网络时,须要大量的手动调优工作,老本很高。

为了升高手动优化的老本,业界广泛应用深度学习编译器(Deep Learning Compiler)对计算图进行主动调优。比拟风行的深度学习编译器包含TensorRT[11]、TVM[12]、XLA[13]等,咱们在以后的模型场景下利用深度学习编译器做了较多的优化尝试,下文会具体进行介绍。

5.3.1 基于TensorRT的尝试

TensorRT是NVIDIA推出的高性能深度学习推理优化框架,反对主动算子交融、量化计算、多流执行等多种优化伎俩,并且能够针对具体kernel抉择最优实现。TensorRT的各优化均通过对应开关管制,应用很简略;然而整体闭源,并且反对的算子不多,只能对计算图的局部算子做优化,遇到不辨认的算子则会跳过,非常影响优化效率。利用TensorRT优化后的计算图,仍旧存在大量op,整体性能晋升无限。为解决这个问题,咱们从以下两个角度进行尝试。

① 手动切分子图

利用TensorRT进行图优化时,会先利用Union Find算法在全图中寻找可辨认op并将其聚类,每个聚类进行具体的编译优化,并产生一个对应的TRTEngineOp。因为计算图中存在大量不辨认op,对聚类过程造成了烦扰,即便可辨认OP也不肯定能实现聚类,则无奈进行对应编译优化,造成优化效率较低。为解决这一问题,图优化前咱们先进行手动切图,将全计算图切分为若干个子图,每个可辨认op都放入对应子图中,并将子图送入TensorRT进行优化。通过这一办法,无效解决了可辨认op未优化的问题,无效升高了全图OP数量。

② 算子替换

如前所述,TensorRT反对OP类型无限,全图中存在大量TensorRT无奈辨认的op,导致优化效率偏低。为了缓解这一问题,咱们将TensorRT不辨认的OP尽量替换成其反对的等价op。例如下图中,TensorRT无奈辨认Select op,咱们将其替换成TensorRT反对的Multiply op,并将Select关联的ExpandDims op从图中消掉。通过相似的等价转换操作,无效升高了未辨认op数量,进步了编译优化覆盖率。

5.3.2 基于TVM的尝试

在尝试TensorRT优化时咱们发现,TensorRT对TensorFlow的算子覆盖率较低(只能笼罩约50+算子),在以后的模型计算图中,有十多个算子无奈反对。即便通过简单的算子替换优化工作,依然存在多个算子难以替换。由此咱们思考采纳其余的深度学习编译器进行图优化。

TVM是陈天奇团队推出的端到端机器学习主动编译框架,在业界宽泛应用。和TensorRT相比,TVM代码开源,具备更强的拓展性和定制能力。此外,TVM反对的TensorFlow算子超过130个,算子覆盖率远超TensorRT。在以后计算图中,TVM不反对的OP只有自定义的LookupTable,这一OP负责查问Embedding,无需进行编译优化。

因而,咱们尝试利用TVM取代TensorRT对以后计算图进行主动编译优化。思考到TensorFlow对TensorRT、XLA均做了官网反对,实现了对应的wrapper op,但目前尚未反对TVM,咱们对TensorFlow做了适配革新,采纳和TensorRT相似的形式,实现了TVMEngineOp以反对TVM。思考模型特点,咱们将计算较重的Attention子图和MLP子图放入了TVMEngineOp中,利用TVM进行编译优化,如下图所示:

6 性能体现与剖析

本章节展现理论生产环境下的测试数据,并剖析上文一系列业内典型优化思路,在咱们的特定场景下的体现及其背地起因。

压测环境中,CPU环境为32核Intel(R) Xeon(R) Gold 5218 CPU @ 2.30GHz+32G内存,GPU环境为8核Intel(R) Xeon(R) Gold 5218 CPU @ 2.30GHz+Tesla T4 GPU+16G内存。上图中,左图比照了不同QPS下(x轴),精排模型在不同优化伎俩下的推理耗时(y轴),其中base-gpu示意只通过简略的图优化并在GPU计算,trt示意通过TensorRT优化并在GPU计算,tvm示意通过TVM优化且叠加All On GPU优化并在GPU计算;右图示意极限QPS下,不同优化伎俩对应的CPU和GPU利用率。从图中能够看出:

  • 只利用CPU进行预估计算时,极限qps为55,此时CPU利用率曾经高达76%,成为瓶颈。
  • 利用惯例手工优化(设施摆放+算子交融+Broadcast优化+高性能库)的GPU预估时,雷同qps下latency大幅升高,且能够将极限qps晋升至85(较CPU版晋升55%)。达到极限吞吐时GPU利用率并不高,瓶颈仍旧为CPU利用率。
  • 利用TensorRT优化预估(手工优化+TensorRT+FP16)时,得益于图编译优化,雷同qps下latency升高约40%。因为瓶颈仍为CPU,极限吞吐未变动。
  • 利用TVM优化预估(手工优化+TVM+FP16+All On GPU)时,将所有OP都搁置于GPU计算,CPU只负责根本的RPC,极大缓解了CPU配额的瓶颈。雷同qps下latency大幅升高约70%,极限吞吐大幅晋升约120%。达到极限吞吐时,GPU利用率较高,成为瓶颈。

通过一系列优化,整体吞吐晋升约4倍(qps从55->220),优化成果非常显著。

7 总结

综上,咱们针对美团外卖场景的业务特点,将经典的CTR/CVR模型从多入口、多环节、多指标的单体模型,逐渐演进到“One Model to Serve All”的多模型对立状态。

同时,联合美团的硬件条件和根底,实现了纯CPU预估架构向CPU+GPU异构架构的切换,在固定成本前提下,无效的开释了算力空间,计算吞吐晋升了近4倍。针对GPU BOX机型对CPU资源的限度,咱们采纳手工优化+DL编译优化联合、模型网络计算All On GPU的思路,无效的晋升了GPU在模型预估计算中的利用率,并在本文中具体分享了GPU落地中的优化过程和实测数据指标。

8 作者简介

  • 杨杰、俊文、瑞东、封宇、王超、张鹏等,来自到家事业群/到家研发平台/搜寻举荐技术部。
  • 王新、陈卓、駃飞等,来自根底研发平台/数据迷信与平台部/数据平台核心。

9 参考文献

  • [1] https://www.usenix.org/system/files/conference/osdi16/osdi16-abadi.pdf
  • [2] https://www.tensorflow.org/tfx/guide/serving
  • [3] https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html
  • [4] https://www.tensorflow.org/guide/graph_optimization
  • [5] https://en.wikipedia.org/wiki/Half-precision_floating-point_format
  • [6] https://www.nvidia.com/en-us/data-center/tensor-cores/
  • [7] https://www.intel.com/content/www/us/en/develop/documentation/get-started-with-mkl-for-dpcpp/top.html
  • [8] https://www.nvidia.com/en-us/data-center/tensor-cores/
  • [9] https://docs.nvidia.com/cuda/cublas/index.html
  • [10] https://developer.nvidia.com/zh-cn/cudnn
  • [11] https://docs.nvidia.com/deeplearning/frameworks/tf-trt-user-guide/index.html
  • [12] https://tvm.apache.org/docs/
  • [13] https://www.tensorflow.org/xla

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

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

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

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