Chris Lattner:Mojo 与可移植 GPU 性能的追求

原标题Chris Lattner on Mojo and the Search for Portable GPU Performance

Ron Minsky 与 Chris Lattner 讨论 Modular 如何通过语言和编译器设计,努力让加速器编程兼顾可移植性与速度。

CLChris Lattner嘉宾 · Modular
频道
Jane Street
发布
2025年9月4日
视频
1:12:58
阅读
18 分钟
原文
英语
在 YouTube 打开
往下滚动阅读时,视频会缩到右下角继续播放。字幕跟随阅读语言。
阅读语言共 2 种语言可读
由 AI 从英语原文翻译。打开“对照原文”可以逐段核对。
摘要

30 秒看懂

在 Signals and Threads 节目中,Ron Minsky 与 LLVM 和 Swift 的创造者 Chris Lattner 探讨 AI 硬件软件栈的碎片化,以及 Modular 为何创建 Mojo。两人讨论了 GPU 硬件、元编程、类型系统、特化、测试,以及依赖“足够聪明的编译器”所带来的风险。 Lattner 介绍了 Modular 的商业模式,以及他对 Mojo 兼容性、Python 集成和未来发展的计划,同时区分了这些愿景与这场 2025 年对话时语言已经具备的能力。

  1. 1碎片化的加速器软件栈Lattner 说,硬件厂商围绕自己的设备构建独立软件栈,使提供性能一致且可移植的软件变得困难。
  2. 2Mojo、MAX 和 Mammoth他介绍了语言层、单节点服务层和集群管理层,并将企业服务作为 Modular 的目标业务。
  3. 3编译期和运行期使用同一语言Mojo 的元编程旨在让库作者用熟悉的语言结构为硬件特化代码,同时避免运行时解释开销。
  4. 4超越单一厂商的特化即使尚未考虑跨厂商移植,数据类型、矩阵形状、内存布局和硬件代际也会影响高效内核的设计。
  5. 5管理抽象的复杂性Lattner 认为,相比不受限制的模板展开,trait 和泛型类型检查可以让接口更容易检查和组合。
  6. 6当前用途与未来计划他将高性能代码和 Python 扩展列为当前用途,同时把更广泛的语言兼容性视为长期目标。

要点建议

  1. 针对特定硬件的 AI 软件栈使可移植性与性能难以兼得。
  2. Mojo 旨在提供类似 Python 的语法,同时让程序员拥有底层控制和编译期元编程能力。
  3. 了解硬件特性的库可以针对数据类型、布局和设备特化同一算法。
  4. 相比不透明的编译器优化,可预测的编程模型能让性能工程师拥有更多控制权。
  5. 经过类型检查的泛型接口可以让抽象更容易推理,但庞大的配置空间仍需要测试。
  6. Lattner 将更广泛的 Python 兼容性和语言发展视为未来目标,而非已经完成的成果。
全文

按章节阅读整理后的全文

只看原始文稿
01

从 LLVM 到 Swift

Lattner 回顾学习计算机、构建 LLVM 和启动 Swift 的经历。他与 Minsky 讨论实际用途和数学基础如何影响语言设计。

Ron Minsky 询问 Chris Lattner 如何进入编译器工程和语言设计领域。Lattner 回忆说,他伴随早期个人电脑长大,从书上逐字输入程序,并学着调试自己犯下的错误。游戏和早期在线讨论激发了他对图形、性能和硬件的兴趣。

在 University of Portland,教授 Steven Vegdahl 对编译器的热情引导 Lattner 进入这一领域。后来他在 University of Illinois 构建了 LLVM。他喜欢编译器课程逐层构建大型系统的方式,而不是只完成互不相干的作业。

Lattner 说,编译器课程也让抽象数据结构在具体系统中发挥了作用。Minsky 将这与操作系统课程相比:学生同样需要逐层构建系统。

Minsky 指出,Lattner 一直在编译器工程和语言设计之间切换。Lattner 说,他的职业经历随兴趣变化:LLVM 让他学习底层代码生成,并为他实现 C++、后来开发更高层的 Swift 语言提供了基础。他认为自己最有价值的工作发生在软硬件交界处。

Lattner 描述了自己从后端代码生成向 Clang 和 Swift 逐步深入的过程。参与 AI 系统和教孩子编程的 iPad 应用,也反映出他希望在技术栈的不同层次解决有用的问题。

Lattner 说,LLVM 始于 2000 年,他于 2005 年加入 Apple。到 2010 年左右,Clang 的 C++ 支持已经能够构建编译器自身及高级库。实现 C++ 在技术上很有趣,但项目交付后他精疲力竭,希望有一门更好的语言。

Swift 最初是他在晚上和周末做的项目,而不是管理层的指令。Lattner 认为,语言设计者不必发明每一种思想:例如模式匹配早已相当成熟,但当时许多主流语言仍没有它。

Minsky 解释了代数数据类型和模式匹配的用处:它们让程序能够表示不同可能性,并可靠地逐一分析。Lattner 说,他以工程师的角度看待这些特性,首先关注它们解决的问题和能够写出的表达力强的代码。

Lattner 说,学习 OCaml 时,模式匹配立刻给他留下了深刻印象:它让普通任务变得简单而富有表达力。他认为,推广特性需要展示实际用途,而形式化类型理论则解释了特性为什么能够正确组合。

Minsky 补充说,扎实的数学基础可以帮助特性推广并组合到最初用途之外。Lattner 同意,好的设计各部分能简单地结合起来,尽管他的设计过程有时会重新发现研究人员早已知道的思想。

Minsky 问 Lattner 在以工程师的方式设计之后,如何寻找数学上的洞见。Lattner 说,他会关注研究,阅读将思想与例子和结果联系起来的解释,尽管密集的数学符号让他不那么自在。

Lattner 说,他经常从论文的例子和结果,或关于学术语言、通俗易懂的博客文章中学习。他重视把复杂特性与具体问题联系起来的解释。Minsky 也认为,非正式解释是严谨理论的补充。

Lattner 把语言复杂性比作一粒沙子,它会在其他地方引发许多麻烦。C++ 面临大量已有约束,不能简单删除旧特性;Swift 和 LLVM 也有他希望重新审视的设计决定。构建新系统是从这些选择中吸取教训的机会。

02

碎片化的 AI 软件栈

硬件厂商开发了各自的加速器软件栈,支持范围和性能各不相同。Lattner 解释 Modular 为什么希望构建可移植的基础平台和企业服务。

Minsky 问到 Mojo 和 Modular。Lattner 将问题追溯到计算从 CPU 转向 GPU、TPU、FPGA 等 AI 加速器。他说,MLIR 从 LLVM 的经验中吸取教训,为这个更新、更多样的世界提供了基础编译器技术。

Lattner 说,LLVM 为 Swift、Rust 和 Julia 等 CPU 时代的语言提供了共同基础。MLIR 将这些经验应用到更广泛的加速器和 AI 编译问题,但共同的中间层技术并没有消除碎片化。

尽管 MLIR 已被广泛使用,Lattner 说,AI 软件仍分散在 NVIDIA CUDA、Google XLA 和 AMD ROCm 等不同软件栈中。PyTorch 等高层工具必须运行在彼此不兼容的基础上,而硬件和模型也在迅速变化。

他认为碎片化部分源于激励机制。硬件厂商必须为自己的芯片和未来路线图构建软件,很少有资源或动力为竞争对手的硬件建立共同层。相比之下,用户希望软件可以在不同设备间移植。

Minsky 指出,高层框架建立在不兼容的底层系统之上,因此跨平台支持也可能不完整。新硬件和软件快速出现,让协调整个生态更加困难。

Lattner 认为,在不一致的软件栈上再添加一层抽象,不一定能修复性能或可靠性问题。一旦出错,用户仍须调试下面的各层。Modular 希望构建一个更底层、可移植的替代方案,取代针对特定硬件的软件基础。

他说,这个目标刻意定得很难:在厂商自己的硬件上达到或超过厂商软件的性能,尽管 NVIDIA 经验丰富,CUDA 也有多年先发优势。他认为,如果用户希望生态不那么依赖单一厂商,总得有人承担这项工作。

Lattner 将这描述为长期投入,而不是快速修补。他希望可移植的基础平台能帮助更多人使用加速器,并减少对单一硬件供应商的依赖。

Minsky 问,既然销售编程语言出了名地困难,Modular 如何建立共享平台。Lattner 说,公司并不销售 Mojo 本身:语言免费使用,目标业务是在基础平台上提供企业服务。

他描述了管理数百或数千个 GPU 的平台团队,以及不断引入新模型的产品团队。不同硬件、CUDA 版本和快速变化的开源依赖让生产部署变得困难。Modular 希望帮助这些团队解决性能、可观测性、可管理性和跨硬件部署问题。

预期的企业价值不只是更快的内核。Lattner 说,协调设备和软件版本的支持可以减少平台团队必须管理的组合数量,让生产工作负载更容易持续运行。

Lattner 描述了三层架构:Mojo 是编程语言,MAX 是单节点高性能服务层,Mammoth 是集群管理层。他说,自己起初不愿意创建新语言,因为语言开发成本高,也很难说服人们采用。

在他看来,问题是如何编写可移植的加速器代码,同时不放弃昂贵硬件的全部性能。对于团队希望支持的异构设备和特殊数值格式,现有语言没有提供令人满意的答案。

03

硬件与性能问题

两人比较 CPU 和 GPU 的执行方式、张量核心、硬件代际变化及现有编程工具。Lattner 解释为什么他认为需要一门新语言。

对话转向硬件。CPU 有许多核心,支持成熟的多线程工作负载。GPU 采用不同模型,包含流式多处理器和大量线程;张量核心则为 AI 常见的矩阵乘法提供专用硬件。

Minsky 将 GPU 的 warp 描述为一起执行的线程组,硬件资源使线程切换足够便宜,从而隐藏延迟。张量核心又引入另一种专门的执行模型,其性能和内存特征会随 GPU 代际变化。

Minsky 描述了 NVIDIA 硬件从 Volta 到 Ampere、Hopper 的变化,包括张量核心和内存模型的差异。他和 Lattner 强调,内核必须考虑这些变化,不能假设 GPU 架构始终不变。

Lattner 认为,CUDA 是为更简单的一代 GPU 设计的,难以随着硬件变化而演进。TPU 和其他加速器可能进一步偏离 GPU 的线程模型,围绕大型矩阵运算组织硬件。他提出的 Mojo 目标是从基本原理出发支持这些系统。

他还指出不同硬件代际之间的不兼容,并认为如果工具牺牲过多峰值性能,用户最终可能需要切换到另一套系统。他希望结合易用性、可移植性和足够的控制权,接近硬件全部性能;这些是目标,并非已经普遍得到证明的保证。

Minsky 将 C++ 传统中的底层 GPU 语言与更安全的方案进行比较。未定义行为给编译器优化正确程序的空间,但未初始化变量等错误会让真实程序难以推理和调试。

Lattner 理解 C++ 实现者的处境,因为大量现有代码必须继续运行。优化器往往需要改进不能修改的程序。他认为,在新的 AI 工作负载中,程序员通常能够控制代码,因此更受益于明确的能力和表达力,而非针对特定基准所做的高难度编译器技巧。

Lattner 说,历史遗留约束可以理解,但新语言可以用清晰的编译错误拒绝使用未初始化变量之类的错误。他认为,易用性和诊断信息与原始性能一样,都是 Mojo 设计的一部分。

Minsky 观察到,GPU 内核通常短小却价值很高,编写者也相对少而专业,因此精确控制性能尤其重要。Lattner 补充说,AI 编码工具可以帮助新人学习语言或翻译现有内核,但也提醒这些工具并非魔法。

04

Mojo 与编译期元编程

Mojo 借鉴 Python 语法,同时追求显式类型、硬件控制和可复用的编译期抽象。Minsky 将它与模板及基于 Python 的 DSL 比较。

谈到 Mojo 的设计,Lattner 说,它从 Python 语法出发,因为 AI 社区很多人已经熟悉 Python。为了性能、明确控制和元编程,Mojo 会在必要时偏离 Python。他希望人们用语言本身构建强大的硬件库,而不是把每一种抽象都硬编码进编译器。

元编程让代码既能在编译期运行,也能在运行期运行。许多语言在两个阶段使用不同机制,例如运行时的普通循环和编译期的递归 C++ 模板。Mojo 希望让程序员在两个阶段使用相似的语言结构。

在编译期使用列表、字符串和算法,让库作者能够在程序运行之前构造更高层的抽象。Lattner 认为,与复杂的模板栈跟踪相比,在不同阶段使用同一语言也有助于调试。

Lattner 说,这对张量核心很重要,因为不同厂商和设备代际的布局与索引方式各不相同。库可以在更高层表示这些细节,并在编译期完成大量工作,而开发者仍使用熟悉的语言和调试工具。

Minsky 把元编程视为解决解释开销的老方法。通用解释器可以表达领域专用计算,但它在运行时做决定。代码生成则可以提前完成已知决策,生成特化的机器代码。

困难在于如何让这些机制容易理解。C 宏和 C++ 模板很强大,但推理起来可能很痛苦,尤其是错误只在深层展开之后才出现时。Minsky 说,Mojo 的目标是用一套语言和类型系统覆盖生成代码与运行时代码,并明确区分阶段。

Minsky 说,他的团队早期使用 Mojo 的体验很有希望。与 C++ 模板和嵌入 Python 的 GPU DSL 相比,他欣赏能够从语法中看出一个值属于编译期还是运行期。这种明确性对性能工程很有用。

Minsky 指出,PyTorch 可以让 Python 代码看起来很直接,实际却通过谨慎延迟操作并重叠 CPU 和 GPU 工作来获得性能。这可能非常高效,但执行模型比源代码看起来更微妙。

两人讨论了“足够聪明的编译器”的吸引力和危险。自动并行化或惰性执行可以让简单示例看起来容易,但很小的代码改动可能使优化失效或性能骤降。发生这种情况时,用户可能不得不检查编译器内部。

05

可预测性、特化与可移植性

两人讨论不透明编译器优化的局限,以及元编程如何针对类型、形状、布局和硬件特化内核。

Minsky 将利用推测执行和预取来加速顺序程序的 CPU,与更明确并行的加速器进行比较。CPU 灵活,硬件技巧也经常效果显著;明确并行的机器对程序员要求更高,但可能在性能和能效上有优势。

Lattner 说,明确控制是 Mojo 刻意做出的设计选择。在他看来,与全自动接口相比,这会让高级硬件编程更难,却能帮助用户理解并追求所需性能。

Minsky 问元编程如何带来可移植的性能。Lattner 说,即便一个矩阵乘法算法也有许多特化版本:数据类型改变缓存能容纳的数据量,矩阵形状改变访问模式,硬件则规定不同布局和操作。

从 32 位值改为 16 位值,缓存中可容纳的元素数量可能翻倍,因此最佳访问模式也可能改变。矩阵形状又增加了更多情况,所以即使看似简单的通用操作,也可能需要大量特化。

这些差异既存在于不同厂商之间,也存在于同一厂商的产品线内部。Lattner 介绍了一种布局张量抽象,它不仅表示多维数组,还表示内存布局和访问模式,让库能够把计算映射到特定硬件。

他提出的组合是类型系统、编译期元编程,以及了解硬件的领域专家。他希望内核专家构建可复用的库,针对计算问题和目标设备进行特化,而不是把每项优化都嵌入编译器。

Minsky 将好处概括为一个连贯的程序,其中编译期部分会选择并生成针对硬件的代码。接着他提出两个担忧:抽象能否隐藏足够的复杂性,让人们按模块推理;以及如何测试可能极其庞大的配置空间。

06

类型、泛型代码与可移植包

Minsky 询问如何管理复杂性并测试庞大的配置空间。Lattner 介绍 trait、泛型检查和可移植的包表示。

Lattner 的回答集中在类型和 trait 上,类似 Swift 协议、Rust trait 或 Haskell 类型类。Trait 可以描述不同集合类型上的迭代等操作,让编译器无需实例化每个具体实现,就能根据接口检查泛型代码。

迭代器是共享接口的简单例子:链表、数组和其他来源可以实现同一种概念。泛型代码可以使用该接口,而编译器会检查所需操作是否可用。

Minsky 说,C++ 模板的展开模型在深层组合时可能让错误难以理解,重复生成也会增加编译成本。基于类型的泛型接口可以改善推理和组合。两人的讨论并未给出覆盖所有硬件配置的完整测试策略。

Lattner 说,Mojo 编译器最初解析泛型代码时不会固定目标的指针大小或架构。该表示随后可以针对 CPU 或 GPU 特化。面向 GPU 的部分最终必须打包为适合该设备的独立代码。

Minsky 问,每个可执行文件是否都必须包含面向所有目标的编译器。Lattner 说,普通构建会生成常规可执行文件,而 Mojo 包可以保留可移植性,供之后特化。他将与目标无关的表示这一总体思想与 Java 比较,同时强调两者实现不同。

Minsky 将它与 NVIDIA 的 PTX 相比:PTX 是一种可移植的中间表示,会进一步编译到特定 GPU。Lattner 认为 Mojo 的表示保留了更丰富的泛型类型信息。Minsky 补充说,保留程序员指定的特化方式,让开发者能更好地控制目标代码的生成。

这种区别也关乎控制权。在 Minsky 描述的 PTX 模型中,针对目标的编译大多对程序员隐藏。Mojo 保留泛型表示的意图,则是把特化指令保留到选定目标的时候。

07

在语言演进中保持简洁

两人考虑语言复杂性、治理和版本兼容性。Lattner 将未来 Mojo 的版本管理与 Python 2 到 Python 3 的迁移进行比较。

Minsky 问,一门语言增加安全和性能所需的精确类型后,如何仍像 Python 一样容易上手。Lattner 说没有完美答案,但 Python 语法给团队提供了起点,也让团队有理由抵制没有充分必要性的特性。

他希望元编程和经过检查的泛型等核心机制能够吸收复杂性,而不是不断累加无关特性。他以 Go 的克制为例:即使每个用户都希望多一个特性,选择较小的特性集合仍能控制复杂度。

Lattner 回忆说,他曾批评 Go 最初没有泛型,但其设计者守住了边界,后来才有意识地加入这一特性。他从中得到的教训是:每个单独看起来有用的特性,都有复杂性成本。

Minsky 将这一挑战称为维持语言的功率重量比。团队需要空间尝试、撤回和调整想法,但一旦庞大的开源生态依赖该语言,这就更难了。Lattner 说,Swift 的开放提案流程带来了有价值的想法,也带来了增加特性的压力。

对于 Mojo,他倾向于由一个小型核心团队审慎决策。他说团队正在讨论 1.0 发布意味着什么,但没有承诺日期;他希望版本机制允许语言变化,同时让不同主版本的包可以互操作。

Lattner 将这一愿景与漫长的 Python 2 到 Python 3 迁移相比:后者要求整个包生态迁移。他指出 C++ 可以链接按不同语言版本构建的代码,希望 Mojo 能将兼容性与帮助迁移源代码的工具结合起来。

08

编码代理与 Mojo 的未来

对话转向 AI 编码工具、Python 扩展和可能的长期语言特性。Lattner 将愿景与已经得到证明的成果区分开来。

Minsky 认为,强类型系统可以在不执行每条路径的情况下发现错误,从而帮助迁移。他说,代码改动后,编码代理沿着类型错误逐一修复的效果也出奇地好。Lattner 表示赞同,并提到 Rust 稳定 API 的方法中有值得借鉴的思想。

Minsky 问,AI 代理如何使用 Mojo 这样较新的语言,因为模型训练数据中可能没有大量相关内容。Lattner 说,公开的 Mojo 代码和 GPU 内核可以由编码工具索引;正确配置工具以访问仓库会带来很大差别。

对话随后转向 Mojo 与 Python 的关系。Lattner 将对性能敏感的 CPU 和 GPU 代码列为当前用途,并说 Python 扩展支持处于预览阶段。他的目标是让用户把慢的部分移到 Mojo 中,而不必承担通常为另一门语言编写绑定的复杂工作。

在这场对话时,Lattner 将 Python 扩展工作流程描述为预览功能。他说,用户可以保留熟悉的语法,把 Python 包中较慢的部分移到 Mojo 文件,而不一定需要重写整个应用。

他举例说,一些用户获得了显著的 CPU 加速,随后又把工作移到 GPU。这些是他提供的个案,而非通用基准。Minsky 指出,许多 Python 包本来就依赖用 C、C++ 等语言编写的扩展。

Lattner 列出未来可能增加的功能,包括更多泛型能力、运行时 trait 和类似 Python 的类。他设想 Mojo 可用于更广泛的应用编程,并最终更像 Python 的演进版本,同时承认在对话时它还不兼容 Python。

他强调,宏大的愿景尚未得到证明:他对过去的语言工作经验有信心,但希望用户根据当前需求评估 Mojo,例如高性能代码、GPU 内核和 Python 扩展。Minsky 认为,即使改善异构计算这一近期目标,本身也已经很有雄心。

同频道的其他文章

1:48:29EN → 简体中文
JSJane Street· 2026年10月16日AI 如何改变编程:John Krazit 与 Ron Minsky 的对话Ron Minsky, John Krazit · Jane StreetJane Street 的 AI 工具负责人和 Signals and Threads 主持人探讨智能体基础设施、安全、代码审查,以及软件开发体验的变化。编程智能体Developer productivity评估+2
1:36:37EN → 简体中文
JSJane Street· 2026年9月23日Aaron Bauer:在 AI 时代教授软件工程Ron Minsky, Aaron Bauer · Jane Street当模型能够生成代码时,学习目标、主动练习和编辑器设计如何影响工程教育。AI in EducationSoftware engineeringEducation+2
9 张幻灯片1:05:45EN → 简体中文
JSJane Street· 2026年9月11日Cyrus Omar:实时编程与人与 AI 共享的计算公共空间Cyrus Omar通过 Hazel 演示,探讨即时反馈、结构化协作和精细权限如何帮助人类与 AI 智能体共同工作。Programming LanguagesHuman-AI Collaboration开发流程与测试+2
1:25:00EN → 简体中文
JSJane Street· 2026年9月2日Eric Mannes:如何将杂乱的外部数据用于交易研究Ron, Eric Mannes · Jane Street从商品期货和 Excel 风险系统,到时点数据集和 AI,Eric Mannes 解释 Jane Street 数据工程背后的领域知识。Data quality & curation开发流程与测试Investing+2
7 张幻灯片1:16:29EN → 简体中文
JSJane Street· 2026年8月26日Grant Sanderson 与 Alok Puranik:从群论看位置编码Grant Sanderson, Alok Puranik · 3Blue1Brown从注意力机制的假设出发,他们推导矩阵指数,并将旋转、衰减和 Jordan 块与 RoPE、ALiBi 联系起来。Transformers & attentionMathematics机器学习基础+1
4:41EN → 简体中文
JSJane Street· 2026年7月6日走进 Jane Street 实习项目:工作、导师与学习Cody · Jane Street实习生和员工讲述协作式面试、从零学习金融,以及参与公司实际使用的项目的经历。CareersCompany CultureMachine Learning+1