Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【Hackathon 6th Article No.1】Inplace 优化性能 #882

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

lightrain-a
Copy link
Contributor

原因说明:尝试sync fork,结果意外关闭了之前提交分支的申请
原pr:#857

Copy link

paddle-bot bot commented Apr 25, 2024

你的PR提交成功,感谢你对开源项目的贡献!
请检查PR提交格式和内容是否完备,具体请参考示例模版
Your PR has been submitted. Thanks for your contribution!
Please check its format and content. For this, you can refer to Template and Demo.

Copy link
Contributor

@GGBond8488 GGBond8488 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

先理解一下叶子节点不能inplace的原因

上述代码在执行 x[0] = 4.0 时会抛出如下错误:

```python
ValueError: (InvalidArgument) Leaf Tensor (generated_tensor_0) that doesn't stop gradient can't use inplace strategy.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个报错是因为对叶子节点做了inplace操作啊,不是这个2. 对后续计算(如求梯度)中仍要需要用到的值,不能使用 Inplace 操作。的例子啊

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

噢噢好像理解了;因为原地修改叶子张量的数据会覆盖前向传递中的值,从而阻碍在反向传播时正确地重建计算图

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

谢谢老师(^▽^)


为避免影响计算的准确性,执行 Inplace 操作时需要特别注意以下情况:

1. **对设置了 `requires_grad=True` 的叶子张量(leaf tensor),应避免使用 Inplace 操作,因为这可能妨碍正确的梯度计算。**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不是可能妨碍正确的梯度计算, 叶子节点不能inplace不是这个原因,为什么可以看我对之前那个pr的评论

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

后面对叶子节点的理解同样需要修正

@lightrain-a
Copy link
Contributor Author

已全部修改,辛苦老师帮忙再看看

1 similar comment
@lightrain-a
Copy link
Contributor Author

已全部修改,辛苦老师帮忙再看看


本文将通过实际的 Paddle 代码示例来,展示如何在PaddlePaddle中使用Inplace操作,并对比其在内存优化和性能提升方面的效果,阐述其在实际应用中的好处、潜在问题以及飞桨是如何保护梯度计算过程的。
# 1. 什么是Inplace操作?
Inplace操作允许直接在原始数据上进行修改,而无需创建数据的副本。这样不仅可以减少内存的占用,还能降低计算的复杂度,从而提升整体的执行性能。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inplace 为什么能降低计算复杂度呢

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已删除该不恰当表述


为避免影响计算的准确性,执行 Inplace 操作时需要特别注意以下情况:

1. **对设置了 `requires_grad=True` 的叶子张量(leaf tensor)应避免使用原地(inplace)操作。** 因为原地修改叶子张量的数据会覆盖前向传递中的值,从而阻碍在反向传播时正确地重建计算图。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为什么会阻碍在反向传播时正确地重建计算图

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修改表述为:就无法正确计算依赖于这个值的梯度

为避免影响计算的准确性,执行 Inplace 操作时需要特别注意以下情况:

1. **对设置了 `requires_grad=True` 的叶子张量(leaf tensor)应避免使用原地(inplace)操作。** 因为原地修改叶子张量的数据会覆盖前向传递中的值,从而阻碍在反向传播时正确地重建计算图。
2. **PaddlePaddle 在执行反向传播时,针对某些特定的函数,能够保存必要的中间状态,或已经实现了策略以正确处理 Inplace 操作。** 不过,对于不常见或复杂的操作,最好在实际使用前通过实验来验证其行为。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里直接说用户在使用的时候无须关心执行了inplace操作会导致反向传播错误的,大部分运算paddle已经都可以保证inplace操作后反向传播仍然正确,小部分反向传播会错误的情况下paddle也会抛出对应的异常

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好的


### 1. 对设置了 `requires_grad=True` 的叶子张量应避免使用原地(inplace)操作

当这类张量设置为 `requires_grad=True`,表示它们的梯度需要被计算以用于反向传播。对这些张量执行原地操作,如 `a.sin_()`,可能会直接修改其数据。这反映了一个关键问题:原地修改叶子张量的数据会覆盖前向传递中的值,从而阻碍在反向传播时正确地重建计算图。这样的修改不仅可能导致梯度计算错误,还可能影响整个模型训练过程的稳定性和准确性。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"requires_grad=True,表示它们的梯度需要被计算以用于反向传播", requires_grad=True 含义是需要保留该tensor的梯度,保留的主要目的不是用于反向传播,只是用于反向传播的话,应该反向计算完了就可以释放了。主要目的是为了后面优化器优化参数的时候使用。
而且paddle也不是requires_grad=True的说法吧

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

阻碍在反向传播时正确地重建计算图 为什么会阻碍呢?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修改

```

错误信息明确指出了“叶子变量不应该停止梯度计算并且不能使用原地策略”,这表明当张量被用于梯度计算时,进行原地操作可能会导致前向传递的值被覆盖,从而无法在反向传播时正确地重建计算图。
即,原地操作 sin_() 在计算图中的叶子节点上不能直接使用,因为它会影响梯度计算。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同上

@lightrain-a
Copy link
Contributor Author

已全部修改,辛苦老师帮忙再看看

当对这些叶子张量执行原地操作,例如 `a.sin_()`(这里 `sin_()` 是一个原地修改 a 的正弦函数版本),会直接修改张量的数据。这种修改是有问题的,因为:

1. **覆盖前向传播的值**:原地操作会改变张量的内容,如果这些内容在计算图中用于之后的梯度计算,原始值被覆盖的丢失,就无法正确计算依赖于这个值的梯度。
2. **计算图的完整性受损**:自动微分依赖于计算图中节点的值来追踪并计算梯度。原地操作可能导致计算图的某些节点丢失所需的前向传播值,这可能导致反向传播过程中错误的梯度或者计算错误。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为什么会让“计算图的完整性受损”呢,解释一下,假如y=x.sin_(), x 是 叶子节点,我需要计算x梯度,并且用这个梯度更新x。inplace场景下,执行y = x.sin_() 以后,x的值已经被原地修改了,记为x‘。梯度更新公式 x = x - a*x_grad, a是这里的步长,x_grad是x的梯度,inplace与非inplace计算结果一致。 但是x已经变成了x', 那这个更新过程就不正确了

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是这样理解吗:因为已经覆盖了(x的原地操作),所以后面的二次覆盖(更新梯度修改x)不是本质错误原因,根本错误原因是第一次的覆盖。
根据这个理解,已修改表述为:### 2. 原地操作对计算图有影响时,抛出异常

自动微分依赖于计算图中的节点值来追踪和计算梯度,而原地操作(例如 x.sin_(),这里 sin_() 是一个原地修改 x 的正弦函数版本)会覆盖前向传播的值导致原始值被覆盖,从而无法正确计算依赖于该值的梯度。这样的修改不仅可能导致梯度计算错误,还可能影响整个模型训练过程的稳定性和准确性。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

谢谢老师耐心的解答,已修改表述

@lightrain-a
Copy link
Contributor Author

已修改表述,麻烦老师帮忙再看看

1 similar comment
@lightrain-a
Copy link
Contributor Author

已修改表述,麻烦老师帮忙再看看

@luotao1
Copy link
Collaborator

luotao1 commented May 28, 2024

【Hackathon 6th】优秀稿件征集与传播:按照活动规则,阶段一已于 5 月 15 日 截止,研发不再审核稿件 PR

@lightrain-a
Copy link
Contributor Author

噢噢好滴,谢谢luotao1老师告知,也谢谢GGBond8488老师一直以来的耐心解答。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants