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