You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
但如果我们可以抽离出来一个函数,这个函数的作用就是传入输入 x: list[Tensor]、以及所需 Program,并返回输出 out: list[Tensor],对于这个函数来说,它只需要执行 Program 并取出输出即可,它不需要关心这个 Program 是前向还是反向。这样无论多少阶微分,我们都可以直接调用这个函数。
背景
动转静可以跟踪动态图 API,自适应构建等价的静态子图,使用内核执行器,实现转静训练加速。目前动转静支持整图级别的高阶微分,即
paddle.grad
接口在@to_static
装饰函数内调用。我们期望动转静支持子图高阶微分,即paddle.grad
接口在@to_static
装饰函数外调用。示例代码如下:
目标
RunProgramOp
(paddle/fluid/eager/to_static
)模块,支持子图高阶微分功能,添加必要单测验证功能正确性,代码合入 PaddlePaddle 框架 repo意义
参考
动转静是在动态图下通过
RunProgramOp
来运行静态图 Program,在pir_run_program_ad_func
中,我们会构建反向GradNode
(PirGradNodeRunProgram
)。目前我们GradNode
的operator()
会调用PirRunProgramGradAPI
来执行反向计算。如果按照目前的思路继续向下开发的话,为了支持高阶微分,我们必然需要支持PirRunProgramGradGradAPI
、PirRunProgramGradGradGradAPI
……但如果我们可以抽离出来一个函数,这个函数的作用就是传入输入
x: list[Tensor]
、以及所需 Program,并返回输出out: list[Tensor]
,对于这个函数来说,它只需要执行 Program 并取出输出即可,它不需要关心这个 Program 是前向还是反向。这样无论多少阶微分,我们都可以直接调用这个函数。当然,我们还需要对当前流程进行若干重构,设想的新架构如下:
run_program_ad_func(x: list[Tensor], program: Program, scope: Scope, x_values: list[Value], out_values: list[Value], **attrs) -> list[Tensor]
(执行前向,构建反向)paddle.grad
,添加反向,前反向拆分 + 前反向关联分析等skip_gc_vars
的计算和设置out_values
获得当前 Program 的输出,构建输出out: list[Tensor]
GradNode
forward_values = x_values + out_values
forward_out_grad_values = out_grad_values
(out_grad_values
在前反向拆分时可以拿到)forward_x_grad_values = x_grad_values
(同上,前反向拆分时可以拿到)forward_inputs = x + out
scope = scope
GradNode::operator(out_grads: list[Tensor])
(执行反向)run_program_ad_func(forward_inputs + out_grads, backward_program, scope, forward_values + forward_out_grad_values, forward_x_grad_values, **new_attrs)
,获取输出x_grads: list[Tensor]
,也即前向是 RunProgram OP 的反向是其自身,只不过输入不同,这便可实现任意阶微分Note
FLAGS_enable_pir_api=True
开启 PIR 模式其他资料
动转静原理文档
目前 PIR 下动转静前反向拆分关系可参考下图
The text was updated successfully, but these errors were encountered: