首页 > 其他分享 >paddleSOT beginner

paddleSOT beginner

时间:2024-11-07 10:47:22浏览次数:4  
标签:转换 Tensor beginner 静态 paddle 计算 paddleSOT Numpy

paddleSOT beginner 入门学习

一个例子说明什么是动转静

示例:在动态图和静态图中的简单计算

假设我们有一个简单的神经网络模型,每次输入一个张量 x,然后做一些数学运算并输出结果。这个过程使用 PaddlePaddle 框架中的动转静技术可以分为两个部分来说明。

1. 动态图实现

在动态图模式下,代码逐步执行,每次传入数据时重新构建计算图。动态图实现如下:

import paddle
import numpy as np

# 动态图环境下
paddle.disable_static()

def simple_net(x):
    y = x * 2
    z = y + 3
    return z

# 输入数据
x = paddle.to_tensor([5.0])
output = simple_net(x)
print(output)  # 输出 [13.0]

在这里,simple_net 函数逐步执行乘法和加法操作,每一步都会即时构建计算图,然后得到结果 [13.0]

  • 优点:动态图的每一步都即时执行,调试方便,易于理解。
  • 缺点:每次运行 simple_net 函数,计算图都会重新构建,较大的网络或复杂计算下效率低。

2. 静态图实现(通过动转静转换)

在静态图模式下,可以预先构建一次完整的计算图,然后在需要时直接运行图中的计算。为了实现动转静转换,我们可以用 @paddle.jit.to_static 装饰器来将动态图代码转换为静态图。

import paddle
import numpy as np

# 启用静态图模式
paddle.enable_static()

@paddle.jit.to_static
def simple_net(x):
    y = x * 2
    z = y + 3
    return z

# 输入数据
x = paddle.to_tensor([5.0])
output = simple_net(x)
print(output)  # 输出 [13.0]
  • 转换过程:通过 @paddle.jit.to_static 装饰器,simple_net 函数在第一次运行时会将计算图构建为静态图,之后的执行会基于这个静态图,从而加快执行速度。
  • 优点:静态图在多次运行时不需要重复构建计算图,尤其适合在复杂的神经网络训练中使用。
  • 缺点:调试灵活性较低,且无法处理动态场景(如 if 条件语句随输入数据变化)。

动转静的优势

这个例子中,动转静技术可以让开发者编写代码时使用动态图模式(调试灵活),而在训练时转换为静态图以提高性能(避免重复构建计算图)。对于大型深度学习模型,动转静可以大幅提升训练速度,降低资源消耗。

AST方案下转换成功VS失败案例介绍

失败案例

def unsupport_func(x):
    x = 2 * x
    t = x.numpy() # t 依赖了 x 的值,依赖静态图的执行结果
    t = np.ones(t)
    return paddle.to_tensor(t)

x = paddle.to_tensor([2])
unsupport_func(x)  # raise error

在传统的 AST(抽象语法树)动转静转换方案中,这个例子会失败的原因主要在于 Tensor 和 Numpy 数据类型之间的动态转换问题。

具体分析

在函数 unsupport_func 中,代码逻辑如下:

  1. x = 2 * xx 是一个 Tensor,将其乘以 2 后依然是一个 Tensor
  2. t = x.numpy()t 依赖于 x 的值,并且调用了 x.numpy() 方法将 Tensor 转换为一个 Numpy 数组。这一步想要得到 x 的具体数值并存储在 t 中。
  3. t = np.ones(t):这里调用了 Numpy 函数 np.ones(t),其中 t 被当作 Numpy 数组来使用。

AST 动转静失败原因

在传统的 AST 动转静方案中,转换逻辑仅能对 Tensor 类型进行处理,且依赖于静态图模式下提前构建的计算图。然而,这里有几个动态转换的步骤导致了问题:

  1. 无法获取真实数值x 是一个 Tensor,在动转静转换时,x 实际上还没有被真正计算得到一个具体数值(即静态图模式下不会执行具体计算)。因此,调用 x.numpy() 时并不会得到实际的数值,而是仅得到一个「计算操作」。

  2. Numpy 和 Tensor 的互操作问题:由于 xt 在动转静转换中依旧被视作 Tensor 类型,传入 np.ones(t) 时,Numpy 接口无法识别 t 是一个真正的 Numpy 数组,而是一个 Tensor 操作。这种情况下,Numpy 并不能直接处理 Tensor,因此会报错。

进一步解释

在动转静转换中,AST 仅关注代码结构的转换,而不会执行代码本身,也无法获取中间计算的具体数值(因为这些值依赖于执行后的结果)。在本例中,由于 t 的值依赖于 x,而 x 本身是 Tensor 的一个符号操作,AST 无法正确处理这种从 Tensor 到具体数值再到 Numpy 数组的复杂操作链,因此最终失败。

解决方案 —— PaddleSOT

PaddleSOT 提供了一种 子图 Fallback(回退)机制,允许在无法直接转换的部分(比如 x.numpy())使用动态方式执行。这种机制可以在无法完全静态化的场景下,自动处理 Tensor 和 Numpy 的混用问题,以确保整个过程的兼容性和成功执行。

通过引入 PaddleSOT,可以在动转静中执行必要的动态操作,从而在不影响代码灵活性的前提下,成功实现这类复杂的动态图转换。

成功案例

import paddle
import numpy as np

# 启用静态图模式
paddle.enable_static()

@paddle.jit.to_static
def simple_net(x):
    y = x * 2
    z = y + 3
    return z

# 输入数据
x = paddle.to_tensor([5.0])
output = simple_net(x)
print(output)  # 输出 [13.0]

在这个例子中,动转静可以成功进行,原因在于所有的操作都是在 Tensor 的计算图 上构建的,而不涉及动态的 Numpy 操作或其他 Python 内建操作。

成功的原因

  1. 纯 Tensor 操作simple_net 中所有的操作(乘法和加法)都是 Tensor 之间的运算,并没有调用任何 Python 或 Numpy 操作。这些 Tensor 运算可以在静态图中直接构建计算图。

  2. 静态图构建的特性:在静态图模式下(即 paddle.enable_static() 之后),Paddle 会将所有 Tensor 运算封装成计算图的节点,而不会立即执行。因此,静态图可以将 simple_net 中的所有计算步骤编译成一个完整的计算图(从输入 x 到输出 z 的操作顺序),并在运行时直接计算输出。

  3. 依赖关系在计算图中表达:在计算图中,y 依赖于 x 的值,z 依赖于 y 的值,但这种依赖关系是在构建图的过程中清晰表达出来的。静态图模式下会将整个计算图一次性构建好,构建完成后才会运行,所有的依赖关系会自动处理,因此不会出问题。

与 Numpy 操作的区别

在前面失败的例子中,问题出在 TensorNumpy 之间的转换。这种转换在静态图中是不可行的,因为 Numpy 需要立即获取 Tensor 的具体数值,而静态图在构建时并不会得到真实的值(只是构建一个符号化的计算图)。这导致了 Numpy 操作无法在静态图模式中工作。

在这个成功的例子中,所有操作都局限在 Tensor 计算图内,不需要转换为 Python 或 Numpy 的数值,因此动转静可以成功构建并执行。

总结

成功的关键在于:

  • 使用的所有运算(乘法、加法)都在 Tensor 范围内,没有依赖 Python 动态数值操作或 Numpy。
  • 静态图能够一次性构建整个依赖链并保持计算图的完整性,从而顺利进行动转静。

这也是为什么这个例子可以成功转换为静态图,而前面的例子会失败的原因。

标签:转换,Tensor,beginner,静态,paddle,计算,paddleSOT,Numpy
From: https://www.cnblogs.com/smartljy/p/18531674

相关文章

  • AtCoder Beginner Contest 284题解
    AtCoderBeginnerContest284A没有什么难点,反着输出一遍就可以了。#include<bits/stdc++.h>usingnamespacestd;stringa[2000];intmain(){ intn; cin>>n; for(inti=1;i<=n;i++)cin>>a[i]; for(inti=n;i;i--)cout<<a[i]<<'\n';......
  • AtCoder Beginner Contest 378
    ContestLink还得加练。A&B&C&D不具备任何思维含量。SubmissionASubmissionBSubmissionCSubmissionDE注意到它计算答案的式子,每个子区间和都需要取模,否则就是沙币题了,可以对于每个位置\(O(1)\)地统计答案扫过去然后\(\bmodM\)。常规地,记\(S_i=\sum......
  • AtCoder Beginner Contest 360 - VP记录
    A-AHealthyBreakfast高桥日常出境。头一次知道getchar()的返回值是int。点击查看代码#include<cstdio>usingnamespacestd;intmain(){ chars[3]={getchar(),getchar(),getchar()}; if(s[0]=='R'&&s[1]=='M')puts("Yes"); els......
  • AtCoder Beginner Contest 378 E
    https://atcoder.jp/contests/abc378/tasks/abc378_ehttps://atcoder.jp/contests/abc378/editorial/11300#include<bits/stdc++.h>#definexfirst#defineysecond#defineall(x)(x).begin(),(x).end()#definelowbit(x)(x)&-(x)usingnamespacestd;ty......
  • AtCoder Beginner Contest 378
    AtCoderBeginnerContest378总结A直接模拟,存\(1\)到\(4\)出现个数。#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<vector>#include<queue>#include<map&g......
  • AtCoder Beginner Contest 378
    ABC378光速切掉前四题,结果倒在了第五题。A-Pairing难度:红。弱智题,不解释。#include<bits/stdc++.h>usingnamespacestd;intmain(){inta[5]={0};for(inti=1;i<=4;i++){intx;cin>>x;a[x]++;}intans=0;for(inti=1;i<=4;i++){......
  • AtCoder Beginner Contest 378 F题题解
    题目:F-AddOneEdge2思路:可以发现题目就是要我们找出有多少个点对满足连成后是一个简单环环上的点度都为3因为是一个简单图所以不可以有重边和自环那么就代表着这个环肯定是由两个度为2的点和大于1个度为3的点组成的注意到两个点的最近公共祖先一定可以跟这两个点形......
  • AtCoder Beginner Contest 378
    省流版A.判断奇偶性即可B.根据余数计算偏移天数即可C.用map记录每个数出现的位置即可D.枚举起点,枚举每步的方向,朴素搜索即可E.考虑前缀和的两数相减代替区间和的情况,减为负数则加回正数,用树状数组维护减为负数的情况数F.枚举点,作为连边的俩个点的lca,考虑维护路径点......
  • AtCoder Beginner Contest 378题解
    省流:dfs都会写错。正片:A:Pairing统计一下每个数字出现了多少次即可,每次减去2。#include<bits/stdc++.h>usingnamespacestd;inta,b,c,d,ans;map<int,int>mp;intmain(){ cin>>a>>b>>c>>d; mp[a]++,mp[b]++,mp[c]++,mp[d]++; while(mp[a]>=2)mp[a......
  • AtCoder Beginner Contest 378题解
    AtCoderBeginnerContest378题解总体情况十分钟翻盘局。A-Pairing题意有四个球,每次可以消掉两个颜色相同的球,问最多能效多少次?题解直接使用贪心即可代码//Problem:A-Pairing//Contest:AtCoder-AtCoderBeginnerContest378//URL:https://atcoder.j......