class_docstr: Applies Batch Normalization over a N-Dimensional input.
  
  The N-D input is a mini-batch of [N-2]D inputs with additional channel dimension) as described in the paper
  `Batch Normalization: Accelerating Deep Network Training by Reducing
  Internal Covariate Shift <https://arxiv.org/abs/1502.03167>`__ .
  
  .. math::
  
      y = \frac{x - \mathrm{E}[x]}{ \sqrt{\mathrm{Var}[x] + \epsilon}} * \gamma + \beta
  
  The mean and standard-deviation are calculated per-dimension over all
  mini-batches of the same process groups. :math:`\gamma` and :math:`\beta`
  are learnable parameter vectors of size `C` (where `C` is the input size).
  By default, the elements of :math:`\gamma` are sampled from
  :math:`\mathcal{U}(0, 1)` and the elements of :math:`\beta` are set to 0.
  The standard-deviation is calculated via the biased estimator, equivalent to
  `torch.var(input, unbiased=False)`.
  
  Also by default, during training this layer keeps running estimates of its
  computed mean and variance, which are then used for normalization during
  evaluation. The running estimates are kept with a default :attr:`momentum`
  of 0.1.
  
  If :attr:`track_running_stats` is set to ``False``, this layer then does not
  keep running estimates, and batch statistics are instead used during
  evaluation time as well.
  
  .. note::
      This :attr:`momentum` argument is different from one used in optimizer
      classes and the conventional notion of momentum. Mathematically, the
      update rule for running statistics here is
      :math:`\hat{x}_\text{new} = (1 - \text{momentum}) \times \hat{x} + \text{momentum} \times x_t`,
      where :math:`\hat{x}` is the estimated statistic and :math:`x_t` is the
      new observed value.
  
  Because the Batch Normalization is done for each channel in the ``C`` dimension, computing
  statistics on ``(N, +)`` slices, it's common terminology to call this Volumetric Batch
  Normalization or Spatio-temporal Batch Normalization.
  
  Currently :class:`SyncBatchNorm` only supports
  :class:`~torch.nn.DistributedDataParallel` (DDP) with single GPU per process. Use
  :meth:`torch.nn.SyncBatchNorm.convert_sync_batchnorm()` to convert
  :attr:`BatchNorm*D` layer to :class:`SyncBatchNorm` before wrapping
  Network with DDP.
  
  Args:
      num_features: :math:`C` from an expected input of size
          :math:`(N, C, +)`
      eps: a value added to the denominator for numerical stability.
          Default: ``1e-5``
      momentum: the value used for the running_mean and running_var
          computation. Can be set to ``None`` for cumulative moving average
          (i.e. simple average). Default: 0.1
      affine: a boolean value that when set to ``True``, this module has
          learnable affine parameters. Default: ``True``
      track_running_stats: a boolean value that when set to ``True``, this
          module tracks the running mean and variance, and when set to ``False``,
          this module does not track such statistics, and initializes statistics
          buffers :attr:`running_mean` and :attr:`running_var` as ``None``.
          When these buffers are ``None``, this module always uses batch statistics.
          in both training and eval modes. Default: ``True``
      process_group: synchronization of stats happen within each process group
          individually. Default behavior is synchronization across the whole
          world
  
  Shape:
      - Input: :math:`(N, C, +)`
      - Output: :math:`(N, C, +)` (same shape as input)
  
  .. note::
      Synchronization of batchnorm statistics occurs only while training, i.e.
      synchronization is disabled when ``model.eval()`` is set or if
      ``self.training`` is otherwise ``False``.
  
  Examples::
  
      >>> # xdoctest: +SKIP
      >>> # With Learnable Parameters
      >>> m = nn.SyncBatchNorm(100)
      >>> # creating process group (optional)
      >>> # ranks is a list of int identifying rank ids.
      >>> ranks = list(range(8))
      >>> r1, r2 = ranks[:4], ranks[4:]
      >>> # Note: every rank calls into new_group for every
      >>> # process group created, even if that rank is not
      >>> # part of the group.
      >>> process_groups = [torch.distributed.new_group(pids) for pids in [r1, r2]]
      >>> process_group = process_groups[0 if dist.get_rank() <= 3 else 1]
      >>> # Without Learnable Parameters
      >>> m = nn.BatchNorm3d(100, affine=False, process_group=process_group)
      >>> input = torch.randn(20, 100, 35, 45, 10)
      >>> output = m(input)
  
      >>> # network is nn.BatchNorm layer
      >>> sync_bn_network = nn.SyncBatchNorm.convert_sync_batchnorm(network, process_group)
      >>> # only single gpu per process is currently supported
      >>> ddp_sync_bn_network = torch.nn.parallel.DistributedDataParallel(
      >>>                         sync_bn_network,
      >>>                         device_ids=[args.local_rank],
      >>>                         output_device=args.local_rank)
class_docstr_tok: ["Applies","Batch","Normalization","over","a","N-Dimensional","input",".","The","N-D","input","is","a","mini-batch","of","[","N-2","]","D","inputs","with","additional","channel","dimension",")","as","described","in","the","paper","`","Batch","Normalization",":","Accelerating","Deep","Network","Training","by","Reducing","Internal","Covariate","Shift","<","https",":","\/\/arxiv.org\/abs\/1502.03167",">","`","__",".","..","math",":",":","y","=","\\frac","{","x","-","\\mathrm","{","E","}","[","x","]","}","{","\\sqrt","{","\\mathrm","{","Var","}","[","x","]","+","\\epsilon","}","}","*","\\gamma","+","\\beta","The","mean","and","standard-deviation","are","calculated","per-dimension","over","all","mini-batches","of","the","same","process","groups",".",":","math",":","`","\\gamma","`","and",":","math",":","`","\\beta","`","are","learnable","parameter","vectors","of","size","`","C","`","(","where","`","C","`","is","the","input","size",")",".","By","default",",","the","elements","of",":","math",":","`","\\gamma","`","are","sampled","from",":","math",":","`","\\mathcal","{","U","}","(","0",",","1",")","`","and","the","elements","of",":","math",":","`","\\beta","`","are","set","to","0",".","The","standard-deviation","is","calculated","via","the","biased","estimator",",","equivalent","to","`","torch.var","(","input",",","unbiased=False",")","`",".","Also","by","default",",","during","training","this","layer","keeps","running","estimates","of","its","computed","mean","and","variance",",","which","are","then","used","for","normalization","during","evaluation",".","The","running","estimates","are","kept","with","a","default",":","attr",":","`","momentum","`","of","0.1",".","If",":","attr",":","`","track_running_stats","`","is","set","to","``","False","``",",","this","layer","then","does","not","keep","running","estimates",",","and","batch","statistics","are","instead","used","during","evaluation","time","as","well",".","..","note",":",":","This",":","attr",":","`","momentum","`","argument","is","different","from","one","used","in","optimizer","classes","and","the","conventional","notion","of","momentum",".","Mathematically",",","the","update","rule","for","running","statistics","here","is",":","math",":","`","\\hat","{","x","}","_\\text","{","new","}","=","(","1","-","\\text","{","momentum","}",")","\\times","\\hat","{","x","}","+","\\text","{","momentum","}","\\times","x_t","`",",","where",":","math",":","`","\\hat","{","x","}","`","is","the","estimated","statistic","and",":","math",":","`","x_t","`","is","the","new","observed","value",".","Because","the","Batch","Normalization","is","done","for","each","channel","in","the","``","C","``","dimension",",","computing","statistics","on","``","(","N",",","+",")","``","slices",",","it","'s","common","terminology","to","call","this","Volumetric","Batch","Normalization","or","Spatio-temporal","Batch","Normalization",".","Currently",":","class",":","`","SyncBatchNorm","`","only","supports",":","class",":","`","~torch.nn.DistributedDataParallel","`","(","DDP",")","with","single","GPU","per","process",".","Use",":","meth",":","`","torch.nn.SyncBatchNorm.convert_sync_batchnorm","(",")","`","to","convert",":","attr",":","`","BatchNorm","*","D","`","layer","to",":","class",":","`","SyncBatchNorm","`","before","wrapping","Network","with","DDP",".","Args",":","num_features",":",":","math",":","`","C","`","from","an","expected","input","of","size",":","math",":","`","(","N",",","C",",","+",")","`","eps",":","a","value","added","to","the","denominator","for","numerical","stability",".","Default",":","``","1e-5","``","momentum",":","the","value","used","for","the","running_mean","and","running_var","computation",".","Can","be","set","to","``","None","``","for","cumulative","moving","average","(","i.e",".","simple","average",")",".","Default",":","0.1","affine",":","a","boolean","value","that","when","set","to","``","True","``",",","this","module","has","learnable","affine","parameters",".","Default",":","``","True","``","track_running_stats",":","a","boolean","value","that","when","set","to","``","True","``",",","this","module","tracks","the","running","mean","and","variance",",","and","when","set","to","``","False","``",",","this","module","does","not","track","such","statistics",",","and","initializes","statistics","buffers",":","attr",":","`","running_mean","`","and",":","attr",":","`","running_var","`","as","``","None","``",".","When","these","buffers","are","``","None","``",",","this","module","always","uses","batch","statistics",".","in","both","training","and","eval","modes",".","Default",":","``","True","``","process_group",":","synchronization","of","stats","happen","within","each","process","group","individually",".","Default","behavior","is","synchronization","across","the","whole","world","Shape",":","-","Input",":",":","math",":","`","(","N",",","C",",","+",")","`","-","Output",":",":","math",":","`","(","N",",","C",",","+",")","`","(","same","shape","as","input",")","..","note",":",":","Synchronization","of","batchnorm","statistics","occurs","only","while","training",",","i.e",".","synchronization","is","disabled","when","``","model.eval","(",")","``","is","set","or","if","``","self.training","``","is","otherwise","``","False","``",".","Examples",":",":",">",">",">","#","xdoctest",":","+SKIP",">",">",">","#","With","Learnable","Parameters",">",">",">","m","=","nn.SyncBatchNorm","(","100",")",">",">",">","#","creating","process","group","(","optional",")",">",">",">","#","ranks","is","a","list","of","int","identifying","rank","ids",".",">",">",">","ranks","=","list","(","range","(","8",")",")",">",">",">","r1",",","r2","=","ranks","[",":4","]",",","ranks","[","4",":","]",">",">",">","#","Note",":","every","rank","calls","into","new_group","for","every",">",">",">","#","process","group","created",",","even","if","that","rank","is","not",">",">",">","#","part","of","the","group",".",">",">",">","process_groups","=","[","torch.distributed.new_group","(","pids",")","for","pids","in","[","r1",",","r2","]","]",">",">",">","process_group","=","process_groups","[","0","if","dist.get_rank","(",")","<","=","3","else","1","]",">",">",">","#","Without","Learnable","Parameters",">",">",">","m","=","nn.BatchNorm3d","(","100",",","affine=False",",","process_group=process_group",")",">",">",">","input","=","torch.randn","(","20",",","100",",","35",",","45",",","10",")",">",">",">","output","=","m","(","input",")",">",">",">","#","network","is","nn.BatchNorm","layer",">",">",">","sync_bn_network","=","nn.SyncBatchNorm.convert_sync_batchnorm","(","network",",","process_group",")",">",">",">","#","only","single","gpu","per","process","is","currently","supported",">",">",">","ddp_sync_bn_network","=","torch.nn.parallel.DistributedDataParallel","(",">",">",">","sync_bn_network",",",">",">",">","device_ids=","[","args.local_rank","]",",",">",">",">","output_device=args.local_rank",")"]
code: def forward(self, input: Tensor) -> Tensor:
      self._check_input_dim(input)
      self._check_non_zero_input_channels(input)
  
      # exponential_average_factor is set to self.momentum
      # (when it is available) only so that it gets updated
      # in ONNX graph when this node is exported to ONNX.
      if self.momentum is None:
          exponential_average_factor = 0.0
      else:
          exponential_average_factor = self.momentum
  
      if self.training and self.track_running_stats:
          assert self.num_batches_tracked is not None
          self.num_batches_tracked.add_(1)
          if self.momentum is None:  # use cumulative moving average
              exponential_average_factor = (
                  1.0 / self.num_batches_tracked.item()
              )
          else:  # use exponential moving average
              exponential_average_factor = self.momentum
  
      r"""
          Decide whether the mini-batch stats should be used for normalization rather than the buffers.
          Mini-batch stats are used in training mode, and in eval mode when buffers are None.
          """
      if self.training:
          bn_training = True
      else:
          bn_training = (self.running_mean is None) and (
              self.running_var is None
          )
  
      r"""
          Buffers are only updated if they are to be tracked and we are in training mode. Thus they only need to be
          passed when the update should occur (i.e. in training mode when they are tracked), or when buffer stats are
          used for normalization (i.e. in eval mode when buffers are not None).
          """
      # If buffers are not to be tracked, ensure that they won't be updated
      running_mean = (
          self.running_mean
          if not self.training or self.track_running_stats
          else None
      )
      running_var = (
          self.running_var
          if not self.training or self.track_running_stats
          else None
      )
  
      # Don't sync batchnorm stats in inference mode (model.eval()).
      need_sync = (
          bn_training
          and self.training
          and torch.distributed.is_available()
          and torch.distributed.is_initialized()
      )
      if need_sync:
          # currently only GPU/PrivateUse1 input is supported
          if input.device.type not in [
              "cuda",
              torch._C._get_privateuse1_backend_name(),
          ]:
              raise ValueError(
                  "SyncBatchNorm expected input tensor to be on GPU or "
                  f"{torch._C._get_privateuse1_backend_name()}"
              )
  
          process_group = torch.distributed.group.WORLD
          if self.process_group:
              process_group = self.process_group
          world_size = torch.distributed.get_world_size(process_group)
          need_sync = world_size > 1
  
      # fallback to framework BN when synchronization is not necessary
      if not need_sync:
          return F.batch_norm(
              input,
              running_mean,
              running_var,
              self.weight,
              self.bias,
              bn_training,
              exponential_average_factor,
              self.eps,
          )
      else:
          assert bn_training
          return sync_batch_norm.apply(
              input,
              self.weight,
              self.bias,
              running_mean,
              running_var,
              self.eps,
              exponential_average_factor,
              process_group,
              world_size,
          )
  
imports: from typing import Optional, Any
  import torch
  from torch import Tensor
  from torch.nn.parameter import Parameter, UninitializedParameter, UninitializedBuffer
  from ..None import functional
  from ..None import init
  from ._functions import SyncBatchNorm
  from .lazy import LazyModuleMixin
  from .module import Module
label_desc: Use image node_id 4 for calling the SyncBatchNorm obj's underlying member method code with example usage: obj.forward(input) and returns: F, sync_batch_norm