class_docstr: Performs loss scaling during backward pass to prevent underflow of half
  precision gradients.
class_docstr_tok: ["Performs","loss","scaling","during","backward","pass","to","prevent","underflow","of","half","precision","gradients","."]
docstr: Perform a single optimization step.
  
  :param closure:
      A closure that reevaluates the model and returns the loss. Optional
      for most optimizers.
  
  :returns:
      - The return value of ``closure``.
      - The result of the loss scale operation.
docstr_tok: ["Perform","a","single","optimization","step",".",":","param","closure",":","A","closure","that","reevaluates","the","model","and","returns","the","loss",".","Optional","for","most","optimizers",".",":","returns",":","-","The","return","value","of","``","closure","``",".","-","The","result","of","the","loss","scale","operation","."]
code: def run_optimizer_step(
      self, closure: Optional[Callable[[], float]] = None
  ) -> Tuple[Optional[float], "LossScaleResult"]:
      """Perform a single optimization step.
  
      :param closure:
          A closure that reevaluates the model and returns the loss. Optional
          for most optimizers.
  
      :returns:
          - The return value of ``closure``.
          - The result of the loss scale operation.
      """
      if isinstance(self._grad_scaler, ShardedGradScaler):
          # As of PyTorch 2.0.1, `ShardedGradScaler` has a bug where it skips
          # calling `unscale_()` for optimizers that natively support gradient
          # scaling. Although this is the expected behavior for `GradScaler`,
          # in distributed settings this causes the scale to get out-of-sync
          # between processes. Here we force ranks to sync their inf/NaNs by
          # manually calling `unscale_()`.
          try:
              self._grad_scaler.unscale_(self.optimizer)  # type: ignore[arg-type]
          except RuntimeError as ex:
              if not str(ex).startswith(
                  "unscale_() has already been called"
              ):
                  raise
  
      loss = self._grad_scaler.step(self.optimizer, closure)
  
      return loss, self._update_scale()
  
imports: from __future__ import annotations
  import logging
  import math
  from dataclasses import dataclass
  from logging import Logger
  from typing import Any, Callable, Dict, Mapping, Optional, Tuple, cast
  import torch
  from torch import Tensor
  from torch.cuda.amp.grad_scaler import GradScaler
  from torch.distributed.fsdp.sharded_grad_scaler import ShardedGradScaler
  from torch.optim import Optimizer
  from fairseq2.gang import Gang
label_desc: Use image node_id 4 for calling the DynamicLossScaler obj's underlying member method code with example usage: obj.run_optimizer_step(closure) and returns: loss,  self