[Dy2St][PIR] Replace output with inplace source #63040
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
PR Category
Execute Infrastructure
PR Types
Bug fixes
Description
问题描述
SOT/AST+PIR 模型暴露问题,伪码描述如下:
对于这个 Program 来说,动转静前向输入包含原输入
x和 parametermean1,前向输出包含原输出y和反向所需的中间变量mean2,问题就出在这个mean1和mean2是 inplace 的(实际上是 view 的,但 PIR 下是一样的)由于
mean1和mean2是 inplace 的,所以他们对应同一个 Variable,mean2作为输出我们会添加shadow_output来确保能够取出来,但由于mean2实际上就是mean1,它已经有作为输入的parameter_1这个名字了,实际上是不需要通过shadow_output来重命名的。而且,如果进行重命名,在第一个 step 我们在 share 到 scope 时需要使用parameter_1这个名字来 share,而第二个 step 因为已经 rename 成另一个名字了,这就会导致 share 失败。解决方案
归根结底,问题出在一个输入 Value 经过若干 inplace 操作得到一个输出 Value,此时这个输出 Value 不应该添加
shadow_output,而是应该直接替换为输入 Value。为了达成这一点,我们需要在前反向拆分时,对 Program 中所有 inplace 链进行分析,比如下图:这里仅标识出了 inplace Value,忽略非 inplace Value,并且按照时序拉直,比如这里的链路 A 中的 A1 作为输入,A4 作为输出,那么 A4 不应该添加
shadow_output。具体替换结果如下图所示:
但是这里为什么不直接将 A4 从中间变量中删掉呢?因为考虑到动转静前向的输出侧并不仅仅包含中间变量,还包含原前向的输出,针对中间变量尚且可以删掉,但如果针对输出的话就不太好删掉了,因此我们对中间变量和输出变量采用相同的操作,就是替换为 inplace 的输入侧源 Value。
如果考虑前反向全部情况,根据下图动转静前反向的输入输出关系,实际上我们需要处理如下几种情况:
但是由于前向输入
x是用dataop 创建的,data op 在经过 lower 到 kernel pass 后会跟随一个shadow_feedop,而shadow_feedop 不是 inplace 的,会创建一个 inner var,也就是说前向输入x永远不会出现上述的同时作为输入和输出的问题,因为在一开始就有一个非 inplace 的操作,因此我们不需要处理前向输入,只需要处理 parameter。类似地,反向全部输入都是通过 block kwarg 创建的,而 kwarg 也会在 lower 后跟随一个
shadow_feed,因此整个反向都不会出现上述问题,也就是说反向不需要处理。因此需要处理的只有:
但由于最开始是考虑这种情况的,即便将来
data/kwarg后不插shadow_feed也能很容易实现。(因为目前看反向会有过多shadow_feed,非常影响性能,也许之后这个shadow_feed会被删掉也说不定)Note
虽然问题清楚了,但仍然没能找到一个简单的复现样例,因此没有添加单测,关于 inplace 的单测在 #62300 已经添加过了,但不能复现,本 PR 在模型上验证通过