prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [Bug] Possible bug in `mmpose/apis/train.py`
  https://github.com/open-mmlab/mmpose/blob/8d668a578f1580373d90a1eea88f23f6816df60e/mmpose/apis/train.py#L140
  
  Here is the code that may have problem. And I think the default value for `workers_per_gpu` should be an integer but not a dict. 
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `mmpose/apis/train.py`
  Content:
  ```
  1 # Copyright (c) OpenMMLab. All rights reserved.
  2 import warnings
  3 
  4 import torch
  5 from mmcv.parallel import MMDataParallel, MMDistributedDataParallel
  6 from mmcv.runner import DistSamplerSeedHook, EpochBasedRunner, OptimizerHook
  7 
  8 from mmpose.core import DistEvalHook, EvalHook, build_optimizers
  9 from mmpose.core.distributed_wrapper import DistributedDataParallelWrapper
  10 from mmpose.datasets import build_dataloader, build_dataset
  11 from mmpose.utils import get_root_logger
  12 
  13 try:
  14     from mmcv.runner import Fp16OptimizerHook
  15 except ImportError:
  16     warnings.warn(
  17         'Fp16OptimizerHook from mmpose will be deprecated from '
  18         'v0.15.0. Please install mmcv>=1.1.4', DeprecationWarning)
  19     from mmpose.core import Fp16OptimizerHook
  20 
  21 
  22 def train_model(model,
  23                 dataset,
  24                 cfg,
  25                 distributed=False,
  26                 validate=False,
  27                 timestamp=None,
  28                 meta=None):
  29     """Train model entry function.
  30 
  31     Args:
  32         model (nn.Module): The model to be trained.
  33         dataset (Dataset): Train dataset.
  34         cfg (dict): The config dict for training.
  35         distributed (bool): Whether to use distributed training.
  36             Default: False.
  37         validate (bool): Whether to do evaluation. Default: False.
  38         timestamp (str | None): Local time for runner. Default: None.
  39         meta (dict | None): Meta dict to record some important information.
  40             Default: None
  41     """
  42     logger = get_root_logger(cfg.log_level)
  43 
  44     # prepare data loaders
  45     dataset = dataset if isinstance(dataset, (list, tuple)) else [dataset]
  46     # step 1: give default values and override (if exist) from cfg.data
  47     loader_cfg = {
  48         **dict(
  49             seed=cfg.get('seed'),
  50             drop_last=False,
  51             dist=distributed,
  52             num_gpus=len(cfg.gpu_ids)),
  53         **({} if torch.__version__ != 'parrots' else dict(
  54                prefetch_num=2,
  55                pin_memory=False,
  56            )),
  57         **dict((k, cfg.data[k]) for k in [
  58                    'samples_per_gpu',
  59                    'workers_per_gpu',
  60                    'shuffle',
  61                    'seed',
  62                    'drop_last',
  63                    'prefetch_num',
  64                    'pin_memory',
  65                    'persistent_workers',
  66                ] if k in cfg.data)
  67     }
  68 
  69     # step 2: cfg.data.train_dataloader has highest priority
  70     train_loader_cfg = dict(loader_cfg, **cfg.data.get('train_dataloader', {}))
  71 
  72     data_loaders = [build_dataloader(ds, **train_loader_cfg) for ds in dataset]
  73 
  74     # determine wether use adversarial training precess or not
  75     use_adverserial_train = cfg.get('use_adversarial_train', False)
  76 
  77     # put model on gpus
  78     if distributed:
  79         find_unused_parameters = cfg.get('find_unused_parameters', True)
  80         # Sets the `find_unused_parameters` parameter in
  81         # torch.nn.parallel.DistributedDataParallel
  82 
  83         if use_adverserial_train:
  84             # Use DistributedDataParallelWrapper for adversarial training
  85             model = DistributedDataParallelWrapper(
  86                 model,
  87                 device_ids=[torch.cuda.current_device()],
  88                 broadcast_buffers=False,
  89                 find_unused_parameters=find_unused_parameters)
  90         else:
  91             model = MMDistributedDataParallel(
  92                 model.cuda(),
  93                 device_ids=[torch.cuda.current_device()],
  94                 broadcast_buffers=False,
  95                 find_unused_parameters=find_unused_parameters)
  96     else:
  97         model = MMDataParallel(
  98             model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids)
  99 
  100     # build runner
  101     optimizer = build_optimizers(model, cfg.optimizer)
  102 
  103     runner = EpochBasedRunner(
  104         model,
  105         optimizer=optimizer,
  106         work_dir=cfg.work_dir,
  107         logger=logger,
  108         meta=meta)
  109     # an ugly workaround to make .log and .log.json filenames the same
  110     runner.timestamp = timestamp
  111 
  112     if use_adverserial_train:
  113         # The optimizer step process is included in the train_step function
  114         # of the model, so the runner should NOT include optimizer hook.
  115         optimizer_config = None
  116     else:
  117         # fp16 setting
  118         fp16_cfg = cfg.get('fp16', None)
  119         if fp16_cfg is not None:
  120             optimizer_config = Fp16OptimizerHook(
  121                 **cfg.optimizer_config, **fp16_cfg, distributed=distributed)
  122         elif distributed and 'type' not in cfg.optimizer_config:
  123             optimizer_config = OptimizerHook(**cfg.optimizer_config)
  124         else:
  125             optimizer_config = cfg.optimizer_config
  126 
  127     # register hooks
  128     runner.register_training_hooks(cfg.lr_config, optimizer_config,
  129                                    cfg.checkpoint_config, cfg.log_config,
  130                                    cfg.get('momentum_config', None))
  131     if distributed:
  132         runner.register_hook(DistSamplerSeedHook())
  133 
  134     # register eval hooks
  135     if validate:
  136         eval_cfg = cfg.get('evaluation', {})
  137         val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))
  138         dataloader_setting = dict(
  139             samples_per_gpu=1,
  140             workers_per_gpu=cfg.data.get('workers_per_gpu', {}),
  141             # cfg.gpus will be ignored if distributed
  142             num_gpus=len(cfg.gpu_ids),
  143             dist=distributed,
  144             drop_last=False,
  145             shuffle=False)
  146         dataloader_setting = dict(dataloader_setting,
  147                                   **cfg.data.get('val_dataloader', {}))
  148         val_dataloader = build_dataloader(val_dataset, **dataloader_setting)
  149         eval_hook = DistEvalHook if distributed else EvalHook
  150         runner.register_hook(eval_hook(val_dataloader, **eval_cfg))
  151 
  152     if cfg.resume_from:
  153         runner.resume(cfg.resume_from)
  154     elif cfg.load_from:
  155         runner.load_checkpoint(cfg.load_from)
  156     runner.run(data_loaders, cfg.workflow, cfg.total_epochs)
  157
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/mmpose/apis/train.py b/mmpose/apis/train.py
  --- a/mmpose/apis/train.py
  +++ b/mmpose/apis/train.py
  @@ -137,7 +137,7 @@
           val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))
           dataloader_setting = dict(
               samples_per_gpu=1,
  -            workers_per_gpu=cfg.data.get('workers_per_gpu', {}),
  +            workers_per_gpu=cfg.data.get('workers_per_gpu', 1),
               # cfg.gpus will be ignored if distributed
               num_gpus=len(cfg.gpu_ids),
               dist=distributed,
  
verification_info: {"golden_diff": "diff --git a/mmpose/apis/train.py b/mmpose/apis/train.py\n--- a/mmpose/apis/train.py\n+++ b/mmpose/apis/train.py\n@@ -137,7 +137,7 @@\n         val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))\n         dataloader_setting = dict(\n             samples_per_gpu=1,\n-            workers_per_gpu=cfg.data.get('workers_per_gpu', {}),\n+            workers_per_gpu=cfg.data.get('workers_per_gpu', 1),\n             # cfg.gpus will be ignored if distributed\n             num_gpus=len(cfg.gpu_ids),\n             dist=distributed,\n", "issue": "[Bug] Possible bug in `mmpose/apis/train.py`\nhttps://github.com/open-mmlab/mmpose/blob/8d668a578f1580373d90a1eea88f23f6816df60e/mmpose/apis/train.py#L140\r\n\r\nHere is the code that may have problem. And I think the default value for `workers_per_gpu` should be an integer but not a dict. \n", "before_files": [{"content": "# Copyright (c) OpenMMLab. All rights reserved.\nimport warnings\n\nimport torch\nfrom mmcv.parallel import MMDataParallel, MMDistributedDataParallel\nfrom mmcv.runner import DistSamplerSeedHook, EpochBasedRunner, OptimizerHook\n\nfrom mmpose.core import DistEvalHook, EvalHook, build_optimizers\nfrom mmpose.core.distributed_wrapper import DistributedDataParallelWrapper\nfrom mmpose.datasets import build_dataloader, build_dataset\nfrom mmpose.utils import get_root_logger\n\ntry:\n    from mmcv.runner import Fp16OptimizerHook\nexcept ImportError:\n    warnings.warn(\n        'Fp16OptimizerHook from mmpose will be deprecated from '\n        'v0.15.0. Please install mmcv>=1.1.4', DeprecationWarning)\n    from mmpose.core import Fp16OptimizerHook\n\n\ndef train_model(model,\n                dataset,\n                cfg,\n                distributed=False,\n                validate=False,\n                timestamp=None,\n                meta=None):\n    \"\"\"Train model entry function.\n\n    Args:\n        model (nn.Module): The model to be trained.\n        dataset (Dataset): Train dataset.\n        cfg (dict): The config dict for training.\n        distributed (bool): Whether to use distributed training.\n            Default: False.\n        validate (bool): Whether to do evaluation. Default: False.\n        timestamp (str | None): Local time for runner. Default: None.\n        meta (dict | None): Meta dict to record some important information.\n            Default: None\n    \"\"\"\n    logger = get_root_logger(cfg.log_level)\n\n    # prepare data loaders\n    dataset = dataset if isinstance(dataset, (list, tuple)) else [dataset]\n    # step 1: give default values and override (if exist) from cfg.data\n    loader_cfg = {\n        **dict(\n            seed=cfg.get('seed'),\n            drop_last=False,\n            dist=distributed,\n            num_gpus=len(cfg.gpu_ids)),\n        **({} if torch.__version__ != 'parrots' else dict(\n               prefetch_num=2,\n               pin_memory=False,\n           )),\n        **dict((k, cfg.data[k]) for k in [\n                   'samples_per_gpu',\n                   'workers_per_gpu',\n                   'shuffle',\n                   'seed',\n                   'drop_last',\n                   'prefetch_num',\n                   'pin_memory',\n                   'persistent_workers',\n               ] if k in cfg.data)\n    }\n\n    # step 2: cfg.data.train_dataloader has highest priority\n    train_loader_cfg = dict(loader_cfg, **cfg.data.get('train_dataloader', {}))\n\n    data_loaders = [build_dataloader(ds, **train_loader_cfg) for ds in dataset]\n\n    # determine wether use adversarial training precess or not\n    use_adverserial_train = cfg.get('use_adversarial_train', False)\n\n    # put model on gpus\n    if distributed:\n        find_unused_parameters = cfg.get('find_unused_parameters', True)\n        # Sets the `find_unused_parameters` parameter in\n        # torch.nn.parallel.DistributedDataParallel\n\n        if use_adverserial_train:\n            # Use DistributedDataParallelWrapper for adversarial training\n            model = DistributedDataParallelWrapper(\n                model,\n                device_ids=[torch.cuda.current_device()],\n                broadcast_buffers=False,\n                find_unused_parameters=find_unused_parameters)\n        else:\n            model = MMDistributedDataParallel(\n                model.cuda(),\n                device_ids=[torch.cuda.current_device()],\n                broadcast_buffers=False,\n                find_unused_parameters=find_unused_parameters)\n    else:\n        model = MMDataParallel(\n            model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids)\n\n    # build runner\n    optimizer = build_optimizers(model, cfg.optimizer)\n\n    runner = EpochBasedRunner(\n        model,\n        optimizer=optimizer,\n        work_dir=cfg.work_dir,\n        logger=logger,\n        meta=meta)\n    # an ugly workaround to make .log and .log.json filenames the same\n    runner.timestamp = timestamp\n\n    if use_adverserial_train:\n        # The optimizer step process is included in the train_step function\n        # of the model, so the runner should NOT include optimizer hook.\n        optimizer_config = None\n    else:\n        # fp16 setting\n        fp16_cfg = cfg.get('fp16', None)\n        if fp16_cfg is not None:\n            optimizer_config = Fp16OptimizerHook(\n                **cfg.optimizer_config, **fp16_cfg, distributed=distributed)\n        elif distributed and 'type' not in cfg.optimizer_config:\n            optimizer_config = OptimizerHook(**cfg.optimizer_config)\n        else:\n            optimizer_config = cfg.optimizer_config\n\n    # register hooks\n    runner.register_training_hooks(cfg.lr_config, optimizer_config,\n                                   cfg.checkpoint_config, cfg.log_config,\n                                   cfg.get('momentum_config', None))\n    if distributed:\n        runner.register_hook(DistSamplerSeedHook())\n\n    # register eval hooks\n    if validate:\n        eval_cfg = cfg.get('evaluation', {})\n        val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))\n        dataloader_setting = dict(\n            samples_per_gpu=1,\n            workers_per_gpu=cfg.data.get('workers_per_gpu', {}),\n            # cfg.gpus will be ignored if distributed\n            num_gpus=len(cfg.gpu_ids),\n            dist=distributed,\n            drop_last=False,\n            shuffle=False)\n        dataloader_setting = dict(dataloader_setting,\n                                  **cfg.data.get('val_dataloader', {}))\n        val_dataloader = build_dataloader(val_dataset, **dataloader_setting)\n        eval_hook = DistEvalHook if distributed else EvalHook\n        runner.register_hook(eval_hook(val_dataloader, **eval_cfg))\n\n    if cfg.resume_from:\n        runner.resume(cfg.resume_from)\n    elif cfg.load_from:\n        runner.load_checkpoint(cfg.load_from)\n    runner.run(data_loaders, cfg.workflow, cfg.total_epochs)\n", "path": "mmpose/apis/train.py"}], "after_files": [{"content": "# Copyright (c) OpenMMLab. All rights reserved.\nimport warnings\n\nimport torch\nfrom mmcv.parallel import MMDataParallel, MMDistributedDataParallel\nfrom mmcv.runner import DistSamplerSeedHook, EpochBasedRunner, OptimizerHook\n\nfrom mmpose.core import DistEvalHook, EvalHook, build_optimizers\nfrom mmpose.core.distributed_wrapper import DistributedDataParallelWrapper\nfrom mmpose.datasets import build_dataloader, build_dataset\nfrom mmpose.utils import get_root_logger\n\ntry:\n    from mmcv.runner import Fp16OptimizerHook\nexcept ImportError:\n    warnings.warn(\n        'Fp16OptimizerHook from mmpose will be deprecated from '\n        'v0.15.0. Please install mmcv>=1.1.4', DeprecationWarning)\n    from mmpose.core import Fp16OptimizerHook\n\n\ndef train_model(model,\n                dataset,\n                cfg,\n                distributed=False,\n                validate=False,\n                timestamp=None,\n                meta=None):\n    \"\"\"Train model entry function.\n\n    Args:\n        model (nn.Module): The model to be trained.\n        dataset (Dataset): Train dataset.\n        cfg (dict): The config dict for training.\n        distributed (bool): Whether to use distributed training.\n            Default: False.\n        validate (bool): Whether to do evaluation. Default: False.\n        timestamp (str | None): Local time for runner. Default: None.\n        meta (dict | None): Meta dict to record some important information.\n            Default: None\n    \"\"\"\n    logger = get_root_logger(cfg.log_level)\n\n    # prepare data loaders\n    dataset = dataset if isinstance(dataset, (list, tuple)) else [dataset]\n    # step 1: give default values and override (if exist) from cfg.data\n    loader_cfg = {\n        **dict(\n            seed=cfg.get('seed'),\n            drop_last=False,\n            dist=distributed,\n            num_gpus=len(cfg.gpu_ids)),\n        **({} if torch.__version__ != 'parrots' else dict(\n               prefetch_num=2,\n               pin_memory=False,\n           )),\n        **dict((k, cfg.data[k]) for k in [\n                   'samples_per_gpu',\n                   'workers_per_gpu',\n                   'shuffle',\n                   'seed',\n                   'drop_last',\n                   'prefetch_num',\n                   'pin_memory',\n                   'persistent_workers',\n               ] if k in cfg.data)\n    }\n\n    # step 2: cfg.data.train_dataloader has highest priority\n    train_loader_cfg = dict(loader_cfg, **cfg.data.get('train_dataloader', {}))\n\n    data_loaders = [build_dataloader(ds, **train_loader_cfg) for ds in dataset]\n\n    # determine wether use adversarial training precess or not\n    use_adverserial_train = cfg.get('use_adversarial_train', False)\n\n    # put model on gpus\n    if distributed:\n        find_unused_parameters = cfg.get('find_unused_parameters', True)\n        # Sets the `find_unused_parameters` parameter in\n        # torch.nn.parallel.DistributedDataParallel\n\n        if use_adverserial_train:\n            # Use DistributedDataParallelWrapper for adversarial training\n            model = DistributedDataParallelWrapper(\n                model,\n                device_ids=[torch.cuda.current_device()],\n                broadcast_buffers=False,\n                find_unused_parameters=find_unused_parameters)\n        else:\n            model = MMDistributedDataParallel(\n                model.cuda(),\n                device_ids=[torch.cuda.current_device()],\n                broadcast_buffers=False,\n                find_unused_parameters=find_unused_parameters)\n    else:\n        model = MMDataParallel(\n            model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids)\n\n    # build runner\n    optimizer = build_optimizers(model, cfg.optimizer)\n\n    runner = EpochBasedRunner(\n        model,\n        optimizer=optimizer,\n        work_dir=cfg.work_dir,\n        logger=logger,\n        meta=meta)\n    # an ugly workaround to make .log and .log.json filenames the same\n    runner.timestamp = timestamp\n\n    if use_adverserial_train:\n        # The optimizer step process is included in the train_step function\n        # of the model, so the runner should NOT include optimizer hook.\n        optimizer_config = None\n    else:\n        # fp16 setting\n        fp16_cfg = cfg.get('fp16', None)\n        if fp16_cfg is not None:\n            optimizer_config = Fp16OptimizerHook(\n                **cfg.optimizer_config, **fp16_cfg, distributed=distributed)\n        elif distributed and 'type' not in cfg.optimizer_config:\n            optimizer_config = OptimizerHook(**cfg.optimizer_config)\n        else:\n            optimizer_config = cfg.optimizer_config\n\n    # register hooks\n    runner.register_training_hooks(cfg.lr_config, optimizer_config,\n                                   cfg.checkpoint_config, cfg.log_config,\n                                   cfg.get('momentum_config', None))\n    if distributed:\n        runner.register_hook(DistSamplerSeedHook())\n\n    # register eval hooks\n    if validate:\n        eval_cfg = cfg.get('evaluation', {})\n        val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))\n        dataloader_setting = dict(\n            samples_per_gpu=1,\n            workers_per_gpu=cfg.data.get('workers_per_gpu', 1),\n            # cfg.gpus will be ignored if distributed\n            num_gpus=len(cfg.gpu_ids),\n            dist=distributed,\n            drop_last=False,\n            shuffle=False)\n        dataloader_setting = dict(dataloader_setting,\n                                  **cfg.data.get('val_dataloader', {}))\n        val_dataloader = build_dataloader(val_dataset, **dataloader_setting)\n        eval_hook = DistEvalHook if distributed else EvalHook\n        runner.register_hook(eval_hook(val_dataloader, **eval_cfg))\n\n    if cfg.resume_from:\n        runner.resume(cfg.resume_from)\n    elif cfg.load_from:\n        runner.load_checkpoint(cfg.load_from)\n    runner.run(data_loaders, cfg.workflow, cfg.total_epochs)\n", "path": "mmpose/apis/train.py"}]}