NVIDIA 在开发者社区中地位显赫。许多代码库都是针对其特定品牌的硬件编写和优化的,而竞争的低级 GPU 编程框架则远没有那么成熟。这种早期势头通常被称为“CUDA 护城河”。
但实际上这条护城河到底有多深?
“坚不可摧”的CUDA
您可能已经猜到了,答案实际上取决于您想要实现的目标。如果您正在为 GPU 进行低级编程,那么 CUDA 护城河就非常真实。现有代码必须移植、重构和优化才能在替代硬件上运行。
这是很难避免的,因为 CUDA 和 NVIDIA 芯片中存在的某些硬件调用在 Intel 或 AMD 硬件中根本不存在——反之亦然。这意味着将三年、四年甚至十年前最初为 CUDA 开发的代码带到 AMD 的 ROCm 或 Intel 的 OneAPI 中是开发人员的承诺。
因此,英特尔和 AMD 投入大量资金开发工具,以自动化将 CUDA 源代码转换为在各自平台上运行的过程。AMD 拥有 HIPIFY,可帮助自动将 CUDA 转换为 HIP C++ 代码。
AMD 人工智能集团高级副总裁 Vamsi Boppana 告诉 El Reg:“如果有人真的在做一些内核创作(kernel authoring),而且他们非常习惯用 CUDA 来编写,或者他们实际上有一堆闲置的 CUDA 代码,那么我认为,我们是唯一能够实现平稳迁移路径的其他真正替代方案,因为我们有 HIPIFY,你可以得到 HIP C++,而且你可以进行编译。”
虽然这种说法可能有些道理,但 HIPIFY 并不完美。The Next Platform之前在之前的文章中曾强调过的一个挑战是,HIPIFY 没有考虑纹理内存(texture memory)中的设备端模板参数(device-side template arguments )或多个 CUDA 头文件(header files),因此需要开发人员手动干预。
与此同时,英特尔拥有 SYCL,它与 HIPIFY 类似,可以处理大部分繁重的工作(据称高达 95%),将 CUDA 代码移植为可以在非 NVIDIA 加速器(包括 AMD 和其他公司的加速器)上运行的格式。
最后,我们不得不提的是,AMD 曾悄悄资助了一个项目,让未翻译的 CUDA 代码能够在其硬件上原生运行。然而,今年早些时候,AMD 放弃了这一努力,并采取措施阻止开发人员进一步开展工作,原因我们之前已经深入讨论过。
不过,尽管 CUDA 护城河对于希望扩大对替代硬件平台的支持的开发人员来说无疑是现实,但在内核级别编写代码的开发人员数量相对较少 —— 至少英特尔和 AMD 的高管是这么告诉El Reg 的。
英特尔数据中心和 AI 软件副总裁 Bill Pearson 在最近接受 The Register 采访时表示:“几年前,一切都是 CUDA,人们都在直接层面进行编程。但现在,我们看到大多数开发人员都在 PyTorch 层面或其他框架上进行编程。”
AMD 的 Instinct 加速器也出现了类似的情况,去年该加速器的采用率突然上升。“现实情况是,人们希望在更高的抽象层次上进行编写,”Boppana 解释道。
基于 PyTorch 构建的梯子
PyTorch 尤其成为许多兜售 NVIDIA 替代品的 AI 芯片公司的首选。它不是现代加速器的唯一高级编程语言,还有 TensorFlow、JAX,也许还有一些我们忘记的东西,但它是最受欢迎的语言之一。
就 AMD 而言,多年来,PyTorch 一直提供对 ROCm 的原生支持,而对英特尔 GPU 的支持则于今年初开始推出。稍后我们将介绍 IPEX 和 Gaudi 的特殊品牌 PyTorch,但在此之前,让我们先谈谈 PyTorch,因为它并不一定是芯片制造商有时所说的灵丹妙药。
PyTorch 背后的理念是,它存在于 CUDA、ROCm 或 OneAPI 等框架之上,并根据系统中安装的硬件简单地调用适当的后端。理论上,这意味着为 PyTorch 编写的代码应该可以在几乎任何支持它的东西上运行。
Boppana 指出:“对于使用 PyTorch 等现代框架以及一组受支持的标准库的人来说,我认为使用我们的 GPU 是一条极其简单、低阻力的途径。”
实际上,我们还没有完全做到这一点。PyTorch 可以在这些加速器上运行,但这并不意味着就不会出现问题。
事实上,用于构建 PyTorch 应用程序的许多库和模块在添加对替代架构的支持方面进展缓慢。因此,通常需要进行一定程度的重构才能运行现有脚本。
BitsandBytes 只是其中一个例子。该量化库通常用于推理和 QLORA 微调,以减少 LLM 的内存占用,以便这些工作负载可以在单个 GPU 或节点上完成。
不幸的是,直到现在,BitsandBytes 还没原生支持 Intel 或 AMD 硬件。这意味着您无法像在 NVIDIA 硬件上那样运行“pip install bitsandbytes”并期望它能够正常工作。相反,Intel 和 AMD 用户必须找到特定于供应商的代码分支,并希望它能够与最新版本的 PyTorch 和 Python 兼容。
需要明确的是,这不仅仅是 BitsandBytes 的情况——这是许多库的现实情况。
“开发人员希望库能够存在。您已经拥有已构建并经过性能优化的 GEMM,我们必须确保我们的相同 GEMM 和库等的版本存在,”Pearson 解释道。
通常,这涉及芯片制造商与社区合作,分叉代码库,进行修改,在他们的硬件上运行,然后理想情况下将调整贡献回主线分支。
“如果我们认为某个特定库或一组技术具有市场主导需求,那么我们就会倾向于推动它。更重要的是,我们希望社区会推动它,因为我们能做的有限,”Boppana 解释道。“如果社区开始做出贡献,那么我们绝对会支持它。”
好消息是,这样的情况正在发生。
Pearson说:“这些依赖关系——那些独特的、依赖于较低层的小块——在某些情况下仍然存在,但它们越来越少见,而且它们正在一点一点地消失。”
自从第一次遇到 BitsandBytes 兼容性问题以来,我们注意到对 AMD 和 Intel GPU 的支持已通过实验性的“多后端”版本得到扩展。然而,在发布时,安装它仍然不像在 NVIDIA 硬件上那么简单。
不过,尽管支持正在改善,但仍有大量工作要做。
软件兼容性雷区
您可能可以想象得到,兼容库的碎片化会造成软件兼容性问题。除非您拥有正确版本的 Python、PyTorch、BitsandBytes(谁知道还有什么),否则您的脚本就会出错,这种情况很容易发生。
公平地说,NVIDIA 的客户也一定会遇到这种情况。但由于需要追踪并在许多情况下编译流行库的兼容版本,情况只会变得更加复杂。
英特尔、AMD 和 NVIDIA 已采取措施缓解其中一些挑战,方法是提供用作开发环境的预配置容器映像(container images )。正如我们之前所探讨的那样,这些容器映像可以像预配置的 ROCm、OneAPI 或 CUDA 环境一样简单,也可以包含完整的 PyTorch 安装。
“例如,我们有一个容器 —— PyTorch 容器 —— 你可以去获取 Gaudi,它拥有所需的所有库,”Pearson 解释说。
当你意识到 PyTorch 支持在不同的硬件供应商之间并不总是意味着同一件事时,这些容器的可用性才会变得更加重要。
英特尔尤其如此,它提供了针对其 GPU 和 Gaudi3 加速器进行调整的 PyTorch 定制版本。前往 PyTorch 网站,向下滚动,您很快就会意识到没有 OneAPI 或 Gaudi 的选项。这是因为 Gaudi 加速器对 PyTorch 的支持依赖于英特尔开发的库的定制版本。
直到最近添加了原生 PyTorch 支持后,英特尔 GPU 的情况才有了类似变化。原生支持仍处于预览阶段,因此从 PyTorch 主页上可能看不出来,但它确实存在,而且我们已经测试过了。
然而,在英特尔的 GPU 增加原生 PyTorch 支持之前,它们依赖于一个名为英特尔 PyTorch 扩展(简称IPEX)的自定义版本。该软件包包含各种性能优化和库,旨在使在其加速器上运行代码更加无缝。
“我们在优化方面做了许多工作,首先构建库,然后优化 GEMM 和这些库中的内容,然后开发人员能够轻松地使用我们提供的模板编写 PyTorch 代码,或者采用我们现有的代码并将其从 CUDA 转移到 Gaudi,”Pearson 解释说。
“当他们这样做时,他们的体验将在很大程度上变得轻松,因为这不是零工作(zero work),但也不是很多工作要做。它涉及将目标从 NVIDIA 更改为 Gaudi,然后将输出更改为相同的目标,”他补充道。
虽然我们还没有测试过英特尔的 Gaudi 平台,但我们可以说,很多 PyTorch 脚本只需要进行少量调整就可以在 IPEX 下运行。
随着芯片制造商推动对流行框架和库的本地支持,某些东西是否可行已不再是一个问题,而是一个性能如何的问题。
开发渠道或缺乏开发渠道
为 x86 或 Arm CPU 构建应用程序如此简单的原因之一是构建应用程序所需的硬件无处不在。您可以在笔记本电脑、台式机或工作站上开始构建,并在其成熟时扩展到具有 CICD 管道的专用构建环境。
对于使用 NVIDIA 硬件进行开发的开发人员来说,情况也类似。除了少数例外,CUDA 在移动 GPU 上的运行方式与在价值 30000 美元的 H100 上的运行方式相同。这意味着,如果您的系统配备了 NVIDIA GPU,那么您已经拥有了开始开发所需的一切。
竞争对手的情况就没那么顺利了。在台式机和工作站领域,AMD 拥有 Radeon 和 Radeon Pro GPU,它们使用 RDNA 微架构,而其专注于数据中心的 Instinct 芯片则使用 CDNA 架构。尽管存在这些差异,AMD 仍将 ROCm 支持扩展到部分 7000 系列 Radeon 卡,以期巩固其开发人员渠道。
在大多数情况下,我们发现一切正常。不过,我们在使用 Flash Attention 2 等产品时遇到了麻烦,这是一个相当重要的库,有助于在更大的上下文长度下控制 GenAI 模型的内存消耗。Flash Attention 2 已经在 Instinct 部件上得到支持一段时间了,而将该库引入 Radeon 的努力仍在进行中。
对于 Flash Attention 来说,提前推出的 Triton 内核库可以提高内存利用率,在某些情况下可以克服这一限制。例如,我们在最近的 Axolotl微调指南中使用了一个实验性的 AoT Triton 内核。
这在很大程度上取决于市场优先顺序。正如您所预料的那样,与那些试图构建训练集群和推理大量万亿以上参数模型的人相比,想要使用游戏 GPU 编写 ML 应用程序的人数量相对较少。
Boppana 承认:“我们仍然非常专注于确保 Instinct 是我们优先考虑的领域。”他补充说,尽管 MI300X仅在一年多前推出,但该部件已通过长期合同或按需方式在云端广泛提供。
然而,Boppana 也承认工作站级硬件的必要性。“我个人认为(云)不能是唯一的方法,开发人员喜欢在办公桌下安装工作站,这样他们就可以尽情发挥创造力,”他说道。
英特尔的情况则更加复杂,英特尔的旗舰 AI 加速器是 Gaudi3,至少目前还没有工作站版本。
此外,Gaudi 加速器实际上并不支持 OneAPI,而是依赖于 Habana 自己的 SynapseAI 软件堆栈。这意味着想要在 Gaudi 上构建应用程序的开发人员实际上只能使用英特尔的 Tiber 开发人员云。
当然,英特尔的 GPU(包括其 Arc 游戏卡)都支持 OneAPI。因此,如果您想编写可以扩展到 Datacenter Flex 或 GPU Max 卡集群的代码,您当然可以。话虽如此,我们观察到软件支持通常在到达 Arc 之前先到达 Datacenter Flex。
另一个不容忽视的问题是 GPU Max(又名 Ponte Vecchio)已经停产。因此,除了阿贡国家实验室(其 Aurora 系统中有 60,000 多个 GPU)之外,我们不确定有多少人会在生产中为 GPU Max 编写代码。
明年推出的 Falcon Shores 可能会改变这一现状,它将采用 GPU 架构,并搭载一些类似 Gaudi 的设计元素。据推测,该部件还将支持 OneAPI。
绕过护城河
虽然CUDA 护城河对于开发商和芯片制造商来说仍然是一个持续的挑战,但如果您只想大规模提供 LLM,那么这并不是您真正需要担心的事情。
无论您选择什么硬件——英特尔、AMD、Cerebras、SambaNova、高通或其他公司,所有这些供应商都开发了或贡献了让 LLM 产生令牌所需的必要代码。
几乎每个人都有一个框架,用于简化在其硬件上部署聊天机器人式应用程序(如检索增强生成 (RAG))。
然而,在某些情况下,提供与 OpenAI 兼容的 API 服务器的能力才是所有开发人员真正想要的。当今的许多 AI 应用程序实际上只是围绕 OpenAI、Anthropic 或 Mistral AI API 服务器构建的包装器 - 这意味着代码永远不必直接与 GPU 或 AI 加速器交互。
这也意味着代码相对可移植。例如,可以使用 Anthropic 的 Claude 构建概念验证,然后出于安全或合规原因,一旦投入生产,API 服务器和密钥就可以换成 vLLM 或 TensorRT-LLM 的本地实例。
尽管几乎任何 AI 加速器都可以提供 LLM,但这并不意味着它的性能或效率能够达到应有的水平。
在最近的 MLPerf 推理提交中,AMD 展示了其 MI300X 加速器,其性能可与 NVIDIA 备受推崇的 H100相媲美。理论上,该部件更高的内存带宽和更快的浮点性能应该会给它带来更大的优势——但对于首次提交而言,这并非什么了不起的事情。
从那时起,我们看到 ROCm 进行了多次更新,旨在提高流行模型运行器(包括 vLLM 和 SG-Lang)的性能,并有望释放额外的性能。
虽然 Guadi3 尚未在 MLPerf 训练或推理中首次亮相,但长期以来,Gaudi2 是唯一值得 NVIDIA 提及的竞争部分。
对于很多开发人员来说,可以说 NVIDIA 的 CUDA 护城河并不像你想象的那么深 - 但它比 AMD 或英特尔希望的要深。