爱奇艺 CTR 场景下的 GPU 推理性能优化

news2024/11/25 18:59:22

01

   背景介绍

GPU 目前大量应用在了爱奇艺深度学习平台上。GPU 拥有成百上千个处理核心,能够并行的执行大量指令,非常适合用来做深度学习相关的计算。在 CV(计算机视觉),NLP(自然语言处理)的模型上,已经广泛的使用了 GPU,相比 CPU 通常能够更快、更经济的完成模型的训练和推理。

CTR (Click Trough Rate) 模型广泛使用在推荐、广告、搜索等场景中,用来估算用户点击某个广告、视频的概率。在 CTR 模型的训练场景中已经大量使用了 GPU,在提升训练速度的同时和降低了所需的服务器成本。

但在推理场景下,当我们直接把训练好的模型通过 Tensorflow-serving 部署在 GPU 之后,发现推理效果并不理想。表现在:

  1. 推理延迟高,CTR 类模型通常是面向终端用户的,对于推理延迟非常敏感。

  2. GPU 利用率低,计算能力未能全部发挥出来。


02

   原因分析

分析工具

  1. Tensorflow Board,tensorflow 官方提供的工具,能够可视化的查看计算流图中各个阶段的耗时,并汇总算子的总耗时。

  2. Nsight 是 NVIDIA 面向 CUDA 开发者提供的开发工具套件,能够对 CUDA 程序进行相对底层的跟踪、调试和性能分析。

分析结论

典型的 CTR 模型输入,包含大量的稀疏类特征(如设备 ID、最近浏览视频 ID 等)。Tensorflow 的 FeatureColumn 会对这些特征进行处理,首先进行 identity/hash 操作,得到 embedding table 的 index。再经 embedding lookup 和求均值等操作后,得到对应的 embedding tensor。多个特征对应的 embedding tensor 拼接后得到一个新的 tensor,再进入后续的 DNN/Transformer 等结构。

因此每个稀疏特征在模型的输入层,都会启动若干个算子。每个算子会对应着一次或者几次 GPU 计算,即 cuda kernel。每个 cuda kernel 包括两个阶段,launch cuda kernel(启动 kernel 所必需的 overhead) 和 kernel 执行(在 cuda 核心上真正执行矩阵计算)。稀疏特征 identity/hash/embedding lookup 对应的算子计算量较小,launch kernel 的耗时往往超过 kernel 执行的时间。一般来说 CTR 模型包含了几十到几百个稀疏特征,理论上就会有数百次 launch kernel,是当前主要的性能瓶颈。

在使用 GPU 训练 CTR 模型时,没有遇到这个问题。因为训练本身是一个离线任务,不关注延迟,所以训练时候的 batch size 都可以很大。虽然仍会进行多次 launch kernel,只要执行 kernel 时候计算的样本数量足够多,lauch kernel 的开销平均到每个样本上的时间就很小了。而对于在线推理的场景,如果要求 Tensorflow Serving 收到足够的推理请求并合并批次后再进行计算,那么推理延迟就会很高。


03

   优化方案

我们的目标是在基本不改变训练代码,不改变服务框架的前提下,进行性能优化。我们很自然的想到两个方法,减少启动的 kernel 数量,提高 kernel 启动的速度。

算子融合

基本操作就是将多个连续的操作或算子合并成一个单一的算子,一方面可以减少 cuda kernel 启动的次数,另一方面可以把计算过程中一些中间结果存在寄存器或者共享内存,只在算子的最后把计算结果写入全局的 cuda 内存。

主要有两种方法

  1. 基于深度学习编译器的自动融合

  2. 针对业务的手动算子融合

自动融合

我们尝试了多种深度学习编译器,如 TVM/TensorRT/XLA,实测可以实现 DNN 部分少量算子的融合,如连续的 MatrixMat/ADD/Relu。由于 TVM/TensorRT 需要导出 onnx 等中间格式,需要修改原有模型的上线流程。所以我们通过 tf.ConfigProto() 开启 tensorflow 内置的 XLA 来进行融合。

但自动融合对稀疏特征相关的算子并没有很好的融合效果。

手动算子融合

我们很自然的想到,如果有多个特征在输入层被相同类型的 FeatureColumn 组合所处理,那么我们可以实现一个算子,把多个特征的输入拼接成数组作为算子的输入。算子的输出是一个张量,这个张量的 shape 和原本多个特征分别计算后再拼接得到的张量 shape 一致。

以原有的 IdentityCategoricalColumn + EmbeddingColumn 组合为例,我们实现了 BatchIdentiyEmbeddingLookup 算子,达到相同的计算逻辑。

为了方便算法同学使用,我们封装了一个新的 FusedFeatureLayer,来代替原生的 FeatureLayer;除了包含融合算子,还实现了以下逻辑:

  1. 融合的逻辑在推理时候生效,训练时候走原来的逻辑。

  2. 需要对特征进行排序,保证相同类型的特征可以排在一起。

  3. 由于每个特征的输入均为变长,在这里我们额外生成了一个索引数组,来标记输入数组的每个元素属于哪个特征。

对于业务来说,只需要替换原来的 FeatureLayer 即可达到融合的效果。

实测原本数百次的 launch kernel,经过手动融合后缩减到了 10 次以内。大大减少了启动 kernel 的开销。

aeba3d6703e6f86c9979d3912d02cb4f.png

4448272748297e33d6e73fc87ef3422f.png


MultiStream 提高 launch 效率

TensorFlow 本身是一个单流模型,只包含一个 Cuda Stream Group(由  Compute Stream、H2D Stream,D2H Stream 和 D2D Stream 组成)多个 kernel 只能在同一个 Compute Stream 上串行执行效率较低。即使通过多个 tensorflow 的 session 来 launch cuda kernel,在 GPU 侧仍然需要排队。

980c461eacbcfedb42ff4d57fb626465.jpeg

为此 NVIDIA 的技术团队维护了一个自己的 Tensorflow 分支,支持多个 Stream Group 同时执行。以此来提高 launch cuda kernel 的效率。我们将此特性移植到了我们的 Tensorflow Serving 里。

0989e9c5373c5da4ca9b71cc9d89f51a.png

在 Tensorflow Serving 运行时候,需要开启 Nvidia MPS,减少多个 CUDA Context 间的相互干扰。

小数据拷贝优化

在前边优化基础上,我们针对小数据拷贝进一步做了优化。当 Tensorflow Serving 从请求中反序列化出中各个特征的值后,会多次调用 cudamemcpy,将数据从 host 拷贝到 device。调用次数取决于特征数量。

大部分 CTR 类业务,实测当 batchsize 较小时和,先将数据在 host 侧拼接,再一次性的调用 cudamemcpy 效率会更高一些。

5279ede055094522af8abb1811229534.png


合并批次

GPU 场景下需要开启批次合并。默认情况下 Tensorflow Serving 是不对请求进行合并的。为了更好的利用 GPU 的并行计算能力,让一次前向计算时候可以包含更多的样本。我们在运行时候打开了 Tensorflow Serving 的 enable_batching 选项,来对多个请求进行批次合并。同时需要提供一个 batch config 文件,重点配置以下参数,以下是我们总结的一些经验。

  1. max_batch_size:一个批次允许的最大请求数量,可以稍微大一点。

  2. batch_timeout_micros:合并一个批次等待的最长时间,即使该批次的数量未达到max_batch_size,也会立即进行计算(单位是微秒),理论上延迟要求越高,这儿设置的越小,最好设置在 5 毫秒以下。

  3. num_batch_threads:最大推理并发线程,在开启了 MPS 之后,设置成 1 到 4 都可以,再多延迟会高。

在这里需要注意的是,CTR 类模型大部分输入的稀疏特征都为变长特征。如果客户端没有专门做约定,可能出现多个请求中在某个特征上的长度不一致。Tensorflow Serving 有一个默认的 padding 逻辑,给较短的请求在对应的特征上补 0。而对于变长特征使用 -1 来表示空,默认的补 0 会事实上改变原有的请求的含义。

比如用户 A 最近的观看视频 id 为 [3,5],用户 B 最近的观看视频 id 为 [7,9,10]。如果默认补齐,请求变成 [[3,5,0], [7,9,10]],在后续的处理中,模型会认为 A 最近观看了 id 为 3,5,0 的 3 个视频。

因此我们修改了 Tensorflow Serving 响应的补齐逻辑,遇到这种情况会补齐为 [[3,5,-1], [7,9,10]]。第一行的含义仍然是观看了视频 3,5。

04

   最终效果

经过各种上述各种优化,在延迟和吞吐量满足了我们的需求,并落地在推荐个性化 Push、瀑布流业务上。业务效果如下:

  1. 吞吐量相比原生Tensorflow GPU 容器提升 6 倍以上

  2. 延迟和 CPU 基本一致,满足业务需求

  3. 支持相同的 QPS 时候,成本降低 40% 以上

7c711e47f79ea1fa32e962fe4a8ae91b.jpeg

也许你还想看

爱奇艺数据湖实战 - Hive数仓平滑入湖

稀疏大模型在爱奇艺广告排序场景中的实践

爱奇艺图片格式演进

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1522910.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

判断一个时间序列中每个元素的年份是否为闰年

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 判断一个时间序列中 每个元素的年份是否为闰年 Series.dt.is_leap_year 选择题 以下代码的输出结果中正确的是? import pandas as pd ts pd.Series(pd.date_range("2024-03-17",…

ARM 汇编指令:(七) STM/LDM多寄存器加载/多存储指令

目录 一.四种栈 1.满增栈:进栈(先移动指针再入栈,指针往地址增大的方向移动);出 栈(先出栈,栈指针往地址减小的地方移动)。 2.满减栈:进栈(先移动指针再入…

android studio设置flutter和dart的sdk配置

提示没有配置dart sdk的时候,其实只需要配置一下flutter的sdk就可以了,因为flutter的安装包里面包含了dart的sdk: 按照提示选中这个flutter的安装包路径就可以了: 并且需要开启windows的开发者开关:start ms-settings:…

【代码随想录】【回溯算法】补day25:组合总和,电话号码的总和

组合总和 def backtracking2(self, n: int, k: int, startindex: int, targetsum, sum):# 递归的终止条件if sum > targetsum:returnif len(self.path) k and sumtargetsum:self.result.append(self.path[:]) # 结果拷贝return self.result# for i in range(startindex,n1…

Java Web项目—餐饮管理系统Day06-套餐管理(一)

文章目录 1. 需求分析与实体类准备2. 依据菜品分类或者名字进行查询的请求(需求B)3. 新增套餐 1. 需求分析与实体类准备 如上图为新增套餐的界面, 它包含了套餐的一些基本信息, 例如名称、价格等, 同时还有套餐分类(因此这里需要一个查询所有套餐分类的请求处理方法, 需求A). 以…

layui table列表重载后保持进度条位置不变

使用layui的table表格组件时,当我们操作了某行的修改后,刷新了页面,进度条则跳回到最上面。 除了layui高版本应该内置有方法解决了此问题,但是低版本需要另外想办法解决。 具体解决方式如下: 1.在编辑操作成功前&am…

量子磁场测量“碰上”脑科学,未磁科技无创脑功能成像系统研发成功

从微观的神经元活动到宏观的认知行为,脑科学探索着人类最神秘、最复杂的领域之一。在这个过程中,科研人员、医生和创业者们扮演着至关重要的角色。他们不仅致力于揭示大脑的奥秘,更将科研成果转化为实际应用,推动脑科学领域的进步…

【SQL Server】实验七 数据完整性

1 实验目的 掌握实体完整性、参照完整性和用户自定义完整性约束的创建方法。掌握完整性约束的运行检查机制。掌握参照完整性的级联删除和修改方法。掌握正确设计关系模式完整性约束的方法。 2 实验内容 2.1 掌握实体完整性约束的创建和使用方法 创建表时定义由一个属性组成…

宜搭faas服务器获取accessToken

可以用faas服务器的OpenAPIUtil.getCustomAccessTokenThenCache(Client ID,Client Secret)就可以获取 至于获取这个Client ID,Client Secret 就需要在钉钉开放平台创建一个应用 然后在这个应用的基础信息里面有 注意的是:如果需要…

Rust 程序设计语言学习——所有权

这一节主要来学习 Rust 语言的其他特性,所有权、引用与借用、Slice 类型。 1 所有权 Rust 的核心功能(之一)是所有权(ownership)。虽然该功能很容易解释,但它对语言的其他部分有着深刻的影响。 所有程序…

Rancher操作手册(v2.7.5-rc1)

1.登录 访问地址:10.66.55.132使用账号和密码登录。初始的页面是英文版本,可以点击左下方改为简体中文 登录成功后可以看到现有的集群。右上角可以进行新集群的创建和导入已有集群。点击箭头所指的蓝色集群名称可以进入集群。 2.集群仪表盘 进入到集…

【leetcode】长度最小的子数组, test ok

题目 代码实现 #include <iostream> #include <vector> using namespace std;class Solution { public:int minSubArrayLen(int s, vector<int>& nums) {int n = nums.size();if (n == 0) {return 0;}int ans = INT_MAX;int start = 0, end = 0;int…

Github 2024-03-17 php开源项目日报 Top9

根据Github Trendings的统计,今日(2024-03-17统计)共有9个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量PHP项目9Blade项目2Laravel:表达力和优雅的 Web 应用程序框架 创建周期:4631 天开发语言:PHP, BladeStar数量:75969 个Fork数量:24281 次关…

Redis远程连接本机——Docker

1. Docker拉取redis镜像并创建容器 1.1 拉取redis镜像 如果要指定redis版本&#xff0c;需要使用redis:&#xff08;版本&#xff09;&#xff0c;不写默认最新版本 docker pull redis1.2 创建容器并挂载配置文件 创建一个redis目录&#xff0c;并在其创建一个conf目录和一个d…

tomcat 实现会话绑定

Tomcat 后端服务器实现 Session ID会话保持 基础架构&#xff1a; 7-6 代理服务器nginx配置 7-3 tomcat 服务器 7-5 同理 测试&#xff1a; 此时刷新&#xff0c;会话ID一直在变&#xff0c;这样不好 如何解决呢&#xff1f; 不好的是确定ip之后&#xff0c;会一直在一台机上…

蓝桥杯单片机快速开发笔记——PWM

一、原理分析 使用定时器输出PWM&#xff08;脉宽调制&#xff09;信号是通过微控制器的定时器模块来生成一种周期性的脉冲信号&#xff0c;通过控制脉冲的高电平时间&#xff08;占空比&#xff09;来控制输出信号的平均功率。以下是生成PWM信号的基本原理概述&#xff1a; 定…

Java获取视频封面图,利用FFmpegFrameGrabber获取视频封面图

依赖 <dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.9</version></dependency>传入视频流获取图片byte /*** 获取视频截图** param frameNumber 视频的指定帧数* param …

01初识Python

一、Python 简介 二、为什么要学Python? 三、Python 安装 四、输出第一条指令 五、总结 一、Python 简介 Python是一种高级编程语言,由Guido van Rossum于1991年创建。它具有简单易学的语法结构,被广泛应用于Web开发、数据科学、人工智能等领域。 Python具有丰富的库…

SQLiteC/C++接口详细介绍之sqlite3类(十三)

返回目录&#xff1a;SQLite—免费开源数据库系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十二&#xff09; 下一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十四&#xff09;&#xff08;未发表&#xff09; 40.sqlite3…

VMware Fusion 13.5.1 OEM BIOS Version - 在 macOS 中运行 Windows 虚拟机的最佳方式

VMware Fusion 13.5.1 OEM BIOS Version VMware Fusion 13 原版 App 中集成 OEM BIOS 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-fusion-13-oem/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 使用 VMware …