We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
SyncBatchNorm breaks after PyTorch 1.9.0
**Describe the Issue**
`torch.nn.SyncBatchNorm` has been updated since PyTorch 1.9.0 and `_specify_ddp_gpu_num()` is no longer available, breaking the following code snippet: https://github.com/open-mmlab/mmcv/blob/eb08835fa246ea81263eb25fbe2caa54ef11271c/mmcv/utils/parrots_wrapper.py#L83-L87

More details: https://github.com/open-mmlab/mmocr/issues/325

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mmcv/utils/parrots_wrapper.py`
Content:
```
1 from functools import partial
2 
3 import torch
4 
5 TORCH_VERSION = torch.__version__
6 
7 
8 def _get_cuda_home():
9     if TORCH_VERSION == 'parrots':
10         from parrots.utils.build_extension import CUDA_HOME
11     else:
12         from torch.utils.cpp_extension import CUDA_HOME
13     return CUDA_HOME
14 
15 
16 def get_build_config():
17     if TORCH_VERSION == 'parrots':
18         from parrots.config import get_build_info
19         return get_build_info()
20     else:
21         return torch.__config__.show()
22 
23 
24 def _get_conv():
25     if TORCH_VERSION == 'parrots':
26         from parrots.nn.modules.conv import _ConvNd, _ConvTransposeMixin
27     else:
28         from torch.nn.modules.conv import _ConvNd, _ConvTransposeMixin
29     return _ConvNd, _ConvTransposeMixin
30 
31 
32 def _get_dataloader():
33     if TORCH_VERSION == 'parrots':
34         from torch.utils.data import DataLoader, PoolDataLoader
35     else:
36         from torch.utils.data import DataLoader
37         PoolDataLoader = DataLoader
38     return DataLoader, PoolDataLoader
39 
40 
41 def _get_extension():
42     if TORCH_VERSION == 'parrots':
43         from parrots.utils.build_extension import BuildExtension, Extension
44         CppExtension = partial(Extension, cuda=False)
45         CUDAExtension = partial(Extension, cuda=True)
46     else:
47         from torch.utils.cpp_extension import (BuildExtension, CppExtension,
48                                                CUDAExtension)
49     return BuildExtension, CppExtension, CUDAExtension
50 
51 
52 def _get_pool():
53     if TORCH_VERSION == 'parrots':
54         from parrots.nn.modules.pool import (_AdaptiveAvgPoolNd,
55                                              _AdaptiveMaxPoolNd, _AvgPoolNd,
56                                              _MaxPoolNd)
57     else:
58         from torch.nn.modules.pooling import (_AdaptiveAvgPoolNd,
59                                               _AdaptiveMaxPoolNd, _AvgPoolNd,
60                                               _MaxPoolNd)
61     return _AdaptiveAvgPoolNd, _AdaptiveMaxPoolNd, _AvgPoolNd, _MaxPoolNd
62 
63 
64 def _get_norm():
65     if TORCH_VERSION == 'parrots':
66         from parrots.nn.modules.batchnorm import _BatchNorm, _InstanceNorm
67         SyncBatchNorm_ = torch.nn.SyncBatchNorm2d
68     else:
69         from torch.nn.modules.instancenorm import _InstanceNorm
70         from torch.nn.modules.batchnorm import _BatchNorm
71         SyncBatchNorm_ = torch.nn.SyncBatchNorm
72     return _BatchNorm, _InstanceNorm, SyncBatchNorm_
73 
74 
75 CUDA_HOME = _get_cuda_home()
76 _ConvNd, _ConvTransposeMixin = _get_conv()
77 DataLoader, PoolDataLoader = _get_dataloader()
78 BuildExtension, CppExtension, CUDAExtension = _get_extension()
79 _BatchNorm, _InstanceNorm, SyncBatchNorm_ = _get_norm()
80 _AdaptiveAvgPoolNd, _AdaptiveMaxPoolNd, _AvgPoolNd, _MaxPoolNd = _get_pool()
81 
82 
83 class SyncBatchNorm(SyncBatchNorm_):
84 
85     def _specify_ddp_gpu_num(self, gpu_size):
86         if TORCH_VERSION != 'parrots':
87             super()._specify_ddp_gpu_num(gpu_size)
88 
89     def _check_input_dim(self, input):
90         if TORCH_VERSION == 'parrots':
91             if input.dim() < 2:
92                 raise ValueError(
93                     f'expected at least 2D input (got {input.dim()}D input)')
94         else:
95             super()._check_input_dim(input)
96
```

Path: `mmcv/cnn/bricks/norm.py`
Content:
```
1 import inspect
2 
3 import torch.nn as nn
4 
5 from mmcv.utils import is_tuple_of
6 from mmcv.utils.parrots_wrapper import SyncBatchNorm, _BatchNorm, _InstanceNorm
7 from .registry import NORM_LAYERS
8 
9 NORM_LAYERS.register_module('BN', module=nn.BatchNorm2d)
10 NORM_LAYERS.register_module('BN1d', module=nn.BatchNorm1d)
11 NORM_LAYERS.register_module('BN2d', module=nn.BatchNorm2d)
12 NORM_LAYERS.register_module('BN3d', module=nn.BatchNorm3d)
13 NORM_LAYERS.register_module('SyncBN', module=SyncBatchNorm)
14 NORM_LAYERS.register_module('GN', module=nn.GroupNorm)
15 NORM_LAYERS.register_module('LN', module=nn.LayerNorm)
16 NORM_LAYERS.register_module('IN', module=nn.InstanceNorm2d)
17 NORM_LAYERS.register_module('IN1d', module=nn.InstanceNorm1d)
18 NORM_LAYERS.register_module('IN2d', module=nn.InstanceNorm2d)
19 NORM_LAYERS.register_module('IN3d', module=nn.InstanceNorm3d)
20 
21 
22 def infer_abbr(class_type):
23     """Infer abbreviation from the class name.
24 
25     When we build a norm layer with `build_norm_layer()`, we want to preserve
26     the norm type in variable names, e.g, self.bn1, self.gn. This method will
27     infer the abbreviation to map class types to abbreviations.
28 
29     Rule 1: If the class has the property "_abbr_", return the property.
30     Rule 2: If the parent class is _BatchNorm, GroupNorm, LayerNorm or
31     InstanceNorm, the abbreviation of this layer will be "bn", "gn", "ln" and
32     "in" respectively.
33     Rule 3: If the class name contains "batch", "group", "layer" or "instance",
34     the abbreviation of this layer will be "bn", "gn", "ln" and "in"
35     respectively.
36     Rule 4: Otherwise, the abbreviation falls back to "norm".
37 
38     Args:
39         class_type (type): The norm layer type.
40 
41     Returns:
42         str: The inferred abbreviation.
43     """
44     if not inspect.isclass(class_type):
45         raise TypeError(
46             f'class_type must be a type, but got {type(class_type)}')
47     if hasattr(class_type, '_abbr_'):
48         return class_type._abbr_
49     if issubclass(class_type, _InstanceNorm):  # IN is a subclass of BN
50         return 'in'
51     elif issubclass(class_type, _BatchNorm):
52         return 'bn'
53     elif issubclass(class_type, nn.GroupNorm):
54         return 'gn'
55     elif issubclass(class_type, nn.LayerNorm):
56         return 'ln'
57     else:
58         class_name = class_type.__name__.lower()
59         if 'batch' in class_name:
60             return 'bn'
61         elif 'group' in class_name:
62             return 'gn'
63         elif 'layer' in class_name:
64             return 'ln'
65         elif 'instance' in class_name:
66             return 'in'
67         else:
68             return 'norm_layer'
69 
70 
71 def build_norm_layer(cfg, num_features, postfix=''):
72     """Build normalization layer.
73 
74     Args:
75         cfg (dict): The norm layer config, which should contain:
76 
77             - type (str): Layer type.
78             - layer args: Args needed to instantiate a norm layer.
79             - requires_grad (bool, optional): Whether stop gradient updates.
80         num_features (int): Number of input channels.
81         postfix (int | str): The postfix to be appended into norm abbreviation
82             to create named layer.
83 
84     Returns:
85         (str, nn.Module): The first element is the layer name consisting of
86             abbreviation and postfix, e.g., bn1, gn. The second element is the
87             created norm layer.
88     """
89     if not isinstance(cfg, dict):
90         raise TypeError('cfg must be a dict')
91     if 'type' not in cfg:
92         raise KeyError('the cfg dict must contain the key "type"')
93     cfg_ = cfg.copy()
94 
95     layer_type = cfg_.pop('type')
96     if layer_type not in NORM_LAYERS:
97         raise KeyError(f'Unrecognized norm type {layer_type}')
98 
99     norm_layer = NORM_LAYERS.get(layer_type)
100     abbr = infer_abbr(norm_layer)
101 
102     assert isinstance(postfix, (int, str))
103     name = abbr + str(postfix)
104 
105     requires_grad = cfg_.pop('requires_grad', True)
106     cfg_.setdefault('eps', 1e-5)
107     if layer_type != 'GN':
108         layer = norm_layer(num_features, **cfg_)
109         if layer_type == 'SyncBN':
110             layer._specify_ddp_gpu_num(1)
111     else:
112         assert 'num_groups' in cfg_
113         layer = norm_layer(num_channels=num_features, **cfg_)
114 
115     for param in layer.parameters():
116         param.requires_grad = requires_grad
117 
118     return name, layer
119 
120 
121 def is_norm(layer, exclude=None):
122     """Check if a layer is a normalization layer.
123 
124     Args:
125         layer (nn.Module): The layer to be checked.
126         exclude (type | tuple[type]): Types to be excluded.
127 
128     Returns:
129         bool: Whether the layer is a norm layer.
130     """
131     if exclude is not None:
132         if not isinstance(exclude, tuple):
133             exclude = (exclude, )
134         if not is_tuple_of(exclude, type):
135             raise TypeError(
136                 f'"exclude" must be either None or type or a tuple of types, '
137                 f'but got {type(exclude)}: {exclude}')
138 
139     if exclude and isinstance(layer, exclude):
140         return False
141 
142     all_norm_bases = (_BatchNorm, _InstanceNorm, nn.GroupNorm, nn.LayerNorm)
143     return isinstance(layer, all_norm_bases)
144
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mmcv/cnn/bricks/norm.py b/mmcv/cnn/bricks/norm.py
--- a/mmcv/cnn/bricks/norm.py
+++ b/mmcv/cnn/bricks/norm.py
@@ -106,7 +106,7 @@
     cfg_.setdefault('eps', 1e-5)
     if layer_type != 'GN':
         layer = norm_layer(num_features, **cfg_)
-        if layer_type == 'SyncBN':
+        if layer_type == 'SyncBN' and hasattr(layer, '_specify_ddp_gpu_num'):
             layer._specify_ddp_gpu_num(1)
     else:
         assert 'num_groups' in cfg_
diff --git a/mmcv/utils/parrots_wrapper.py b/mmcv/utils/parrots_wrapper.py
--- a/mmcv/utils/parrots_wrapper.py
+++ b/mmcv/utils/parrots_wrapper.py
@@ -82,10 +82,6 @@
 
 class SyncBatchNorm(SyncBatchNorm_):
 
-    def _specify_ddp_gpu_num(self, gpu_size):
-        if TORCH_VERSION != 'parrots':
-            super()._specify_ddp_gpu_num(gpu_size)
-
     def _check_input_dim(self, input):
         if TORCH_VERSION == 'parrots':
             if input.dim() < 2:

{"golden_diff": "diff --git a/mmcv/cnn/bricks/norm.py b/mmcv/cnn/bricks/norm.py\n--- a/mmcv/cnn/bricks/norm.py\n+++ b/mmcv/cnn/bricks/norm.py\n@@ -106,7 +106,7 @@\n     cfg_.setdefault('eps', 1e-5)\n     if layer_type != 'GN':\n         layer = norm_layer(num_features, **cfg_)\n-        if layer_type == 'SyncBN':\n+        if layer_type == 'SyncBN' and hasattr(layer, '_specify_ddp_gpu_num'):\n             layer._specify_ddp_gpu_num(1)\n     else:\n         assert 'num_groups' in cfg_\ndiff --git a/mmcv/utils/parrots_wrapper.py b/mmcv/utils/parrots_wrapper.py\n--- a/mmcv/utils/parrots_wrapper.py\n+++ b/mmcv/utils/parrots_wrapper.py\n@@ -82,10 +82,6 @@\n \n class SyncBatchNorm(SyncBatchNorm_):\n \n-    def _specify_ddp_gpu_num(self, gpu_size):\n-        if TORCH_VERSION != 'parrots':\n-            super()._specify_ddp_gpu_num(gpu_size)\n-\n     def _check_input_dim(self, input):\n         if TORCH_VERSION == 'parrots':\n             if input.dim() < 2:\n", "issue": "SyncBatchNorm breaks after PyTorch 1.9.0\n**Describe the Issue**\r\n`torch.nn.SyncBatchNorm` has been updated since PyTorch 1.9.0 and `_specify_ddp_gpu_num()` is no longer available, breaking the following code snippet: https://github.com/open-mmlab/mmcv/blob/eb08835fa246ea81263eb25fbe2caa54ef11271c/mmcv/utils/parrots_wrapper.py#L83-L87\r\n\r\nMore details: https://github.com/open-mmlab/mmocr/issues/325\n", "before_files": [{"content": "from functools import partial\n\nimport torch\n\nTORCH_VERSION = torch.__version__\n\n\ndef _get_cuda_home():\n    if TORCH_VERSION == 'parrots':\n        from parrots.utils.build_extension import CUDA_HOME\n    else:\n        from torch.utils.cpp_extension import CUDA_HOME\n    return CUDA_HOME\n\n\ndef get_build_config():\n    if TORCH_VERSION == 'parrots':\n        from parrots.config import get_build_info\n        return get_build_info()\n    else:\n        return torch.__config__.show()\n\n\ndef _get_conv():\n    if TORCH_VERSION == 'parrots':\n        from parrots.nn.modules.conv import _ConvNd, _ConvTransposeMixin\n    else:\n        from torch.nn.modules.conv import _ConvNd, _ConvTransposeMixin\n    return _ConvNd, _ConvTransposeMixin\n\n\ndef _get_dataloader():\n    if TORCH_VERSION == 'parrots':\n        from torch.utils.data import DataLoader, PoolDataLoader\n    else:\n        from torch.utils.data import DataLoader\n        PoolDataLoader = DataLoader\n    return DataLoader, PoolDataLoader\n\n\ndef _get_extension():\n    if TORCH_VERSION == 'parrots':\n        from parrots.utils.build_extension import BuildExtension, Extension\n        CppExtension = partial(Extension, cuda=False)\n        CUDAExtension = partial(Extension, cuda=True)\n    else:\n        from torch.utils.cpp_extension import (BuildExtension, CppExtension,\n                                               CUDAExtension)\n    return BuildExtension, CppExtension, CUDAExtension\n\n\ndef _get_pool():\n    if TORCH_VERSION == 'parrots':\n        from parrots.nn.modules.pool import (_AdaptiveAvgPoolNd,\n                                             _AdaptiveMaxPoolNd, _AvgPoolNd,\n                                             _MaxPoolNd)\n    else:\n        from torch.nn.modules.pooling import (_AdaptiveAvgPoolNd,\n                                              _AdaptiveMaxPoolNd, _AvgPoolNd,\n                                              _MaxPoolNd)\n    return _AdaptiveAvgPoolNd, _AdaptiveMaxPoolNd, _AvgPoolNd, _MaxPoolNd\n\n\ndef _get_norm():\n    if TORCH_VERSION == 'parrots':\n        from parrots.nn.modules.batchnorm import _BatchNorm, _InstanceNorm\n        SyncBatchNorm_ = torch.nn.SyncBatchNorm2d\n    else:\n        from torch.nn.modules.instancenorm import _InstanceNorm\n        from torch.nn.modules.batchnorm import _BatchNorm\n        SyncBatchNorm_ = torch.nn.SyncBatchNorm\n    return _BatchNorm, _InstanceNorm, SyncBatchNorm_\n\n\nCUDA_HOME = _get_cuda_home()\n_ConvNd, _ConvTransposeMixin = _get_conv()\nDataLoader, PoolDataLoader = _get_dataloader()\nBuildExtension, CppExtension, CUDAExtension = _get_extension()\n_BatchNorm, _InstanceNorm, SyncBatchNorm_ = _get_norm()\n_AdaptiveAvgPoolNd, _AdaptiveMaxPoolNd, _AvgPoolNd, _MaxPoolNd = _get_pool()\n\n\nclass SyncBatchNorm(SyncBatchNorm_):\n\n    def _specify_ddp_gpu_num(self, gpu_size):\n        if TORCH_VERSION != 'parrots':\n            super()._specify_ddp_gpu_num(gpu_size)\n\n    def _check_input_dim(self, input):\n        if TORCH_VERSION == 'parrots':\n            if input.dim() < 2:\n                raise ValueError(\n                    f'expected at least 2D input (got {input.dim()}D input)')\n        else:\n            super()._check_input_dim(input)\n", "path": "mmcv/utils/parrots_wrapper.py"}, {"content": "import inspect\n\nimport torch.nn as nn\n\nfrom mmcv.utils import is_tuple_of\nfrom mmcv.utils.parrots_wrapper import SyncBatchNorm, _BatchNorm, _InstanceNorm\nfrom .registry import NORM_LAYERS\n\nNORM_LAYERS.register_module('BN', module=nn.BatchNorm2d)\nNORM_LAYERS.register_module('BN1d', module=nn.BatchNorm1d)\nNORM_LAYERS.register_module('BN2d', module=nn.BatchNorm2d)\nNORM_LAYERS.register_module('BN3d', module=nn.BatchNorm3d)\nNORM_LAYERS.register_module('SyncBN', module=SyncBatchNorm)\nNORM_LAYERS.register_module('GN', module=nn.GroupNorm)\nNORM_LAYERS.register_module('LN', module=nn.LayerNorm)\nNORM_LAYERS.register_module('IN', module=nn.InstanceNorm2d)\nNORM_LAYERS.register_module('IN1d', module=nn.InstanceNorm1d)\nNORM_LAYERS.register_module('IN2d', module=nn.InstanceNorm2d)\nNORM_LAYERS.register_module('IN3d', module=nn.InstanceNorm3d)\n\n\ndef infer_abbr(class_type):\n    \"\"\"Infer abbreviation from the class name.\n\n    When we build a norm layer with `build_norm_layer()`, we want to preserve\n    the norm type in variable names, e.g, self.bn1, self.gn. This method will\n    infer the abbreviation to map class types to abbreviations.\n\n    Rule 1: If the class has the property \"_abbr_\", return the property.\n    Rule 2: If the parent class is _BatchNorm, GroupNorm, LayerNorm or\n    InstanceNorm, the abbreviation of this layer will be \"bn\", \"gn\", \"ln\" and\n    \"in\" respectively.\n    Rule 3: If the class name contains \"batch\", \"group\", \"layer\" or \"instance\",\n    the abbreviation of this layer will be \"bn\", \"gn\", \"ln\" and \"in\"\n    respectively.\n    Rule 4: Otherwise, the abbreviation falls back to \"norm\".\n\n    Args:\n        class_type (type): The norm layer type.\n\n    Returns:\n        str: The inferred abbreviation.\n    \"\"\"\n    if not inspect.isclass(class_type):\n        raise TypeError(\n            f'class_type must be a type, but got {type(class_type)}')\n    if hasattr(class_type, '_abbr_'):\n        return class_type._abbr_\n    if issubclass(class_type, _InstanceNorm):  # IN is a subclass of BN\n        return 'in'\n    elif issubclass(class_type, _BatchNorm):\n        return 'bn'\n    elif issubclass(class_type, nn.GroupNorm):\n        return 'gn'\n    elif issubclass(class_type, nn.LayerNorm):\n        return 'ln'\n    else:\n        class_name = class_type.__name__.lower()\n        if 'batch' in class_name:\n            return 'bn'\n        elif 'group' in class_name:\n            return 'gn'\n        elif 'layer' in class_name:\n            return 'ln'\n        elif 'instance' in class_name:\n            return 'in'\n        else:\n            return 'norm_layer'\n\n\ndef build_norm_layer(cfg, num_features, postfix=''):\n    \"\"\"Build normalization layer.\n\n    Args:\n        cfg (dict): The norm layer config, which should contain:\n\n            - type (str): Layer type.\n            - layer args: Args needed to instantiate a norm layer.\n            - requires_grad (bool, optional): Whether stop gradient updates.\n        num_features (int): Number of input channels.\n        postfix (int | str): The postfix to be appended into norm abbreviation\n            to create named layer.\n\n    Returns:\n        (str, nn.Module): The first element is the layer name consisting of\n            abbreviation and postfix, e.g., bn1, gn. The second element is the\n            created norm layer.\n    \"\"\"\n    if not isinstance(cfg, dict):\n        raise TypeError('cfg must be a dict')\n    if 'type' not in cfg:\n        raise KeyError('the cfg dict must contain the key \"type\"')\n    cfg_ = cfg.copy()\n\n    layer_type = cfg_.pop('type')\n    if layer_type not in NORM_LAYERS:\n        raise KeyError(f'Unrecognized norm type {layer_type}')\n\n    norm_layer = NORM_LAYERS.get(layer_type)\n    abbr = infer_abbr(norm_layer)\n\n    assert isinstance(postfix, (int, str))\n    name = abbr + str(postfix)\n\n    requires_grad = cfg_.pop('requires_grad', True)\n    cfg_.setdefault('eps', 1e-5)\n    if layer_type != 'GN':\n        layer = norm_layer(num_features, **cfg_)\n        if layer_type == 'SyncBN':\n            layer._specify_ddp_gpu_num(1)\n    else:\n        assert 'num_groups' in cfg_\n        layer = norm_layer(num_channels=num_features, **cfg_)\n\n    for param in layer.parameters():\n        param.requires_grad = requires_grad\n\n    return name, layer\n\n\ndef is_norm(layer, exclude=None):\n    \"\"\"Check if a layer is a normalization layer.\n\n    Args:\n        layer (nn.Module): The layer to be checked.\n        exclude (type | tuple[type]): Types to be excluded.\n\n    Returns:\n        bool: Whether the layer is a norm layer.\n    \"\"\"\n    if exclude is not None:\n        if not isinstance(exclude, tuple):\n            exclude = (exclude, )\n        if not is_tuple_of(exclude, type):\n            raise TypeError(\n                f'\"exclude\" must be either None or type or a tuple of types, '\n                f'but got {type(exclude)}: {exclude}')\n\n    if exclude and isinstance(layer, exclude):\n        return False\n\n    all_norm_bases = (_BatchNorm, _InstanceNorm, nn.GroupNorm, nn.LayerNorm)\n    return isinstance(layer, all_norm_bases)\n", "path": "mmcv/cnn/bricks/norm.py"}], "after_files": [{"content": "from functools import partial\n\nimport torch\n\nTORCH_VERSION = torch.__version__\n\n\ndef _get_cuda_home():\n    if TORCH_VERSION == 'parrots':\n        from parrots.utils.build_extension import CUDA_HOME\n    else:\n        from torch.utils.cpp_extension import CUDA_HOME\n    return CUDA_HOME\n\n\ndef get_build_config():\n    if TORCH_VERSION == 'parrots':\n        from parrots.config import get_build_info\n        return get_build_info()\n    else:\n        return torch.__config__.show()\n\n\ndef _get_conv():\n    if TORCH_VERSION == 'parrots':\n        from parrots.nn.modules.conv import _ConvNd, _ConvTransposeMixin\n    else:\n        from torch.nn.modules.conv import _ConvNd, _ConvTransposeMixin\n    return _ConvNd, _ConvTransposeMixin\n\n\ndef _get_dataloader():\n    if TORCH_VERSION == 'parrots':\n        from torch.utils.data import DataLoader, PoolDataLoader\n    else:\n        from torch.utils.data import DataLoader\n        PoolDataLoader = DataLoader\n    return DataLoader, PoolDataLoader\n\n\ndef _get_extension():\n    if TORCH_VERSION == 'parrots':\n        from parrots.utils.build_extension import BuildExtension, Extension\n        CppExtension = partial(Extension, cuda=False)\n        CUDAExtension = partial(Extension, cuda=True)\n    else:\n        from torch.utils.cpp_extension import (BuildExtension, CppExtension,\n                                               CUDAExtension)\n    return BuildExtension, CppExtension, CUDAExtension\n\n\ndef _get_pool():\n    if TORCH_VERSION == 'parrots':\n        from parrots.nn.modules.pool import (_AdaptiveAvgPoolNd,\n                                             _AdaptiveMaxPoolNd, _AvgPoolNd,\n                                             _MaxPoolNd)\n    else:\n        from torch.nn.modules.pooling import (_AdaptiveAvgPoolNd,\n                                              _AdaptiveMaxPoolNd, _AvgPoolNd,\n                                              _MaxPoolNd)\n    return _AdaptiveAvgPoolNd, _AdaptiveMaxPoolNd, _AvgPoolNd, _MaxPoolNd\n\n\ndef _get_norm():\n    if TORCH_VERSION == 'parrots':\n        from parrots.nn.modules.batchnorm import _BatchNorm, _InstanceNorm\n        SyncBatchNorm_ = torch.nn.SyncBatchNorm2d\n    else:\n        from torch.nn.modules.instancenorm import _InstanceNorm\n        from torch.nn.modules.batchnorm import _BatchNorm\n        SyncBatchNorm_ = torch.nn.SyncBatchNorm\n    return _BatchNorm, _InstanceNorm, SyncBatchNorm_\n\n\nCUDA_HOME = _get_cuda_home()\n_ConvNd, _ConvTransposeMixin = _get_conv()\nDataLoader, PoolDataLoader = _get_dataloader()\nBuildExtension, CppExtension, CUDAExtension = _get_extension()\n_BatchNorm, _InstanceNorm, SyncBatchNorm_ = _get_norm()\n_AdaptiveAvgPoolNd, _AdaptiveMaxPoolNd, _AvgPoolNd, _MaxPoolNd = _get_pool()\n\n\nclass SyncBatchNorm(SyncBatchNorm_):\n\n    def _check_input_dim(self, input):\n        if TORCH_VERSION == 'parrots':\n            if input.dim() < 2:\n                raise ValueError(\n                    f'expected at least 2D input (got {input.dim()}D input)')\n        else:\n            super()._check_input_dim(input)\n", "path": "mmcv/utils/parrots_wrapper.py"}, {"content": "import inspect\n\nimport torch.nn as nn\n\nfrom mmcv.utils import is_tuple_of\nfrom mmcv.utils.parrots_wrapper import SyncBatchNorm, _BatchNorm, _InstanceNorm\nfrom .registry import NORM_LAYERS\n\nNORM_LAYERS.register_module('BN', module=nn.BatchNorm2d)\nNORM_LAYERS.register_module('BN1d', module=nn.BatchNorm1d)\nNORM_LAYERS.register_module('BN2d', module=nn.BatchNorm2d)\nNORM_LAYERS.register_module('BN3d', module=nn.BatchNorm3d)\nNORM_LAYERS.register_module('SyncBN', module=SyncBatchNorm)\nNORM_LAYERS.register_module('GN', module=nn.GroupNorm)\nNORM_LAYERS.register_module('LN', module=nn.LayerNorm)\nNORM_LAYERS.register_module('IN', module=nn.InstanceNorm2d)\nNORM_LAYERS.register_module('IN1d', module=nn.InstanceNorm1d)\nNORM_LAYERS.register_module('IN2d', module=nn.InstanceNorm2d)\nNORM_LAYERS.register_module('IN3d', module=nn.InstanceNorm3d)\n\n\ndef infer_abbr(class_type):\n    \"\"\"Infer abbreviation from the class name.\n\n    When we build a norm layer with `build_norm_layer()`, we want to preserve\n    the norm type in variable names, e.g, self.bn1, self.gn. This method will\n    infer the abbreviation to map class types to abbreviations.\n\n    Rule 1: If the class has the property \"_abbr_\", return the property.\n    Rule 2: If the parent class is _BatchNorm, GroupNorm, LayerNorm or\n    InstanceNorm, the abbreviation of this layer will be \"bn\", \"gn\", \"ln\" and\n    \"in\" respectively.\n    Rule 3: If the class name contains \"batch\", \"group\", \"layer\" or \"instance\",\n    the abbreviation of this layer will be \"bn\", \"gn\", \"ln\" and \"in\"\n    respectively.\n    Rule 4: Otherwise, the abbreviation falls back to \"norm\".\n\n    Args:\n        class_type (type): The norm layer type.\n\n    Returns:\n        str: The inferred abbreviation.\n    \"\"\"\n    if not inspect.isclass(class_type):\n        raise TypeError(\n            f'class_type must be a type, but got {type(class_type)}')\n    if hasattr(class_type, '_abbr_'):\n        return class_type._abbr_\n    if issubclass(class_type, _InstanceNorm):  # IN is a subclass of BN\n        return 'in'\n    elif issubclass(class_type, _BatchNorm):\n        return 'bn'\n    elif issubclass(class_type, nn.GroupNorm):\n        return 'gn'\n    elif issubclass(class_type, nn.LayerNorm):\n        return 'ln'\n    else:\n        class_name = class_type.__name__.lower()\n        if 'batch' in class_name:\n            return 'bn'\n        elif 'group' in class_name:\n            return 'gn'\n        elif 'layer' in class_name:\n            return 'ln'\n        elif 'instance' in class_name:\n            return 'in'\n        else:\n            return 'norm_layer'\n\n\ndef build_norm_layer(cfg, num_features, postfix=''):\n    \"\"\"Build normalization layer.\n\n    Args:\n        cfg (dict): The norm layer config, which should contain:\n\n            - type (str): Layer type.\n            - layer args: Args needed to instantiate a norm layer.\n            - requires_grad (bool, optional): Whether stop gradient updates.\n        num_features (int): Number of input channels.\n        postfix (int | str): The postfix to be appended into norm abbreviation\n            to create named layer.\n\n    Returns:\n        (str, nn.Module): The first element is the layer name consisting of\n            abbreviation and postfix, e.g., bn1, gn. The second element is the\n            created norm layer.\n    \"\"\"\n    if not isinstance(cfg, dict):\n        raise TypeError('cfg must be a dict')\n    if 'type' not in cfg:\n        raise KeyError('the cfg dict must contain the key \"type\"')\n    cfg_ = cfg.copy()\n\n    layer_type = cfg_.pop('type')\n    if layer_type not in NORM_LAYERS:\n        raise KeyError(f'Unrecognized norm type {layer_type}')\n\n    norm_layer = NORM_LAYERS.get(layer_type)\n    abbr = infer_abbr(norm_layer)\n\n    assert isinstance(postfix, (int, str))\n    name = abbr + str(postfix)\n\n    requires_grad = cfg_.pop('requires_grad', True)\n    cfg_.setdefault('eps', 1e-5)\n    if layer_type != 'GN':\n        layer = norm_layer(num_features, **cfg_)\n        if layer_type == 'SyncBN' and hasattr(layer, '_specify_ddp_gpu_num'):\n            layer._specify_ddp_gpu_num(1)\n    else:\n        assert 'num_groups' in cfg_\n        layer = norm_layer(num_channels=num_features, **cfg_)\n\n    for param in layer.parameters():\n        param.requires_grad = requires_grad\n\n    return name, layer\n\n\ndef is_norm(layer, exclude=None):\n    \"\"\"Check if a layer is a normalization layer.\n\n    Args:\n        layer (nn.Module): The layer to be checked.\n        exclude (type | tuple[type]): Types to be excluded.\n\n    Returns:\n        bool: Whether the layer is a norm layer.\n    \"\"\"\n    if exclude is not None:\n        if not isinstance(exclude, tuple):\n            exclude = (exclude, )\n        if not is_tuple_of(exclude, type):\n            raise TypeError(\n                f'\"exclude\" must be either None or type or a tuple of types, '\n                f'but got {type(exclude)}: {exclude}')\n\n    if exclude and isinstance(layer, exclude):\n        return False\n\n    all_norm_bases = (_BatchNorm, _InstanceNorm, nn.GroupNorm, nn.LayerNorm)\n    return isinstance(layer, all_norm_bases)\n", "path": "mmcv/cnn/bricks/norm.py"}]}