深入浅出腾讯BERT推理模型--TurboTransformers

Overview
TurboTransformers是腾讯最近开源的BERT推理模型,它的特点就是一个字,快。本人用BERT(huggingface/transformers)在V100上做了测试,测试结果和官宣的基本一致:TurboTransformers的推理速度要比Pytorch快上1~4倍。

它之所以快,是因为它是专用于BERT的轻量级推理模型。
分层
不管是计算机的硬件、软件,还是现在的深度学习,它们都遵循着一个很重要的设计思想--分层:
- 用简单的代码(或电路)来实现一个基本功能组件。
- 用几个基本组件组合成一个功能更强的复杂组件。
- 从简单到复杂,像搭积木一样,一层层地搭建出拥有很强功能的组件。
开发者只需要基于PyTorch的几个基本组件就能搭建出BERT模型,而且这些组件本身对他们来说都是透明的。正因如此,PyTorch才越来越受到研究者青睐。

分层设计的优点很多,例如,可以简化问题、降低创新门槛、加速开发等,但它的缺点也很明显:
- 流程固定化
- 存在中间层延迟
深度神经网络里有个经典套路:一个激活函数层后面紧跟着一个dropout层。PyTorch需要lanuch两个GPU kernel程序来完成这两步计算。
F.dropout(F.relu(x))
实际上,这两项计算都是element-wise的,是可以合并成一个kernel的。但目前来说,不管是PyTorch,还是其他的通用训练框架,它们都很少有提供这种融合计算的API。
至于中间层延迟,最经典的要属“hello world”程序。虽然只有几行代码,但实际上要经过的中间层数根本数不过来。
你可以阅读深入浅出PyTorch(算子篇)来了解下矩阵相乘这个最基本的计算在PyTorch里要经过多少个中间层。
分层展开
要想将程序的低延迟最大化,就需要把分层的代码完全展开,并重构代码。典型例子就是嵌入式系统,为了实现某种需求,它可以打破应用程序、程序库、操作系统甚至是硬件设备的界限,打造一个软硬件一体化产品。
这种分层展开的设计模式当然也有它的局限性:专用。由于高度定制化,它通常只能用于完成某个特定功能。低延迟和专用化是呈绝对的正相关的。
TurboTransformers就是采用这种设计:只实现BERT模型前向传播所需要的算子,并融合那些可以合并的算子。
turbo.Tensor
首先,它用CUDA开发了一个轻量级的tensor计算库,所谓的轻量级,指的是不用考虑反向传播、稀疏矩阵等操作,只实现BERT前向传播所必需的operator。
虽然tensor库是用C++写的,但考虑到python在AI开发中的地位,它用pybind11将C++ API暴露给前端的python Tensor类。
# turbo_transformers/python/pybind.cpp
72 py::class_<core::Tensor>(m, "Tensor")
73 .def_static("from_dlpack",
74 [](py::capsule capsule) -> std::unique_ptr<core::Tensor> {
75 auto tensor = (DLManagedTensor *)(capsule);
76 PyCapsule_SetName(capsule.ptr(), "used_tensor");
77 return absl::make_unique<core::Tensor>(tensor);
78 })
79 .def("to_dlpack",
80 [](core::Tensor &tensor) -> py::capsule {
81 auto *dlpack = tensor.ToDLPack();
82 return py::capsule(dlpack, "dltensor", DLPack_Capsule_Destructor);
83 })
84 .def("n_dim", &core::Tensor::n_dim)
85 .def("shape", &core::Tensor::shape)
从预训练模型(PyTorch)那迁移参数时,turbo.Tensor不能直接对接torch.Tensor,需要先将PyTorch的参数转成dlpack格式, 再通过from_dlpack()将这些数据导入生成TurboTransformers tensor。除了dlpack之外,还支持*.npz文件格式。

turbo.xxxlayer
TurboTransformers用CUDA重构了Embedding、self-attention、intermediate、output、LayerNorm和pooler等layer。turbo.layer不仅代码结构简洁,overhead少,还合并了一部分算子。

这里以intermediate layer为例,来分析这些算子的特点。

intermediate layer的实现比较简单:一个Linear layer后面紧跟着一个gelu activation layer。
PyTorch的intermediate layer的会lanuch 3个kernel来完成这部分计算:
- #1: y = input.matmul(weight)
- #2: y = y + bias
- #3: y = gelu(y)
由于#2和#3都是element-wise kernel,turbo把它们进行了融合--AddBiasAct(),相同的计算操作,只需要lanuch 2个kernel,计算速度当然更快。

和PyTorch一样,turbo的MatMul算子也是调用cuBLAS来进行矩阵运算,而且turbo还启用了Tensor Core来加速计算(CUBLAS_TENSOR_OP_MATH)。
总结
到此,本文基本上讲清了TurboTransformers的速度优势来源,由于篇幅所限,不能分析所有的算子。BERT的核心模块是self-attention,如果想了解更多,可以阅读深入浅出Transformer。
更多精彩文章,欢迎扫码关注下方的公众号 ~~ 欢迎关注和点赞,你的鼓励将是我创作的动力
欢迎转发至朋友圈,公众号转载请后台留言申请授权~

深入浅出腾讯BERT推理模型--TurboTransformers的更多相关文章
- Redis云端架构深入浅出
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云数据库 TencentDB 发表于云+社区专栏 作者介绍:邹鹏,腾讯云数据库Redis产品负责人,多年数据库.网络安全研发经验. ...
- [转帖]单集群10万节点 走进腾讯云分布式调度系统VStation
单集群10万节点 走进腾讯云分布式调度系统VStation https://www.sohu.com/a/227223696_355140 2018-04-04 08:18 云计算并非无中生有的概念, ...
- 微信小游戏爆款秘笈 数据库MongoDB攻略篇
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云数据库 TencentDB 发表于云+社区专栏 随着微信小游戏的爆发,越来越多开发者关注到MongoDB与小游戏业务的契合度. ...
- Paddle Release Note
Paddle Release Note 重要更新 飞桨paddle框架2.0.0版本有如下重要更新: 编程范式:默认开启动态图模式进行模型开发和训练,通过动转静的方式进行模型部署和训练加速.如果需要使 ...
- [NLP自然语言处理]谷歌BERT模型深度解析
我的机器学习教程「美团」算法工程师带你入门机器学习 已经开始更新了,欢迎大家订阅~ 任何关于算法.编程.AI行业知识或博客内容的问题,可以随时扫码关注公众号「图灵的猫」,加入”学习小组“,沙雕博主 ...
- Scala 深入浅出实战经典 第81讲:Scala中List的构造是的类型约束逆变、协变、下界详解
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-97讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Scala 深入浅出实战经典 第79讲:单例深入讲解及单例背后的链式表达式
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Scala 深入浅出实战经典 第78讲:Type与Class实战详解
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...
- Scala 深入浅出实战经典 第77讲:模式匹配下的提取器动手构造实战
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
随机推荐
- HotRing: A Hotspot-Aware In-Memory Key-Value Store(FAST ’20)
本文主要解决的是基于内存的K-V存储引擎在实际应用中出现的热点问题,设计了一个热点可感知的KV存储引擎,极大的提升了KV存储引擎对于热点数据访问的承载能力. Introduction 热点问题,可 ...
- Java实现 LeetCode 738 单调递增的数字(暴力)
738. 单调递增的数字 给定一个非负整数 N,找出小于或等于 N 的最大的整数,同时这个整数需要满足其各个位数上的数字是单调递增. (当且仅当每个相邻位数上的数字 x 和 y 满足 x <= ...
- Java实现 蓝桥杯 基础练习 闰年判断
基础练习 闰年判断 时间限制:1.0s 内存限制:256.0MB 提交此题 锦囊1 锦囊2 问题描述 给定一个年份,判断这一年是不是闰年. 当以下情况之一满足时,这一年是闰年: 年份是4的倍数而不是1 ...
- Java实现 LeetCode 514 自由之路
514. 自由之路 视频游戏"辐射4"中,任务"通向自由"要求玩家到达名为"Freedom Trail Ring"的金属表盘,并使用表盘拼写 ...
- 第六届蓝桥杯JavaC组省赛真题
解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1.隔行变色 隔行变色 Excel表的格子很多,为了避免把某行的数据和相邻行混淆,可以采用隔行变色的样式. 小明设计的样式为:第1行蓝色, ...
- java实现第七届蓝桥杯凑平方数
凑平方数 把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的. 比如:0, 36, 5948721 再比如: 1098524736 1, 25, 6390784 0, 4, 28 ...
- 从linux源码看socket的阻塞和非阻塞
从linux源码看socket的阻塞和非阻塞 笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情. 大部分高性能网络框架采用的是非阻塞模式.笔者这次就从linux ...
- 2020最新IDEA插件大集合,一款能帮助你写代码的工具是多么重要
摘要 12款为用户精心打造的Idea插件,含盖前后端,另把使用小技巧分享给大家,提高大家的码率,希望对你们有帮助! Lombok Lombok为Java项目提供了非常有趣的附加功能,使用它的注解可以有 ...
- Spring AOP—注解配置方法的使用
Spring除了支持Schema方式配置AOP,还支持注解方式:使用@AspectJ风格的切面声明. 1 启用对@AspectJ的支持 Spring默认不支持@AspectJ风格的切面声明,为了支持需 ...
- 如何在Vim中的查找替换
“%s/最/第二/g” 用vim的人都知道,这是把所有“最”替换成“第二”的意思.其实vim的查找替换功能非常强大,用的好可以极大提升效率. vim的查找替换命令如下所示: :{作用范围}s/{ ...