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()

```

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}.')

{"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"}]}