PyTorch 设计哲学 ¶
本文档旨在帮助贡献者和模块维护者理解 PyTorch 在发展过程中形成的高层次设计原则。这些原则并非硬性规定,而是作为指导,帮助权衡不同关注点,并在开发 PyTorch 时解决可能出现的分歧。有关贡献、模块维护以及如何将分歧升级至核心维护者的更多信息,请参阅 PyTorch 治理。
设计原则 ¶
原则 1:可用性优于性能 ¶
这个原则可能令人惊讶!正如一位 Hacker News 帖子作者所写:PyTorch 很棒! [...] 虽然我感到困惑。一个机器学习框架怎么能不痴迷于速度/性能呢?请参阅 PyTorch 在 Hacker News 上的讨论。
Soumith 的关于扩大 PyTorch 社区博客文章对此进行了深入探讨,但总的来说:
PyTorch 的主要目标是可用性
一个次要目标是实现合理的性能
我们认为保持我们的灵活性以支持在顶层构建抽象的研究者至关重要。我们无法预知未来工作负载的具体情况,但我们知道我们希望它们首先基于 PyTorch 构建,而这需要灵活性。
更具体地说,我们以可用性为首要原则,并尽量避免在没有清晰权衡的情况下直接进入以限制为首要的机制(例如,静态形状,仅图模式)。通常,人们会倾向于一开始就施加严格的使用限制,因为这可以简化实现,但这也伴随着风险:
性能可能不值得用户摩擦,要么因为性能优势不够令人信服,要么它只适用于相对狭窄的子问题集。
即使性能优势非常诱人,限制也可能将生态系统分割成不同的限制集合,这些限制很快就会变得难以理解。
我们希望用户能够无缝地将他们的 PyTorch 代码迁移到不同的硬件和软件平台,与不同的库和框架进行交互,并体验 PyTorch 用户的完整丰富性,而不仅仅是最低共同基数子集。
原则 2:简单至上
这里,我们借鉴了《Python 之禅》:
明确优于隐晦
简单优于复杂
描述这两个目标的更简洁方式是“简单胜于容易”。让我们从一个例子开始,因为在日常英语中,简单和容易经常被互换使用。考虑如何在 PyTorch 中建模设备:
简单/明确(易于理解、调试):每个张量都与一个设备相关联。用户明确指定张量设备移动。需要跨设备移动的操作会导致错误。
简单/隐式(使用):用户无需担心设备;系统会自动确定全球最优的设备放置位置。
在这个特定案例中,以及作为一般的设计理念,PyTorch 更倾向于暴露简单和明确的构建块,而不是易于实践者使用的 API。简单版本对于新 PyTorch 用户来说立即易懂且易于调试:如果你在程序中实际调用需要跨设备移动的操作符时,你会得到一个清晰的错误。简单的解决方案可能让新用户一开始就能更快地移动,但调试这样的系统可能很复杂:系统是如何做出决定的?如何将 API 插入到这样的系统中,以及对象在其 IR 中的表示方式是什么?
一些支持这种设计的经典论点来自《关于分布式计算的笔记》(TLDR:不要将具有非常不同性能特性的资源统一建模,细节会泄露)和端到端原则(TLDR:将智能构建到堆栈的底层可以防止在堆栈的更高层构建高性能功能,而且通常不起作用)。例如,我们可以构建操作级或全局设备移动规则,但精确的选择并不明显,构建一个可扩展的机制不可避免地具有复杂性和延迟成本。
这里有一个注意事项,这并不意味着高级“简单”API 没有价值;例如,在大型集群中支持高效张量计算的高级堆栈确实有价值。相反,我们的意思是,专注于简单的底层构建块有助于指导简单的 API,同时当用户需要离开常规路径时,仍能保持良好的体验。这也为创新和更多有见地的工具的增长留出了空间,这些工具的增长速度是我们无法在 PyTorch 核心库中支持的,但最终会从中受益,正如我们的丰富生态系统所证明的那样。换句话说,一开始不进行自动化,我们可以更快地达到良好的自动化水平。
原则 3:以 Python 为首选,具有最佳语言互操作性
这一原则始于以 Python 为首选:
PyTorch 并不是将 Python 绑定到一个单体 C++ 框架中。它是为了深度集成到 Python 中而构建的。你可以像使用 NumPy、SciPy、scikit-learn 或其他 Python 库一样自然地使用它。你可以使用你喜欢的库在 Python 自身中编写新的神经网络层,并使用 Cython 和 Numba 等包。我们的目标是,在不必要的地方不重复造轮子。
多年来,PyTorch 需要处理的一个问题是 Python 的开销:我们首先用 C++ 重写了 autograd 引擎,然后是大多数操作定义,接着开发了 TorchScript 和 C++ 前端。
尽管如此,在 Python 中工作为我们的用户提供的是最好的体验:它灵活、熟悉,也许最重要的是,拥有一个庞大的科学计算库和扩展生态系统可供使用。这一事实激励了我们最近的一些贡献,这些贡献试图在接近 Python 可用性曲线的 Python 端达到帕累托最优点:
TorchDynamo,一个能够以最小用户干预加速现有 eager-mode PyTorch 程序的 Python 框架评估工具。
torch_function 和 torch_dispatch 扩展点,它们使得在 C++ 内部构建基于 Python 的功能成为可能,分别对应 torch.fx 跟踪器和 functorch。
这些设计原则并非一成不变的规则,而是经过深思熟虑的选择,它们是构建今天我们所拥有的可调试、可修改和灵活的 PyTorch 框架的基石。随着我们拥有更多的贡献者和维护者,我们期待与您一起将这些核心原则应用于我们的库和生态系统。我们也愿意随着我们学习新事物以及 AI 领域的发展而不断演进这些原则,正如我们所知,它必将如此。