
1. 从“能跑”到“好用”多元硬件时代 AI 基础设施的真实门槛如果你最近两年搭过训练集群或者推理服务大概率会有一种强烈的撕裂感模型代码本身没怎么改但底层硬件从一家独大变成了“八仙过海”。CPU、GPU、NPU、各类加速卡甚至同一家厂商的不同代际产品指令集、内存层级、通信拓扑都不一样。PyTorch Conference China 2026 的同期活动把“多元硬件时代如何构建好用的 AI 基础设施”作为核心议题恰恰戳中了当下工程团队最疼的地方——不是没有硬件而是硬件多了之后软件栈的适配成本呈指数级上升。我先说一个反直觉的结论多元硬件适配的难点从来不在“驱动装不上”这种表层问题而在于“性能可移植性”。什么意思同一段 PyTorch 模型在 A 卡上跑出 70% 的算力利用率换到 B 卡上可能只有 30%而且你很难一眼看出瓶颈在哪。这就是“好用”和“能跑”的分水岭。能跑是框架层面把算子映射过去好用是让开发者不需要为每块卡重写一遍 kernel也不需要为每个后端维护一套独立的部署流水线。这篇文章适合三类人看一是正在做异构集群选型和适配的 Infra 工程师二是被“换卡就要重调性能”折磨过的算法工程师三是想理解 AI 编译器、算子库、运行时之间关系的技术管理者。我会围绕 PyTorch 生态在多元硬件下的适配逻辑、AI 编译器的实际作用边界、以及基础设施“好用”的评判标准展开尽量把那些文档里不会写的坑和取舍讲透。需要先明确一个前提PyTorch 本身是一个“前端框架 后端调度”的分层结构。前端负责图捕获、自动微分、内存管理策略后端负责把算子落到具体硬件。多元硬件时代真正决定体验的是后端这一层——也就是torch.compile、Inductor、各类 vendor backend、以及底层算子库的协同。理解了这条链路你才能判断一套基础设施到底“好用”在哪、卡在哪。2. PyTorch 在异构硬件上的分层适配逻辑2.1 从 eager 到 compile图捕获为什么是适配的前提早期 PyTorch 以 eager 模式为主算子逐个下发硬件厂商只需要实现对应的算子接口就能“跑起来”。但 eager 模式的问题是框架看不到全局计算图无法做跨算子的融合和内存复用优化。到了多元硬件场景这个问题被放大——不同硬件的内存带宽、片上缓存、并行粒度差异巨大逐算子下发几乎不可能榨出性能。torch.compile 的出现改变了这个局面。它通过 TorchDynamo 做字节码级别的图捕获把 Python 执行流里的张量计算抽成 FX Graph再交给后端编译器处理。对硬件厂商来说这意味着适配的接口从“实现几百个算子”变成了“实现一套图编译后端”。工作量结构变了但难度并没有消失因为图级别的优化对硬件特性的依赖更深。我实测下来的体会是图捕获的完整性直接决定了后端优化的上限。如果模型里有大量动态控制流、data-dependent 的分支Dynamo 会频繁 graph break退回到 eager 执行。这时候无论后端多强性能都上不去。所以在异构硬件上做适配第一步不是急着调后端而是先看 graph break 率。用TORCH_LOGSgraph_breaks跑一遍把 break 点逐个消掉往往比换任何硬件都管用。2.2 Inductor 与 vendor backend 的分工边界TorchInductor 是 PyTorch 默认的编译后端它负责把 FX Graph 降成 Triton kernel 或者 C 代码。但在多元硬件场景下很多厂商会提供自己的 backend比如针对特定加速器的图编译器。这里有个常见的误解以为 vendor backend 会完全替代 Inductor。实际上更合理的分工是——Inductor 负责通用的图优化和调度决策vendor backend 负责把调度后的中间表示映射到自家硬件的指令和内存模型。这个边界如果划不清就会出现两种典型问题。第一种是厂商把太多逻辑塞进自己的 backend导致和上游 PyTorch 版本耦合严重每次框架升级都要大改。第二种是厂商只做最薄的算子映射图优化全靠 Inductor结果硬件特有的融合机会比如某些加速器的矩阵乘加融合单元完全用不上。我的建议是把硬件无关的图优化留在 Inductor把硬件相关的调度和指令选择下沉到 vendor backend。判断标准很简单——如果某个优化换一块卡就不成立了那它就该属于 vendor 层如果换卡之后依然有效那它就该留在通用层。这条线划清楚后续维护成本会低很多。2.3 算子库与运行时的“最后一公里”图编译之后真正执行的是算子库和运行时。这一层最容易被忽视却往往是性能差异的来源。以矩阵乘为例同样一个matmul不同硬件上的最优分块策略、数据排布、流水线深度完全不同。厂商的 BLAS 类库如果针对自家硬件调得好性能可能比通用实现高出一大截调得不好反而拖后腿。运行时层面还涉及内存分配器、流调度、通信库。多元硬件集群里不同节点的加速器可能不一样集合通信的实现也要跟着变。我见过一个案例训练任务在纯 A 卡集群上扩展效率很好混入 B 卡之后all-reduce 的耗时突然翻倍排查很久才发现是通信库对异构拓扑的路径选择有问题。这类问题不会在框架文档里写只能靠实际压测暴露。提示评估一套异构基础设施时不要只看单卡峰值算力一定要看“同模型跨硬件性能方差”。方差越小说明软件栈的适配越成熟。3. AI 编译器在多元硬件里的真实作用与边界3.1 编译器不是万能药它解决的是映射问题不是算力问题很多人对 AI 编译器抱有过度期待觉得只要编译器够强任何硬件都能自动跑出最优性能。这个期待需要降温。编译器的核心能力是把高层计算图映射到目标硬件的执行原语它能做算子融合、内存规划、循环变换但它无法凭空创造硬件不具备的能力。如果某块卡没有特定的矩阵运算单元编译器再聪明也只能用通用指令模拟性能天花板就在那里。所以选型时的正确姿势是先看硬件的能力集是否匹配你的模型结构再看编译器能否高效利用这些能力。比如你的模型以大规模矩阵乘为主那就要重点考察该硬件在 matmul 上的实际吞吐和编译器的融合策略如果模型里有大量小算子那编译器的 kernel launch 开销和融合能力就更关键。3.2 图级优化与算子级优化的取舍AI 编译器的工作可以粗分为图级和算子级。图级优化关注算子之间的融合、内存复用、并行调度算子级优化关注单个算子在特定硬件上的指令选择和循环展开。两者需要配合但资源有限时要有取舍。我的经验是在多元硬件适配的早期阶段优先投入图级优化。原因是图级优化的收益更通用换硬件后大部分逻辑依然成立而且能快速把 graph break 带来的性能损失补回来。算子级优化则应该交给最了解硬件的厂商去做框架团队没必要越俎代庖。等图级优化稳定之后再针对关键算子做深度调优投入产出比更高。3.3 编译缓存的工程价值还有一个容易被低估的点编译缓存。图编译是有成本的尤其是大模型首次编译可能耗时几分钟甚至更久。在多元硬件集群里如果每次任务启动都要重新编译调度效率会非常低。把编译结果按“图结构 硬件标识 编译选项”做缓存能显著缩短冷启动时间。这里有个坑缓存 key 的设计要足够细。我见过只按模型名做缓存的方案结果换了硬件或者改了 batch size 就命中错误的缓存跑出莫名其妙的精度问题。正确的做法是把硬件型号、驱动版本、编译器版本、关键编译参数都纳入 key。宁可缓存命中率低一点也不能命中错误的缓存。4. 构建“好用”基础设施的四个实操维度4.1 统一抽象层让开发者不感知硬件差异“好用”的第一条标准是算法工程师写模型时不需要关心底层是哪块卡。这需要一层统一抽象把设备管理、内存分配、算子调用都封装起来。PyTorch 的device抽象已经提供了基础但在多元硬件下还不够因为不同后端的初始化方式、内存池行为、错误码都不一样。实操上我建议在框架和硬件之间加一层薄薄的适配层统一设备枚举、健康检查、内存查询这些接口。这层不要做太多逻辑否则会变成新的耦合点。它的价值在于当新硬件接入时只需要实现这层接口上层的训练脚本和部署流程基本不用改。我们内部做过对比有这层抽象之后接入一款新加速器的时间从两周缩短到三天左右。4.2 性能可观测性没有度量就没有优化第二条标准是性能可观测性。多元硬件环境下性能问题的根因可能在框架、编译器、算子库、驱动、甚至硬件本身。如果没有统一的 profiling 数据排查就是盲人摸象。PyTorch Profiler 和 Kineto 提供了基础能力但不同后端的支持程度参差不齐。我的做法是建立一套跨硬件的性能基线同一组模型、同一组输入在不同硬件上跑出算子级耗时、内存占用、通信耗时存进统一的数据库。每次框架或驱动升级后自动回归一旦某项指标偏离基线超过阈值就告警。这套机制帮我们抓到过好几次隐蔽的性能回退比如某次编译器升级导致某个融合算子被拆开单看端到端耗时只涨了 3%但算子级数据一眼就能看出问题。4.3 容错与降级异构集群的稳定性设计第三条标准是容错。异构集群里不同硬件的故障模式不一样有的会直接报错有的会静默降频有的会在特定负载下才暴露问题。如果基础设施没有降级机制一个节点的异常可能拖垮整个任务。具体做法包括任务级检查点要足够频繁且检查点格式与硬件无关调度器要能识别节点健康状态把异常节点摘除对于非关键路径的计算可以配置降级策略比如从加速卡回退到 CPU 执行。这些机制在纯同构集群里可能显得多余但在多元硬件环境下是刚需。4.4 版本矩阵管理最枯燥但最致命的一环第四条标准是版本管理。PyTorch 版本、编译器版本、驱动版本、算子库版本任意一个不匹配都可能导致性能下降甚至功能异常。多元硬件意味着版本组合的数量成倍增长靠人工维护几乎不可能。我建议用矩阵化的方式管理把每个硬件后端支持的版本范围明确列出来CI 里针对关键组合做冒烟测试。不要追求覆盖所有组合而是覆盖“生产环境实际使用的组合 边界组合”。同时升级任何一个组件之前都要在矩阵里查清楚影响范围。这一步很枯燥但跳过它前面所有的优化都可能因为一次不经意的升级而付诸东流。5. 踩坑实录异构适配中那些文档不会写的问题5.1 精度对齐不同硬件的浮点行为差异第一个坑是精度。不同硬件的浮点运算实现可能有细微差异尤其是涉及归约、累加、超越函数的时候。单卡上看不出来多卡或者跨硬件对比时loss 曲线可能慢慢分叉。我们遇到过一次同一模型在两种卡上训练前几百步 loss 几乎一致到后面逐渐偏离最后精度差了零点几个百分点。排查思路是先固定随机种子对比前向输出的逐层差异定位到具体算子然后检查该算子在两种硬件上的累加顺序和精度模式。解决办法通常有两个一是统一使用更高精度的累加牺牲一点性能换一致性二是在关键位置插入精度对齐操作。没有银弹只能逐个算子确认。5.2 内存碎片长时间训练任务的隐形杀手第二个坑是内存碎片。不同硬件的内存分配器策略不同有的对碎片不敏感有的跑几个小时之后就会出现大块内存申请失败。表现是任务突然 OOM但显存监控显示还有余量。应对方式是尽量使用框架提供的内存池避免频繁申请释放不同大小的张量对于长任务定期做内存整理或者重启 worker。另外编译器的内存规划策略也会影响碎片程度如果发现某后端碎片严重可以尝试调整编译选项让内存分配更规整。5.3 通信拓扑异构节点间的带宽陷阱第三个坑是通信。异构集群里不同节点的加速器之间可能没有高速互联或者互联带宽不对称。如果调度器不考虑拓扑把通信密集的任务分配到慢链路上整体效率会大打折扣。实操上要在调度层引入拓扑感知把通信密集的 rank 尽量放在同一节点或同一高速互联域内对于跨域通信评估是否值得做梯度压缩或者通信重叠。这些优化在同构集群里也有用但在异构环境下收益更明显。6. 从 Conference 议题看未来的适配趋势PyTorch Conference China 2026 把多元硬件适配放在核心位置本身就说明了一件事生态的重心正在从“框架统一”转向“后端多元”。过去大家关心的是用哪个框架现在关心的是同一套框架代码怎么在不同硬件上都跑得好。这个转变对基础设施团队提出了更高要求也带来了新的机会。我观察到几个趋势。一是编译器的标准化接口在推进厂商接入的成本会逐步降低但差异化竞争会转移到编译质量和算子库调优上。二是性能可移植性会成为核心指标未来评估一套基础设施可能不再看单卡峰值而是看“跨硬件性能保持率”。三是自动化调优工具会越来越重要靠人工为每块卡调参不可持续。对一线工程师来说我的建议是不要把自己绑死在某一款硬件上而是深入理解 PyTorch 的编译链路和性能分析方法。这些能力是跨硬件通用的硬件会换但“看懂图、定位瓶颈、做取舍”的功夫不会过时。多元硬件时代真正稀缺的不是会用某块卡的人而是能在不同卡之间做迁移和权衡的人。最后分享一个我在实际项目中反复验证的小技巧每次接入新硬件先跑一个最小可复现的 benchmark 套件包含 matmul、attention、elementwise、通信四类负载把数据记录下来。这套基线不需要很复杂但能在后续任何一次升级或变更时帮你快速判断是硬件问题、软件问题还是配置问题。基础设施的“好用”往往就藏在这些不起眼的基线数据里。