博客

vLLM 与 PyTorch 携手改进 aarch64 上的开发者体验

作者: 2026年5月18日暂无评论

特色项目

TLDR:PyTorch 2.11 使得用户可以直接从 PyPI 安装适用于 aarch64 Linux 的 CUDA 支持版 PyTorch wheel,无需再使用自定义软件包索引或各种变通方案,这些旧方案曾让 NVIDIA GH200、GB200 和 GB300 等系统的部署变得十分复杂。在这篇文章中,Kaichao You (Inferact) 解释了这一打包方式的改进如何优化了 vLLM 用户的安装体验,并重点介绍了 vLLM 和 PyTorch 如何通过 PyTorch 基金会开展合作,从而将此修复推向生产环境。

一项酝酿了两年、让 GB200 / GB300 / GH200 使用体验大幅提升的修复。

我在黑客松中首次遇到的问题

这个故事实际上始于 2024 年 10 月。

当时我正在参加 CUDA MODE(现为 GPU MODE)的线下黑客松,试图在 GH200 服务器上运行 vLLM。这本应是一个五分钟就能搞定的任务。然而,我却沮丧地花了大半天时间盯着 pip install 的过程——表面上看,一切都很完美:wheel 解析成功,依赖项满足,安装过程也没有报错——但在运行时,torch.cuda.is_available() 却固执地返回了 False

深入调查后发现,原因极其普通且令人无奈:在 aarch64 Linux 上,pip install torch 默认从 PyPI 拉取的是仅支持 CPU 的 wheel 包。默认的 PyPI 索引中根本没有发布适用于 aarch64 的 GPU wheel。要获得支持 CUDA 的构建版本,必须显式地让 pip 指向 PyTorch 的下载索引:

pip install torch --index-url https://download.pytorch.org/whl/cu128

如果仅此而已,那不过是有点麻烦。真正的隐患在于它与传递依赖(transitive dependencies)的交互方式。PyPI 不允许软件包为其依赖项指定自定义索引。因此,如果 vLLM 依赖树中的任何软件包声明了 torch==<some_version> 且版本不匹配,pip 就会自动回到默认的 PyPI 索引,找到 CPU wheel,静默卸载我刚费尽心思安装好的 GPU 构建版本,并将其替换为 CPU 版本。你以为一切正常,直到你的模型因为找不到 GPU 而报错。

对于任何试图在 GH200(以及后来的 GB200 / GB300)上部署 vLLM 的人来说,这使得原本一行代码就能完成的安装,变成了一个充斥着 --index-url 标志、固定版本号和安装后 sanity check(完整性检查)的迷宫。

vLLM 此前采用的变通方案

在等待官方修复的同时,vLLM 不得不发布自己的变通方案,以确保 aarch64 用户不会被卡住。

第一个方案是 use_existing_torch.py,于 2024 年 9 月在 vllm-project/vllm#8713 中加入——PR 标题明确指出:“启用现有的 pytorch(针对 GH200、aarch64、nightly)”。流程正如其名:你自己安装正确的 torch 构建版本(来自 PyTorch 索引、nightly 版本或自定义构建),然后运行 python use_existing_torch.py,它会从 vLLM 的 requirements/*.txtrequirements/*.inpyproject.toml 中剔除所有 torch/torchvision/torchaudio 要求。去除了这些限制后,后续的 vLLM 安装就不会再触发 pip 去“好心”地从默认 PyPI 索引中下载并静默替换掉你安装好的 CUDA 版 torch。这虽然很笨拙——我们实际上是在安装时重写了自己的依赖文件——但它让 GH200 用户在一年多时间里没被卡住。

后来,随着 uv 的成熟,我们有了更简洁的选择。在 vllm-project/vllm#24303 中,我们在 pyproject.toml 中添加了以下内容:

[tool.uv]
no-build-isolation-package = ["torch"]

这告诉 uv 不要在隔离环境中构建 torch——实际上意味着 uv 将重复使用当前环境中已有的 torch,而不是尝试解析并重新安装它。结合从正确的索引预先安装 torch,这为我们提供了一条比文件重写技巧更符合工程学的路径:只需在 pyproject.toml 中配置一行,执行 uv pip install vllm(或 uv sync)时就会尊重 aarch64 上已预装的 CUDA 版 torch

vLLM 的变通方案是社区在打包标准缺失情况下的应急之举。Wheel Variants(Wheel 变体)正是 NVIDIA 和 Astral 旨在通过规范化修复,让这种应急方案不再必要。

从黑客松的头痛问题到 TAC 议程

时间快进到 2025 年。vLLM 加入了 PyTorch 基金会,我也成为了技术咨询委员会 (TAC) 的代表之一。aarch64 wheel 的问题不断出现——既存在于我的工作中,也反映在其他 Grace Hopper 和 Grace Blackwell 系统用户的反馈中。2025 年 8 月,我提交了 pytorch/pytorch#160162 来正式跟踪此问题,并在今年 1 月的 TAC 会议上,我代表 vLLM 用户直接提出了这一问题。

诉求非常简单:将 aarch64 GPU wheel 发布到默认的 PyPI 索引,这样 pip install torch 在 GB200 级机器上就能“直接使用”,就像在 x86 上一样。这些 wheel 将动态链接到 NCCL 和 cuBLAS 等库(与 x86 上使用的方法相同),从而避免体积过大。如此巨大的二进制文件对用户来说既难以下载,对 PyPI 项目维护者来说托管成本也过高。因此,这种做法受到限制且被 PyPI 维护者强烈反对。

Nvidia 工程团队要求将 CUDA SBSA wheel 发布到 PyPI,并推动了通过链接这些库来保持 wheel 轻量化的方案。

这正是 PyTorch 基金会最擅长协调的那类跨项目、基础设施层面的问题。vLLM 和 PyTorch 都是基金会项目,拥有一个共同的论坛来公开生态系统中的摩擦点——而不是让每个项目各自为战地去寻找变通方案——这确实起到了关键作用。

修复已落地

2026 年 4 月,在另一次 TAC 会议上,我得知问题已解决:从 PyTorch 2.11.0 开始,aarch64 Linux 上的默认 pip install torch 现在会拉取支持 CUDA 的 wheel,而不是仅支持 CPU 的版本。来自 NVIDIA 的 Piotr Bialecki 确认该变更已在 2.11.0 版本中生效。

我在 GB200 上进行了验证,其结果正如所愿——以最美妙的方式平庸而平凡。

$ uv run --no-project --python 3.12 --with 'torch==2.11.0' -- python -c "import torch; print(torch.cuda.is_available())"
True

$ uv run --no-project --python 3.12 --with 'torch==2.10.0' -- python -c "import torch; print(torch.cuda.is_available())"
False

仅仅是一个版本更新,整个变通方案栈就消失了。不再需要通过需求文件传播自定义索引 URL。不再有静默的 CPU wheel 替换破坏正常的安装。也不再需要为了让新用户明白“为什么我的 GB200 找不到 GPU”而进行重复的排查工作。

对于 vLLM 而言,这意味着在 GB200 / GB300 上的安装现在变得真正顺滑。使用 Grace Blackwell 系统的新用户只需遵循标准安装说明,即可一次成功——当你在尝试在一个全新的平台上进行推理工作时,这至关重要。

vLLM 中的变通方案——包括 use_existing_torch.py[tool.uv] no-build-isolation-package = ["torch"] 设置——将会保留。它们对于运行自定义 PyTorch 构建(如 nightly、打补丁的分支或从源码构建并搭配 vLLM 源码安装)的高级用户仍然很有用,因为他们需要 vLLM 安装程序严格保持 torch 的环境不变。变化的是默认路径:aarch64 上的普通用户不再需要了解这些。他们只需执行 pip install 即可直接投入工作,变通方案也会静静地从“所有人的负担”转变为“高级用户的工具”。

为什么值得写出来

从大局来看,这是一个小小的改动——只是一个打包调整,而非什么新功能。但我认为它值得我们花点时间来赞赏,原因有二。

首先,这是 vLLM 和 PyTorch 在 PyTorch 基金会支持下高效协作的具体案例。TAC 不仅仅是一种治理仪式;它是一个平台,让下游项目的痛点能够直接呈现在能够解决问题的人面前,并使跨项目协调成为常态,而非偶然。这个问题经历了完整的旅程——从黑客松时开发者对着终端咒骂,到 TAC 讨论,再到 GitHub 议题跟踪,直至最终发布——而基金会正是缩短这一路径的核心力量。

其次,开发者体验具有复合效应。人们不用在 --index-url 标志上花费的每一个小时,都是实实在在用于在 vLLM 和 PyTorch 之上构建应用的时间。aarch64 GPU 系统只会越来越普及,最好现在就在基础设施层面解决这个问题,而不是让每个用户都不得不自己去发现并处理它。

uv 端的变通方案(构建隔离穿透)是更广泛的 WheelNext 计划 的一部分——这是一项非常值得欢迎的推动,旨在重塑 AI 时代 Python 打包如何处理加速器依赖问题。

特别感谢促成此事的人员:PyTorch 核心团队的 Alban Desmaison、Nikita Shulga 和 Andrey Talman,他们接收了最初的诉求并推动其落地;NVIDIA PyTorch 团队,他们推动了 aarch64 的构建工作,并确认修复已在 2.11.0 中落地,同时感谢 Piotr Bialecki 在 NVIDIA 和上游之间保持协调;感谢 PyTorch 发布工程团队构建并发布了这些 wheel;还要感谢幕后无数的工程师——跨越 PyTorch、NVIDIA 和 Arm——是他们在工具链、CI 基础设施和打包工作上的努力让这一切成为可能。也感谢 TAC 的每一位成员,保持了对话的大门敞开。

继续前行。