sync_norm_hook.py 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637
  1. # Copyright (c) OpenMMLab. All rights reserved.
  2. from collections import OrderedDict
  3. from mmengine.dist import get_dist_info
  4. from mmengine.hooks import Hook
  5. from torch import nn
  6. from mmdet.registry import HOOKS
  7. from mmdet.utils import all_reduce_dict
  8. def get_norm_states(module: nn.Module) -> OrderedDict:
  9. """Get the state_dict of batch norms in the module."""
  10. async_norm_states = OrderedDict()
  11. for name, child in module.named_modules():
  12. if isinstance(child, nn.modules.batchnorm._NormBase):
  13. for k, v in child.state_dict().items():
  14. async_norm_states['.'.join([name, k])] = v
  15. return async_norm_states
  16. @HOOKS.register_module()
  17. class SyncNormHook(Hook):
  18. """Synchronize Norm states before validation, currently used in YOLOX."""
  19. def before_val_epoch(self, runner):
  20. """Synchronizing norm."""
  21. module = runner.model
  22. _, world_size = get_dist_info()
  23. if world_size == 1:
  24. return
  25. norm_states = get_norm_states(module)
  26. if len(norm_states) == 0:
  27. return
  28. # TODO: use `all_reduce_dict` in mmengine
  29. norm_states = all_reduce_dict(norm_states, op='mean')
  30. module.load_state_dict(norm_states, strict=False)