英伟达CUDA对机器学习的垄断正逐步瓦解
在过去十年中,机器学习软件开发的格局发生了重大变化。许多框架来来去去,但大多数都严重依赖于利用Nvidia的CUDA,并且在NvidiaGPU上表现最佳。然而,随着PyTorch2。0和OpenAI的Triton的到来,英伟达在该领域主要依靠其软件护城河的主导地位正在被打破。
这份报告将涉及诸如为什么谷歌的TensorFlow输给PyTorch、为什么谷歌未能公开利用其早期在AI领域的领导地位、机器学习模型训练时间的主要组成部分、内存容量带宽成本等主题墙,模型优化,为什么其他AI硬件公司至今无法削弱Nvidia的主导地位,为什么硬件将开始变得更加重要,Nvidia在CUDA方面的竞争优势如何被抹去,以及Nvidia的重大胜利之一竞争对手拥有大量用于训练硅的云。
机器学习模型的默认软件堆栈将不再是Nvidia的闭源CUDA。球在Nvidia的球场上,他们让OpenAI和Meta控制了软件堆栈。由于Nvidia的专有工具失败,该生态系统构建了自己的工具,现在Nvidia的护城河将被永久削弱。TensorFlow与PyTorch
几年前,框架生态系统相当分散,但TensorFlow是领跑者。谷歌看起来准备控制机器学习行业。他们凭借最常用的框架TensorFlow以及通过设计部署唯一成功的AI应用程序特定加速器TPU获得了先发优势。
相反,PyTorch赢了。谷歌未能将其先发优势转化为对新兴ML行业的主导地位。如今,谷歌在机器学习社区中有些孤立,因为它不使用PyTorch和GPU,而是使用自己的软件堆栈和硬件。按照典型的谷歌方式,他们甚至还有一个名为Jax的第二个框架,它直接与TensorFlow竞争。
由于大型语言模型,尤其是来自OpenAI和使用OpenAIAPI或正在构建类似基础模型的各种初创公司的大型语言模型,谷歌在搜索和自然语言处理方面的主导地位甚至没完没了。虽然我们认为这种厄运和阴霾被夸大了,但这个故事是另一天的事了。尽管存在这些挑战,谷歌仍处于最先进机器学习模型的前沿。他们发明了变压器,并在许多领域(PaLM、LaMBDA、Chinchilla、MUM、TPU)保持最先进的水平。
回到为什么PyTorch赢了。虽然谷歌在争夺控制权方面存在一些因素,但这主要是由于PyTorch与TensorFlow相比具有更高的灵活性和可用性。如果我们将其归结为第一个主要级别,PyTorch与TensorFlow的不同之处在于使用Eagermode而不是GraphMode。
Eager模式可以被认为是一种标准的脚本执行方法。深度学习框架会像任何其他Python代码一样,逐行立即执行每个操作。这使得调试和理解您的代码更容易,因为您可以看到中间操作的结果并查看您的模型的行为方式。
相反,图形模式有两个阶段。第一阶段是表示要执行的操作的计算图的定义。计算图是一系列相互连接的节点,表示操作或变量,节点之间的边表示它们之间的数据流。第二阶段是延迟执行计算图的优化版本。
这种两阶段方法使理解和调试代码更具挑战性,因为在图形执行结束之前您无法看到发生了什么。这类似于解释与编译语言,如Python与C。调试Python更容易,主要是因为它是解释型的。
虽然TensorFlow现在默认具有Eager模式,但研究社区和大多数大型科技公司已经围绕PyTorch安定下来。有关PyTorch获胜原因的更深入解释,请参见此处。机器学习训练组件
如果我们将机器学习模型训练简化为最简单的形式,那么机器学习模型的训练时间有两个主要的时间组成部分。计算(FLOPS):在每一层内运行密集矩阵乘法内存(带宽):等待数据或层权重到达计算资源。带宽受限操作的常见示例是各种规范化、逐点操作、SoftMax和ReLU。
过去,机器学习训练时间的主导因素是计算时间,等待矩阵乘法。随着Nvidia的GPU不断发展,这很快就不再是主要问题。
Nvidia的FLOPS通过利用摩尔定律提高了多个数量级,但主要是架构变化,例如张量核心和较低精度的浮点格式。相比之下,记忆并没有走同样的道路。
如果我们回到2018年,那时BERT模型是最先进的,NvidiaV100是最先进的GPU,我们可以看到矩阵乘法不再是提高模型性能的主要因素。从那时起,最先进的模型在参数数量上增长了3到4个数量级,而最快的GPU在FLOPS上增长了一个数量级。
即使在2018年,纯计算绑定的工作负载也占FLOPS的99。8,但仅占运行时的61。与矩阵乘法相比,归一化和逐点运算分别实现了250倍和700倍的FLOPS,但它们消耗了模型运行时间的近40。记忆墙
随着模型规模的不断飙升,大型语言模型仅用于模型权重就需要100GB(如果不是TB)。百度和Meta部署的生产推荐网络需要数十TB的内存来存储其海量嵌入表。大型模型训练推理中的大部分时间都没有花在计算矩阵乘法上,而是在等待数据到达计算资源。显而易见的问题是,为什么架构师不将更多内存放在更靠近计算的位置。答案是。
内存遵循从近、快到慢、便宜的层次结构。最近的共享内存池在同一芯片上,一般由SRAM构成。一些机器学习ASIC试图利用巨大的SRAM池来保存模型权重,但这种方法存在问题。即使是Cerebras的价值约5,000,000美元的晶圆级芯片也只有40GB的SRAM。内存容量不足以容纳100B参数模型的权重。
Nvidia的体系结构在裸片上一直使用的内存量要少得多。当前一代A100有40MB,下一代H100有50MB。台积电5纳米工艺节点上的1GBSRAM需要约200mm2的硅。一旦实现了相关的控制逻辑结构,将需要超过400mm2的硅,或Nvidia数据中心GPU总逻辑面积的大约50。鉴于A100GPU的成本为1万美元以上,而H100更接近2万美元以上,从经济角度来看,这是不可行的。即使忽略Nvidia在数据中心GPU上约75的毛利率(约4倍加价),对于完全量产的产品,每GBSRAM内存的成本仍将在100美元左右。
此外,片上SRAM存储器的成本不会随着传统摩尔定律工艺技术的缩小而降低太多。同样的1GB内存,采用台积电下一代3nm制程工艺,成本反而更高。虽然3DSRAM将在一定程度上帮助降低SRAM成本,但这只是曲线的暂时弯曲。
内存层次结构的下一步是紧密耦合的片外内存DRAM。DRAM的延迟比SRAM高一个数量级(100纳秒对10纳秒),但它也便宜得多(1saGB对100sGB。)
几十年来,DRAM一直遵循着摩尔定律。当戈登摩尔创造这个词时,英特尔的主要业务是DRAM。他对晶体管密度和成本的经济预测在2009年之前对DRAM普遍适用。不过自2012年以来,DRAM的成本几乎没有改善。
对内存的需求只会增加。DRAM现在占服务器总成本的50。这就是记忆墙,它已经出现在产品中。将Nvidia的2016P100GPU与刚刚开始出货的2022H100GPU进行比较,内存容量增加了5倍(16GB80GB),但FP16性能增加了46倍(21。2TFLOPS989。5TFLOPS)。
虽然容量是一个重要的瓶颈,但它与另一个主要瓶颈带宽密切相关。增加的内存带宽通常是通过并行性获得的。虽然如今标准DRAM的价格仅为每GB几美元,但为了获得机器学习所需的海量带宽,Nvidia使用HBM内存,这是一种由3D堆叠DRAM层组成的设备,需要更昂贵的封装。HBM在每GB10到20美元的范围内,包括包装和产量成本。
内存带宽和容量的成本限制不断出现在Nvidia的A100GPU中。如果不进行大量优化,A100往往具有非常低的FLOPS利用率。FLOPS利用率衡量训练模型所需的总计算FLOPS与GPU在模型训练时间内可以计算的理论FLOPS。
即使领先研究人员进行了大量优化,60的FLOPS利用率也被认为是大型语言模型训练的非常高的利用率。其余时间是开销,空闲时间花在等待来自另一个计算内存的数据,或者及时重新计算结果以减少内存瓶颈。
从当前一代的A100到下一代H100,FLOPS增长了6倍以上,但内存带宽仅增长了1。65倍。这导致许多人担心H100的利用率低。A100需要很多技巧才能绕过内存墙,H100还需要实现更多技巧。
H100为Hopper带来了分布式共享内存和L2多播。这个想法是不同的SM(thinkcores)可以直接写入另一个SM的SRAM(共享内存L1缓存)。这有效地增加了缓存的大小并减少了DRAM读写所需的带宽。未来的架构将依赖于向内存发送更少的操作,以最大限度地减少内存墙的影响。应该注意的是,较大的模型往往会实现更高的利用率,因为FLOPS需要参数计数的三次方缩放,而内存带宽和容量需求往往会二次缩放。运算符融合解决方法就像训练ML模型一样,了解您所处的状态可以让您缩小重要的优化范围。例如,如果您将所有时间都花在内存传输上(即您处于内存带宽限制状态),那么增加GPU的FLOPS将无济于事。另一方面,如果您将所有时间都花在执行大型matmuls(即计算绑定机制)上,那么将您的模型逻辑重写为C以减少开销将无济于事。
https:horace。iobrrrintro。html
回顾PyTorch获胜的原因,这是由于Eager模式提高了灵活性和可用性,但转向Eager模式并不全是阳光和彩虹。在Eager模式下执行时,每个操作都从内存中读取、计算,然后在处理下一个操作之前发送到内存。如果不进行大量优化,这会显着增加内存带宽需求。
因此,在Eager模式下执行的模型的主要优化方法之一称为算子融合。操作被融合,而不是将每个中间结果写入内存,因此在一次传递中计算多个函数以最小化内存读写。运算符融合改善了运算符调度、内存带宽和内存大小成本。
这种优化通常涉及编写自定义CUDA内核,但这比使用简单的python脚本要困难得多。作为一种内置的妥协,随着时间的推移,PyTorch在PyTorch中稳定地实现了越来越多的操作符。其中许多运算符只是简单地将多个常用运算融合到一个更复杂的函数中。
运算符的增加使得在PyTorch中创建模型变得更容易,并且由于内存读写更少,Eager模式的性能更快。缺点是PyTorch在几年内激增到2,000多个操作员。
我们会说软件开发人员很懒惰,但说实话,几乎所有人都是懒惰的。如果他们习惯了PyTorch中的一个新运算符,他们将继续使用它。开发人员可能甚至没有意识到性能的提高,而是使用该运算符,因为这意味着编写更少的代码。
此外,并非所有操作都可以融合。通常花费大量时间来决定要融合哪些操作以及将哪些操作分配给芯片和集群级别的特定计算资源。哪些操作在哪里融合的策略虽然大体相似,但根据架构的不同会有很大差异。英伟达为王
运营商的增长和默认位置对Nvidia有所帮助,因为每个运营商都针对其架构进行了快速优化,但并未针对任何其他硬件进行优化。如果一家AI硬件初创公司想要全面实施PyTorch,那就意味着以高性能原生支持不断增长的2,000个运算符列表。
由于提取最大性能所需的所有技巧,在GPU上训练具有高FLOPS利用率的大型模型所需的人才水平越来越高。Eagermodeexecutionplusoperatorfusion意味着开发的软件、技术和模型被推动以适应当前一代GPU具有的计算和内存比率。
每个开发机器学习芯片的人都依赖于同一个内存墙。ASIC有责任支持最常用的框架。ASIC受制于默认的开发方法,GPU优化的PyTorch代码混合了Nvidia和外部库。避开GPU的各种非计算包袱而支持更多FLOPS和更严格的编程模型的架构在这种情况下意义不大。
易用性为王。
打破恶性循环的唯一方法是让在NvidiaGPU上运行模型的软件尽可能轻松地无缝转移到其他硬件。随着模型架构的稳定和来自PyTorch2。0、OpenAITriton和MLOps公司(如MosaicML)的抽象成为默认,芯片解决方案的架构和经济性开始成为购买的最大驱动力,而不是提供给它的易用性Nvidia的高级软件。PyTorch2。0
PyTorch基金会成立并于几个月前从Meta的羽翼下撤出。除了对开放式开发和治理模型的更改外,2。0还发布了早期测试,并于3月全面上市。PyTorch2。0带来了许多变化,但主要区别在于它添加了一个支持图形执行模型的编译解决方案。这种转变将使正确利用各种硬件资源变得更加容易。
PyTorch2。0在NvidiaA100上的训练性能提升了86,在CPU上的推理性能提升了26!这大大减少了训练模型所需的计算时间和成本。这些好处可以扩展到来自AMD、英特尔、Tenstorrent、LuminousComputing、特斯拉、谷歌、亚马逊、微软、Marvell、Meta、Graphcore、Cerebras、SambaNova等的其他GPU和加速器。
对于当前未优化的硬件,PyTorch2。0的性能改进会更大。Meta和其他公司对PyTorch的巨大贡献源于这样一个事实,即他们希望在他们价值数十亿美元的GPU训练集群上以更少的努力更容易地实现更高的FLOPS利用率。他们也有动力使他们的软件堆栈更易于移植到其他硬件,以将竞争引入机器学习领域。
PyTorch2。0还通过更好的API支持数据并行、分片、管道并行和张量并行,为分布式训练带来了进步。此外,它在整个堆栈中原生支持动态形状,在许多其他示例中,这使得LLM的不同序列长度更容易支持。这是主要编译器首次支持从训练到推理的DynamicShapes。
手电筒
为PyTorch编写一个完全支持所有2,000多个运算符的高性能后端对于除NvidiaGPU之外的每个机器学习ASIC来说都是困难的。PrimTorch将运算符的数量减少到约250个原始运算符,同时还保持PyTorch最终用户的可用性不变。PrimTorch使PyTorch的不同非Nvidia后端的实现变得更加简单和易于访问。定制硬件和系统供应商可以更轻松地推出他们的软件堆栈。火炬发电机
转向图形模式需要一个健壮的图形定义。Meta和PyTorch已经尝试了大约5年的时间来实现这一点,但是他们提出的每个解决方案都有明显的缺点。他们终于用TorchDynamo破解了这个难题。TorchDynamo将摄取任何PyTorch用户脚本,包括调用外部3rd方库的脚本,并生成FX图形。
Dynamo将所有复杂操作减少到PrimTorch中的约250个原始操作。一旦图形成,未使用的操作将被丢弃,图决定哪些中间操作需要存储或写入内存,哪些可能被融合。这极大地减少了模型内的开销,同时对用户来说也是无缝的。
TorchDynamo已经适用于7,000个经过测试的PyTorch模型中的99以上,包括来自OpenAI、HuggingFace、Meta、Nvidia、Stability。AI等的模型,而无需对原始代码进行任何更改。测试的7,000个模型是从GitHub上使用PyTorch的最流行项目中不分青红皂白地挑选出来的。
谷歌的TensorFlowJax和其他图形模式执行管道通常要求用户确保他们的模型适合编译器架构,以便可以捕获图形。Dynamo通过启用部分图捕获、受保护的图捕获和即时重新捕获来改变这一点。部分图形捕获允许模型包含不受支持的非python构造。当无法为模型的那部分生成图时,将插入图中断,并且将在部分图之间以急切模式执行不支持的构造。受保护的图捕获检查捕获的图是否对执行有效。守卫是需要重新编译的更改。这很重要,因为多次运行相同的代码不会多次重新编译。如果捕获的图对于执行无效,则即时重新捕获允许重新捕获图。
PyTorch的目标是创建一个具有流畅UX的统一前端,该前端利用Dynamo生成图形。该解决方案的用户体验不会发生变化,但性能可以得到显着提升。捕获图形意味着可以在大量计算资源上更有效地并行执行。
Dynamo和AOTAutograd然后将优化的FX图传递给PyTorch本机编译器级别TorchInductor。硬件公司也可以将此图输入到他们自己的后端编译器中。手电筒电感
TorchInductor是一个python原生深度学习编译器,可以为多个加速器和后端生成快速代码。Inductor将采用具有约250个运算符的FX图,并将它们降低到约50个运算符。Inductor然后进入调度阶段,在该阶段融合运算符,并确定内存规划。
Inductor然后进入WrapperCodegen,它生成在CPU、GPU或其他AI加速器上运行的代码。包装器codegen取代了编译器堆栈的解释器部分,可以调用内核和分配内存。后端代码生成部分利用适用于GPU的OpenAITriton并输出PTX代码。对于CPU,英特尔编译器生成C(也适用于非英特尔CPU)。
未来将支持更多硬件,但关键是Inductor大大减少了编译器团队在为其AI硬件加速器制作编译器时必须做的工作量。此外,代码针对性能进行了更优化。显着降低了内存带宽和容量要求。我们不想构建只支持GPU的编译器。我们想要一些可以扩展以支持各种硬件后端的东西,并且拥有C和〔OpenAI〕Triton会强制实现这种通用性。
杰森安塞尔元人工智能OpenAI海卫一
OpenAI的Triton对Nvidia的机器学习闭源软件护城河具有颠覆性的角度。Triton直接采用Python或通过PyTorchInductor堆栈提供数据。后者将是最常见的用例。Triton然后将输入转换为LLVM中间表示,然后生成代码。对于NvidiaGPU,它直接生成PTX代码,跳过Nvidia的闭源CUDA库(例如cuBLAS),转而使用开源库(例如cutlass)。
CUDA通常被专门从事加速计算的人员使用,但在机器学习研究人员和数据科学家中却鲜为人知。高效使用可能具有挑战性,并且需要深入了解硬件架构,这可能会减慢开发过程。因此,机器学习专家可能依赖CUDA专家来修改、优化和并行化他们的代码。
Triton弥合了使高级语言能够实现与使用低级语言的语言相当的性能的差距。Triton内核本身对于典型的ML研究人员来说非常清晰,这对于可用性来说非常重要。Triton在SM中自动执行内存合并、共享内存管理和调度。Triton对逐元素矩阵乘法不是特别有用,这已经非常有效地完成了。Triton对于昂贵的逐点操作和减少更复杂操作的开销非常有用,例如FlashAttention涉及矩阵乘法作为较大融合操作的一部分。
OpenAITriton目前仅正式支持NvidiaGPU,但在不久的将来这种情况会发生变化。未来将支持多个其他硬件供应商,这个开源项目正在获得令人难以置信的动力。其他硬件加速器直接集成到作为Triton一部分的LLVMIR的能力大大减少了为新硬件构建AI编译器堆栈的时间。
Nvidia庞大的软件组织缺乏远见,无法利用其在ML硬件和软件方面的巨大优势,成为机器学习的默认编译器。他们缺乏对可用性的关注,这使得OpenAI和Meta的外部人员能够创建可移植到其他硬件的软件堆栈。
本报告的其余部分将指出在微软取得巨大胜利的具体硬件加速器,以及正在迅速集成到PyTorch2。0OpenAITrion软件堆栈中的多家公司的硬件。此外,它将分享相反的观点,以捍卫Nvidia在AI培训市场的护城河实力。