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