class_docstr: Similar to the torch version, but support non-Tensor outputs.
  
  The caller is expected to provide a dict (*parent_ctx_dict*) that will hold
  the non-Tensor outputs. These should be combined with the Tensor *outputs*
  by calling :func:`unpack_non_tensors`.
class_docstr_tok: ["Similar","to","the","torch","version",",","but","support","non-Tensor","outputs",".","The","caller","is","expected","to","provide","a","dict","(","*","parent_ctx_dict","*",")","that","will","hold","the","non-Tensor","outputs",".","These","should","be","combined","with","the","Tensor","*","outputs","*","by","calling",":","func",":","`","unpack_non_tensors","`","."]
code: def backward(ctx: Any, *args: Any) -> Tuple[Optional[Tensor], ...]:
      if not torch.autograd._is_checkpoint_valid():
          raise RuntimeError(
              "Checkpointing is not compatible with .grad(), please use .backward() if possible"
          )
  
      tensor_inputs: Tuple = ctx.saved_tensors
      tensor_inputs = torch_checkpoint.detach_variable(tensor_inputs)
      if ctx.fwd_device is not None:
          tensor_inputs = tuple(
              t.to(ctx.fwd_device[i], non_blocking=True)
              for i, t in enumerate(tensor_inputs)
          )
          for i, need_grad in enumerate(ctx.grad_requirements):
              tensor_inputs[i].requires_grad = need_grad
      inputs = unpack_non_tensors(
          tensor_inputs, ctx.packed_non_tensor_inputs
      )
  
      # Store the current states.
      bwd_rng_state = get_rng_state()
  
      # Set the states to what it used to be before the forward pass.
      set_rng_state(ctx.fwd_rng_state)
  
      with torch.enable_grad(), enable_recomputing(), autocast(
          ctx.had_autocast_in_fwd
      ):
          unpacked_args, unpacked_kwargs = unpack_kwargs(
              ctx.kwarg_keys, inputs
          )
          outputs = ctx.run_function(*unpacked_args, **unpacked_kwargs)
          tensor_outputs, _ = split_non_tensors(outputs)
  
      # Set the states back to what it was at the start of this function.
      set_rng_state(bwd_rng_state)
  
      # Run backward() with only Tensors that require grad
      outputs_with_grad = []
      args_with_grad = []
      for i in range(len(tensor_outputs)):
          if tensor_outputs[i].requires_grad:
              outputs_with_grad.append(tensor_outputs[i])
              args_with_grad.append(args[i])
  
      if len(outputs_with_grad) == 0:
          raise RuntimeError(
              "None of the outputs have requires_grad=True, "
              "this checkpoint() is not necessary"
          )
  
      torch.autograd.backward(outputs_with_grad, args_with_grad)
  
      grads = tuple(
          inp.grad if isinstance(inp, torch.Tensor) else None
          for inp in inputs
      )
  
      return (None, None, None, None) + grads
  
imports: from contextlib import contextmanager
  from dataclasses import dataclass
  import functools
  import threading
  from typing import Any, Dict, Generator, Optional, Tuple
  import weakref
  import torch
  from torch import Tensor
  import torch.nn
  import torch.utils.checkpoint
  from fairscale.internal.containers import pack_kwargs, split_non_tensors, unpack_kwargs, unpack_non_tensors
  from .checkpoint_utils import patch_batchnorm
label_desc: Use image node_id 2 for calling the CheckpointFunction obj's underlying member method code with example usage: obj.backward(ctx) and returns: unknown