共计 11117 个字符,预计需要花费 28 分钟才能阅读完成。
导读
本次分享将解说如何联合 profiling 工具,发现训练与推理的性能瓶颈。介绍联合 GPU 产品特点,利用算子交融、低精度等技术,以及 Faster Transformer 最佳实际,晋升性能并放慢吞吐。
12 月份的「百度百舸 – 云原生 AI」技术公开课的 4 期整顿文字曾经全副公布,直播回放视频将在明年 1 月份陆续上线,大家能够通过百度智能云技术站视频号观看。
大家好,我是来自 NVIDIA GPU 计算专家团队的陶砺,很快乐明天有机会在这里跟大家分享一下我和我的共事陈庾,在 Swin Transformer 这个视觉大模的型训练和推理优化上的一些工作。其中一些的办法与策略,在其余的模型训练、推理的优化上都能够应用,来进步模型的吞吐、晋升 GPU 的应用效率、放慢模型的迭代。
我会介绍 Swin Transformer 模型的训练局部的优化,在推理优化局部的工作,将由我的共事来做具体的介绍。
这里是咱们明天分享的目录,次要分为四个局部,既然是针对特定模型进行的优化,那么咱们首先会简略介绍一下 Swin Transformer 模型。而后,我会联合 profiling 的工具,也就是 nsight system 对训练的流程进行剖析和优化。在推理局部,我的共事会给出推理优化的策略和办法,蕴含较为细节的 cuda 层面的优化。最初,是明天优化内容的一个总结。
首先是第一局部,也就是 Swin Transformer 的介绍。
一、Swin Transformer 简介
从模型的名称咱们能够看出,这是一个基于 transformer 的模型,咱们先对 transformer 进行一下简略的回顾。
Transformer 模型从 attention is all you need 这篇文章中被提出后,在自然语言解决畛域的很多工作上大放异彩。
Transformer 模型的外围就是所谓的注意力机制,也就是 attention mechanism。对于注意力模块,通常的输出是 query,key 和 value 三个张量。通过 query 和 key 的作用,加上 softmax 的计算,能够失去通常被称为 attention map 的注意力后果,依据 attention map 中的数值的高下,模型就能够学习到须要更加留神 value 中的哪些区域,或者说模型能够学习到,value 中的哪些数值对咱们的工作有很大的帮忙。这就是最根底的单头注意力模型。
咱们通过减少这样单头注意力的模块的数量,也就能够形成常见的多头注意力模块。常见的 encoder、decoder 都是基于这样的多头注意力模块搭建的。
很多模型通常蕴含了 self-attention,cross-attention 这两种注意力模块,或者是一个或多个模块的重叠。如驰名的 BERT 就是由多个 encoder 模块组成,当初大热的 diffusion 模型通常同时蕴含了 self-attention 和 cross-attention。
在 Swin Transformer 之前,Vision Transformer (ViT) 首先将 transformer 利用到了计算机视觉畛域。ViT 的模型构造,如下图左侧所示,ViT 会将一个图像宰割成一系列的 patch,每一个 patch 类比于自然语言解决中的 token,而后通过一个 Transformer-based 的 encoder 对这一系列 patch 进行 encode,最初失去可用于分类等工作的 feature。
而来到 Swin Transformer,它引入了 window attention 的概念,不同于 ViT 对整个图像进行 attention,Swin Transformer 会先将图像划分成若干个 window,而后仅对 window 外部的 patch 进行 attention,从而缩小计算量。
为了补救 window 带来的边界问题,Swin Transformer 进一步引入 window shift 的操作。同时为了使得模型有更丰盛的地位信息,还在 attention 时引入了 relative position bias。其实这里的 window attention 和 window shift,就是 Swin Transformer 中的 Swin 名称的由来。
这里给出的是 Swin Transformer 的网络结构,大抵的一个网络结构和传统的 CNN 如 ResNet 非常相近。
能够看到整个网络结构被划分为多个 stage,在不同 stage 两头,会有对应的降采样的过程。每个 stage 的分辨率是不一样的,从而造成了一个分辨率金字塔,这样也使得每个 stage 的计算复杂程度也逐步升高。
而后每个 stage 中会有若干个 transformer block。每一个 transformer block 中,就会用到下面提到的 window attention 模块。
接下来,咱们从具体操作的角度来对 Swin Transformer 进行解构。
能够看到,一个 transformer block 中波及到三大部分,第一局部是 window shift/partition/reverse 的 window 相干的操作,第二局部是 attention 计算,第三局部是 FFN 计算;而 attention 和 FFN 局部又能够进一步细分为若个 op,最终咱们能够将整个模型细分为几十个 op 的组合。
这样的算子划分对于咱们进行性能剖析,定位性能瓶颈以及发展减速优化而言,都是十分重要的。
以上就是第一局部的介绍。接下来,咱们来介绍一下在训练上咱们进行的一些优化工作,特地的,咱们联合 profiling 工具,也就是 nsight system,对整体的训练流程做一个剖析和优化。
二、Swin Transformer 优化训练
对于大模型的训练而言,通常会用到多卡、多节点的计算资源。针对 Swin Transformer,咱们发现卡间通信的开销占比会绝对较少,随着卡数的增长,整体速度的晋升简直出现线性的增长,所以在这里,咱们优先对单 GPU 上的计算瓶颈进行剖析和优化。
nsight system 是一个零碎层面的性能剖析工具,通过这个工具,咱们能够很不便的看到模型的各个模块的 GPU 的应用状况,是否存在数据期待等可能存在的性能瓶颈和优化空间,能够便于咱们正当的布局 CPU、GPU 之间的负载。
nsight system 能够捕捉到 CUDA,以及一些 gpu 计算库如 cublas,cudnn,tensorRT 等调用的核(kernel)函数的调用和运行状况,以及能够不便用户增加一些标记,来统计标记范畴内对应 gpu 的运行状况。
一个规范的模型优化流程如下图所示,咱们对模型进行 profiling,拿到性能剖析报告,发现性能优化点,而后有针对性的去做性能调优。
这里是一个 nsight system 的界面,咱们能够很清晰地看到核函数的发射,也就是 kernel launch;核函数的运行,也就是这里的 runtime 局部。对于具体的核函数,咱们能够看到在整个流程里的工夫占比,以及 gpu 是否存在闲暇等信息。在增加完 nvtx 标记之后,咱们能够看到模型前向,反向所须要的工夫。
在前向局部,如果放大,咱们也能够清晰地看到具体每个 SwinTransformer Block 的计算须要的工夫。
咱们首先通过 nsight system 性能剖析工具来看一下整个 baseline 的性能体现,下图中展现的就是 FP32 的 baseline,能够看到它的 GPU 利用率是很高的,而其中占比最高的是矩阵乘的 kernel。
那么对于矩阵乘法而言,咱们的一个优化伎俩,就是充分利用 tensor core 进行减速。
咱们晓得 NVIDIA 的 GPU 内有 cuda core 和 tensor core 这样的硬件资源,tensor core 是专门为了矩阵乘法的减速的模块。咱们能够思考间接采纳 tf32 tensor core 或者混合精度下,采纳 fp16 tensor core。要晓得,应用 fp16 的 tensor core 在矩阵乘法上的吞吐,会比 tf32 要高,比照纯 fp32 的矩阵乘也会有很高的减速成果。
在此,咱们采纳了混合精度的计划。通过采纳 torch.cuda.amp 的混合精度的模式,咱们能够获得了 1. 63 倍的吞吐晋升。
在 profiling 的后果里也可能很清晰地看到,本来占最高的矩阵乘,通过优化后,在整个 timeline 中的占比降到了 11.9%。至此,占比拟高的 kernel 都是 elementwise kernel。
对于 elementwise kernel,咱们首先要理解哪里会用到 elementwise 的 kernel。
Elementwise kernel 里,比拟常见的 unrolled elementwise kernel 和 vectorized elementwise kernel。其中 unrolled elementwise kernel 宽泛存在于一些有偏置的卷积,或者线性层中,以及一些保证数据在内存连续性的 op 中。
vectorized elementwise kernel 则经常出现在一些激活函数,如 ReLU 的计算中。如果想要缩小这里大量的 elementwise kernel,一个常见的做法是做算子交融,比方矩阵乘法中,咱们能够通过将 elementwise 的操作与矩阵乘法的算子交融在一起,来升高这部分的工夫开销。
对于算子交融,一般而言能够为咱们带来两个益处:
一个是缩小 kernel launch 的开销,如下图所示,两个 cuda kernel 的执行须要两次 launch,那样可能会导致 kernel 之间存在 gap,使得 GPU 闲暇,那么如果咱们将两个 cuda kernel 交融成一个 cuda kernel,一方面节俭了一次 launch,同时也能够防止 gap 的产生。
另外一个益处是缩小了 global memory 的拜访,因为 global memory 的拜访是十分耗时的,而两个独立的 cuda kernel 之间要进行后果传递,都须要通过 global memory,将两个 cuda kernel 交融成一个 kernel,咱们能够在寄存器或者 share memory 上进行后果传递,从而防止了一次 global memory 写和读,晋升性能。
对于算子交融,咱们第一步是采纳现成的 apex 库来进行 Layernorm 和 Adam 中操作的交融,能够看通过简略的指令替换,咱们能够使能 apex 的 fused layernorm 和 fused Adam,从而使得减速从 1.63 倍晋升至 2.11 倍。
从 profling 的日志咱们也能够看到,通过算子交融之后,elementwise kernel 在这个 timeline 的占比大幅升高,矩阵乘法从新成为工夫占比最大的 kernel。
除了利用现有的 apex 库,咱们也进行了手工的交融算子开发。
通过观察 timeline,以及对模型的了解,咱们发现 Swin Transformer 中有特有的 window 相干操作,如 window partition/shift/merge 等,这里的一次 window shift,须要调用两个 kernel,并在 shift 实现之后调用 elementwise 的 kernel。并且,attention 模块前如果须要做一次这样的操作,那么之后会有对应的 reverse 操作。这里单单 window shift 调用的 roll\_cuda\_kernel 就在整个 timeline 中占比 4.6%。
方才提到的这些操作,其实只是对数据进行了划分,即对应的数据会被划分到一个 window 中去,对应的原始代码如下图所示。
咱们发现,这部分的操作其实实质上只是 index mapping,因而,咱们对这一部分进行的交融算子开发。开发的过程,咱们须要把握 CUDA 编程的相干常识,并且编写算子的前向计算和反向计算的相干代码。
如何向 pytorch 中引入自定义算子,官网给出了教程,咱们能够依照教程编写 CUDA 代码,编译好后就能够作为一个模块引入原始的模型。能够看到,通过引入咱们的定制化交融算子,咱们能够将减速比进一步晋升至 2.19 倍。
接下来展现的是,咱们对 mha 局部的交融工作。
Mha 局部是 transformer 模型中一个占比很大的模块,因而对它的优化往往能够带来较大的减速成果。从图中能够看到,在没有进行算子交融之前,mha 局部的操作占比为 37.69%,其中包含了不少 elementwise 的 kernel。如果咱们可能将相干操作交融成一个独立的 kernel,并具备更快的速度,减速比能够失去进一步晋升。
对于 Swin Transformer,这部分的模块除了 query,key 和 value 外,mask 和 bias 都是以 tensor 的模式传入的,咱们开发了 fMHA 这样的一个模块,能够将本来的若干 kernel 交融起来。从 fMHA 这个模块波及到的计算来看,针对 Swin Transformer 中遇到的一些 shape,该模块都有比较显著的晋升。
模型用上 fMHA 模块后,咱们能够将减速比进一步晋升 2. 85 倍。上述是咱们在单卡上获得的训练减速成果,那么咱们来看一下单机 8 卡的训练状况,能够看到,通过上述优化,咱们能够将训练吞吐从 1612 晋升至 3733,获得 2.32 倍的减速。
对于训练优化而言,减速比咱们心愿越高越好,对应的,咱们也心愿减速后的性能可能与减速前保持一致。
叠加上上述若干减速计划后,能够看到,模型的收敛性与原始的 baseline 保持一致,优化前后的模型的收敛、精度的一致性,在 Swin-Tiny,Swin-Base 以及 Swin-Large 上都失去了验证。
对于训练局部,一些其余的减速策略包含 CUDA graph、multi-stream 等,都能对 Swin Transformer 的性能有进一步晋升;其余方面,目前咱们介绍的是应用混合精度的计划,也就是 Swin Transformer 官网 repo 采纳的策略;应用纯 fp16 的计划(即 apex O2 模式)能够达到更快的减速成果。
尽管 Swin 对通信的要求不高,然而对于多节点大模型的训练,相比于原始的分布式训练,应用正当的策略去暗藏通信的开销,可能在多卡训练上取得进一步的收益。
接下来,有请我的共事来介绍一下咱们在推理上的减速计划和成果。
三、Swin Transformer 推理优化
大家好,我是来自英伟达 GPU 计算专家团队的陈庾,非常感谢陶砺在训练减速上的介绍,接下来由我来介绍一下推理上的减速。
跟训练一样,推理的减速离不开算子交融这一计划。不过绝对于训练而言,在推理上进行算子交融有更好的灵活性,次要体现有两点:
- 推理上的算子交融不须要思考反向,所以 kernel 开发过程中不须要思考保留计算梯度所须要的两头后果;
- 推理过程容许预处理,咱们能够对一些只须要一次计算便可重复使用的操作,提前算好,保留后果,每次推理时间接调用从而防止反复计算。
在推理侧,咱们能够进行不少的算子交融,这里给出的是咱们在 Transformer 模型中常见的一些算子交融的 pattern 以及实现相干 pattern 所须要用到的工具。
首先,咱们独自列出矩阵乘法和卷积,是因为有一大类算子交融是围绕他们进行的,对于矩阵乘法相干的交融,咱们能够思考采纳 cublas,cutlass,cudnn 这三个库;对于卷积,咱们能够采纳 cudnn 或者 cutlass。那么对于矩阵乘法的算子交融而言,在 Transformer 模型中,咱们演绎为 gemm + elementwise 的操作,比方 gemm + bias, gemm + bias + 激活函数等,这一类的算子交融,咱们能够思考间接调用 cublas 或 cutlass 来实现。
此外,如果咱们 gemm 之后的 op 操作比较复杂,比方 layernorm,transpose 等,咱们能够思考将 gemm 和 bias 离开,而后把 bias 交融到下一个 op 中,这样能够更为容易地调用 cublas 来实现简略的矩阵乘法,当然这种 bias 和下一个 op 进行交融的 pattern 个别是须要咱们手写 cuda kernel 来实现。
最初,有一些特定 op,同样须要咱们以手写 cuda kernel 的形式进行交融,比方 layernorm + shift + window partition。
因为算子交融须要咱们比拟奇妙地设计 cuda kernel,所以咱们个别倡议先通过 nsight system 性能剖析工具对整体 pipeline 进行剖析,优先针对热点模块进行算子交融优化,以达到性能和工作量的均衡。
那么在泛滥的算子交融优化中,咱们筛选了两个减速成果比拟显著的算子进行介绍。
首先是 mha 局部的算子交融,咱们将 position bias lookup 这一操作提前到预处理局部,从而防止每次推理时都进行 lookup。
而后将 batch gemm,softmax,batch gemm 交融成一个独立的 fMHA kernel,同时咱们把 transpose 相干的操作交融到了 fMHA kernel I/O 操作中,通过肯定的数据读写的 pattern 来防止显式的 transpose 操作。
能够看到,交融后该局部获得了 10 倍的减速,而端到端也获得了 1.58 倍的减速。
另一个我想介绍一下的算子交融是 QKV gemm + bias 的交融。
gemm 和 bias 的交融是一个非常常见的交融伎俩,在这里为了配合咱们后面提到的 fMHA kernel,咱们须要对 weight 和 bias 提前进行格局上的变换。
我之所以在这里抉择介绍这个算子交融,也正是因为这种提前变换体现了咱们后面提到的,推理上进行算子交融的灵活性,咱们能够对模型的推理流程做一些不影响其精度的变动,从而实现更好算子交融 pattern,获得更好的减速成果。
最初,通过 QKV gemm+bias 的交融,咱们能够进一步获得 1.1 倍的端到端减速。
下一个优化伎俩是矩阵乘法 padding。
在 Swin Transformer 的计算中,有时候咱们会遇到主维为奇数的矩阵乘法,这时候并不利于咱们的矩阵乘法 kernel 进行向量化读写,从而使得 kernel 的运行效率变低,此时咱们能够思考对参加运算的矩阵主维进行 padding 操作,使其变为 8 的倍数,这样一来,矩阵乘 kernel 就能够以 alignment=8,一次读写 8 个元素的形式来进行向量化读写,晋升性能。
如下表所示,咱们将 n 从 49 padding 到 56 后,矩阵乘法的 latency 从 60.54us 降落为 40.38us,获得了 1.5 倍的减速比。
下一个优化伎俩是巧用 half2 或者 char4 这样的数据类型。
以下的代码是一个 half2 优化的示例,它实现的是一个简略的加 bias 再加残差这样的算子交融操作,能够看到通过应用 half2 数据类型,绝对于 half 数据类,咱们能够将 latency 从 20.96us 降落到 10.78us,减速 1.94 倍。
那么采纳 half2 数据类型个别有什么益处呢?次要有三点:
第一个益处是向量化读写能够晋升 memory 的带宽利用效率并升高访存指令数;如下图右侧所示,通过 half2 的应用,访存指令缩小了一半,同时 memory 的 SOL 也有显著晋升;
第二个益处是联合 half2 专有的高吞吐的数学指令,能够减低 kernel 的 latency。这两点都曾经体现在了这个示例程序中;
第三个益处是在进行 reduction 相干 kernel 开发时,采纳 half2 数据类型意味着一个 cuda 线程同时解决两个元素,能够无效缩小闲暇的线程数,也能够缩小线程同步的 latency。
下一个优化伎俩是巧用寄存器数组。
在咱们进行 layernorm 或者 softmax 等 Transformer 模型常见的算子优化时,咱们常常须要在一个 kernel 中屡次应用同一个输出数据,那么绝对于每次都从 global memory 读取,咱们能够采纳寄存器数组来缓存数据,从而防止反复读取 global memory。
因为寄存器是每个 cuda 线程独占的,所以在进行 kernel 设计时,咱们须要提前设定好每个 cuda 线程所须要缓存的元素个数,从而开拓对应大小的寄存器数组,并且在调配每个 cuda 线程所负责元素时,须要确保咱们能够做到合并拜访,如下图右上侧所示,当咱们有 8 个线程时,0 号线程能够解决 0 号元素,当咱们有 4 个线程是,0 号线程则解决 0 号和 4 号元素,如此类推。
咱们个别倡议能够采纳模板函数的形式,通过模板参数来管制每 个 cuda 线程的寄存器数组大小。
此外,在应用寄存器数组时,须要保障咱们的下标是常量,如果是循环变量作为下标,咱们应该尽量保障能够进行循环展开,这样能够防止编译器将数据放到了 latency 很高的 local memory 中,如下图所示,咱们在循环条件中增加限度,通过 ncu report 能够看到,防止了 local memory 的应用。
最初一个我想介绍优化伎俩是 INT8 量化。
INT8 量化是推理减速十分重要的减速伎俩,对于 Transformer based 的模型而言,INT8 量化能够在缩小显存耗费的同时带来更好的性能。
而对于 Swin 来说,通过联合适合的 PTQ 或 QAT 量化计划,能够在获得良好减速的同时,保障量化精度。个别咱们进行 int8 量化,次要是对矩阵乘法或者卷积进行量化,比方 int8 矩阵乘法中,咱们会先将原始的 FP32 或 FP16 的 input 和 weight 量化为 INT8 而后再进行 INT8 矩阵乘法,累加到 INT32 数据类型上,这是咱们会进行反量化操作,失去 FP32 或 FP16 的后果。
比拟常见调用 INT8 矩阵乘法的工具是 cublasLt,为了能够获得更好的性能,咱们有必要深刻地理解一下 cublasLt api 的一些个性。
cublasLt 对于 int8 矩阵乘法,提供了两种输入类型,别离是下图左侧所示,以 INT32 输入,或者下图右侧所示,以 INT8 输入,图中蓝框所示的 cublasLt 的计算操作。
能够看到绝对于 INT32 输入而言,INT8 输入会多了一对反量化和量化操作,这样一来个别会带来更多的精度损失,然而因为 INT8 输入,在写出到 global memory 时绝对 INT32 输入少了 3/4 的数据量,性能会更好,所以这外面存在着精度和性能 tradeoff。
那么对于 Swin Transformer 而言,咱们发现配合 QAT,以 INT8 输入会在取好的减速比的前提下,保障精度,因为咱们采纳了 INT8 输入的计划。
另外,对于 cublasLt 中 INT8 矩阵乘法,还须要思考数据的布局问题,cublasLt 反对两种布局,一种 IMMA-specific 的布局,其中波及到一些比较复杂的格局,而且在这种布局只反对 NT-gemm,另外一种是惯例的列优先的布局,在此布局下反对 TN-gemm。
一般来说,采纳列优先的布局,会更有利于整个 pipeline 代码的开发,因为如果咱们用 IMMA-specific 布局的话,咱们为了兼容这种布局可能须要很多额定的操作,以及上下游 kernel 也须要为这种非凡布局做兼容。然而在一些尺寸的矩阵乘法上,IMMA-specific 布局可能会有更好的性能,所以如果咱们要尝试搭建 int8 推理的话,倡议咱们能够先做一些 benchmark,以便更好地从性能和开发难易水平做取舍。
在 FasterTransformer 中咱们采纳了 IMMA-specific 布局。所以接下来,咱们以 IMMA-specific 布局为例,简略介绍了一下 cublasLt int8 矩阵乘法的根本搭建流程,以及一些开发技巧。
cublasLt int8 矩阵乘法的根本搭建流程,一共能够分为 5 步:
- 首先咱们须要创立句柄和乘法描述符;
- 接下来咱们为每个矩阵创立一个矩阵描述符;
- 因为个别咱们的输出都是惯例 layout 的,所以咱们须要对惯例布局的矩阵进行布局转换,使其变为 IMMA-specific 的布局;
- 而后再进行 int8 矩阵乘法,失去后果之后,咱们能够思考持续用这个后果进行上游的乘法计算,这样能够防止转变会惯例布局的开销;
- 只有最初一个矩阵乘法的后果,咱们须要转换惯例布局以便输入。
上述介绍了 IMMA-specific 布局下的搭建流程,能够看到外面会有不少限度。为了防止这些限度对性能的影响,咱们在 Faster Transformer 中采纳了以下技巧:
- 首先 IMMA-specific 布局对矩阵是有特定的尺寸要求,为了防止推理过程中须要额定调配空间的操作,咱们会提前调配好合乎 IMMA-specific 布局尺寸的 buffer;
- 而后,因为 weight 能够一次解决重复使用,所以咱们会提前对 weight(相当于乘法中的 B 矩阵)进行布局变换,防止在推理过程中重复变换 weight;
- 第三个技巧是,对于不得不进行非凡布局变换的 A 和 C,咱们会把变换和上游或上游 op 进行算子交融,以便暗藏这部分的开销;
- 最初一点,是与布局无关,而是 int8 矩阵乘法必有的量化和反量化的操作,咱们同样会采纳算子交融的形式,把它的 latency 暗藏起来。
以下是咱们在 Faster Transformer 中采纳的的 INT8 流程的示意图,能够看到,所有矩阵乘都变为了 int8 数据类型,每个 int8 矩阵乘法前后都会插入对应的量化和反量化节点,而后对于加 bias,加残差或 layernorm 等操作,咱们还是保留原始的 FP32 或 FP16 数据类型,当然它的 I/O 可能是 int8 的,从而会比 FP16 或 FP32 I/O 性能要好。
这里展现的是 Swin Transformer int8 量化的精度状况,通过 QAT 咱们能够保障精度损失在千分之 5 以内。
而在 PTQ 那一列,咱们能够看到 Swin-Large 的掉点比较严重,个别对应掉点重大的问题,咱们都能够思考采纳缩小一些量化节点的形式来晋升量化精度,当然这样可能会带来减速成果的削弱。
在 FT 中,咱们能够通过禁用 FC2 和 PatchMerge 中 int 8 矩阵乘法的 int8 输入前的反量化和量化结点(即采纳 int32 输入),来进一步晋升量化精度,能够看到在此优化操作下,swin-large 的 PTQ 精度也显著晋升了。
接下来是咱们推理侧获得的减速成果,咱们别离在不同型号的 GPU T4、A10、A100 上进行了跟 pytorch FP16 实现的性能比照。
其中下图左侧是优化后跟 pytorch 的 latency 比照,右图为优化后 FP16 下跟 pytorch 以及 INT8 优化跟 FP16 优化的减速比。能够看到,通过优化,在 FP16 精度上,咱们能够获得,绝对于 pytorch 2.82x ~ 7.34x 的减速,联合 INT8 量化,咱们能够在此基础上进一步获得 1.2x ~ 1.5x 的减速。
四、Swin Transformer 优化总结
最初,咱们总结一下,本次分享中咱们介绍了如何通过 nsight system 性能剖析工具发现性能瓶颈,而后针对性能瓶颈,介绍了一系列训练推理减速技巧,其中包含 1. 混合精度训练 / 低精度推理,2. 算子交融,3. cuda kernel 优化技巧:如矩阵补零,向量化读写,巧用寄存器数组等,4. 推理优化上采纳一些预处理,来欠缺咱们的计算流程;咱们也介绍了 multi-stream,cuda graph 的一些利用。
联合上述优化,咱们在训练上,以 Swin-Large 模型为例获得了单卡 2.85x 的减速比,8 卡 2.32x 的减速比;在推理上,以 Swin-tiny 模型为例,在 FP16 精度下获得了 2.82x ~ 7.34x 的减速比,联合 INT8 量化,进一步获得 1.2x ~ 1.5x 的减速比。
上述视觉大模型训练与推理的减速办法都曾经在百度百舸 AI 异构计算平台的 AIAK 减速性能中实现,欢送大家应用。
—— END——
举荐浏览:
百度工程师带你玩转正则
Diffie-Hellman 密钥协商算法探索
贴吧低代码高性能规定引擎设计
浅谈权限零碎在多利熊业务利用
分布式系统要害门路提早剖析实际
百度工程师教你玩转设计模式(装璜器模式)