项目背景
以BERT为代表的Transformer神经网络是近年来NLP领域最重要的模型创新,很多NLP任务,如阅读理解、文章摘要、语义分类、同义改写等,都通过采用BERT获得了显著的效果提升。但是,如下图所示,Transformer带来更高的模型精度的同时也引入了更多的计算量,使用Transformer的线上NLP服务的高效部署面临着巨大挑战。鉴于BERT在各大互联网公司的广泛应用,非常必要实现一个能发挥充分CPU/GPU硬件计算能力的Transformer推理方法。
TurboTransformers的诞生源于腾讯内部对开源协同的推动。2019年初,腾讯技术委员会成立,下设开源协同、自研上云两个项目组和对外开源管理办公室,以此来促进内部代码的开放共享和协同共建。TurboTransformers来自于深度学习自然语言处理基础平台TencentNLP Oteam,作为基础性技术版块,率先进行了开源协同的实践,旨在搭建统一的深度学习 NLP (Natural Language Processing,自然语言处理)基础平台、提升研发效能。在内部对技术反复打磨的基础上,该项目进一步对外开源。
在业界,Transformers模型的训练部分通常采用tensorflow或者pytorch这种训练框架完成。由于深度学习的训练和推理任务存在差异,训练框架直接应用于线上推理并不能得到极致的性能。众多算法工程师经常遇到模型效果很好,但是无法上线的问题。很多工作尝试弥合推理和训练之间实现差异的鸿沟,如onnxruntime、tensorRT、torchlib、XLA等,这些工作大多需要根据输入尺寸预先对计算图进行预处理和优化,以获得更好的推理时性能。和图像处理任务的输入常常没有变化不同,NLP推理任务输入尺寸多个维度会存在变化。实际推理时通过补零或者截断成整理成固定的输入尺寸,这样引入了额外补零计算开销,预处理优化的方案对NLP任务并不适用。
项目介绍
面对丰富的Transformer的线上服务场景,腾讯微信开源了名为TurboTransformers的Transformer推理加速工具。就像增压器turbo能跑给汽车的发动机引擎带来更强劲的功率,TurboTransformers也可以让你的Transformer推理引擎变强。它的特点是高速、实用、简单。它在CPU和GPU上力求取得业界最佳的性能表现。它支持变长输入序列,无需预处理更适合NLP任务。它支持C++和python方式调用,在pytorch基础上增加几行代码可以获得端到端BERT加速。
Turbo具有如下特性。
-
优异的CPU/GPU性能表现。面向Intel多核CPU和NVIDIA GPU硬件平台,通过核心融合,TurboTransformers充发挥硬件的各层级计算能力。在多种CPU和GPU硬件上获得了超过pytorch/tensorflow和目前主流优化引擎(如onnxruntime-mkldnn/onnxruntime-gpu, torch JIT, NVIDIA faster transformers)的性能表现。
-
为NLP推理任务特点量身定制。TurboTransformers可以支持变长输入序列处理,且不需要预处理过程。
- 简单的使用方式。TurTurboTransformers支持python和C++接口进行调用。它可以作为pytorch的加速插件,在Transformer任务上,通过加入几行python代码获得的端对端加速效果。
TurboTransformers的已经应用腾讯内部于多个线上BERT服务服务场景。比如,微信的FAQ的服务获得1.88x加速,公有云情感分析服务获得2.11x加速,QQ推荐服务获得13.6x加速。
和其他工作的对比如下,TurboTransformers在性能,使用方式都具备优势。
技术创新
TurboTransformers的软件架构如下图,它让微信内部众多NLP线上应用能够充分榨取底层硬件的计算能力,让算法更好地服务的用户。
具体来说TurboTransformers可以在算子优化、框架优化和接口部署方式简化三个方面做了工作。
- 算子层优化
让我们先看看Transformer都包含了什么计算。如下图所示,图(a)展示了论文Transformer结构示意图,这里称灰色方框内的结构为·一个Transformer Cell,BERT encoder堆叠了Nx个这样的Transformer Cell。图(b)将一个Cell的细节加以展开,每一个矩形都是一个独立的计算核心。
Transformer Cell计算包含了8个GEMM(通用矩阵乘法,General Matrix Multiplication)运算。我们通过调优Intel MKL和cuBLAS的GEMM调用方式来获得最佳GEMM性能。通过调整了预训练矩阵存储方式。并且在硬件允许条件下,在GPU上使用tensor core方式进行GEMM运算。
类似NVIDIA FasterTransformers方案,我们将所有GEMM运算之间的计算融合成一个调用核心。融合会带来两个好处,一是减少了内存访问开销,二是减少多线程启动开销。对于这些核心,我们在CPU上采用openmp进行并行,在GPU上使用CUDA进行优化实现。对于比较复杂的LayerNorm和Softmax算子,它们包含了不适合GPU上并行的规约操作,TurboTransformers为它们设计了创新并行算法,极大降低了这些算子的延迟。理论上Transformers推理延迟应该近似于矩阵乘法延迟。
-
框架层优化
TurboTransformers采用了一个有效的内存管理方式。由于NLP的采用变长输入特性,每次运算中间结果的大小其实并不相同。为了避免每次都分配释放内存,我们通过Caching方式管理显存。
为了能够无缝支持pytorch/tensorflow训练好的序列化模型,我们提供了一些脚本可以将二者的预训练模型转化为npz格式,供TurboTransformers读入。特别的,考虑到pytorch huggingface/transformers是目前最流行的transformers训练方法,我们支持直接读入huggingface/transformers预训练模型。
- 应用部署
我们提供了C++和Python调用接口。可以嵌入到C++多线程后台服务流程中,也可以加入到pytorch服务流程中。
我们建议TurboTransformers通过docker部署,一方面保证了编译的可移植性,另一方面也可以无缝应用于K8S等线上部署平台。
性能结果
下图是在Intel Xeon 6133 CPU的性能测试结果。
下图是在NVIDIA RTX 2060 GPU的性能测试结果
下图是在NVIDIA P40 GPU的性能测试结果
下图是在NVIDIA V100 GPU的性能测试结果
未来展望
TurboTransformers是一个的小而美的Transformer推理加速插件,由于自身业务限制,它的功能还相对有限,很多方面待能和开源社区一起努力,共同完善。
TurboTransformers只支持了FP32的计算,对于GPU FP16支持将作为我们的未来工作。TurboTransformers目前重点支持了BERT模型,未来我们会增加TurboTransformers的自动化优化的能力。TurboTransformers解决了计算加速的问题,用户还需要自己搭建服务框架,未来我们会将服务流程开源,打通用户上线的最后一站。
来源:oschina
链接:https://my.oschina.net/u/4342210/blog/4254316