前言
笔者从GPU行业转行,加入AI芯片软件团队正好一年时间。参与了Alibaba NPU(含光800)的架构,软件建模,芯片驱动,框架等多方面的工作。在一年到来之际,特别想针对自己过去一年的工作和学习写一些“思想总结”。正好我们在准备云栖大会的材料,学习了竞争对手的相关文档,萌生了利用一些夜深人静的晚上,写写一些体会。因为相关工作学习时间短,写的这些东西大都很浅显,对内行来说不值一提。文章的价值在于从一个比较全面的角度来分析推理芯片的整个系统,因为笔者先后接触硬件架构,软件栈,以及深度学习框架等,习惯于系统化思考。借此希望能给软件部门,硬件部门,或者研究部门的同事,在某一个不熟悉的方面提供一点有用的信息。
后续,笔者会继续对Goya和含光800做些比较,讨论一些各自的优缺点,以及我们如何从软硬件方面借鉴一些竞争者的好的设计。这就是研究对手的目的:他山之石,可以攻玉!
在开始之前,推广一下我们的含光800:
为什么是Habana Labs?
Habana Labs是一家以色列人工智能芯片新创公司。公司的相关产品在市场上竞争力强,在业界地位上升迅速。去年宣布推出全球性能最高的人工智能推理处理器,并获得了Intel投资领投的融资。今年发布了性能为当前在训练神经网络任务中最为强大的英伟达Tesla V100近四倍的训练芯片。
Habana Labs的产品(Goya),产品路线图(先推理再训练),以及性能表现和我们的定位比较接近。产品是一种采用 PCIe接口的计算卡,面向云端高性能的AI芯片。(为了更高的执行效率,Habana特意为训练和推理工作)
不像TPU是google自用,Habana是对外部客户的,所以产品公开,容易看到更多的资料。在学习相关文档的时候,我发现他们的设计里有些思路比较值得我们学习,包括硬件架构的设计,以及软件栈架构的设计。所以特做一些深度阅读和总结,以助于我们未来的开发。
本文的主要从系统的角度来解读Goya的一些我能看到的比较有价值的特性。这个系统既包括硬件也包括软件系统。在后续文章中会一一解析为什么关注这些特性。
引用于Goya白皮书:
“Habana’s Goya is a product line of AI processors dedicated to inference workloads. The HL-1000 processor is the first commercially available, deep learning inference processor, designed specifically to deliver superior performance, power efficiency and cost savings for cloud, data centers and other emerging applications.”
Goya硬件特性简析
Goya有两种类型的计算引擎:GEMM(GEneral Matrix to Matrix Multiplication)核心和TPC(Tensor Processing Core)核心。前者以矩阵计算(convolution/matmul)为主要目标,执行密集线性代数计算;而后者执行更一般性向量(vector)计算,可以让Goya支持不同神经网络的结构,处理不同的数据类型。避免一些不能使用TPC加速的算子严重影响网络的整体性能。从这点来说,这个架构和一些的架构比较类似。
- VTA(Vanilla Tensor Accelerator): GEMM核心 + Tensor ALU
- DaVinci: Cube核心 + Vector核心
另外,Goya有一个DMA引擎,用于片上共享存储和外部存储之间的DMA传输。三种引擎是独立并行的。
GEMM加速器
GEMM加速器的主要目的是执行数据密集矩阵运算。加入这样一个加速器的动机,扬清的论文里面有张图说得比较清楚。
Nvidia的相关产品中,比如V100,是由Tensor Core提供4x4矩阵乘加。而NVDLA架构中,是有独立的卷积的核心(Convolution Core)。
DaVinci核心里,Cube的能做4096次FP16MACs和8192次INT8MACs.
一些比较重要的信息,在公开的文档中没有提到,比如:
- GEMM和TPC的联系
-
- 为何设计为一对多,而且GEMM显得相对TPC来说小很多
- 核心之间的同步等
- GEMM怎么和Local Memory连接?
TPC核心主要特性
TPC核心的微架构设计,是整个人工智能芯片的计算部分的一个难点。主要的难点在于“平衡”:功能的支持,性能的高低,功耗和面积的开销,如何做到平衡。
Habana的设计,提到了下面几个特点:
可扩缩TPC数目
Habana特别强调实际的TPC的数目是可以根据需求来调整的。可以理解为针对不同的应用场景,调整TPC数目来做一定程度的定制,提高芯片利用率,因为看起来GEMM核心是不可调整的。比如应用在图像方面的芯片,卷积的比例很高,相对配TPC的数量可以少一些。而语音方面的专用芯片相反,可以配更多的TPC来提高整体效能。
仍然以NV Volta架构为对比,每个SM中的Sub-Core里包含两个4x4x4Tensor Core。应该是不可以调整的。这种设置是可以理解的,因为GPU是通用的架构,深度网络只是其中的一部分应用。
VLIW SIMD向量处理器
自然的选择:向量体系结构+简单的指令集设计+SIMD+VLIW
当前AI芯片的使用场景,是大量的向量计算,而在计算过程中,很少有跳转控制操作。因此,比较适合采用VLIW设计多发射处理器。这种设计放弃了指令控制的灵活性,将很多的工作放到软件,依赖于编译器以及驱动程序完成,从而大大地降低了硬件实现的复杂度。
SIMD, 单指令多数据,也是AI专用芯片的一个自然选择,达到数据并行的目的。具体的数据并行方式没有相关材料。
类C可编程
类C可编程是一个比较模糊的说法。没有看到具体的指令,很难说清楚可编程的程度怎么样。不过从后面的一些介绍看得出来,Goya的指令应该是中等级别的粒度。能做到比较好的可编程程度。
AI特殊功能模块(Special Function)
几乎所有的AI专用芯片都用或多或少的AI特殊功能模块,用以支持高效地支持一些比较常用的,但又比较特殊的算法,比如,公开的文档中,Goya提到了Sigmoid/GeLU, Tanh;而DaVinci提到了Activations, NMS, ROI, SORT。
具体选择支持哪些特殊功能和哪些功能使用专用模块支持,取决于比较多的因素,包括芯片的主打业务,主推通用性还是高性能。
混合精度数据类型
现有的DNN算法,不同的网络模型对精度有不同的要求。另外,在不同的应用场景中,用户也会对精度和性能做不同的要求。比如,有时对延迟的要求很高,用户愿意牺牲一点点精度来达到更低的延迟,比如一些实时的AI服务。而有些场景,用户会更在乎精度。
为了满足这种需求,不论是AI的Goya,DaVinci核心,还是主流GPU,都支持多种混合精度的计算。当然不论是在硬件实现上和软件使用上,都是各有区别的。
Goya的TPC硬件原生支持的是混合精度的数据类型,包括FP32/INT32/INT16/INT8/UINT32/UINT16/UINT8。
大致看得出,TPC虽然支持混合精度,但不是所有计算都支持上面所有的精度。也就是说,特定算子支持的数据类型的种数和精度是不定的,而是可以根据实际情况来决定的,特别是SPF模块的算子。比如,有些算子可能支持精度比较低的8bit+16bit数据类型就可以了,有些需要16Bit+32bit的数据类型。精度的选择,也是算法准确性,性能,功率,面积等多方面的平衡。
存储系统
AI是数据密集型计算,除了计算本身,存储系统的设计也是非常的重要。存储系统需要设计与并行计算相匹配的带宽,同时,特别地针对推理应用,也需要考虑延迟。
Goya采用了三级存储系统:包括TPC本地存储,核间共享SRAM存储,以及DDR4。如果再加上DMA访问系统内存,可以认为整个存储系统有4级层次架构。Habana的训练芯片使用了HBM代替了DDR4。整个存储系统的分层设计,和当前GPU的存储层次比较类似。多层次的存储分层设计,是要在存储的大小,面积,带宽和延时等各方面能到达一个微妙的平衡。复杂的分层设计,不仅提高了硬件的复杂度,而且还非常依赖于软件对存储数据的管理和优化,包括数据在各个层次之间的传输和同步等,才能充分利用存储,达到最好的带宽和最低的延时。
从更专用的角度来说,用于推理的芯片存储系统应该不需要太过于复杂的存储分层。因为推理的整个数据流相对简单。Habana应该是考虑设计一个通用的存储系统给训练和推理使用。
Habana在文档中强调了Goya设计中的低延迟的特性。这是相对GPU一个比较明显的优势。这其实是AI专用芯片相对GPU的一个优势,因为深度神经网络算法中,数据的使用相对简单,更有规律,重复少,因此专用芯片不用设计复杂的cache/coherence机制,不用分专用类型存储(纹理,常量等)。
SynapseAI特性简析
推理平台
Habana推理平台的设计,还是没有摆脱Nvidia推理平台TensorRT的影响。整个设计有很多相似之处。其实可以理解,TensorRT在NV的CUDA等其他软件系统的帮助下,成为一个比较常用的推理平台,也已经考虑到了大部分的推理需求。Habana强调了SynapseAI的一些特点:
- 支持框架/模型格式多,
- 训练平台无关(Training-platform-agnostic),即其他任何平台训练的网络模型都可以使用
- 首先把训练好的模型转成自己的中间表达(Internal Representation)
- 然后使用AOT编译,优化模型,生成模型的工作计划 (Recipe)
灵活的模型装载方式
SynapseAI提供了两种装载模型的方式,和TensorRT类似,既可以使用Parser载入一个完整的模型文件,也可以使用它提供的Layer API逐层添加生成模型。
SynapseAI的两种API:
- Python API:载入一个支持框架(Tensorflow, MxNet, etc.)模型格式的模型文件,或者使用ONNX
- C API:一层一层的描述一个深度学习网络
后者存在的好处是,当你在一个它不支持的平台上训练生成模型之后,你不用想办法把模型转成某一种支持的模型,而可以使用Layer API转成SynapseAI的IR。这样的优势在于可以跳过一次转换,以及和其他框架的依赖,得到比较靠近SynapseAI IR的模型表达。
另外一个特点,SynapseAI也允许用户自定义的网络层,插入到模型中,这样为Goya不支持的算子提供在其他平台上的实现的解决方案。可以以Hybrid的方式,提高整个模型,以及整个系统的性能。
支持多领域网络模型
Habana特别强调Goya的设计不是局限在Resnet等CNN网络,而是一个支持多领域网络模型的相对通用的AI推理芯片。
- Vision - object detection, classfication, segmenation, etc
- NLP - Neural Machine Translation, text classification,
- Speech - recognition, synthesis
这既是硬件的特性,需要比较通用的计算核心,当然也更离不开软件的支持。这么多的框架模型和算子支持,需要好的软件栈框架来支持。这一块暂时不展开详细讨论。
量化和编译
推理和训练在精度要求上不同,当前主流的网络模型,大都不需要Float32的精度来做推理。比如,CNN类型的网络,使用INT8能达到比较好的精度了。因此量化通常是做网络推理的第一步。
其次,为了更高效的运行推理,不同于训练框架的单算子调度执行,推理应用使用AOT(Ahead-of-Time)的方式,把整个模型输入预先编译好,生成working plan,序列化后给推理运行。
性能和精度可调节的自动量化
SynapseAI称支持对浮点精度的模型提供接近0精度损失的自动量化。他提供自动量化的方式和NV TensorRT不大一样。他不是由用户直接指定莫一个数据类型或精度。
Habana通过SynapseAI提供的使用方式是:用户可以指定需要的性能增长的等级,以及是否可以接受牺牲部分精度来提高性能,然后根据相关输入,包括模型和模型输入,SynapseAI应该能自动地进行
- 量化算法的选择,
- 网络中各级计算量化精度的选择,
- 评估精度和性能,
直到做出一个他认为最符合要求的量化结果。用户觉得不满意的话,当然可以继续调整等级参数,寻找有没有更合适的量化结果。
支持GLOW编译器,开源Habana-Glow
编译器技术是深度学习框架里一个比较重要,也比较热门的技术。各家框架都在尝试引入一些新的技术,打造新的编译器:Mxnet,陈天奇团队推出了TVM+NNVM,作为“深度学习到各种硬件的完整优化工具链”,其中,NNVM编译器是一个基于TVM工具链的编译器。Tensorflow,先使用XLA技术优化框架编译,接着尝试通过MLIR来打造通用的中间语言,连接底层编译器,虽然不是直接的开发编译器,但主要目的也是优化编译,加快深度学习网络的运行。而Facebook的Pytorch,主推的基于LLVM的GLOW编译器及执行引擎,等到了其他的一些公司的支持,其中包括Habana。
需要注意的是,同是编译器,框架和芯片的角度其实是不一样的。框架在上层,框架的角色是连接上层应用和底层各种硬件,它看重的是如何方便而高效地连接底层编译器,选择合适硬件达到最好的性能。而芯片在底层,作为一种硬件,它的角色是应用在多个不同的框架里,提供方便的连接和优异地性能。
Habana积极地参与GLOW编译器的支持,宣称Goya(HL-100)是第一个整合到GLOW的AI处理器。同时,其Habana-Glow整合部分已经开源了。
在其内部底层,Habana编译器使用的应该还是基于LLVM的后端编译器。
看得出来,Habana希望透过这一系列支持把自己的AI生态做好做大,扩大自己的影响力。
工具
SynapseAI还包括一系列的软件开发工具,看起来比较完善:
- TPC tool
-
- Compiler
- Assembler
- IDE: debugger / simulator
- Performance profiling tool
-
- Performance Analysis
- Graphical views
- Real time
- Performance library: Deep learning operators
- On-borad processor software: Debugger
性能分析
性能本身,是多个参数的相互制约和最终体现,而不仅仅是FPS,or QPS。还包括其他的一些参数:
- 延迟
- 能效 (桢/秒/瓦)
- 面积能效(PPA)
低延迟
推理的应用场景中,有越来越多的AI驱动的实时服务,比如NMT(Neural Machine Translation),虚拟助理等,因此,低延迟成了一个关键的因素。例如,在针对数据中心和边缘推理工作的MLPerf基准测试中,延时成为了一个重要的指标。
延迟是一个综合的系统指标,低延迟的实现,首先依赖芯片架构的支持,比如
- 算力
- 存储吞吐,Goya架构中,应该有较大的本地存储(Local Memory)和共享存储(Shared Memory)。
其次,低延迟更依赖于软件的配合和优化,后面的很多软件特性其实都对低延迟做出了贡献。比如,轻量级的推理平台,CPU和AI芯片的合作和同步,Host和AI芯片间的数据传输,等。
小批量时保持高吞吐
为了最小化网络的端到端响应时间,推理相比于训练通常需要更小的批量大小。
特别是一些推理应用特别是在线引用,对小批量的性能要求也比较高。低延时的另一个关键,也在于在小批量的时候也能有高的利用率,从而保持高吞吐,缩短运行时间。影响这一部分的因素,在于TPC核心的并行设计:并行需要在不同的维度上都能实现:
- 每个核心处理不同的一个batch(简单,不用核间协同,也容易核间到达负载平衡)
- 所有核心处理同一个batch,每个核心处理其中的一部分 (小批量的时候能调度更多的核)
- 鉴于两者中间的多核心处理多batch
不同的并行模式有不同的优势,因此灵活地支持多种模式,在不同模式上做到可以切换,这样可以保证芯片在小批量的时候也能保持较高的吞吐,这可能是Habana特意强调的SynapseAI一个特点。
软件管理片上存储及DMA
不论是哪一种性能参数,存储管理都是非常重要的因数。因为深度学习的网络计算是大数据的计算,涉及到大量数据的传输和存储。
比如上面提到的多层存储系统,需要软件保证整个数据流的通畅:Client-->Host-->Shared Memory-->Local Memory的装载过程,以及相反的下载过程,如何与计算做到尽可能多的并行。从这个角度来说,层次的越多,对软件的要求越高。Habana特别提到了软件管理片上存储和DMA等存储管理,也是强调
性能参数
ResNet 50:
- ~15000 图/秒,大概3倍于T4
- 延迟大概在1毫秒
- 149 图/秒/瓦
BERT
- Goya支持所有BERT算子
- GEMM和TPC充分使用
- 硬件加速非线性函数
- 精度:INT16+FP32
- 延迟大概是T4的一半
综合来说,Goya以ResNet等CNN网络的矢量加速为第一目的,同时考虑了向量加速,在BERT等应用下保证GEMM和TPC都能充分使用。
综合思考
Goya整体看起来是一个不错的推理芯片,性能良好,网络模型覆盖广,在同性能和通用方面做的比较“平衡”。
很多时候,系统设计都是在做“选择”!我用了“选择”这个词,而不是“平衡”,是因为它们之间有细微的差别:我们的选择一定是“平衡”吗?这背后的隐藏了一些什么“玄学”呢?
其实“平衡”本身也是相对的,与产品和系统的定位,这本身就是一种选择。比如:
- Nvidia的芯片,更多地定位成:适合深度学习计算的通用计算(GPGPU),同时兼顾训练和推理。
- Da Vinci架构,针对AI运算特征而设计,以高性能3D Cube计算引擎为基础,集成张量,矢量,标量多种计算单元,同时覆盖训练和推理需求。
- Goya:作为其第一代纯推理芯片,集成张量,矢量,还多一个AI固定功能pipe。主打覆盖当前主流深度网络的推理运算下的专用高性能芯片。
所以可以看到,几个产品的架构设计有不小的区别。
关于两种计算引擎
除去标量计算,向量(2D)和张量(主要是3D)的计算是AI芯片的两大主力计算引擎。AI专用芯片之所以在AI计算方面快于GPU,主要在于其专用的AI核心。画一个简单的示意图:
但AI网络模型中,还是有一部分vector计算,为了照顾到这一部分,通常需要设计VPU(vector process unit)。但关键的问题来了,两种引擎之间显然不是一种固定的比例关系,那应该怎么设计这种搭配呢?
Goya文档里提到,TPC数目是可调整的,但不知道GEMM会不会随着变化。DoVinci的配比看来在特定core version上是固定的,Davinci Max/Lite都是32:1,Davinci Tiny是16:1,但他也提到仔细地分配了Cube和Vector的MAC数目,以及它的数据依据。
一个我的想法是:可以把这种配比设计成动态可调整的吗?让软件/编译器来根据计算量做一些微调。
如果是固定的配比,是否需要分析大量目标算法,得到模型里的Tensor/Vector计算量比,然后分别给这些算法一定的权重,得到一个比较优化的配比?
关于可编程和固定功能模块
我们当然希望上面的两种可编程引擎能覆盖所有的计算。但实际上有些计算很不适合上面两种引擎,这时候,固定功能模块用来做相关运算,保证这些计算不会成为瓶颈。所以现在看几乎所有的AI芯片都有或多或少的固定模块。
但哪些计算应该设计为固定功能模块呢?这是应该大都是随着优化目标算法来决定的。提前做好调研,了解AI算法应用和研究各方面的趋势,可以让芯片做得更有的放矢,精准高效。
关于混合精度
算法的多样性,让混合精度成为必备。但混合精度增加了算法复杂度,功耗和面积。另外,纯推理的芯片和同时支持推理/训练的芯片也有不同的精度需求,后者要求更高。
如何寻找“刚刚好”的精度支持,也是一个需要仔细斟酌的地方。有些算法团队在GPU上做过量化和混合精度的优化工作,这些结论应该可以帮助我们,还有一些数据可能通过公开的一些工作,论文获得,可能还需要我们自己也做一些尝试。最后根据相关数据,需要在功耗面积和计算精度方面做一些选择。
关于存储系统
存储系统的设计是吞吐和延时的关键。它本身就是一个非常复杂的系统,光从最大的设计考虑,就涉及到但不限于一些系列的考量:
- 存储级数选择 (memory hierarchy)
- 各级大小
- 细分各种用途cache,buffer的个数和大小,连接关系
- 是否需要tiling,如何tiling
- 是否需要考虑一致性(coherence)
- 对软件编译器的影响,以及如何协同工作
- 对软件驱动的影响,以及如何保证数据流化(data streaming)
- ...
专用(Domain Specific)芯片可能需要摆脱传统的束缚。因为应用场景毕竟相对比较少,可以更优化。
关于吞吐和延时
大多数的设计因素里,吞吐和延时是一致的,没有冲突:高吞吐意味着低延时。少数时候两者之间需要选择一下。这方面,Goya是推理专用,所以做得比较多一点。而Dovinci似乎考虑延时相对少些,因为吞吐显得更重要。
关于框架和API
回到软件,Habana并没有推出自己的深度学习框架,甚至没有自己的推理引擎。而是只是通过一系列API,支持其它的主流框架,包括GLOW推理执行引擎等来使用自己的芯片。这和它对独立芯片公司的定位(IHV)相对应的。它的目的是支持主流生态,而不是改变上层生态。
但不得不说,Habana的软件系统做的不错。API接口设计比较合适,工具够用,算法库支持相对少,虽然总体相比NV远远不足,但相对国内企业来说,还是不错的。有一些值得借鉴之处。具体会在后续的一些地方继续讨论。
关于编译器
AI编译器群雄逐鹿时代,现在看来,还很难在出现一个新的"LLVM"一统江湖。各家编译软件栈的差异,给我们芯片软件栈提供了难度和工作量。可以看到Habana和华为都在尝试一些新的先进的编译器技术。
AI编译是一个多层次的过程,一个重要的考虑是如何把软件栈做得兼容和可持续:
- 前端,如何支持多框架/多模型IR,
- 独立图层,与前端无关,同时更是与硬件架构无关
- 计算层(Low level Intrinsic Op/C)
- ISA level
层间的功能分工,接口设计需要清晰,这样,我们在扩张支持更多的前端,或者更多的硬件架构/ISA指令集的时候,对现有架构的冲击会比较小。
关于软件和硬件
最后,回到起点,“软硬协同”是芯片系统的一个非常重要的设计因素。几乎每一个功能都涉及到:
- 软硬件如何共同完成一个功能?这里的软件主要是编译器和驱动。
- 部分功能是放在硬件做还是软件做好?
- 软件怎么确保硬件的性能得到充分的发挥,或者工作在高能效状态?
- 软件如何获取硬件的状态信息,已经进行调试硬件(profiling and debuging)?
- 应用程序,框架,应用场景对硬件有什么影响?
- ......
所以,一个好的芯片一定是架构,软件,硬件部门共同合作的结晶!
后记
上面散乱地记录了笔者这一年的一些学习和思考。后续,将引入我们的含光800NPU,做一些更深入地探讨,寻找一些芯片设计的方法学和实践。