-
Notifications
You must be signed in to change notification settings - Fork 4.4k
[Dev] fix(combined-1f1b): release loss-node input storage after combined backward #4908
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
Changes from all commits
f802e0e
8e9f993
b5b1be9
b9466b1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| # Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. | ||
| # Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
|
|
||
| import contextlib | ||
| from contextlib import nullcontext | ||
|
|
@@ -21,6 +21,17 @@ | |
| Shape = Union[List[int], torch.Size] | ||
|
|
||
|
|
||
| def _release_tensor_storage(tensors): | ||
| """Release tensor storage after all backward users are done.""" | ||
| if tensors is None: | ||
| return | ||
|
|
||
| for tensor in tensors: | ||
| if isinstance(tensor, torch.Tensor) and tensor.is_cuda: | ||
| tensor.record_stream(torch.cuda.current_stream()) | ||
| tensor.untyped_storage().resize_(0) | ||
|
|
||
|
|
||
|
Comment on lines
23
to
+34
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: the |
||
| def combined_1f1b_schedule_for_no_pipelining( | ||
| forward_step_func, | ||
| data_iterator, | ||
|
|
@@ -405,6 +416,7 @@ def forward_backward_step(): | |
| # backward preprocess, the same as the backward_step() | ||
| unwrap_input_tensor_grad = False | ||
| b_schedule_plan = None | ||
| loss_node_inputs_to_release = None | ||
| if b_model is not None: | ||
| # Retain the grad on the input_tensor. | ||
| if not isinstance(b_input_tensor, list): | ||
|
|
@@ -432,6 +444,8 @@ def forward_backward_step(): | |
| # Backward pass for loss function | ||
| torch.autograd.backward(b_output_tensor[0], grad_tensors=b_output_tensor_grad[0]) | ||
| b_output_tensor_grad[0] = loss_node.get_grad() | ||
| loss_node_inputs_to_release = loss_node.inputs | ||
| loss_node._release_state() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess the reason why the input is saved additionally is to release loss_node as early as possible, but do we really need it, considering the loss tensor is small? |
||
|
|
||
| # If fp8_recipe is delayed, wrap the entire pass with get_fp8_context(), | ||
| # otherwise do nothing extra at the outer level | ||
|
|
@@ -454,6 +468,7 @@ def forward_backward_step(): | |
| post_forward=post_forward, | ||
| post_backward=post_backward, | ||
| ) | ||
| _release_tensor_storage(loss_node_inputs_to_release) | ||
|
|
||
| # forward post process | ||
| num_tokens = None | ||
|
|
||
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.
Nit:
record_stream()will raise on CPU tensors. Adding a.is_cudaguard is cheap insurance: