如何看待PyTorch 2.0?

news2024/11/16 9:36:13

e3ef9c9220012a710b2a7f2a0350b792.png
 

作者|吴育昕
 

1

为什么是TorchDynamo
 

Graph capture 把用户 Python 写的模型代码变成 graph,是一切编译的根基。而 PyTorch 在试了这么多方案之后似乎已经锁定 TorchDynamo 作为 graph capture 的未来方向了,所以写一点关于 TorchDynamo 的内容,主要是解释到底为什么要做这个东西(离开FB一年了,内容主要凭自己的猜测和理解)。

一句话尽量解释 TorchDynamo 干了什么:利用 PEP523(https://peps.python.org/pep-0523/) 的 API 在用户执行每个 python frame 前, 拿到这个 frame 的 bytecode,把其中认识的部分用 tracing 的方式提取出 graph (并送给后端编译),不认识的部分维持原样。把修改后的‍ bytecode还给 CPython 跑。

由于 LazyTensor 和 TorchDynamo 都做 tracing,并且都是 best-effort graph capture,即只编译自己能 capture 的部分,capture 不到的用 Python 跑 (aka Python fallback),所以观感上两者可能会差不多。

然而,这两个方案的差别正是 TorchDynamo 关键的地方:

LazyTensor 是个纯靠 tracing 的方案,不可避免的问题是「只能看见 trace 到的部分,只有 trace 一下才知道哪里不能 trace」。而每次执行模型的时候,不能 trace 的部分可能不太一样。为了保证正确性,LazyTensor 就不得不每次执行都要重新 trace。举个极端的例子,模型里写了一个torch.add(tensor, random.random()) ,其中 random 是个 LazyTensor 看不见摸不着的 Python 函数,那只有重新 trace 才能保证正确性。

而当 TorchDynamo 修改 bytecode 的时候,事情就不太一样了:

  1. 在 bytecode 里能够看得见所有需要的信息,所以能够证明「这段模型代码没有用到奇怪的东西所以不需要重新 trace」。

  2. 光证明了「不需要 trace」不代表可以真的不 trace,因为用户的代码还是一行行给 Python 来跑的。但是 TorchDynamo 又来了:CPython 到底跑什么 bytecode 是可以被它换掉的!

因此它可以做到这么一件事:当用户 call 一个被 capture 过的模型时,模型里大部分 Python 代码都相当于不存在了,连 symbolic execution 的 overhead 都没有,而被换成了编译后的 native code。这一点在以前所有的 partial graph capture 的方案里是做不到的:
 

  • LazyTensor 即使编译过的 graph 也要每次重新在 Python 里 trace 一遍,才能发现「哦,这个 graph 我曾见过的」。

  • @torch.jit.script 、@tf.function、 @jax.jit 可以把装饰的 python code 换成编译后的,但是这都依赖用户把这个 subgraph refactor 出来放到一个单独的函数里。而 TorchDynamo 是全自动不需要用户改代码的。

  • 这种 refactor 除了增加额外的工作量之外,还可能与用户的代码结构冲突,因为 「用来编译的graph的边界」与「用户代码需要的抽象边界」很可能不 match:例如用户本来希望写三个函数,但是最佳的优化是把其中两个半函数变成一个 graph,这会让用户很尴尬。

这只是一个最直接的例子。由于能够读写 bytecode,理论上 TorchDynamo 能 access 更多 LazyTensor 根本没有的信息,做更多事情(后面会提到)。而读写 bytecode 的难度比 source code要低不少,所以成为了一个可行的方案。

2
whole-graph capture用处不大?

有的人可能会说,上面提到的东西对 whole-graph capture 没太大用啊。 

我觉得确实是这样:TorchDynamo 是一个对 partial-graph capture 追求极致的方案,能够对几乎所有的 Python 实现的模型开箱即用有加速,不用改代码——前提是还要跑 Python 作为 fallback。但是部署一般需要的是 whole-graph capture 整个模型在一个 graph 里不能用 Python。

用 tracing 做 whole-graph capture 的前提是用户要在 Python 代码里避免所有不能被 trace 的东西,最常见的用户要做的三件事是:使用 symbolic shape,使用 symbolic control flow,禁用除了当前 tensor library之外的所有其它 library。如果用户做到了这些,那只要一个普通的 symbolic tracing 就能 capture 到完整的 graph 了,不需要 TorchDynamo 这么复杂的机制。TorchDynamo 可能可以略微简化用户做这些的工作量,但我感觉不会有本质不同。

我个人的观点是,从实用角度出发,要求用户做上面几件事不算是太复杂的要求:禁用其他 library 理所应当就不说了;即使今天 PyTorch 还没有很好的 symbolic {shape, control flow},但是只要用 @torch.jit.script_if_tracing 来处理少量的 symbolic shape 和 symbolic control flow,大多数模型都是可以正确的被 torch.jit.tracecapture 的。Meta 应该有几十上百个 vision 模型实现在 detectron2/d2go 里, 目前基本都是走这条路部署的(我另有篇文章https://ppwwyyxx.com/blog/2022/TorchScript-Tracing-vs-Scripting/介绍这里面的细节)。

TensorFlow 的 whole-graph capture 就简单了:TF 从第一天就有很好的 symbolic shape 和 symbolic control flow,用就完了。tf.autograph 甚至还自动化了一部分 control flow 的改写工作。

所以,用户少量改代码仍然是必须的。当然,TorchDynamo 毕竟有着"改变用户要跑的 bytecode" 的超能力。所以如果愿意的话,理论上可以让用户的 whole-graph capture 工作变得更简单。例如:
 

  • 模型中间的一些像 if x.shape[0] > 100 的分支,有的可以通过 shape inference 等价转移到模型开头的。这样的话就可以 capture 到更大的没有分支的 subgraph。 这件事在 TorchDynamo 里现在叫做 "guard"。 

  • 理论上可以把 python control flow 自动替换成 symbolic 的,类似tf.autograph 做的事情,只不过输入是 bytecode 而不是 source code。 
     

目前 TorchDynamo 的 "nopython" 模式就是 whole-graph capture 了。不过似乎还不是工作重心 (以下引用自https://docs.google.com/document/d/1tlgPcR2YmC3PcQuYDPUORFmEaBPQEmo8dsh4eUjnlyI/edit#heading=h.rmxeybu31e0):

PT2 will provide infrastructure for a no python export mode for edge and performance sensitive serving cases. The PT2 team won’t drive this end to end stack, but we will keep a feedback loop with the teams in charge of this and ensure the components we build are reusable in these situations.

不过与此同时,PyTorch 2.0 最近在完善 symbolic shape 的支持;functorch 里也加入了少量 control flow operator。这算是利好 whole-graph capture 的消息。

3
总结

总的来说,由于 TorchDynamo 在 bytecode 层面做文章,能做到一些其他方案做不到的事情。它的优点主要为 partial graph capture 服务: 让用户的 Python 模型代码在 0 修改的情况下就能 capture 并获得加速。这体现了 PyTorch 对于 "Python first" 哲学的执念。这种执着是否有必要,见仁见智。

TorchDynamo 的主要优势来自对 bytecode 的读写。JIT scripting compiler 的失败表明在 source code level 做不了太多事,TorchDynamo 能在 bytecode level 做事情确实很巧妙。不过,要完整的复刻 CPython bytecode interpreter,它的工作量、维护难度(以及出 bug 的概率)都是不小的。

另外,TorchDynamo 对 whole-graph capture 没有很大的帮助。 对于复杂的模型,用户该做的改写还是得做。不过我估计 2.0 至少能对「用户该做什么」有个清晰的说法。

当然,最后 PT2 到底能不能把 compiler 做好,还有很多其他因素:IR 怎么设计,何时specialize/recompile,各种 backend 不同的特性等等。比如 TorchDynamo 和 LazyTensor 使用的 IR 其实也不一样。但是本文只讨论 graph capture,其他问题就不提了。

(本文经授权后发布。原文:https://www.zhihu.com/question/570220953/answer/2798657470)
 

其他人都在看

  • 李白:你的模型权重很不错,可惜被我没收了

  • 单RTX 3090训练YOLOv5s,时间减少11小时

  • OpenAI掌门Sam Altman:AI下一个发展阶段

  • 32篇年度最佳AI论文;Python编译器Codon开源

  • 对比四大深度学习框架,我发现都关注两大问题

  • 比快更快,开源Stable Diffusion刷新作图速度

  • OneEmbedding:单卡训练TB级推荐模型不是梦

欢迎Star、试用OneFlow最新版本:GitHub - Oneflow-Inc/oneflow: OneFlow is a deep learning framework designed to be user-friendly, scalable and efficient.OneFlow is a deep learning framework designed to be user-friendly, scalable and efficient. - GitHub - Oneflow-Inc/oneflow: OneFlow is a deep learning framework designed to be user-friendly, scalable and efficient.https://github.com/Oneflow-Inc/oneflow/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/136824.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

假如面试官问你Babel的原理该怎么回答

1. 什么是 Babel 简单地说,Babel 能够转译 ECMAScript 2015 的代码,使它在旧的浏览器或者环境中也能够运行。 // es2015 的 const 和 arrow function const add (a, b) > a b;// Babel 转译后 var add function add(a, b) {return a b; };Babel…

pwr | 谁说样本量计算是个老大难问题!?(二)(独立样本均值篇)

1写在前面 上次介绍了两组发生率的样本量计算方法,通过pwr包进行计算非常简单,可以有效地减少我们的工作量。😘 有时候我们想比较两组之间的均值,如何计算样本量又一次成了老大难问题。🤒 本期我们还是基于pwr包&#…

【自学Java】Windows安装PyCharm IDE

Windows安装PyCharm IDE PyCharm下载 PyCharm下载地址 https://www.jetbrains.com/pycharm/PyCharm下载 打开上面的链接,打开 Python 的开发工具 PyCharm 的下载页面,如下图所示: 这里我们点击 Download,跳转到新的页面&#…

错过短视频,微博奔向新浪

以后新浪或许会被叫做“微博新浪”。 2022年12月23日晚,港股微博发布公告称,拟斥资15亿元收购新浪网技术有限公司100%股权。此举被外界解读为微博将反向收购新浪。 曾经,微博还是新浪移动互联网时代的“船票”。随着门户网站逐渐凋零&#…

基于ODX/OTX诊断的整车扫描

| ODX (Open Diagnostic data eXchange) 是基于XML语言、开放的诊断数据格式,用于车辆整个生命周期中诊断数据的交互。它一开始由ASAM提出并形成标准MCD-2D,后来以ODX2.2.0为基础形成了ISO标准——ISO 22901-1。 | OTX (Open Test sequence eXchange) …

Redis主从复制哨兵模式

Redis主从复制&哨兵模式一 什么是Redis主从复制1.1 主从复制的架构1.2 主从复制的原理1.3 主库是否要开启持久化1.4 辅助配置(主从数据一致性配置)二 主从复制配置2.1 slave 命令2.2 配置文件三 主从复制常见问题四 Redis哨兵机制4.1 什么是哨兵模式…

WebSocket服务端和客户端代码示例

目录一、WebSocket简介二、WebSocket服务端代码示例三、WebSocket客户端代码示例四、运行服务端和客户端,查看输出结果一、WebSocket简介 WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信&#x…

UE4 优化笔记

一、衡量场景性能的指标(这些指标优化前就要先记录下来,这样才知道优化了多少!) 1.stat unit:单元的状态。最开始根据这个数据,确定大致的优化方向 Frame:每帧消耗的总时长 Game:游戏线程运行消耗的时间 D…

迭代最近点ICP点云配准

传统ICP存在匹配速度慢,误匹配率高等缺点。 粗配准是在不清楚两个点云的相对位置的情况下,找到这两个点云近似的旋转平移矩阵,主要是为精配准提供初始变换矩阵;精配准在已知旋转平移矩阵的情况下,通过多次迭代优化进一…

Redis超详细版教程通俗易懂

【狂神说Java】Redis最新超详细教程通俗易懂 一、缓存、关系型数据库、非关系型数据库 关系型数据库存放在磁盘上,读取数据需要IO操作,速度非常慢非关系型数据库存放在内存上,读取数据速度非常快两者关系:一般会将数据存储在关系…

BGP在数据中心的应用4——BGP配置再优化

注: 本文根据《BGP in the Datacenter》整理,有兴趣和英文阅读能力的朋友可以直接看原文:https://www.oreilly.com/library/view/bgp-in-the/9781491983416/上一部分笔记请参考:https://blog.csdn.net/tushanpeipei/article/deta…

图论(3)单源最短路拓展

活动 - AcWing acw1137 如果我们确定了起点,那么就是一个模板题 选起点有两个办法:1.选取虚拟原点,连接家附近的所有车站。直接以虚拟原点作为我起点跑最短路即可。2.反向建图,取终点到家附近所有车站的dist,取min即…

JVM垃圾回收器-Serial回收器:串行回收

文章目录学习资料垃圾回收器Serial回收器:串行回收学习资料 【尚硅谷宋红康JVM全套教程(详解java虚拟机)】 【阿里巴巴Java开发手册】https://www.w3cschool.cn/alibaba_java JDK 8 JVM官方手册 垃圾回收器 Serial回收器:串行回…

JVM垃圾回收相关算法-垃圾清除阶段

文章目录学习资料垃圾回收相关算法垃圾清除阶段标记-清除(Mark - Sweep)算法复制算法标记-压缩(或标记-整理、Mark - Compact)算法分代收集算法增量收集算法分区算法学习资料 【尚硅谷宋红康JVM全套教程(详解java虚拟…

助力工业物联网,工业大数据项目介绍及环境构建【三】

01:业务系统结构 目标:了解一站制造中的业务系统结构 实施 数据来源 业务流程 油站站点联系呼叫中心,申请工单呼叫中心分派工单给工程师工程师完成工单工程师费用报销呼叫中心回访工单 ERP系统:企业资源管理系统,存…

RHCSE第一天(Linux的例行性工作)

文章目录Linux搭建服务器的准备工作第一章 Linux的例行性工作1.1 单一执行的例行性工作at1.1.1 at命令的实际工作过程1.1.2 at命令详解1.2 循环执行的例行性工作1.2.1 crontab命令的实际工作过程1.2.2 crontab命令详解1.3 实验实验一:定义三分钟之后显示hello实验二…

【前端】Vue项目:旅游App-(4)TabBar:Vant库实现功能与样式

文章目录目标代码和过程Vant库引入自定义样式初步修改样式修改修改active颜色icon调大实现路由跳转效果总代码修改的文件tab-bar.vuemain.js目标 前文手写了TabBar的样式和功能,本篇我们用vant库重新实现这些功能。 代码和过程 Vant库引入 Vant4 官方文档 安装&…

Servlet运行原理及生命周期

Servlet运行原理及生命周期一、Servlet 运行原理1.1 Tomcat 的定位1.2 Tomcat 的伪代码1.2.1 Tomcat 初始化流程1.2.2 Tomcat 处理请求流程1.2.3 Servlet 的 service 方法的实现二、Servlet生命周期一、Servlet 运行原理 承接 Servlet基础教程:https://blog.csdn.n…

spring oAuth2.0

会话 用户认证通过后,为了避免用户的每次操作都进行认证可将用户的信息保证在会话中。会话就是系统为了保持当前用户的登录状态所提供的机制,常见的有基于session方式,基于token方式等。 基于session的认证方式: 用户认证成功后&a…

Qt扫盲-QSS帮助手册使用

QSS帮助手册使用一、概述1. 查找 Qt Style Sheets Reference2. 收藏一下二、Qt Assistant 查阅帮助1. List of Stylable Widgets2. List of Properties3. List of Icons4. List of Property Types5. List of Pseudo-States6. List of Sub-Controls一、概述 导言:这…