NVIDIA Tensor Core深度学习核心解析:全是干货
不久前,NVIDIA在SIGGRAPH 2018上正式发布了新一代GPU架构——Turing(图灵),黄仁勋称Turing架构是自2006年CUDA GPU发明以来最大的飞跃。
Turing架构的两大重要特性便是集成了用于光线追踪的RT Core以及用于AI计算的Tensor Core,使其成为了全球首款支持实时光线追踪的GPU。
不过说到AI计算,NVIDIA GPU成为最好的加速器早已是公认的事实,但将Tensor Core印上GPU名片的并不是这次的Turing,而是他的上任前辈——Volta。
基于Volta架构的Titan V是NVIDIA在计算领域成就的集大成者。深度学习和神经网络已成为NVIDIA GPU的背后驱动力,作为最先进的计算加速器,它集成了用于机器学习操作的内置硬件和软件加速,深度学习能力完全可以被当做Titan V和Volta的名片。
Titan V与初代基于开普勒的GeForce GTX Titan已经相去甚远,初代Titan的定位是一款万能显卡,既可作为游戏发烧友的旗舰游戏显卡,也为专业消费者提供全双精度浮点(FP64)计算能力。
在Titan V诞生之前,Titan产品线几乎都是基于这种设计方法,一颗巨大的GPU核心是NVIDIA“高大全”设计思路的最好代表。
而在Titan V上,NVIDIA再次扩展了大核心的上限。Volta最引人注目的则是其全新的专用处理模块——Tensor Core(张量计算核心),它与Volta的其他微架构改进,以及支持深度学习和高性能计算(HPC)的软件/框架集成在一起。
凭借面积达815mm?的巨大GV100核心,Titan这一产品线变得比以往任何时候都更接近工作站级,Titan V在拥有世界最强图形渲染性能的同时,深度学习和高性能计算方面的性能都有了极大的提升,当然它的价格也达到了工作站级的3000美元。
强化算力,重造Titan
除了深度学习和通用计算之外,Titan品牌的这次迭代还涉及到其他一些因素。 NVIDIA其实已经不太需要通过Titan系列为自己树立形象,最初的GTX Titan已经通过NVIDIA K20Xs为Oak Ridge国家实验室的Titan超级计算机提供计算力。况且,Titan系列在产品价格和性能方面也没有任何特别的竞争压力。
尽管Titan V的非ECC HBM2显存和GeForce驱动程序堆栈都更加面向消费者,但该卡仍可直接受益于框架和API的软件支持,这是NVIDIA深度学习开发整体工作的一部分。
鉴于单路Titan V并不会对服务器计算卡Quadro GV100产生什么影响,NVIDIA在Titan V上只砍掉了针对服务器多路互联设计的NVLink高速总线,而主要的计算能力(FP64/FP16/Tensor Core)都被完整保留。
与Pascal及更早期的产品均使用面向PC设计的GPU以及常规GDDR5(x)显存不同,NVIDIA这次选择了一颗规模巨大、产量和良品率都不高的服务器级芯片,有大量的晶体管被花费在了非图形功能上(即Tensor Core),这是NVIDIA在计算领域押下的赌注,NVIDIA已经不满足于只在传统图形计算卡和通用计算方面处于领先地位。
由于是首次分析GPU的深度学习性能,所以目前市面上还没有确定一套标准的基准测试,特别是对于Volta独特的张量内核和混合精度功能。对于Titan V,我们将使用百度DeepBench、NVIDIA的Caffe2 Docker、Stanford DAWNBench和HPE深度学习基准套件(DLBS)来测试。
但是在深入研究这些测试数据之前,雷锋网首先会就深度学习、GPU、Volta微架构以及深度学习性能基准进行一些背景介绍。
GPU与深度学习
首先要说明的是,虽然“机器学习”或更通用的“AI”有时可互换用于“深度学习”,但从技术上讲,它们各自指的是不同的东西,机器学习是AI的子集,深度学习则是机器学习的子集。
深度学习是因“深度神经网络”(Deep Neural Networks)而得名,其最终被设计为识别数据中的模式,产生相关预测,接收关于预测准确度的反馈,然后基于反馈进行自我调整。计算发生在“节点”上,“节点”被组织成“层”:原始输入数据首先由“输入层”处理,“输出层”推出代表模型预测的数据。两者之间的任何一层都被称为“隐藏层”,而“deep”则代表着深度神经网络有许多隐藏层。
这些隐藏层可以在不断增加的抽象层次上运行,使得它们甚至可以从复杂的输入数据中提取和区分非线性特征。一个标准的例子是图像识别,其中初始层寻找某些边缘或形状,这通知后面的层寻找鼻子和眼睛,之后的层可能寻找面部。最后的图层组合了所有这些数据以进行分类。
随着输入数据在模型中向前推进,计算包括特殊的内部参数(权重),最后会产生一个表示模型预测与正确值之间误差的损失函数。然后使用此错误信息反向运行模型以计算将改善模型预测的权重调整,该前向和后向传递(或反向传播)序列包括单个训练迭代。
为了进行推断,这个过程自然地排除了逆向传递,最终需要的计算强度比训练模型更小。从这个意义上说,推断也不太需要像FP32这样高的精度,并且可以对模型进行适当的修剪和优化,以便在特定的设备上部署。然而推断设备对延迟、成本和功耗变得更加敏感,尤其是在边缘计算的场景下。
卷积神经网络(CNN)和递归神经网络(RNN)是深度神经网络的两个重要子类型。卷积本身是一种操作,将输入数据和卷积核结合起来形成某种特征映射,转换或过滤原始数据以提取特征。
CNN通常是“前馈”的,因为数据在没有循环的情况下流过各层。而对于RNN(以及像LSTM和GRU这样的变体)来讲,每次计算后都会有一个单独的权重循环回自身,给网络一种“记忆”感,这让网络能够做出有时间意识的预测,在文本分析等场景中很有用。
由于深度学习数学可以归结为线性代数,因此某些操作可以重写为对GPU更友好的矩阵间乘法。当NVIDIA首次开发并公布cuDNN时,其中一个重要实现就是将算法降级为矩阵乘法以加速卷积。多年来cuDNN的发展包括“预先计算的隐式GEMM”卷积算法,它恰好是触发Tensor Core卷积加速的唯一算法。
NVIDIA GPU的优势
对于深度学习训练来说,GPU已经成为加速器的最佳选择。大多数计算本质上是并行的浮点计算,即大量的矩阵乘法,其最佳性能需要大量的内存带宽和大小,这些需求与HPC的需求非常一致,GPU正好可以提供高精度浮点计算、大量VRAM和并行计算能力,NVIDIA的CUDA可谓恰逢其时。
CUDA和NVIDIA的计算业务的发展与机器学习的研究进展相吻合,机器学习在2006年左右才重新成为“深度学习”。GPU加速神经网络模型相比CPU可提供数量级的加速,反过来又将深度学习重新推广到如今的流行词汇。与此同时,NVIDIA的图形竞争对手ATI在2006年被AMD收购;OpenCL 1.0在2009年才发布,同年AMD剥离了他们的GlobalFoundries晶圆厂。
随着DL的研究人员和学者们成功地使用CUDA来更快地训练神经网络模型,NVIDIA才发布了他们的cuDNN库的优化深度学习原语,其中有很多以HPC为中心的BLAS(基本线性代数子例程)和相应的cuBLAS先例,cuDNN将研究人员创建和优化CUDA代码以提高DL性能的需求抽象出来。至于AMD的同类产品MIOpen,去年才在ROCm保护伞下发布,目前也只在Caffe公开发布。
所以从这个意义上讲,尽管NVIDIA和AMD的底层硬件都适合DL加速,但NVIDIA GPU最终成为了深度学习的参考实现。
剖析Tensor Core
在关于Volta混合精度Tensor Core的几个谜团中,一个比较烦人的问题是4 x 4矩阵乘法的能力。Tensor Core是一种新型处理核心,它执行一种专门的矩阵数学运算,适用于深度学习和某些类型的HPC。Tensor Core执行融合乘法加法,其中两个4*4 FP16矩阵相乘,然后将结果添加到4*4 FP16或FP32矩阵中,最终输出新的4*4 FP16或FP32矩阵。
NVIDIA将Tensor Core进行的这种运算称为混合精度数学,因为输入矩阵的精度为半精度,但乘积可以达到完全精度。碰巧的是,Tensor Core所做的这种运算在深度学习训练和推理中很常见。
Tensor Core虽然在GPU里是全新的运算单元,但其实它与标准的ALU流水线并没有太大差别,只不过Tensor Core处理的是大型矩阵运算,而不是简单地单指令流多数据流标量运算。Tensor Core是灵活性和吞吐量权衡的选择,它在执行标量运算时的表现很糟糕,但它可以将更多的操作打包到同一个芯片区域。
Tensor Core虽然有一定的可编程性,但仍然停留在4*4矩阵乘法累加层面上,并且不清楚累积步骤是如何以及何时发生的。尽管被描述为进行4*4矩阵数学运算,但实际上Tensor Core运算似乎总是使用16*16矩阵,并且操作一次跨两个Tensor Core进行处理。这似乎与Volta架构中的其他变化有关,更具体地说,与这些Tensor Core是如何集成进SM中有关。
对于Volta架构,SM被划分为四个处理块或子核。对于每个子核,调度器每个时钟向本地分支单元(BRU)、Tensor Core阵列、数学分派单元或共享MIO单元发出一个warp指令,这就首先阻止了Tensor运算和其他数学运算同时进行。在利用两个Tensor Core时,warp调度器直接发出矩阵乘法运算,并且在从寄存器接收输入矩阵之后,执行4*4*4矩阵乘法。待完成矩阵乘法后,Tensor Core再将得到的矩阵写回寄存器。
在Tensor Core执行实际指令时,即使在使用NVVM IR(LLVM)的编译器级别上,也仅存在用于warp级矩阵操作的本征,对于CUDA++和PTX ISA,warp级别仍然是唯一级别。加载输入矩阵的形式是每个扭曲线程持有一个片段,其分布和身份均未指定。从广义上讲,它遵循标准CUDA核心的基于线程级别拼接的GEMM计算的相同模式。
一般而言,给定A*B+C Tensor Core操作,片段由A的8个FP16*2元素(即16个FP16元素)和B的另外8个FP16*2元素,以及FP16累加器的4个FP16*2元素或 FP32累加器的8个FP32元素组成。
在矩阵乘法累加运算之后,计算结果会分散在每个线程的目标寄存器片段中,需要在整个范围内统一,如果其中一个warp线程退出,这些低级操作基本上就会失败。
Citadel LLC团队的低级微基准测试揭示了许多Volta微体系结构细节,包括Tensor Core操作和相关的片段,与输入矩阵相比,它们都位于寄存器和标识中。他们观察到,子核核心以特定的拼接模式计算矩阵乘法,其中所有32个warp线程都在运行。
从概念上讲,Tensor Core在4*4子矩阵上运行,以计算更大的16*16矩阵。warp线程被分成8组,每组4个线程,每个线程组连续计算一个8*4块,总共要经过4组的过程,每一个线程组都处理了目标矩阵的1/8。
在一个集合中,可以并行完成四个HMMA步骤,每个步骤适用于4*2子块。这四个线程直接链接到寄存器中的那些矩阵值,因此线程组可以处理单个Step 0 HMMA指令,从而一次性计算子块。
由于矩阵乘法在数学上需要对某些行列进行复用,以允许跨所有8*4块并行执行,每个4*4矩阵被映射到两个线程的寄存器。在计算16*16父矩阵的4*4次子矩阵运算中,这将包括将连续计算的集合相加,形成16*16矩阵中4*8个元素的相应块。尽管Citadel没有对FP16进行测试,但它们发现FP16 HMMA指令只产生2个步骤,而不是4个步骤,这或许与FP16只占用的较小的寄存器空间有关。
通过独立的线程调度和执行,以及warp同步和warp-wide结果分配,基本的4*4*4 Tensor Core操作转换为半可编程16*16*16混合精度矩阵乘法累加。虽然CUDA 9.1支持32*8*16 and 8*32*16矩阵,但相乘的矩阵都需要相应的列和行为16,最终矩阵为32*8或8*32。
Tensor Core的运行方式似乎是NVIDIA GEMM计算层次结构的一个硬件实现的步骤,如CUTLASS(用于GEMM操作的CUDA C ++模板库)中所示。对于传统的CUDA核心,最后一步需要将warp tile结构分解为由各个线程拥有的标量和向量元素。使用WMMA API(现在表示张量核),所有这些都被抽象掉了,只剩下了需要处理的合作矩阵片段加载/存储和多重积累。积累发生在一个FMA类型的操作中。
在寄存器级别上,NVIDIA在他们的Hot Chips 2017论文中提到“使用三个相对较小的乘法和累加器数据的4*4矩阵,可以执行64次乘加运算。”而增强的Volta SIMT模型的每线程程序计数器(能够支持张量核)通常需要每个线程2个寄存器槽。HMMA指令本身会尽可能多复用寄存器,所以我无法想象寄存器在大多数情况下不会出现瓶颈。
对于独立的4*4矩阵乘法累加,Tensor Core阵列在寄存器、数据路径和调度方面很有核能并没有物理设计,它只能用于特定的子矩阵乘法。
无论如何,从NVIDIA的角度来看,Volta不是一颗深度学习的专用ASIC,它仍然覆盖GPGPU的领域,因此保持CUDA可编程Tensor Core适用于GEMM / cuBLAS和HPC是合乎逻辑的。对于CUDA c++的CUTLASS来说,情况更是如此,因为它的WMMA API支持旨在为广泛的应用程序启用Tensor CoreGEMM操作。从根本上说,NVIDIA深度学习硬件加速的发展与cuDNN(以及cuBLAS)的发展有很大关系。
让FP16适用于深度学习
Volta的深度学习能力是建立在利用半精度浮点(IEEE-754 FP16)而非单精度浮点(FP32)进行深度学习训练的基础之上。
该能力首先由cuDNN 3支持并在Tegra X1的Maxwell架构中实现,随后原生半精度计算被引入Pascal架构并被称为“伪FP16”,即使用FP32 ALUs处理成对的FP16指令,理论上可以使每个时钟的FP16吞吐量增加一倍。这一特性实际上已经在Tensor Core处理寄存器中矩阵片段的过程中得到体现,其两个FP16输入矩阵被收集在8个FP16*2或16个FP16元素中。
就FP32与FP16而言,由于单精度浮点所包含的数据多于半精度浮点,因此计算量更大,需要更多的内存容量和带宽来容纳和传输数据,并带来更大的功耗。因此,在计算中成功使用低精度数据一直是穷人的圣杯,而目标则是那些不需要高精度数据的应用程序。
除了API/编译器/框架的支持之外,深度学习一直都有在使用FP16数据类型时损失精度的问题,这会让训练过程不够准确,模型无法收敛。
据雷锋网了解,NVIDIA以前也曾在类似的情况下推出过“混合精度”这一概念,在Pascal的快速FP16(针对GP100)和DP4A/DP2A的整数点积操作(针对GP102、GP104和GP106 GPU)中,就曾提出过类似的说法。
当时人们关注的是推理能力,就像Titan V的“深度学习TFLOPS”一样,Titan X(Pascal)推出了“44 TOPS(新型深度学习推断指令)”。新的指令对4元8位向量或2元8位/16位向量执行整数点积,从而得到一个32位整数积,可以与其他32位整数一起累积。
对于Volta的混合精度而言,重要的精度敏感数据(如主权重)仍然会存储为FP32;而Tensor Core的混合精度训练则会将两个半精度输入矩阵相乘得到一个精度乘积,然后累积成一个精度和。NVIDIA表示,在将结果写入内存之前,Tensor Core会将结果转换回半精度,这样当使用半精度格式时,寄存器和存储器中需要的数据更少,这有助于处理超大矩阵中的数据。
FP16与FP32所包含的数据空间并不相同,归一化方法可以解决FP32格式数据超出FP16可表示范围的问题。举个例子,许多激活梯度的值都落在FP16的范围之外,但由于这些值聚集在一起,因此将损耗乘以缩放因子便可以移动FP16范围内的大部分值。在完成最终的权重更新之前,将梯度重新缩放到原始范围,便可以维持其原始的精度。
不过,并非所有的数学、神经网络和层都适用于FP16,通常FP16和Tensor Core的混合精度最适合卷积和RNN重图像处理等,而对于不适合的神经网络框架或类型,FP16将默认禁用或不推荐使用。
内存改进,SM变化
使用Tensor Core处理混合精度数据似乎可以减轻内存带宽问题,但事实证明,尽管Volta在几乎所有方面都得到了内存子系统的增强,但幅度并不明显。
首先,Volta有一个12 KB的L0指令缓存,虽然Pascal及其他之前的GPU核心也有指令缓存,但Volta更高效的L0是子核心SM分区私有的,因此它对warp调度器来说也是私有的,这对Volta架构更大的指令大小是一种补偿,并有可能为支持Tensor Core通道的框架做出贡献。同时Volta指令延迟也要低于Pascal,特别是核心FMAs从6个周期减少到了4个周期。
随着每个SM中调度器比例的增加,砍掉第二个调度端口似乎是对具有独立数据路径和数学调度单元的子核心的权衡。而具备FP32/INT32执行能力,也为其他低精度/混合精度模型打开了大门。这些子核方面的增强,都是为了优化Tensor Core阵列。
另一个重大变化是合并L1缓存和共享内存。在同一个块中,共享内存可配置为每SM 最高96 KB。HBM2控制器也进行了更新,其效率提高了10~15%。
深度学习基准测试
深度学习从框架到模型,再到API和库,AI硬件的许多部分都是高度定制化的,这样的新领域有时会让人非常难以理解。
俗话说“光说不练假把式”,实践永远是检验真理的唯一标准。对计算机来说,介绍的再详细也不如真刀真枪跑一下测试,没有什么比benchmark更能提现硬件的实际表现了。
随着ImageNet和一些衍生模型(AlexNet、VGGNet、Inception、Resnet等)的影响,ILSVRC2012(ImageNet大规模视觉识别挑战)中的图像数据集训练逐渐被行业所认可。
现在基本上所有深度学习框架都支持CUDA和cuDNN,对于Volta而言,支持FP16存储的框架也都支持Tensor Core加速,启用FP16存储后Tensor Core加速会自动启用。
- 半导体行业观察
- 摩尔芯闻
最新新闻
热门文章 本日 七天 本月
- 1 两万字解读射频前端,国产现状如何?
- 2 摩尔斯微电子推出突破性物联网连接平台 新型 MM6108-EKH05 评估套件助力开发人员创建下一代物联网解决方案
- 3 共筑国产汽车芯片未来,中国汽车芯片联盟全体大会即将开启
- 4 数字疗法加脑机接口,赋能儿童多动症干预