r"""Execute backward pass on the loss Arguments: loss: Torch tensor on which to execute backward propagation retain_graph: bool, default: false forward on user defined choice of retain_graph scale_wrt_gas: bool, default: true
(self, loss, retain_graph=False, scale_wrt_gas=True)
| 3064 | |
| 3065 | @instrument_w_nvtx |
| 3066 | def backward(self, loss, retain_graph=False, scale_wrt_gas=True): |
| 3067 | r"""Execute backward pass on the loss |
| 3068 | Arguments: |
| 3069 | loss: Torch tensor on which to execute backward propagation |
| 3070 | retain_graph: bool, default: false |
| 3071 | forward on user defined choice of retain_graph |
| 3072 | scale_wrt_gas: bool, default: true |
| 3073 | whether to scale gradients and return value by gradient accumulation steps |
| 3074 | """ |
| 3075 | assert self.optimizer is not None and not isinstance(self.optimizer, DummyOptim), \ |
| 3076 | "must provide optimizer during init in order to use backward" |
| 3077 | assert maybe_loss_for_backward( |
| 3078 | loss), "loss must be a scalar tensor. If you need to pass output gradients, backward() of output tensors" |
| 3079 | |
| 3080 | self._running_engine_backward = True |
| 3081 | # Store scale_wrt_gas so the hook can respect it |
| 3082 | self._scale_wrt_gas = scale_wrt_gas |
| 3083 | |
| 3084 | # Set flag to prevent hooks from firing (we'll manually call prologue/epilogue) |
| 3085 | backward_kwargs = {"retain_graph": retain_graph} |
| 3086 | if self.eigenvalue_enabled(): |
| 3087 | backward_kwargs["create_graph"] = True |
| 3088 | backward_kwargs["retain_graph"] = True |
| 3089 | |
| 3090 | # Used only for return value |
| 3091 | gas_scaled_loss = loss / self.gradient_accumulation_steps() if scale_wrt_gas else loss |
| 3092 | |
| 3093 | # TODO: handle these scaling with direct calls to loss.backward() |
| 3094 | if isinstance(self.optimizer, ZeROOptimizer): |
| 3095 | loss = self.optimizer.scale_if_loss(loss) |
| 3096 | elif self.torch_autocast_z0_gradscaler: |
| 3097 | loss = self.torch_autocast_z0_gradscaler.scale(loss) |
| 3098 | |
| 3099 | with compiled_autograd(self._is_compiled_autograd_enabled, self._compile_kwargs): |
| 3100 | if self.zero_optimization() or not self.amp_enabled(): |
| 3101 | loss.backward(**backward_kwargs) |
| 3102 | elif self.amp_enabled(): |
| 3103 | # AMP requires delaying unscale when inside gradient accumulation boundaries |
| 3104 | # https://nvidia.github.io/apex/advanced.html#gradient-accumulation-across-iterations |
| 3105 | delay_unscale = not self.is_gradient_accumulation_boundary() |
| 3106 | with amp.scale_loss(loss, self.optimizer, delay_unscale=delay_unscale) as scaled_loss: |
| 3107 | scaled_loss.backward(**backward_kwargs) |
| 3108 | |
| 3109 | # backward_epilogue is not called in a hook when self._support_torch_style_backward is False |
| 3110 | self._backward_epilogue() |
| 3111 | |
| 3112 | self._running_engine_backward = False |
| 3113 | |
| 3114 | return gas_scaled_loss |
| 3115 | |
| 3116 | def is_gradient_accumulation_boundary(self): |
| 3117 | """ |
nothing calls this directly
no test coverage detected