PyTorch 设计理念¶
本文档旨在帮助贡献者和模块维护者了解在PyTorch中随时间发展形成的高级设计原则。这些原则并不是硬性规定,而是作为指导,帮助权衡不同的关注点,并解决在开发PyTorch过程中可能出现的分歧。有关如何贡献、模块维护以及如何将分歧升级到核心维护人员的信息,请参阅PyTorch治理。
设计原则¶
原则1:可用性优于性能¶
这个原则可能令人惊讶!正如一位Hacker News的用户写道: PyTorch太棒了![…] 虽然我很困惑。一个机器学习框架怎么可能不痴迷于速度/性能? 参见 Hacker News关于PyTorch的讨论。
Soumith的博客文章《发展PyTorch社区》对此有深入的探讨,但总体来说:
PyTorch的主要目标是易用性
次要目标是具有合理的性能
我们认为保持灵活性以支持在我们抽象基础上进行研究的人员仍然至关重要。我们无法预见未来的工作负载会是什么样子,但我们知道我们希望它们首先基于PyTorch构建,而这需要灵活性。
在更具体的情况下,我们以易用性优先的方式操作,并尽量避免直接跳转到限制优先的模式(例如,静态形状、仅图形模式)而没有清晰地权衡利弊。通常有一种诱惑是在前期对用户施加严格的限制,因为这可以简化实现,但这伴随着风险:
性能提升可能不值得用户付出额外的麻烦,要么是因为性能优势不够显著,要么是因为它只适用于相对狭窄的一系列子问题。
即使性能优势令人信服,这些限制也可能将生态系统分割成不同的限制集合,这些集合很快就会让用户难以理解。
我们希望用户能够无缝地将他们的PyTorch代码迁移到不同的硬件和软件平台,与不同的库和框架进行互操作,并体验到PyTorch用户界面的全部丰富性,而不仅仅是最小公分母子集。
原则2:简单优于容易¶
在这里,我们引用自 Python 之禅:
显式优于隐式
简单优于复杂
对这两个目标更简洁的描述是 简单胜于容易。让我们从一个例子开始,因为在日常英语中,“简单”和“容易”经常被互换使用。考虑如何在 PyTorch 中建模 设备:
简单/明确(易于理解、调试):每个张量都与一个设备关联。用户显式指定张量的设备移动。 需要跨设备移动的操作将导致错误。
简单 / 隐式(使用): 用户无需担心设备;系统会找出全局最优的设备放置位置。
在这种特定情况下,以及作为一般的设计理念,PyTorch 更倾向于暴露简单和明确的构建块,而不是提供易于从业者使用的 API。简单的版本对于新的 PyTorch 用户来说是立即可以理解和调试的:如果你在程序中调用一个需要跨设备移动的操作符时,你会得到一个清晰的错误提示。虽然简单的解决方案可以让新用户在初期更快地进行操作,但调试这样的系统可能会变得复杂:系统是如何做出判断的?将对象插入到这种系统中的 API 是什么,这些对象在其 IR 中是如何表示的?
一些支持这种设计的经典论点来自关于分布式计算的说明(简而言之:不要统一建模性能特征差异很大的资源,细节会泄露)和端到端原则(简而言之:在堆栈的较低层中构建智能功能可能会阻碍在较高层中构建高性能特性,并且通常也不起作用)。例如,我们可以构建操作符级别的或全局设备移动规则,但具体的选择并不明显,而且构建可扩展机制不可避免地会带来复杂性和延迟成本。
这里的一个警告是,这并不意味着更高级的“简单”API没有价值;当然,在堆栈的更高级别上支持在大型集群中跨异构计算进行高效的张量计算是有价值的。相反,我们的意思是,专注于简单的低级构建块有助于为简单的API提供信息,同时在用户需要偏离常规路径时仍能保持良好的体验。这也为创新和更多有主见的工具的发展留出了空间,其发展速度是我们无法在PyTorch核心库中支持的,但最终会从中受益,正如我们< a data-trkey="0">丰富的生态系统所证明的那样。换句话说,一开始不进行自动化可以使我们更快地达到良好的自动化水平。
原则3:首先使用Python,具备最佳语言互操作性¶
这一原则最初是 Python优先:
PyTorch is not a Python binding into a monolithic C++ framework. It is built to be deeply integrated into Python. You can use it naturally like you would use NumPy, SciPy, scikit-learn, or other Python libraries. You can write your new neural network layers in Python itself, using your favorite libraries and use packages such as Cython and Numba. Our goal is to not reinvent the wheel where appropriate.
多年来,PyTorch 需要处理的一个问题是 Python 的开销:我们首先用 C++ 重写了 autograd 引擎,然后是大部分操作符定义,接着开发了 TorchScript 和 C++ 前端。
尽管如此,使用Python工作为我们的用户提供了最好的体验:它灵活、熟悉,并且也许最重要的是,拥有庞大的科学计算库和扩展生态系统可供使用。这一事实激发了我们最近的一些贡献,这些贡献试图在接近Python易用性一端的曲线上找到一个帕累托最优点:
TorchDynamo, 一个Python框架评估工具,能够在最小的用户干预下加速现有的 即时模式PyTorch程序。
torch_function 和 torch_dispatch 扩展点,这些扩展点使基于C++内部实现构建以Python为主的特性成为可能,例如 torch.fx 跟踪器 和 functorch 分别实现了这些功能。
这些设计原则并不是一成不变的规则,而是经过艰苦努力做出的选择,并且决定了我们如何构建PyTorch成为今天这样可调试、可修改和灵活的框架。随着我们有更多的贡献者和维护者,我们期待与您一起在我们的库和生态系统中应用这些核心原则。我们也愿意随着我们学习新事物以及AI领域的发展而不断进化这些原则,因为我们知道这是必然的趋势。