From 1ab934ed4db8a13236eb5773b8fd5b7f6ba06973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Haian=20Huang=28=E6=B7=B1=E5=BA=A6=E7=9C=B8=29?= <1286304229@qq.com> Date: Mon, 8 Nov 2021 20:23:03 +0800 Subject: [PATCH] [Enchance] Set a random seed when the user does not set a seed. (#6457) * fix random seed bug * add comment * enchance random seed * rename Co-authored-by: Haobo Yuan --- mmdet/apis/__init__.py | 5 +++-- mmdet/apis/train.py | 36 +++++++++++++++++++++++++++++++++++- tools/train.py | 14 +++++++------- 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/mmdet/apis/__init__.py b/mmdet/apis/__init__.py index 4a8987d1da8..a865e942afd 100644 --- a/mmdet/apis/__init__.py +++ b/mmdet/apis/__init__.py @@ -2,10 +2,11 @@ from .inference import (async_inference_detector, inference_detector, init_detector, show_result_pyplot) from .test import multi_gpu_test, single_gpu_test -from .train import get_root_logger, set_random_seed, train_detector +from .train import (get_root_logger, init_random_seed, set_random_seed, + train_detector) __all__ = [ 'get_root_logger', 'set_random_seed', 'train_detector', 'init_detector', 'async_inference_detector', 'inference_detector', 'show_result_pyplot', - 'multi_gpu_test', 'single_gpu_test' + 'multi_gpu_test', 'single_gpu_test', 'init_random_seed' ] diff --git a/mmdet/apis/train.py b/mmdet/apis/train.py index b8b6eefc8ab..a7ed2d267eb 100644 --- a/mmdet/apis/train.py +++ b/mmdet/apis/train.py @@ -4,10 +4,11 @@ import numpy as np import torch +import torch.distributed as dist from mmcv.parallel import MMDataParallel, MMDistributedDataParallel from mmcv.runner import (HOOKS, DistSamplerSeedHook, EpochBasedRunner, Fp16OptimizerHook, OptimizerHook, build_optimizer, - build_runner) + build_runner, get_dist_info) from mmcv.utils import build_from_cfg from mmdet.core import DistEvalHook, EvalHook @@ -16,6 +17,39 @@ from mmdet.utils import get_root_logger +def init_random_seed(seed=None, device='cuda'): + """Initialize random seed. + + If the seed is not set, the seed will be automatically randomized, + and then broadcast to all processes to prevent some potential bugs. + + Args: + seed (int, Optional): The seed. Default to None. + device (str): The device where the seed will be put on. + Default to 'cuda'. + + Returns: + int: Seed to be used. + """ + if seed is not None: + return seed + + # Make sure all ranks share the same random seed to prevent + # some potential bugs. Please refer to + # https://github.com/open-mmlab/mmdetection/issues/6339 + rank, world_size = get_dist_info() + seed = np.random.randint(2**31) + if world_size == 1: + return seed + + if rank == 0: + random_num = torch.tensor(seed, dtype=torch.int32, device=device) + else: + random_num = torch.tensor(0, dtype=torch.int32, device=device) + dist.broadcast(random_num, src=0) + return random_num.item() + + def set_random_seed(seed, deterministic=False): """Set random seed. diff --git a/tools/train.py b/tools/train.py index f59f195332d..45fa03bfad6 100644 --- a/tools/train.py +++ b/tools/train.py @@ -13,7 +13,7 @@ from mmcv.utils import get_git_hash from mmdet import __version__ -from mmdet.apis import set_random_seed, train_detector +from mmdet.apis import init_random_seed, set_random_seed, train_detector from mmdet.datasets import build_dataset from mmdet.models import build_detector from mmdet.utils import collect_env, get_root_logger @@ -148,12 +148,12 @@ def main(): logger.info(f'Config:\n{cfg.pretty_text}') # set random seeds - if args.seed is not None: - logger.info(f'Set random seed to {args.seed}, ' - f'deterministic: {args.deterministic}') - set_random_seed(args.seed, deterministic=args.deterministic) - cfg.seed = args.seed - meta['seed'] = args.seed + seed = init_random_seed(args.seed) + logger.info(f'Set random seed to {seed}, ' + f'deterministic: {args.deterministic}') + set_random_seed(seed, deterministic=args.deterministic) + cfg.seed = seed + meta['seed'] = seed meta['exp_name'] = osp.basename(args.config) model = build_detector(