共计 5049 个字符,预计需要花费 13 分钟才能阅读完成。
只管 AI 的倒退获得了巨大进步,但编译器 LLVM 之父 Chris Lattner 认为,AI 技术利用并不深刻,远远没有施展出已有机器学习钻研的所有后劲。而 AI 零碎和工具的单一化和碎片化正是造成这一问题的本源。
为了让 AI 施展其真正的后劲,计算碎片化是须要解决的重点问题之一,指标是让 AI 软件开发人员可能无缝地充分利用现有硬件和下一代翻新硬件。但解决这一问题并不容易,硬件、模型和数据的多样性使得以后市场上的现有解决方案都只是单点性质的,Chris Lattner 创建的 Modular 团队从矩阵算法的角度对此进行了深入分析。
(以下内容由 OneFlow 编译公布,译文转载请分割 OneFlow 取得受权。https://www.modular.com/blog/ais-compute-fragmentation-what-m…)
作者|Eric Johnson、Abdul Dakkak、Chad Jarvis
OneFlow 编译
翻译|徐佳渝、杨婷
1
算力碎片化正在妨碍 AI 的倒退
AI 由数据、算法(即模型)和算力驱动,三者之间造成了良性循环。其中任意一方的倒退会推动其余方面需要的增长,从而重大影响开发者在可用性和性能等方面的体验。现在,咱们领有更多的数据,做了更多的 AI 模型钻研,但算力的扩大速度却没有跟上,这次要是因为物理限度。
如果你始终在关注 AI 和硬件的倒退,可能据说过摩尔定律时代行将完结。过来 60 年,单核处理器每 18 个月翻一倍性能晋升速度的状况未然扭转。除了持续制作越来越小的晶体管的物理限度之外(例如,电流透露会导致功耗过高,从而引起发热),性能也越来越多地受到内存提早的限度,而这种限度的增长速度比处理速度要迟缓得多。
(Hennessy 和 Patterson 的图灵演讲:不同期间 CPU 处理器性能晋升的剖析(性能晋升的速度保持稳定))
然而,随着模型不断扩大,在边缘计算中创立和解决的企业数据更多,对 AI 计算的需要也在一直减少。因而,尽可能地利用硬件设施的性能已成为业界的关注焦点。
(机器学习三个时代的算力走向(https://arxiv.org/pdf/2202.05924.pdf),Sevilla:计算需要随工夫呈对数形式变动的剖析。其中,2010 年左右深度学习开始受到关注,2016 年左右迎来了大型模型时代,这促使了算力需要急剧增长。)
那么,算力的碎片化是如何妨碍 AI 倒退的呢?因为传统 CPU 无奈扩大以满足更多的算力需要,因而,惟一的解决之道是创立并行的、用于特定畛域的硬件平台,只管这些硬件平台的通用性不强,但在特定的 AI 畛域却体现良好——例如图形处理单元 (GPU)、张量处理单元(TPU) 和其余专用集成电路(ASIC)。
尽管这些翻新推动了 AI 行业的倒退,让边缘设施可能应用规模更大、效率更高的处理器,但硬件的多样性使得整个 AI 行业变得碎片化,AI 开发者们须要致力解决以下问题:
1. 开发出可能充分利用硬件能力的软件,且能与其他软件协同工作。
2. 在任意一款设施上实现并行软件算法。
3. 将软件扩大到多设施的生态系统,甚至扩大到异构零碎。
Modular 公司致力于从零开始重建寰球的 AI 基础设施。在本系列博客中,咱们将探讨如何采纳全新的办法解决 AI 行业的算力碎片化问题。咱们会专一于单个运算符——矩阵乘法(matrix multiplication,matmul),这是机器学习算法中的要害计算。
通过这种形式,咱们会看到构建真正对立的解决方案所面临的底层挑战。咱们将深入研究矩阵乘法的外部运作,探讨其工作原理的一些细节,以理解矩阵乘法为什么如此艰难。
2
矩阵乘法为何如此艰难
矩阵对机器学习零碎来说至关重要,因为它提供了一种简略而高效的形式来示意数据。例如,输出数据(图像中的像素汇合)或者模型外部不同层之间的运作机制都能够用矩阵来示意。因而,矩阵相乘的运算在深度学习模型总计算量中占据很大比例。
实际上,在许多以后风行的 Transformer 模型 BERT、CLIP 以及 ChatGPT 中,矩阵乘法的运行时长约占其总运行时长的 45-60%。矩阵乘法在计算卷积运算中扮演着重要角色,该运算是大多数计算机视觉模型的根底,也是许多高性能计算利用的外围。
思考到矩阵乘法在机器学习和计算机视觉等畛域的重要性,钻研人员对其进行了宽泛的算法钻研,以编写出高效的矩阵乘法算法。自 60 年代(https://ieeexplore.ieee.org/abstract/document/1687427)、70 年代(https://apps.dtic.mil/sti/pdfs/AD0705509.pdf)、80 年代(https://dl.acm.org/doi/10.1145/356012.356020), 90 年代(https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.54….)、21 世纪初至今(https://netlib.org/lapack/lawnspdf/lawn147.pdf),始终有论文在尝试应用过后的硬件来解决该问题。
简略的 O(n^3)矩阵乘法算法。
然而概念上的矩阵乘法并不是难点。相同,挑战在于编写一个足够高效的矩阵乘法,以在 AI 行业的所有硬件、模型和数据多样性上实现 SOTA 性能。此外,与其余 AI 算子的协同工作更具挑战性。
硬件
每种用于运行 AI 模型的设施都有其独特的特色,例如内存层次结构不同、乘法和累加单元(MAC)不同等等。
例如,CPU 采纳了这种内存层次结构——从慢速的 RAM 到越来越快的缓存,包含 Level-3、Level-2、Level- 1 和 CPU 寄存器。内存大小与速度成反比,例如,L1 缓存的访问速度通常为 1 纳秒量级,而 RAM 的访问速度为 100 纳秒量级。
要取得最高性能的矩阵运算,必须让算法无效地解决不同的内存级别和大小。因为原始矩阵太大,所以无奈将其一次性放入寄存器或最快的内存缓存中。因而,挑战在于将原始矩阵合成为大小适合的 block 或 tiles,以最大限度地利用最快内存。
此外,解决外围矩阵性能(core matrix functionality)单元的理论形态因硬件而异。就传统意义而言,CPU 是一种标量(scalar)机器,这意味着它须要一一解决指令。然而,在过来二十年中,所有 CPU 供应商都减少了向量单元(如 SIMD),GPU 则采纳了 SIMT(单指令多线程,Single Instruction, Multiple Threads)的形式,以最大限度地进步高度并行、反复运算的效率。
此外,更业余的硬件通过对二维矩阵进行运算来进一步实现这一点。最驰名的是 Google 的 TPU,不过苹果和英特尔曾经减少了本人的矩阵乘法性能 AMX。尽管更先进的 MAC 单元进步了性能,但也产生了相应的需要,即可能在标量、向量和矩阵处理器上工作的灵便算法。
(深刻理解谷歌的第一个张量处理单元:不同乘法和累加(MAC)单元形态。)
模型
AI 模型具备多样性。尽管矩阵乘法是许多模型的根底,但它们的矩阵大小可能差别微小。例如,模型具备不同的输出形态(如不同的序列长度)、不同的外部形态(即作为模型暗藏层一部分的相乘矩阵),以及不同的 batch size 大小(对于训练和推理效率至关重要)。因而,矩阵乘法在生产中有数百种不同的形态,使得难以将它们合成为不同的 block,以实现内存效率最大化。
(Transformer 图解,Jay Alammar:多头注意力块中波及的各种矩阵大小,Transformer 模型(如 BERT, GPT2 和 CLIP)的要害构建块。)
数据
数据也存在差别。大多数读者可能比拟相熟结构化和非结构化数据方面的差别,但在本文,咱们重点关注数据类型(“dtype”)。在 AI 模型中,数据通常应用 dtype FP32,但为了缩小模型大小,进步模型性能,业界也承受较低精度的数据类型,如 Bfloat16,Int8 以及更非凡的 FP4 和 Int4。用例不同,Matmul 算法须要运行的数据精度也不同。
量化在 AI 中的重要性:将 FP32 量化为 Int8。
3
以后的 SOTA 矩阵乘法算法
那么,目前的 SOTA 矩阵乘法算法是如何实现的呢?鉴于其重要性,matmul 通常是硬件供应商最先优化的算法之一,一般来说,供应商会利用他们的库来实现优化,比方英特尔的 MKL 和 OneDNN 库、AMD 的 AOCL 和 RocBLAS、ARM 的 performance 库、Apple 的 Accelerate、Nvidia 的 CUBLAS。
就效率而言,在上述提及的硬件库中,以后的 SOTA 是无效地编写汇编代码:在最低层级向硬件提供间接指令来宏观治理硬件,而无需形象。
面向 AVX512,用 x86 汇编编写的矩阵算法
这样做的次要起因是什么?编写汇编能够实现任意特定用例的最佳性能,通过汇编编写,开发人员能够防止编译器的不可预测性,编译器将 Python 和 C ++ 等高级语言转换为汇编语言,能够执行编译器难以做到的优化,因为编译器必须泛化。更重要的是,它们能够利用编译器未意识到的指令和模式,因为扩大编译器以反对新的硬件性能须要工夫。
4
手写汇编 kernel 无奈扩大
那么,汇编是否真正解决用户的碎片问题呢?尽管汇编编写能够最大限度地进步集体用例性能,但它不可移植、组合、扩大且对用户不够敌对。多数手工编写和微调汇编代码的专家怎么可能将他们的工作扩大到不同配置,同时整合到所有 AI 框架中呢?这几乎就是不可能实现的工作。
(机器学习编译优化器介绍,Chip Huyen:一直减少的框架和硬件反对组合)
可移植性
汇编是应用特定于硬件的接口(指令集架构 ISA)编写的,因而它不能跨硬件移植。事实上,汇编甚至无奈在同一硬件供应商的多代芯片上实现最佳性能!
此外,即便咱们在开发模型时思考了指标硬件,也依然存在两大理论问题:
1. 首先,咱们无奈在云上管制运行汇编的特定硬件。你可能会说“我抉择了一个非常适合本人模型的实例”。但事实是,某些云提供商(如 AWS)上的实例不能保障特定的 CPU 类型。比方,如果你抉择了 c5.4xlarge 实例,那么相应的,你只能应用老一代英特尔 SkyLake 处理器或新一些的级联湖处理器(Cascade Lake processor)。汇编无奈适应运行代码的特定芯片,更无奈为其提供最佳性能。
2. 你的产品将持续迅速迭代,你可能心愿齐全迁徙到不同的硬件架构。确定一种特定配置会限度你依据模型需要的变动或新一代硬件进行适应性调整的灵活性。
可扩展性和可组合性
如前所述,AI 模型的多样性导致了矩阵形态差别。应用基于汇编的库意味着抉择对内存 tile 大小等参数进行硬编码的特定处理器指令。这些硬编码的汇编库能够针对特定的张量形态进行优化,但须要对其余张量形态进行不同的实现。
因而,许多现有的 kernel 库收缩到了千兆字节(例如,MKL 为 3.2GB,cuDNN 最高可达 2.5GB)。当这些库的大小影响到容器构建工夫时,如果你想部署到不切实际的边缘端,或者想要部署供应商尚未手动优化的新翻新和钻研时,这将成为一个麻烦。
从整体来看,高性能矩阵乘法对性能的确很重要。但为了获得最佳后果,矩阵乘法运算能够与其余运算一起执行,例如 Elementwise、跨步拜访(strided accesses)、播送(broadcasts)等。通过缩小内存数据流量,算子交融(Operator fusion)带来了显著的性能改良,但问题是有成千上万的 AI 算子。
此外,模型应用了很多不同运算的排列组合,手动交融所有重要组合是不切实际的(尽管有些人曾经尝试过了!),特地是在 AI 高速倒退的状况下。
用户敌对性
最初,汇编对于用户来说并不敌对,不利于跨组织的生产力。汇编编程在古代编程语言(如参数化和面向对象编程)中可用的性能无限,且不能在调试(debugging)、代码覆盖率(code coverage)、测试(testing)等方面提供无效助益。
尽管大多数想要编写新运算符的钻研人员都对 Python 比较满意,但还是有一些家喻户晓的性能问题(https://en.wikipedia.org/wiki/Global_interpreter_lock)。为了应答这些问题,组织不得不花高价高薪延聘专家来填补鸿沟。
欢送 Star、试用 OneFlow 最新版本:https://github.com/Oneflow-Inc/oneflow/