prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [Feature Request] CPU Testing
  Since CPU training is already supported in PR #219, what about also adding the feature of CPU testing. 
  
  Besides, it seems there are still some problems with the CPU training feature @wangruohui : 
  When we set `--device CPU`, the expected behavior is using CPU for training, no matter if there exist GPUs on this machine. However, mmcls will use GPU for training if it exists, even if we set `--device CPU`. 
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `mmcls/apis/train.py`
  Content:
  ```
  1 import random
  2 import warnings
  3 
  4 import numpy as np
  5 import torch
  6 from mmcv.parallel import MMDataParallel, MMDistributedDataParallel
  7 from mmcv.runner import DistSamplerSeedHook, build_optimizer, build_runner
  8 
  9 from mmcls.core import DistOptimizerHook
  10 from mmcls.datasets import build_dataloader, build_dataset
  11 from mmcls.utils import get_root_logger
  12 
  13 # TODO import eval hooks from mmcv and delete them from mmcls
  14 try:
  15     from mmcv.runner.hooks import EvalHook, DistEvalHook
  16 except ImportError:
  17     warnings.warn('DeprecationWarning: EvalHook and DistEvalHook from mmcls '
  18                   'will be deprecated.'
  19                   'Please install mmcv through master branch.')
  20     from mmcls.core import EvalHook, DistEvalHook
  21 
  22 # TODO import optimizer hook from mmcv and delete them from mmcls
  23 try:
  24     from mmcv.runner import Fp16OptimizerHook
  25 except ImportError:
  26     warnings.warn('DeprecationWarning: FP16OptimizerHook from mmcls will be '
  27                   'deprecated. Please install mmcv>=1.1.4.')
  28     from mmcls.core import Fp16OptimizerHook
  29 
  30 
  31 def set_random_seed(seed, deterministic=False):
  32     """Set random seed.
  33 
  34     Args:
  35         seed (int): Seed to be used.
  36         deterministic (bool): Whether to set the deterministic option for
  37             CUDNN backend, i.e., set `torch.backends.cudnn.deterministic`
  38             to True and `torch.backends.cudnn.benchmark` to False.
  39             Default: False.
  40     """
  41     random.seed(seed)
  42     np.random.seed(seed)
  43     torch.manual_seed(seed)
  44     torch.cuda.manual_seed_all(seed)
  45     if deterministic:
  46         torch.backends.cudnn.deterministic = True
  47         torch.backends.cudnn.benchmark = False
  48 
  49 
  50 def train_model(model,
  51                 dataset,
  52                 cfg,
  53                 distributed=False,
  54                 validate=False,
  55                 timestamp=None,
  56                 device='cuda',
  57                 meta=None):
  58     logger = get_root_logger(cfg.log_level)
  59 
  60     # prepare data loaders
  61     dataset = dataset if isinstance(dataset, (list, tuple)) else [dataset]
  62 
  63     data_loaders = [
  64         build_dataloader(
  65             ds,
  66             cfg.data.samples_per_gpu,
  67             cfg.data.workers_per_gpu,
  68             # cfg.gpus will be ignored if distributed
  69             num_gpus=len(cfg.gpu_ids),
  70             dist=distributed,
  71             round_up=True,
  72             seed=cfg.seed) for ds in dataset
  73     ]
  74 
  75     # put model on gpus
  76     if distributed:
  77         find_unused_parameters = cfg.get('find_unused_parameters', False)
  78         # Sets the `find_unused_parameters` parameter in
  79         # torch.nn.parallel.DistributedDataParallel
  80         model = MMDistributedDataParallel(
  81             model.cuda(),
  82             device_ids=[torch.cuda.current_device()],
  83             broadcast_buffers=False,
  84             find_unused_parameters=find_unused_parameters)
  85     else:
  86         if device == 'cuda':
  87             model = MMDataParallel(
  88                 model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids)
  89         elif device == 'cpu':
  90             model = MMDataParallel(model.cpu())
  91         else:
  92             raise ValueError(F'unsupported device name {device}.')
  93 
  94     # build runner
  95     optimizer = build_optimizer(model, cfg.optimizer)
  96 
  97     if cfg.get('runner') is None:
  98         cfg.runner = {
  99             'type': 'EpochBasedRunner',
  100             'max_epochs': cfg.total_epochs
  101         }
  102         warnings.warn(
  103             'config is now expected to have a `runner` section, '
  104             'please set `runner` in your config.', UserWarning)
  105 
  106     runner = build_runner(
  107         cfg.runner,
  108         default_args=dict(
  109             model=model,
  110             batch_processor=None,
  111             optimizer=optimizer,
  112             work_dir=cfg.work_dir,
  113             logger=logger,
  114             meta=meta))
  115 
  116     # an ugly walkaround to make the .log and .log.json filenames the same
  117     runner.timestamp = timestamp
  118 
  119     # fp16 setting
  120     fp16_cfg = cfg.get('fp16', None)
  121     if fp16_cfg is not None:
  122         optimizer_config = Fp16OptimizerHook(
  123             **cfg.optimizer_config, **fp16_cfg, distributed=distributed)
  124     elif distributed and 'type' not in cfg.optimizer_config:
  125         optimizer_config = DistOptimizerHook(**cfg.optimizer_config)
  126     else:
  127         optimizer_config = cfg.optimizer_config
  128 
  129     # register hooks
  130     runner.register_training_hooks(cfg.lr_config, optimizer_config,
  131                                    cfg.checkpoint_config, cfg.log_config,
  132                                    cfg.get('momentum_config', None))
  133     if distributed:
  134         runner.register_hook(DistSamplerSeedHook())
  135 
  136     # register eval hooks
  137     if validate:
  138         val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))
  139         val_dataloader = build_dataloader(
  140             val_dataset,
  141             samples_per_gpu=cfg.data.samples_per_gpu,
  142             workers_per_gpu=cfg.data.workers_per_gpu,
  143             dist=distributed,
  144             shuffle=False,
  145             round_up=True)
  146         eval_cfg = cfg.get('evaluation', {})
  147         eval_cfg['by_epoch'] = cfg.runner['type'] != 'IterBasedRunner'
  148         eval_hook = DistEvalHook if distributed else EvalHook
  149         runner.register_hook(eval_hook(val_dataloader, **eval_cfg))
  150 
  151     if cfg.resume_from:
  152         runner.resume(cfg.resume_from)
  153     elif cfg.load_from:
  154         runner.load_checkpoint(cfg.load_from)
  155     runner.run(data_loaders, cfg.workflow)
  156
  ```
  --- 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/mmcls/apis/train.py b/mmcls/apis/train.py
  --- a/mmcls/apis/train.py
  +++ b/mmcls/apis/train.py
  @@ -87,7 +87,7 @@
               model = MMDataParallel(
                   model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids)
           elif device == 'cpu':
  -            model = MMDataParallel(model.cpu())
  +            model = model.cpu()
           else:
               raise ValueError(F'unsupported device name {device}.')
  
verification_info: {"golden_diff": "diff --git a/mmcls/apis/train.py b/mmcls/apis/train.py\n--- a/mmcls/apis/train.py\n+++ b/mmcls/apis/train.py\n@@ -87,7 +87,7 @@\n             model = MMDataParallel(\n                 model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids)\n         elif device == 'cpu':\n-            model = MMDataParallel(model.cpu())\n+            model = model.cpu()\n         else:\n             raise ValueError(F'unsupported device name {device}.')\n", "issue": "[Feature Request] CPU Testing\nSince CPU training is already supported in PR #219, what about also adding the feature of CPU testing. \r\n\r\nBesides, it seems there are still some problems with the CPU training feature @wangruohui : \r\nWhen we set `--device CPU`, the expected behavior is using CPU for training, no matter if there exist GPUs on this machine. However, mmcls will use GPU for training if it exists, even if we set `--device CPU`. \n", "before_files": [{"content": "import random\nimport warnings\n\nimport numpy as np\nimport torch\nfrom mmcv.parallel import MMDataParallel, MMDistributedDataParallel\nfrom mmcv.runner import DistSamplerSeedHook, build_optimizer, build_runner\n\nfrom mmcls.core import DistOptimizerHook\nfrom mmcls.datasets import build_dataloader, build_dataset\nfrom mmcls.utils import get_root_logger\n\n# TODO import eval hooks from mmcv and delete them from mmcls\ntry:\n    from mmcv.runner.hooks import EvalHook, DistEvalHook\nexcept ImportError:\n    warnings.warn('DeprecationWarning: EvalHook and DistEvalHook from mmcls '\n                  'will be deprecated.'\n                  'Please install mmcv through master branch.')\n    from mmcls.core import EvalHook, DistEvalHook\n\n# TODO import optimizer hook from mmcv and delete them from mmcls\ntry:\n    from mmcv.runner import Fp16OptimizerHook\nexcept ImportError:\n    warnings.warn('DeprecationWarning: FP16OptimizerHook from mmcls will be '\n                  'deprecated. Please install mmcv>=1.1.4.')\n    from mmcls.core import Fp16OptimizerHook\n\n\ndef set_random_seed(seed, deterministic=False):\n    \"\"\"Set random seed.\n\n    Args:\n        seed (int): Seed to be used.\n        deterministic (bool): Whether to set the deterministic option for\n            CUDNN backend, i.e., set `torch.backends.cudnn.deterministic`\n            to True and `torch.backends.cudnn.benchmark` to False.\n            Default: False.\n    \"\"\"\n    random.seed(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n    if deterministic:\n        torch.backends.cudnn.deterministic = True\n        torch.backends.cudnn.benchmark = False\n\n\ndef train_model(model,\n                dataset,\n                cfg,\n                distributed=False,\n                validate=False,\n                timestamp=None,\n                device='cuda',\n                meta=None):\n    logger = get_root_logger(cfg.log_level)\n\n    # prepare data loaders\n    dataset = dataset if isinstance(dataset, (list, tuple)) else [dataset]\n\n    data_loaders = [\n        build_dataloader(\n            ds,\n            cfg.data.samples_per_gpu,\n            cfg.data.workers_per_gpu,\n            # cfg.gpus will be ignored if distributed\n            num_gpus=len(cfg.gpu_ids),\n            dist=distributed,\n            round_up=True,\n            seed=cfg.seed) for ds in dataset\n    ]\n\n    # put model on gpus\n    if distributed:\n        find_unused_parameters = cfg.get('find_unused_parameters', False)\n        # Sets the `find_unused_parameters` parameter in\n        # torch.nn.parallel.DistributedDataParallel\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        if device == 'cuda':\n            model = MMDataParallel(\n                model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids)\n        elif device == 'cpu':\n            model = MMDataParallel(model.cpu())\n        else:\n            raise ValueError(F'unsupported device name {device}.')\n\n    # build runner\n    optimizer = build_optimizer(model, cfg.optimizer)\n\n    if cfg.get('runner') is None:\n        cfg.runner = {\n            'type': 'EpochBasedRunner',\n            'max_epochs': cfg.total_epochs\n        }\n        warnings.warn(\n            'config is now expected to have a `runner` section, '\n            'please set `runner` in your config.', UserWarning)\n\n    runner = build_runner(\n        cfg.runner,\n        default_args=dict(\n            model=model,\n            batch_processor=None,\n            optimizer=optimizer,\n            work_dir=cfg.work_dir,\n            logger=logger,\n            meta=meta))\n\n    # an ugly walkaround to make the .log and .log.json filenames the same\n    runner.timestamp = timestamp\n\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 = DistOptimizerHook(**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        val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))\n        val_dataloader = build_dataloader(\n            val_dataset,\n            samples_per_gpu=cfg.data.samples_per_gpu,\n            workers_per_gpu=cfg.data.workers_per_gpu,\n            dist=distributed,\n            shuffle=False,\n            round_up=True)\n        eval_cfg = cfg.get('evaluation', {})\n        eval_cfg['by_epoch'] = cfg.runner['type'] != 'IterBasedRunner'\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)\n", "path": "mmcls/apis/train.py"}], "after_files": [{"content": "import random\nimport warnings\n\nimport numpy as np\nimport torch\nfrom mmcv.parallel import MMDataParallel, MMDistributedDataParallel\nfrom mmcv.runner import DistSamplerSeedHook, build_optimizer, build_runner\n\nfrom mmcls.core import DistOptimizerHook\nfrom mmcls.datasets import build_dataloader, build_dataset\nfrom mmcls.utils import get_root_logger\n\n# TODO import eval hooks from mmcv and delete them from mmcls\ntry:\n    from mmcv.runner.hooks import EvalHook, DistEvalHook\nexcept ImportError:\n    warnings.warn('DeprecationWarning: EvalHook and DistEvalHook from mmcls '\n                  'will be deprecated.'\n                  'Please install mmcv through master branch.')\n    from mmcls.core import EvalHook, DistEvalHook\n\n# TODO import optimizer hook from mmcv and delete them from mmcls\ntry:\n    from mmcv.runner import Fp16OptimizerHook\nexcept ImportError:\n    warnings.warn('DeprecationWarning: FP16OptimizerHook from mmcls will be '\n                  'deprecated. Please install mmcv>=1.1.4.')\n    from mmcls.core import Fp16OptimizerHook\n\n\ndef set_random_seed(seed, deterministic=False):\n    \"\"\"Set random seed.\n\n    Args:\n        seed (int): Seed to be used.\n        deterministic (bool): Whether to set the deterministic option for\n            CUDNN backend, i.e., set `torch.backends.cudnn.deterministic`\n            to True and `torch.backends.cudnn.benchmark` to False.\n            Default: False.\n    \"\"\"\n    random.seed(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n    if deterministic:\n        torch.backends.cudnn.deterministic = True\n        torch.backends.cudnn.benchmark = False\n\n\ndef train_model(model,\n                dataset,\n                cfg,\n                distributed=False,\n                validate=False,\n                timestamp=None,\n                device='cuda',\n                meta=None):\n    logger = get_root_logger(cfg.log_level)\n\n    # prepare data loaders\n    dataset = dataset if isinstance(dataset, (list, tuple)) else [dataset]\n\n    data_loaders = [\n        build_dataloader(\n            ds,\n            cfg.data.samples_per_gpu,\n            cfg.data.workers_per_gpu,\n            # cfg.gpus will be ignored if distributed\n            num_gpus=len(cfg.gpu_ids),\n            dist=distributed,\n            round_up=True,\n            seed=cfg.seed) for ds in dataset\n    ]\n\n    # put model on gpus\n    if distributed:\n        find_unused_parameters = cfg.get('find_unused_parameters', False)\n        # Sets the `find_unused_parameters` parameter in\n        # torch.nn.parallel.DistributedDataParallel\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        if device == 'cuda':\n            model = MMDataParallel(\n                model.cuda(cfg.gpu_ids[0]), device_ids=cfg.gpu_ids)\n        elif device == 'cpu':\n            model = model.cpu()\n        else:\n            raise ValueError(F'unsupported device name {device}.')\n\n    # build runner\n    optimizer = build_optimizer(model, cfg.optimizer)\n\n    if cfg.get('runner') is None:\n        cfg.runner = {\n            'type': 'EpochBasedRunner',\n            'max_epochs': cfg.total_epochs\n        }\n        warnings.warn(\n            'config is now expected to have a `runner` section, '\n            'please set `runner` in your config.', UserWarning)\n\n    runner = build_runner(\n        cfg.runner,\n        default_args=dict(\n            model=model,\n            batch_processor=None,\n            optimizer=optimizer,\n            work_dir=cfg.work_dir,\n            logger=logger,\n            meta=meta))\n\n    # an ugly walkaround to make the .log and .log.json filenames the same\n    runner.timestamp = timestamp\n\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 = DistOptimizerHook(**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        val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))\n        val_dataloader = build_dataloader(\n            val_dataset,\n            samples_per_gpu=cfg.data.samples_per_gpu,\n            workers_per_gpu=cfg.data.workers_per_gpu,\n            dist=distributed,\n            shuffle=False,\n            round_up=True)\n        eval_cfg = cfg.get('evaluation', {})\n        eval_cfg['by_epoch'] = cfg.runner['type'] != 'IterBasedRunner'\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)\n", "path": "mmcls/apis/train.py"}]}