TVM优化GPU机器翻译

背景

神经机器翻译(NMT)是一种自动化的端到端方法,具有克服传统基于短语的翻译系统中的弱点的潜力。最近,阿里巴巴集团正在为全球电子商务部署NMT服务。

将Transformer用作NMT系统的关键技术,相对于基于经典RNN / LSTM的模型具有同等(甚至更高)的精度,对于高效的离线训练更为友好。尽管Transformer在离线训练阶段很友好,打破了跨时间步长的依赖性,但在线推理效率不高。在生产环境中,已经发现,初始版本的Transformer的推理速度约为1.52倍,比LSTM版本慢。已经进行了一些优化来提高推理性能,例如图形级op融合,循环不变节点运动。观察到的一个特殊挑战是,批处理matmul是Transformer中的主要性能热点,而cuBLAS中的当前实现并未得到很好的优化。

下面的结果表明TVM生成内核(与调度表优化)带来至少13X批量MATMUL计算加速,futher加快算子融合功能。

批处理Matmul

为什么批量Matmul

在Transformer中,批处理matmul广泛用于multi-head attention计算。使用matmul批处理,关注层中multiple heads并行运行,帮助提高硬件的计算效率。

在推理阶段对Transformer模型进行了全面的分析,结果表明,批量matmul计算贡献了约30%的GPU内核执行时间。使用nvprof,对cuBLAS批处理matmul内核进行一些第一性原理分析,可以清楚地表明,当前的实现方式表现不佳,并且观察到了一些有趣的现象。

什么是批量matmul

通常,批量矩阵计算对一批矩阵执行乘法。批处理被认为是“统一的”,即所有实例具有相同的维度(M,N,K),前导维度(lda,ldb,ldc),以及各自的A,B和C矩阵的转置。

批量matmul计算,可以更具体地描述如下:

void BatchedGemm(input A, input B, output C, M, N, K, batch_dimension) {
  for (int i = 0; i < batch_dimension; ++i)  {
    DoGemm(A[i],B[i],C[i],M,K,N)
  }
}

批处理matmul形状

在语言翻译任务中,在其它工作负载中,批处理matmul的形状显着小于常规matmul计算。Transformer中的形状与输入语句的长度和解码器步长有关。通常小于30。

对于批处理尺寸,给定一定的推断批处理大小,这是一个固定的数字。例如,如果将16用作光束大小为4的批大小,则批大小为16 * 4 * #head(多头注意中的头数,通常为8)。矩阵M,K,N的形状,在[1,最大解码长度]或[1,最大编码长度]的范围内。

cuBLAS batch matmul的性能问题

首先,对批处理matmul内核进行了理论上的FLOP分析。结果非常有趣:所有批处理Matmul的计算强度都有限(少于1个TFLOP)。

然后,通过nvprof剖析了具有多种形状的matmul批处理cuBLAS性能。下表显示了在带有CUDA8.0的NVIDIA M40 GPU上获得的一些指标。

输入形状

[
批,MNK]

核心

理论FLOP

nvprof观察到的FLOP

理论FLOPs /

观察到的FLOPs

[512、17、17、128]

maxwell_sgemmBatched_128x128_raggedMn_tn

18939904

2155872256

0.87%

[512、1、17、128]

maxwell_sgemmBatched_128x128_raggedMn_tn

1114112

2155872256

0.052%

[512,17,1,128]

maxwell_sgemmBatched_128x128_raggedMn_tn

1114112

2155872256

0.052%

[512,30,30,128]

maxwell_sgemmBatched_128x128_raggedMn_tn

58982400

2155872256

2.74%

即使具有不同的形状(M,N,K不同),所有maxwell_sgemmBatched_128x128_raggedMn_tn调用,也执行相同数量的FLOP,这比理论值大得多。可以推断出,所有这些不同的形状都可以被填充成一定的形状。在所有这些形状中,即使在最佳情况下,理论上的FLOP仍然仅是实际执行的FLOP的2.74%,因此,大多数计算都是相当多余的。同样,另一个cuBLAS内核maxwell_sgemmBatched_64x64_raggedMn_tn的调用显示相同的现象。

显然,cuBLAS的批量matmul实施远非效率。因此,使用TVMNMT工作负载生成有效的批处理matmul内核。

批量matmul计算

在TVM中,一般的批量Matmul计算可以声明为:

# computation representation
A = tvm.placeholder((batch, M, K), name='A')
B = tvm.placeholder((batch, K, N), name='B')
k = tvm.reduce_axis((0, K), 'k')
C = tvm.compute((batch, M, N),
         lambda b, y, x: tvm.sum(A[b, y, k] * B[b, k, x], axis = k),
         name = 'C')

调度优化

在宣布计算之后,需要精心设计自己的调度表以压缩性能潜力。

块/线程数的调整参数

  # thread indices
  block_y = tvm.thread_axis("blockIdx.y")
  block_x = tvm.thread_axis("blockIdx.x")
  thread_y = tvm.thread_axis((0, num_thread_y), "threadIdx.y")
  thread_x = tvm.thread_axis((0, num_thread_x), "threadIdx.x")
  thread_yz = tvm.thread_axis((0, vthread_y), "vthread", name="vy")
  thread_xz = tvm.thread_axis((0, vthread_x), "vthread", name="vx")
 
  # block partitioning
  BB, FF, MM, PP = s[C].op.axis
  BBFF = s[C].fuse(BB, FF)
  MMPP = s[C].fuse(MM, PP)
  by, ty_block = s[C].split(BBFF, factor = num_thread_y * vthread_y)
  bx, tx_block = s[C].split(MMPP, factor = num_thread_x * vthread_x)
  s[C].bind(by, block_y)
  s[C].bind(bx, block_x)
  vty, ty = s[C].split(ty_block, nparts = vthread_y)
  vtx, tx = s[C].split(tx_block, nparts = vthread_x)
  s[C].reorder(by, bx, vty, vtx, ty, tx)
  s[C].reorder(by, bx, ty, tx)
  s[C].bind(ty, thread_y)
  s[C].bind(tx, thread_x)
  s[C].bind(vty, thread_yz)
  s[C].bind(vtx, thread_xz)

融合了批处理matmul的外部尺寸,即op尺寸的BB和FF,在批处理matmul计算中通常称为“批处理”尺寸。然后将外部和内部尺寸除以(number_thread * vthread)。

在批处理matmul中不需要交错模式,因此虚拟线程号(vthread_yvthread_x)都设置为1。

寻找number_thread的最佳组合

以下结果是在具有CUDA8.0的NVIDIA M40 GPU设备上获得的。

输入形状[批处理,特征,MNK]

num_thread_ynum_thread_x

num_vthread_ynum_vthread_x

时间(us

[64,8,1,17,128]

8,1

32,1

37.62

[64,8,1,17,128]

4,1

32,1

39.30

[64,8,1,17,128]

1,1

32,1

38.82

[64,8,1,17,128]

1,1

256,1

41.95

[64,8,1,17,128]

32,1

1,1

94.61

以往的经验了解到,该方法找到的最佳组合num_thread_ynum_thread_x通过强力搜索。经过蛮力搜索后,可以找到当前形状的最佳组合,在当前计算中为num_thread_y= 8和num_thread_x= 32。

将批处理matmul 与其它算子融合

通常,现有的“黑盒” cuBLAS库,调用扮演着通常使用的“ op Fusion”优化策略的边界的角色。但是,利用所生成的高效批处理matmul核,可以容易地打破融合边界,不仅可以融合元素的操作方式,还可以进一步提高性能。

从计算图可以看出,批处理matmul总是跟在添加操作或转置操作广播之后。通过将“ add”或“ transpose”操作与批处理matmul融合,可以减少内核启动开销和冗余内存访问时间。

批处理matmul和添加融合广播计算,可以声明如下:

# computation representation
A = tvm.placeholder((batch_size, features, M, K), name='A')
# the shape of B is (N, K) other than (K, N) is because B is transposed is this fusion pattern
B = tvm.placeholder((batch_size, features, N, K), name='B')
ENTER = tvm.placeholder((batch_size, 1, M, N), name = 'ENTER')
k = tvm.reduce_axis((0, K), 'k')
C = tvm.compute(
           (batch_size, features, M, N),
           lambda yb, yf, m, x: tvm.sum(A[yb, yf, m, k] * B[yb, yf, x, k], axis = k),
           name = 'C')
D = topi.broadcast_add(C, ENTER)

批处理matmul和转置融合计算可以声明为:

# computation representation
A = tvm.placeholder((batch_size, features, M, K), name='A')
B = tvm.placeholder((batch_size, features, K, N), name='B')
k = tvm.reduce_axis((0, K), 'k')
C = tvm.compute(
           (batch_size, M, features, N),
           lambda yb, m, yf, x: tvm.sum(A[yb, yf, m, k] * B[yb, yf, k, x], axis = k),
           name = 'C')

融合内核性能

选择[batch = 64,heads = 8,M = 1,N = 17,K = 128]的形状,详细说明所生成代码的性能。选择17作为序列长度,这是生产场景中的平均输入长度。

  • TF-R1.4 BatchMatmul:513.9
  • TF-R1.4 BatchMatmulTranspose(另购):541.9
  • TVM BatchMatmul:37.62美元
  • TVM BatchMatmulTranspose(融合):38.39美元

内核融合优化进一步提高了1.7倍的速度。

与Tensorflow集成

批量matmul在工作量中的输入形状是有限的,可以很容易地预先枚举。使用这些预定义的形状,可以提前生成高度优化的CUDA内核(固定形状计算可以带来最佳的优化潜力)。将生成适用于大多数形状的通用批处理matmul内核,为没有相应的提前生成的内核的形状提供回退机制。

针对特定形状生成的高效内核和后备内核已集成到Tensorflow框架中。开发了融合操作,例如BatchMatMulTranspose或BatchMatMulAdd,使用TVM的runtime API生成特定生成的内核,实现某些输入形状或调用后备内核。进行图形优化遍历,用算子融合自动替换原始批处理matmul +添加/转置模式。通过结合更积极的图形优化过程,试图利用TVM为长尾算子模式生成更有效的融合内核,以进一步提高端到端性能。

概括

在阿里巴巴内部,发现TVM是开发高性能GPU内核,满足内部需求的非常有效的工具。以NMT Transformer模型为例来说明使用TVM的优化策略。首先,通过第一性原理分析确定了Transformer模型的热点。然后使用TVM生成高度优化的CUDA内核来取代CUBLAS版本(13X加速观察)。接下来,利用TVM的内核融合机制融合批处理matmul的先前/以下操作,以进一步提高性能(进一步提高1.7倍的性能)。端到端性能提高了1.4。基于这些生成的内核,开发了图优化遍历以自动用TVM融合内核替换原始计算模式,确保优化对最终用户是透明的,作为AI基础设施提供商,发现优化策略的透明性对于推广其优化算法非常重要采用。最后,并非最不重要的一点是,所有这些优化都以松散耦合的方式集成到TensorFlow中,展示了将TVM与不同的深度学习框架集成的潜在方法。此外,正在进行一项将TVM集成为TensorFlow的代码源后端的工作,希望将来能与社区共享更多结果。

TVM优化GPU机器翻译的更多相关文章

  1. TensorFlow+TVM优化NMT神经机器翻译

    TensorFlow+TVM优化NMT神经机器翻译 背景 神经机器翻译(NMT)是一种自动化的端到端方法,具有克服传统基于短语的翻译系统中的弱点的潜力.本文为全球电子商务部署NMT服务. 目前,将Tr ...

  2. TVM 优化 ARM GPU 上的移动深度学习

    TVM 优化 ARM GPU 上的移动深度学习 随着深度学习的巨大成功,将深度神经网络部署到移动设备的需求正在迅速增长.与桌面平台上所做的类似,在移动设备中使用 GPU 既有利于推理速度,也有利于能源 ...

  3. TVM优化Deep Learning GPU算子

    TVM优化Deep Learning GPU算子 高效的深度学习算子是深度学习系统的核心.通常,这些算子很难优化,需要HPC专家付出巨大的努力. 端到端张量IR / DSL堆栈TVM使这一过程变得更加 ...

  4. unity优化-GPU(网上整理)

    优化-GPUGPU与CPU不同,所以侧重点自然也不一样.GPU的瓶颈主要存在在如下的方面: 填充率,可以简单的理解为图形处理单元每秒渲染的像素数量.像素的复杂度,比如动态阴影,光照,复杂的shader ...

  5. GPU 编程入门到精通(五)之 GPU 程序优化进阶

    博主因为工作其中的须要,開始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识.鉴于之前没有接触过 GPU 编程.因此在这里特地学习一下 GPU 上面的编程. 有志同道合的小伙 ...

  6. GPU 编程入门到精通(四)之 GPU 程序优化

    博主因为工作其中的须要,開始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识,鉴于之前没有接触过 GPU 编程.因此在这里特地学习一下 GPU 上面的编程.有志同道合的小伙伴 ...

  7. TVM:一个端到端的用于开发深度学习负载以适应多种硬件平台的IR栈

    TVM:一个端到端的用于开发深度学习负载以适应多种硬件平台的IR栈  本文对TVM的论文进行了翻译整理 深度学习如今无处不在且必不可少.这次创新部分得益于可扩展的深度学习系统,比如 TensorFlo ...

  8. TVM如何训练TinyML

    TVM如何训练TinyML 机器学习研究人员和从业人员对"裸机"(低功耗,通常没有操作系统)设备产生了广泛的兴趣.尽管专家已经有可能在某些裸机设备上运行某些模型,但是为各种设备优化 ...

  9. 桥接PyTorch和TVM

    桥接PyTorch和TVM 人工智能最引人入胜的一些应用是自然语言处理.像BERT或GPT-2之类的模型及其变体,可以获住足够多的文本信息. 这些模型属于称为Transformers的神经网络类体系结 ...

随机推荐

  1. 906. Super Palindromes

    Let's say a positive integer is a superpalindrome if it is a palindrome, and it is also the square o ...

  2. 10276 - Hanoi Tower Troubles Again!(思维,模拟)

    People stopped moving discs from peg to peg after they know the number of steps needed to complete t ...

  3. 1.8.7- HTML值label标签

    1.label直接进行包裹input就可以了.

  4. hdu4950 打怪(简单题目)

    题意:       打怪,一开始怪有h滴血,每回合可以让对方减少a滴血,每次打完之后怪会恢复b滴血,每连续k回合之后自己会休息一回合,这一回合怪物依然回血,问是否可以把怪打死. 思路:      比较 ...

  5. 浅谈Java中的公平锁和非公平锁,可重入锁,自旋锁

    公平锁和非公平锁 这里主要体现在ReentrantLock这个类里面了 公平锁.非公平锁的创建方式: //创建一个非公平锁,默认是非公平锁 Lock lock = new ReentrantLock( ...

  6. Raspberry PI 4B 安装和配置 Raspbian

    做记录,以备之后需要,待完成中 目录 做记录,以备之后需要,待完成中 下载镜像和安装程序 ssh 远程访问 下载镜像和安装程序 Raspbian: installer: ssh 远程访问 开启ssh ...

  7. 微服务架构开发电商系统需要用Redis、ES和MQ吗?

    如果不用什么很高大上的东西,就是有多个微服务就行这种技术架构会很难吗? 我看了一些视频,他们都用到了es.mq.redis的东西,我想不用这些东西,就简单的有多个服务,这样可行吗? 01 使用微服务你 ...

  8. vue中的nextTick

    ​ 今天在浏览elementUI官网时,又一次看到了nextTick,其实nextTIck我已经不是第一次看到了,但之前都没怎么弄懂,这次决定好好研究一番-- 异步说明 vue是异步执行DOM更新的. ...

  9. Git 系列教程(7)- 撤销操作

    撤销操作 在任何一个阶段,你都有可能想要撤销某些操作 有些撤销操作是不可逆的 --amend 修补提交 有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了. 此时,就可以运行带有 -- ...

  10. [网络编程之客户端/服务器架构,互联网通信协议,TCP协议]

    [网络编程之客户端/服务器架构,互联网通信协议,TCP协议] 引子 网络编程 客户端/服务器架构 互联网通信协议 互联网的本质就是一系列的网络协议 OSI七层协议 tcp/ip五层模型 客户端/服务器 ...