当前位置: 首页 > news >正文

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

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数仓平滑入湖

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

爱奇艺图片格式演进

相关文章:

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

01 背景介绍 GPU 目前大量应用在了爱奇艺深度学习平台上。GPU 拥有成百上千个处理核心,能够并行的执行大量指令,非常适合用来做深度学习相关的计算。在 CV(计算机视觉),NLP(自然语言处理)的模型…...

详解MySql索引

目录 一 、概念 二、使用场景 三、索引使用 四、索引存在问题 五、命中索引问题 六、索引执行原理 一 、概念 索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。暂时可以理解成C语言的指针,文章后面详解 二、使用场景 数据量较大,且…...

struct 和 union 的区别?

struct和union的分对应点总结 存储方式: struct:struct中的每个成员都拥有独立的内存空间。一个struct变量的总长度是其所有成员的长度之和,且通常会根据编译器的内存对齐规则进行适当调整。union:union中的所有成员共享同一段内…...

Linux - 安装 Jenkins(详细教程)

目录 前言一、简介二、安装前准备三、下载与安装四、配置镜像地址五、启动与关闭六、常用插件的安装 前言 虽然说网上有很多关于 Jenkins 安装的教程,但是大部分都不够详细,或者是需要搭配 docker 或者 k8s 等进行安装,对于新手小白而已&…...

【JAVA】JAVA方法的学习和创造

🌈个人主页: Aileen_0v0 🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​💫个人格言:“没有罗马,那就自己创造罗马~” 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不…...

Rust写一个wasm入门并在rspack和vite项目中使用(一)

rust打包wasm文档 文档地址 安装cargo-generate cargo install cargo-generate 安装过程中有问题的话手动安装cargo-generate下载地址 根据自己的系统下载压缩包,然后解压到用户/.cargo/bind目录下,将解压后的文件放到该目录下即可。 创建wasm项目 …...

HTTP和HTTPS的区别,HTTPS加密原理是?

HTTP和HTTPS都是网络传输协议,主要用于浏览器和服务器之间的数据传输,但它们在数据传输的安全性、加密方式、端口等方面有所不同。 数据传输的安全性:HTTP是明文传输,数据不加密,容易被黑客窃听、篡改或者伪造&#x…...

基于Spring Boot+Vue的校园二手交易平台

目录 一、 绪论1.1 开发背景1.2 系统开发平台1.3 系统开发环境 二、需求分析2.1 问题分析2.2 系统可行性分析2.2.1 技术可行性2.2.2 操作可行性 2.3 系统需求分析2.3.1 学生功能需求2.3.2 管理员功能需求2.3.3游客功能需求 三、系统设计3.1 功能结构图3.2 E-R模型3.3 数据库设计…...

什么是软件开发?软件开发阶段划分是什么?并以LabVIEW为例进行说明

软件开发是一种创建、设计、编码、测试和维护应用程序、框架或其他软件组件的过程。它涉及从理解需求到设计、实现、测试、部署和最终维护的全过程。软件开发可以用来创建新的软件应用、系统软件、游戏、或开发网络应用等。 软件开发过程通常可以分为以下几个阶段:…...

PTAL1-006 连续因子

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话: 知不足而奋进,望远山而前行&am…...

【Java】容器|Set、List、Map及常用API

目录 一、概述 二、List 1、List的常用API 2、ArrayList 3、List遍历 三、Set 1、Set的常用方法: 2、HashSet 3、遍历集合: 四、Map 1、Map常用API 2、HashMap 3、遍历Map 五、迭代器 一、概述 在Java中所有的容器都属于Collection接口下的内容 1…...

Navicat 面试题及答案整理,最新面试题

Navicat 在数据库管理中的主要用途有哪些? Navicat 是一款数据库管理工具,其主要用途包括: 1、多数据库支持: Navicat 支持多种数据库连接,包括 MySQL、Oracle、PostgreSQL、SQLite、SQL Server 等,方便用…...

android studio 连接mumu模拟器调试

1、打开mumu模拟器 2、在Android Studio 中 控制台 cd 到 sdk 目录下 platform-tools 文件夹,有一个adb.exe 可运行程序 一般指令: adb connect 127.0.0.1:7555 但是这个执行在window环境下可能会报错 解决方法是在 adb 之前加 ".\", 问题…...

四连通与八连通的区别 -- 图例讲解

概念 四连通区域:指从某个点出发,只能通过上、下、左、右四个方向的运动到达区域内的其他点,且不能跨越区域的边界。 八连通区域:除了上、下、左、右四个方向,还可以沿对角线方向(左上、右上、左下、右下…...

关于分布式微服务数据源加密配置以及取巧方案(含自定义加密配置)

文章目录 前言Spring Cloud 第一代1、创建config server项目并加入加解密key2、启动项目,进行数据加密3、实际项目中的测试server Spring Cloud Alibaba低版本架构不支持,取巧实现无加密配置,联调环境问题加密数据源配置原理探究自定义加密解…...

快速了解JavaScript

1.1 javaScript 历史 创始人 布兰登 艾奇 生于1961年 在1995设计LiveScript后改名为JavaScript 1.2 javaScript 是什么类型的语言 JavaScript是一种在客户端运行的脚本语言(不需要编译,由js引擎逐行解释执行) 1.3 JavaScript可以做什么 …...

【安全类书籍-3】XSS跨站脚剖析与防御

目录 内容简介 作用 下载地址 内容简介 这本书涵盖以下几点: XSS攻击原理:解释XSS是如何利用Web应用未能有效过滤用户输入的缺陷,将恶意脚本注入到网页中,当其他用户访问时被执行,实现攻击者的目的,例如窃取用户会话凭证、实施钓鱼攻击等。 XSS分类:分为存储型XSS(…...

http postman

地址 : https://oaqas.lingyiitech.com:9800/auth-api/openapi/dingtalk-oa/topapi/message/corpconversation/asyncsend_v2?token40216bf0ceea8e56b778d537b20f5d23 https://oaqas.lingyiitech.com:9800/auth-api/openapi/dingtalk-oa/topapi/message/corpconve…...

[数据集][目标检测]螺丝螺母检测数据集VOC+YOLO格式2100张13类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2100 标注数量(xml文件个数):2100 标注数量(txt文件个数):2100 标注…...

华为鲲鹏ARM处理器920、916系列

鲲鹏处理器-鲲鹏社区 (hikunpeng.com) 产品规格 鲲鹏920系列 型号: 7260(64核)、5250(48核)、5220(32核)、3210(24核)7260核数64核 主频2.6GHz 内存通道8TDP功耗180W 组…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

ES6从入门到精通:前言

ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

JVM垃圾回收机制全解析

Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

【机器视觉】单目测距——运动结构恢复

ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛&#xf…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色&#xf…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...