NV Ampere GPU架构学习与思考-阿里云开发者社区

开发者社区> 人工智能> 正文

NV Ampere GPU架构学习与思考

简介: 前言 这几天,GTC2020上,Nvidia发布了最新的Ampere架构。Ampere架构的改进重心,大部分放在AI上的改动,包括第三代的Tensor Core,以及相关的调度性能,以及互联等。它展示了在加强算力,特别是TC (TC == Tensor Core,下同)算力的情况下,整个系统的改进。 整体上,可以看到NV的GPU向向AI方向快速发展,看起来跟随市场的必然选择。转去吃AI芯片的蛋

前言

这几天,GTC2020上,Nvidia发布了最新的Ampere架构。Ampere架构的改进重心,大部分放在AI上的改动,包括第三代的Tensor Core,以及相关的调度性能,以及互联等。它展示了在加强算力,特别是TC (TC == Tensor Core,下同)算力的情况下,整个系统的改进。

整体上,可以看到NV的GPU向向AI方向快速发展,看起来跟随市场的必然选择。转去吃AI芯片的蛋糕。原CUDA Core并行度增加放缓,A100所有大的改动,看起来都是以AI计算为主要目的,所以Tensor Core以及SM里AI加速的模块和功能大大加强。在数据中心AI芯片这块,弯道超车时间快结束了。基本上大家都回到了vector+tensor混合架构上的直线竞争。

这样,GPGPU逐渐成为了通用和专用混合的架构形态

•Core 架构:CUDA vector core + Tensor core

•Memory system:传统的cache system + AI memory system

•Scale and connection:scale up + scale out in one GPU

•Program Model:original CUDA + WMMA

异构的难题在于利用率上:NV的一些提高效率的改变,包括

•资源动态分配,L1C, L2C, MIG

•软硬件结合

这样,软件栈任务更重了。

 

因为我一直在GPU/AI软件架构方面工作,我会比较多的从软硬件结合,编程模型,软件上层应用的角度出发来考虑问题。希望给大家不同的视野。

 

下面从几个方面来学习和思考:

  • 核心算力
    • A100如何大幅度提升算力?
  • 数据带宽
    • 如何解决算力高涨下的带宽问题?
  • 计算效率
    • 如何提高计算效率?

 

核心算力

A100的算力提升主要集中在AI应用需要的FP16精度以下的类型。

  • 传统FP32和FP64只有1.25x的增长。
  • FP16有了2.5x的增长 (both CUDA core and Tensor core)
  • 通过TF32的引入,让FP32(应用层)的数据处理大幅提升
  • 再通过Sparsity的优化,对TC的几个数据类型又double了算力

Tensor core精度

  • TF32 TC
    • FP16/FP32的混合精度训练问题比较多,使用很麻烦,给软件栈和框架都带来不小的难题。(大家可以看一下混合精度训练的实现和问题一些材料)
    • FP32 in/out的计算复杂,算力小
    • TF32 TC能很好的解决FP16/FP32的混合精度的问题,又能以较小的代价,获得比较好的精度。

Fine-grained structured sparsity

非常棒的一个“快速”解决方案。之前我们关于AI芯片加速sparsity的优化想法,都是局限在"被动"sparsity的方面,也就是上层应用和框架主动做剪枝以后,针对稀疏矩阵做被动的优化。难度很大。原因是各种剪枝出来的数据没有共同特性,因此硬件上很难实现通用的加速。

A100的方法,是主动(由软件)提供固定结构化的剪枝,对训练好后的Dense权重剪枝后,再稍做Fine-tuning,这样得到的稀疏矩阵可以直接使用针对这一特定结构的压缩,硬件加速推理。获得近乎两倍的性能提升。精度方面,50%的剪枝,应该能保证足够的精度。他们应该是论证过的。

截屏2020-05-17 下午5.56.00.png

整个方法是比较典型的软硬件结合的思路:

  • 软件提供包装好的4选2的剪枝方案,(软件实现,可升级算法,结合硬件)
  • 简单的Fine-tuning训练
  • 压缩剪枝后的weight,得到非零数据和Index,用于推理
  • 提升
    • 减少一半MMA计算
    • weight数据,从host->device就开始节省带宽
    • activation
      • 根据不同的实现,可以节省L1开始,或者L2开始的带宽

数据带宽

A100算力的暴涨,应该是让原来的存储系统,特别是SM内的存储设计跟不上了。

特别的是TF32 TC的引入,带宽需求和FP32一样,但是算力上大了好多。以Tensor Core FP16作为对比,同样使用Tensor Core,同样的操作(Ops/byte ratio),要保证相同的计算吞吐,需要的存储带宽大大地增长了。

  • V100,FP16,FLOPS=125T,input data type FP16
  • A100,TF32 TC,FLOPS=312T,input data type FP32,

因此,同样利用率的情况下,大概就需要5倍(312/125*2)的带宽了,在打开Sparsity的功能后,还需要更多的带宽,因为Sparse Matrix只压缩weight matrix。

作为对比基础,先给出Volta的存储体系:

截屏2020-05-17 上午10.30.15.png

数字上的增长

  • HBM2
    • 16GB to 40GB, achive 1.6TB/sec, 73% increase.
  • L2 cache
    • 6M L2 to 40MB, about 7x size, 2.3x read bandwidth with a new partitioned crossbar structure(没有细节,还不理解,后续继续学习)
  • L1 data cache and Shared memory
    • 128 KB to 196 KB1.5x larger

从数字上看,整个系统的吞吐/容量的纯增长,基本是在2倍左右,偏下。这些改进,相对CUDA core算力1.25x-2.5x的改进,其实是差不多足够了。但是,对于Tensor Core 5倍以上的需求增长,远远不够,所以需要其他架构的改进和新的特性来进一步支持算力。另外,为什么L2 cache急剧地增加到了40MB?

 

架构和特性的改进

思考

在理解这些改动之前,一定要充分地思考一下,AI特别是DNN的数据流特点,以及计算的特点。然后可以发现,主要的这些改进,都是充分考虑Tensor core的数据和计算特点,给Tensor Core做一些快速,简洁,或者并行性更高的通道。而且,有些改进能在其他芯片中看到类似的理念,但A100的选择和实现总是更通用,更“软”,更巧妙

 

我理解的数据特点:

  • activation只读,不会更改。流量大。
  • 权重复用度高,推理时const只读,训练时需要读和写。
  • AI数据里冗余数据多,本质上是稀疏的,特别是Relu之后activation,压缩权重,Embedding输入数据,broadcast数据等。

 

我理解的AI计算特点(暂时还没有统计数据来支持):

  • 一个网络模型由很多的小Kernel组成。
  • 单个Kernel宽而不深,也就是thread多,但kernel不长,指令数不多。
  • Tensor Core (MMA)和Compute core的并行优化可能比较难做(库与编译器)

 

看看A100的存储系统改进,我关注了以下这些:

  • 新的异步Copy指令,从global memory直接load到shared memory。
  • 超大L2C,partitioned,use it smarter。

 

  • 新的指令做L2 cache residency control。
  • Compute Data Compression: 4x DRAM and L2 bandwidth, 2x L2 capacity. (不同于Structured Sparsity)
  • Combined L1 data cache and shared memory (其实是Volta架构开始就有的)

 

A100-Memory.png

Asynchronous copy

我理解为这是专为DNN Kernel里的Input/Activation数据类似的数据流优化。

  • 因为这类数据,读自Global Memory,大都一次使用,不需要到RF,用完不需写回。因此没必要走复杂的L1/RF。而把RF/L1的带宽留给weigh和temp变量。
  • 另外,这是异步操作,和SM里其他操作可并发,从而可以隐藏较长的copy cycles。使用新的shared-memory-based barrier来做同步。
  • 同时,需要新的编程模型(CUDA)支持和编译器支持。

截屏2020-05-20 下午5.32.37.png

L2 cache residency control

首先,L2的设计很复杂,整理一下思路,根据新的特性出发来思考:

  • 大幅度增长的L2 size (40MB),
    • 首先,主要是为了大量的权重数据重用。
    • 其次,MIG architecture的引入,需要将L2分成最多7份,也需要更大的size
  • 大的L2,开始分区使用,类似于我们的LLC+L2的设计。
    • 分区以后,每个GPC直连L2了,带宽增加(细节不懂。。。)
    • 每个区应该也继续像以前一样分类,这样就是看,L2像是被做了两维的拆分,不知道这个是不是就是NV提到的new partitioned crossbar structure。
    • 但整个L2Cache仍然保持“Shared”属性,HW cache-coherence,以及CUDA编程模型。

 

AI应用中,L2C应该主要优化了权重的复用,根据模型的大小,可以有不同级别的重用粒度,这个思路和之前在V1.5里提到的根据权重大小不同而产生的不同工作模式

  • 权重全部在L2C,就像V1一样,整个模型权重只用装载一次到L2C。
  • 权重需要分段轮流装载L2C,
    • 装载一部分权重后,把相关的计算一个一个batch做完。然后换下一段权重,继续做。
    • 这个时候,多batch的工作模式比较有优势。能公用更多的权重。
    • 使用double buffer (ping-pong buffer)的模式,可以让计算和权重装载并行。

 

说到这里,大概就知道为什么需要L2 cache residency control。就是用来分段装载,实现ping-pong buffer的。

同样,也需要指令和CUDA编程模型的支持。

截屏2020-05-20 下午6.21.03.png

Compute Data Compression

注意这不是Structured Sparsity,而是针对unstructured sparsity and other compressible data patterns.

我知道我们也在看相关的技术。只是现在还不知道A100是怎么做的,但至少证明了这条路是可行的。需要大家一起持续关注。

截屏2020-05-20 下午6.20.16.png

 

Combined L1 cache and shared memory

从Volta架构开始,这个改变就发生了。理由看起来也比较充分:越来越多的计算场景,对Shared Memory和Cache的需求有很大不同。很难有一个固定比例能满足大部分的场景。所以可以配置的Shared Memory和L1C应该能比较方便而显著地提高性能。不需要为了固定的Shared Memory/L1C而绞尽脑汁地调整程序和调试性能。

之前的讨论中邹老师提到,做过一些实验发现差别不大。我有一些猜测,可能是实验面不够广,我们可以做进一步的实验:

  • 这个改变是在Volta架构里,随着Tensor core一起引入。TC计算里这种差别可能特别明显,比如
    • 做Matmul/Conv等使用TC的Kernel,通常是Shared Memory要的比较多(绝大部分),而cache用的很少
    • 如果是LSTM的复杂Kernel,则会对Cache要求比较多。
  • 越来越多的通用/AI计算场景,

整体而言,这个灵活性是有价值的。非常有利用调整和控制Kernel访存的性能和最终性能。

cache系统总结

首先是提供能力:BW/Capacity/利用率

  • 直接提高带宽
  • Capacity

不止单纯的大小,还包括动态分配等方式

  • DRAM BW

1.7x BW不足,通过6.7x L2 + Residency Control弥补

其次是减少需求:

  • Sparsity
  • Compression

 

截屏2020-05-20 下午8.53.44.png

计算效率

Task Graph Acceleration

这应该是对整体性能(整个模型甚至多个模型)非常意义的一个特性。针对的是“一个网络模型由很多的小Kernel组成”这个特征。

这个思路---把多个Tasks,memory copies(uploading/downloading)做成一个图(Graph,Directed Acyclic Graph),加上Dependency关系,以前都是在软件端实现的。比如:

  • GPU应用领域,多个draw batches,相互间或有复杂的dependency,为做到高效地并行,避免不必要的bubble,最好能做到out-of-order的执行。我知道的软件栈,做过相关的优化处理:UMD建立有dependency关系的DAG,KMD根据DAG,dependency信息,以及硬件的执行状态,动态的调度draw batches。
  • AI领域,DNN本身就是一个DAG。
    • 在NPU V1架构上,这个问题不明显但也存在。不明显的原因是大部分连续的可支持的算子被合并成了一个执行Engine。但遇到大的Engine需要拆分的时候,还是需要会有这个问题的,所以我们还是在软件栈实现了基于DAG的推理引擎。
    • 在GPGPU架构,加上训练功能,将会有很多很多小的Kernel了。因此特别需要这个优化。

因此存在CPU和GPU之间的来回调度。A100的创新是把这个移到了硬件上。去除了这个CPU-GPU调度代价。

 

CUDA Graph

CUDA 10开始支持的一个特性,是Task Graph Acceleration的基础。首先把多个Kernel一起提交(submit)到GPU。减少kernel提交和同步的时间。不过submit之后的kernel只能按照顺序执行。并行度比较差。

截屏2020-05-20 下午9.03.27.png

Task Graph Acceleration

Ampere架构支持以图的方式提交,并带有相互的依赖关系。因此GPU硬件可能更高效的调度kernel并行。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
人工智能
使用钉钉扫一扫加入圈子
+ 订阅

了解行业+人工智能最先进的技术和实践,参与行业+人工智能实践项目

其他文章