-
Notifications
You must be signed in to change notification settings - Fork 274
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 使用指南 #839
Conversation
AndSonder
commented
Mar 27, 2024
•
edited
Loading
edited
- 【Hackathon 6th】优秀稿件征集与传播 Paddle#62907
…20240321_guide_to_using_Inplace.md
|
||
### 2.1 View 形式的操作 | ||
|
||
在深度学习框架中,view 形式的操作得到的结果变量与原始变量共享数据存储,但拥有不同的元数据(如形状或步长)。这意味着,虽然两个变量在逻辑上是独立的,但它们实际上指向同一块内存区域。View 操作的一个典型例子是改变 Tensor 的形状。通过这种方式,可以在不增加额外内存负担的情况下,灵活地重组数据的维度。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个“步长“是什么含义?“两个变量在逻辑上是独立的,但它们实际上指向同一块内存区域” 这个说法有待斟酌,可以说从python的视角,他们是两个不同的变量,但是从数据内存的视角,他们共享一个数据区,可以先简单说明一下一个Tensor的组成(meta_data+numerical_data)
|
||
### 2.2 Inplace 形式的操作 | ||
|
||
与 view 形式的操作相比,inplace形式的操作进一步深化了对内存的优化。在进行 inplace 操作时,操作直接在原始数据上进行修改,不仅共享数据存储,连元数据也保持不变。换言之,inplace 操作实际上是在原地更新数据,避免了任何额外内存的分配。这种操作对于优化内存使用和加速计算过程尤为重要,因为它消除了不必要的数据复制和内存分配开销。例如,`paddle.add_(a, b)` 就是一个inplace操作,它将 a 和 b 的和直接存储回 a,而不需要为结果分配新的内存空间。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“操作直接在原始数据上进行修改,不仅共享数据存储,连元数据也保持不变。” 这个说法也要斟酌,这里应该表示的是输入和输出是同一个Tensor,拥有相同的meta和data,这里可以画个图说明一下三种操作(view, inplace, normal)的区别
|
||
该示例中的 `relu_` 是一种逐元素的 Inplace 操作。它对张量中的每个元素应用ReLU激活函数,并直接覆盖原始元素值。 | ||
|
||
对于像 ReLU 这种简单的元素 wise 操作,使用 Inplace 方式可以避免创建新的临时张量,从而减少内存开销。但同时也要注意,如果原始张量在后续还需要使用,就不应该进行 Inplace 操作。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"wise 操作" 是?聪明的操作?
|
||
### 3.3 线性代数计算 | ||
|
||
PaddlePaddle 提供了一系列支持 Inplace 形式的线性代数计算 API,如 `add_()`、`multiply_()` 等。这些 API 可以直接在原地更新数据,避免了额外的内存分配。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add, multiply 应该不是线性代数代表性操作吧
# 67108864 (inplace=True) | ||
``` | ||
|
||
当 `inplace=True` 时, 最大显存占用为 67108864, 而当 `inplace=False` 时, 最大显存占用为 134217728。可以看到, 使用 Inplace 操作可以减少一半的显存占用。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
可以简单说明一下为什么在这里的relu适合去使用inplace操作
|
||
叶子节点不可使用 Inplace 操作,主要是由于动态图机制下自动微分的计算原理所决定的。 | ||
|
||
在Paddle的动态图机制下,叶子节点 (Leaf Tensor) 指的是需要计算梯度的输入张量,它们是整个计算图的起点。为了能够正确完成反向传播,Paddle 需要记录叶子节点的数值, 并在前向计算时构建完整的计算图。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
如果从计算梯度的角度来说,其实是可以的,因为paddle 支持 对inplace 操作的输入求梯度。
至于为什么不能对叶子节点做inplace操作,有一个比较重要的点就是:
叶子节点一般都是需要求梯度并且保留梯度的节点,那哪些节点需要保留梯度呢,一般是模型网络中的权重,需要保留梯度一般意味着需要使用这个梯度去更新权重,如果说权重在被梯度更新之前就被inplace操作修改了,那显然训练得到的权重是不正确的。
这里可以先解释一下叶子节点的概念,再说明为什么不能对叶子节点做inplace操作
@GGBond8488 都按照研发老师的要求修改了,麻烦再review一下~ |
|
||
需要注意的是,虽然 Inplace 操作带来了显著的性能提升,但也需谨慎使用。因为 Inplace 操作会修改原始数据,某些场景下使用可能会导致数据丢失或错误的计算结果。 | ||
|
||
![picture 0](images/4e95c08593efdbf45c00b112e8baf2cfb2d1c4c0a6c11c1893b5c43ab656eb99.jpg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个图放到2.1 之前吧,然后输入tensor 和 输出tensor 用方框框出来,表示是两个tensor,然后数值数据的部分,可以画成,方框里面的是一个指针,然后再下一层画一片内存区域,view就是两个指针指向同一个地方,一般的操作就是两个指针指向不同的地方,inplace 就是 x, y 就是同一个tensor的不同名字
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
### 4.1 叶子节点不可使用 Inplace | ||
|
||
在 Paddle 的动态图机制中,叶子节点(Leaf Tensor)指的是需要计算梯度的张量,它们不允许使用 Inplace 操作。如果在叶子节点上使用了 Inplace,会导致梯度计算错误,从而影响模型训练。示例代码如下: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个梯度计算错误的说法不对,理由和之前一样
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个梯度计算错误的说法不对,理由和之前一样
已删除梯度计算错误的说法:
在 Paddle 的动态图机制中,叶子节点(Leaf Tensor)指的是需要计算梯度的张量,它们不允许使用 Inplace 操作。如果叶子节点使用了 Inplace 操作, Paddle 会抛出错误。示例代码如下:
import paddle
x = paddle.rand([3, 4])
x.stop_gradient = False # 将 x 标记为叶子节点
# 错误做法,会导致报错
x.scale_(2.0)
y = x.sum()
y.backward()
上述代码在执行 x.scale_(2.0) 时会抛出如下错误:
ValueError: (InvalidArgument) Leaf Var () that doesn't stop gradient can't use inplace strategy.
[Hint: Expected !autograd_meta->StopGradient() && IsLeafTensor(target) == false, but received !autograd_meta->StopGradient() && IsLeafTensor(target):1 != false:0.] (at /Users/paddle/xly/workspace/f4429c34-48ba-44c2-9571-abaff039446b/Paddle/paddle/fluid/eager/utils.cc:200)
在Paddle的动态图机制下,叶子节点(Leaf Tensor)指的是整个计算图的输入张量, 通常就是模型的可训练权重或输入数据。
对于需要计算梯度并更新的权重张量来说, 在梯度计算和应用更新前, 它们必须保持数值不变,以确保计算的准确性。如果说权重在被梯度更新之前就被 inplace 操作修改了,那显然训练得到的权重是不正确的。
为了避免这种情况发生,Paddle 在执行 Inplace 操作前,会先检查当前张量是否为叶子节点。如果是,就会抛出错误,阻止 Inplace 操作的执行。这样可以确保自动微分过程的正确性。
|
||
为了更加深入地了解 Inplace 操作,我们先介绍一下 Paddle 中的三类数据操作:view形式的操作、inplace形式的操作和普通的操作。这些操作方式直接关系到内存管理和计算效率。 | ||
|
||
![picture 1](images/622111f0036252eee044a8a4e148f54685ec1bac5628b540a713705a0c0d3b71.jpg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
view 和 普通的这么画没问题,但是inpalce 的 这个 没有体现出输入tensor 和 输出tensor 本质是一个tensor,这里更像是有一个tensor a, 还有一个 tensor b, a 和 b 的成员 meta, data 都是一个东西,但是没有表明出b就是a
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM