基于TensorRT的BERT实时自然语言理解(下)

BERT Inference with TensorRT

请参阅Python脚本bert_inference.py还有详细的Jupyter notebook BERT_TRT.ipynb在sample文件夹中进行推理过程的逐步描述和演练。在本节中,让我们回顾几个关键参数和概念,以便使用TensorRT进行推理。

BERT(更具体地说是编码器层)使用以下参数来控制其操作:

  1. Batch size
  2. Sequence Length
  3. Number of attention heads

这些参数的值取决于所选的BERT模型,用于设置TensorRT计划文件(执行引擎)的配置参数。

对于每个编码器,还要指定隐藏层的数量和注意头的大小。您也可以从Tensorflow检查点文件中读取上述所有参数。

由于我们所使用的BERT模型已经针对SQuAD数据集上的问答下游任务进行了微调,网络的输出(即输出完全连接层)将是一段文本,答案出现在文章中(在示例中称为h_output)。一旦我们生成了TensorRT引擎,我们就可以对其进行序列化,然后在TensorRT运行时中使用它。

在推理过程中,我们异步地执行从CPU到GPU的内存复制,反之亦然,从而分别将张量导入和移出GPU内存。异步内存复制操作通过与设备和主机之间的内存复制操作重叠计算来隐藏内存传输的延迟。异步内存复制和内核执行如图3所示。

Figure 3: TensorRT Runtime process

The inputs to the BERT model, which are shown in Figure 3, include:

  1. input_ids: tensor with token ids of paragraph concatenated along with question that is used as input for inference
  2. segment_ids: distinguishes between passage and question
  3. input_mask: indicates which elements in the sequence are tokens, and which ones are padding elements

输出(start_logits)和end_logits结束逻辑表示答案的范围,网络根据问题在文章中预测答案的范围。

在Jupyter笔记本中,我们使用了作为TensorRT插件实现的层的加速和高效实现。请参阅TensorRT文档以了解有关TensorRT插件以及如何在TensorRT中导入自定义层的更多信息。

Optimizing BERT for Inference

让我们浏览一下在TensorRT优化的BERT中实现的关键优化。

BERT架构基于Transformer,由12个用于BERT基的Transformer单元和24个用于BERT大型单元的Transformer单元组成。在被Transformer处理之前,输入标记通过一个嵌入层传递,该层查找它们的向量表示并对它们在句子中的位置进行编码。每个Transformer单元由两个连续的剩余块组成,每个剩余块随后进行层标准化。第一残差块代替第一完全连通层并通过多头自注意机制激活,第二剩余块使用高斯误差线性单元(GELU6)激活。

图4说明了Transformer单元的结构。

为了用TensorRT优化BERT,我们重点研究了Transformer单元的优化。由于在BERT中堆叠了几个Transformer单元,因此我们能够通过这组优化实现显著的性能提升。

为了在TensorRT中使用这些优化,我们使用定制插件来加速BERT模型中Transformer编码器元素中的关键操作。插件将多个操作融合到单个CUDA内核中的子图中。每个子图由几个基本计算组成,每个计算都需要对GPU的全局内存(即最慢的设备内存)进行读写。通过将基本操作融合到单个CUDA内核中,我们允许计算在更大的子图上进行,同时访问全局内存的次数最少。让我们更详细地看看这些插件。

Figure 4: Optimizations through TensorRT for BERT encoder cell of Transformer

The Gelu Activation performs the following  elementwise computation where a, b and c are some scalar constants:

gelu(x) = a * x * (1 + tanh( b * (x + c * x^3) ))

A naive implementation using elementary layers in TensorRT would require the following operations:

Result =  x^3

Result =  c * Result

Result =  x + Result

Result =  b * Result

Result = tanh(Result)

Result = x * Result

Result = a * Result

对于k层,朴素的实现将需要。k-1不必要的全局内存往返,我们将其合并到单个CUDA内核中的元素计算中。参考geluPlugin.cu目录中获取更多详细信息。

跳过层和层规范化(LN)层在每个转换器层出现两次,并在单个内核中融合。有关此融合操作的实现,请参见中的skipLayerNormPlugin.cu在plugins目录中。

Transformer中的自我注意机制(图5)基于使用完全连接(FC)层的输入嵌入计算查询(Q)、键(K)和值(V)的表示。所有这些FC层的输入和输出维都是B x S x(N*H),其中B是批大小,S是序列长度,N是注意头数,H是隐藏层大小。然后将每个FC层的输出转置以形成大小为B x N x S x H的结果矩阵。将3个FC层合并到单个较大的层中可得到B x S x(3*N*H)的输出维度。

在融合的FC层之后,有三个转置操作可以被融合到单个更大的转置中,从而产生3xb×N×S×H的输出维。通过融合FC层,然后在较大张量上执行单个转置,Q、K和V表示被连续地放置在存储器中,以便进行以下操作他们。这将导致更快的内存访问,提高模型的吞吐量。

我们还融合了元素级缩放和softmax层(图5a和5b的右侧)。

参考qkvToContextPlugin.cu在自我注意实现的plugins目录中。

Figure 5a: Self-Attention Layer before Optimization

Figure 5b: Self-attention Layer after Optimization

Benchmarking BERT Inference Performance

BERT可以应用于在线和离线用例。在线NLU应用程序,如会话式人工智能,在推理过程中会有较紧的延迟预算。为了响应单个用户的查询,需要按顺序执行多个模型。当作为服务使用时,客户体验的总时间包括计算时间以及输入和输出网络延迟。时间越长,性能就越差,客户体验也就越差。

虽然单个模型可用的确切延迟可能因应用程序而异,但多个实时应用程序需要语言模型在10毫秒内执行。使用Tesla T4 GPU,使用TensorRT优化的BERT可以在2.2毫秒内对批处理大小=1、序列长度=128的QA任务执行推断。使用TensorRT优化的示例,对于BERT base,您可以执行高达8的批处理大小,对于在10毫秒延迟预算内具有较少Transformer层的模型,可以执行更高的批处理大小。对于批处理大小=1,在仅CPU平台上用高度优化的代码执行相同的任务需要40毫秒,而更高的批处理大小不会运行到完成并出现错误退出。

Figure 6: Compute latency in milliseconds for executing BERT-base on an NVIDIA T4 GPU versus a CPU-only server

该基准测试测量在将张量作为输入传递和将逻辑集作为输出之间执行QA任务时仅计算的延迟时间。您可以在中找到用于对示例进行基准测试的代码sampleBERT.cpp.

Conclusion

NVIDIA是开放源码的几个优化,使它能够在2.2ms内使用TensorRT在T4 gpu上执行BERT推断。优化的代码可以在TensorRT开源repo中作为开源示例提供。要在GCP上运行这个示例,可以从google cloud ai Hub访问它。repo展示了如何优化Transformer层,它是BERT和其他几种语言模型的核心构建块。我们希望您能够轻松地定制这些构建块,以适合您的定制模型和应用程序。本文概述了如何使用TensorRT示例、关键优化和性能结果。我们进一步描述了如何使用BERT示例作为简单应用程序和Jupyter笔记本的一部分的工作流程,在这里您可以传递一个段落并询问与之相关的问题。

新的优化和可实现的性能使得首次将BERT用于延迟预算较紧的应用程序(如会话式AI)成为现实。在接下来的几个月里,我们希望分享更多的例子,展示如何将BERT用作其他工作流的一部分。

我们一直在寻找新的想法来分享新的例子和应用程序。您使用BERT进行哪些NLP应用程序?您将来希望从我们这里看到哪些示例?

If you have questions regarding the TensorRT sample repo, check the NVIDIA TensorRT Developer Forum to see if other members of the TensorRT community have a resolution first. NVIDIA Registered Developer Program can also file bugs at https://developer.nvidia.com/nvidia-developer-program.

  • CPU-only specifications: Gold 6240@2.60GHz 3.9GHz Turbo (Cascade Lake) HT Off, Single node, Single Socket, Number of CPU Threads = 18, Data=Real, Batch Size=1; Sequence Length=128; nireq=1; Precision=FP32; Data=Real; OpenVINO 2019 R2

GPU-server specification: Gold 6140@2GHz 3.7GHz Turbo (Skylake) HT On, Single node, Dual Socket, Number of CPU Threads = 72, Tesla T4 16GB, Driver Version 418.67 (r418_00), BERT-base, Batch Size=1; Number of heads = 12, Size per head = 64; 12 layers; Sequence Length=128; Precision=FP16; XLA=Yes; Data=Real; TensorRT 5.1

References:

  1. [Devlin et al 2018] BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. Jacob Devlin, Ming-Wei Chang, Kenton Lee, Kristina Toutanova
  2. [Y Liu ‎2019] RoBERTa: A Robustly Optimized BERT Pretraining Approach
  3. SQuAD leaderboard
  4. [Vaswani et al 2017] Attention Is All You Need Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Lukasz Kaiser, Illia Polosukhin
  5. [Jinhyuk Lee et al 2019] BioBERT: a pre-trained biomedical language representation model for biomedical text mining Jinhyuk Lee, Wonjin Yoon, Sungdong Kim2, Donghyeon Kim1, Sunkyu Kim1, Chan Ho So3 and Jaewoo Kang
  6. [Dan et al 2016] Gaussian Error Linear Units (GELUs)  Dan Hendrycks, Kevin Gimpel

基于TensorRT的BERT实时自然语言理解(下)的更多相关文章

  1. 基于TensorRT的BERT实时自然语言理解(上)

    基于TensorRT的BERT实时自然语言理解(上) 大规模语言模型(LSLMs)如BERT.GPT-2和XL-Net为许多自然语言理解(NLU)任务带来了最先进的精准飞跃.自2018年10月发布以来 ...

  2. 基于TensorRT车辆实时推理优化

    基于TensorRT车辆实时推理优化 Optimizing NVIDIA TensorRT Conversion for Real-time Inference on Autonomous Vehic ...

  3. java自然语言理解demo,源码分享(基于欧拉蜜)

    汇率换算自然语言理解功能JAVA DEMO >>>>>>>>>>>>>>>>>>>&g ...

  4. 【中文版 | 论文原文】BERT:语言理解的深度双向变换器预训练

    BERT:Pre-training of Deep Bidirectional Transformers for Language Understanding 谷歌AI语言组论文<BERT:语言 ...

  5. 基于TensorRT 3的自动驾驶快速INT8推理

    基于TensorRT 3的自动驾驶快速INT8推理 Fast INT8 Inference for Autonomous Vehicles with TensorRT 3 自主驾驶需要安全性,需要一种 ...

  6. 如何使用OLAMI自然语言理解开放平台API制作自己的智能对话助手小程序

    我们经常在电影中看到机器和人对答如流,随着越来越多自然语言开放平台的出现,IT爱好者制作一个自己的APP或者小玩具等逐渐可以变为现实. 自然语言对话即你的APP或者你制作的工具.机器人等能够对用户输入 ...

  7. 基于socket.io的实时在线选座系统

    基于socket.io的实时在线选座系统(demo) 前言 前段时间公司做一个关于剧院的项目,遇到了这样一种情况. 在高并发多用户同时选座的情况下,假设A用户进入选座页面,正在选择座位,此时还没有提交 ...

  8. 苏宁基于Spark Streaming的实时日志分析系统实践 Spark Streaming 在数据平台日志解析功能的应用

    https://mp.weixin.qq.com/s/KPTM02-ICt72_7ZdRZIHBA 苏宁基于Spark Streaming的实时日志分析系统实践 原创: AI+落地实践 AI前线 20 ...

  9. 微软自然语言理解平台LUIS:从零开始,帮你开发智能音箱

    今年微软开发者大会Build 2017上展示了一款Invoke智能音箱,受到了媒体和大众的广泛关注.近两年,不少大公司纷纷涉足该领域,使得智能音箱逐渐成为一款热门的人工智能家用电器.智能音箱的兴起也改 ...

随机推荐

  1. Python脚本暴力破解SSH口令以及构建僵尸网络(pxssh)

    目录 暴力破解SSH口令 SSH远端执行命令 构建僵尸网络 环境:Kali Linux  python 2.7.13 暴力破解SSH口令 Pxssh是pexpect库的ssh专用脚本,他能用预先写好的 ...

  2. Windows PE 第一章开发环境和基本工具使用

    第一章 Windows PE 基本工具 1.1开发语言MASM32 1.1.1设置开发环境 这个不细说了,我在整理Intel汇编的时候详细的说了环境搭建以及细节.地址是:http://blog.csd ...

  3. 风变编程(Python自学笔记)第12关-我们都是中国人

    1.类的个例叫做实例:类,是对某个群体的统称(类是某个特定的群体),实例是群体中某个具体的个体. 2.Python中的对象等于类和实例的集合. 3. 类的创建:class+类名+冒号,后面语句要缩进. ...

  4. 『政善治』Postman工具 — 13、Postman接口测试综合练习

    目录 (一)项目接口文档 1.鉴权接口 2.注册接口 3.登录接口 4.用户信息接口 5.注销接口 (二)网站上手动验证 (三)Postman测试实现 1.准备工作 (1)创建一个Collection ...

  5. 进入除错模式!进入此模式后,将会出现更多的选项,分别是: · 以基本图形介面安装 CentOS 7 (使用标准显卡来设定安装流程图示); · 救援Centos系统; · 执行内存测试(Run a memory test);

    Centos 7.3 安装 0.0392017.07.14 20:12:09字数 1550阅读 985 Centos 7.3 基于 Red Hat 企业版的源代码的最新版本的 CentOS 7 在今年 ...

  6. 查找目录下的所有文件中是否含有某个字符串 find .|xargs grep -ri "IBM"

    linux查看目录下所有文件内容中是否包含某个字符串 2017-07-25 15:13:22 默一鸣 阅读数 21556 文章标签: linux查找文件夹文件内容字符串 更多 分类专栏: Unix   ...

  7. linux进阶之gitlab仓库搭建及免密使用

    一.Gitlab简介 GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务. 可通过Web界面进行访问公开的或者私人项目.它拥有与Github类 ...

  8. 10.6 ip:网络配置工具

    ip命令是iproute软件包中的一个强大的网络配置工具,用于显示或管理Linux系统的路由.网络设备.策略路由和隧道.   ip [option] [object] [command] ip [选项 ...

  9. Java并发:ThreadLocal的简单介绍

    作者:汤圆 个人博客:javalover.cc 前言 前面在线程的安全性中介绍过全局变量(成员变量)和局部变量(方法或代码块内的变量),前者在多线程中是不安全的,需要加锁等机制来确保安全,后者是线程安 ...

  10. Redux 原理和简单实现

    前端开发中React + Redux 是大部分项目的标配,Redux也是我喜欢的库之一,他的源码也拜读过几遍,每次都有很多收获,尤其他的中间件设计模式,对自己封装一些库提供了思想上的指导. Redux ...