prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  The cluster boot benchmark should the num_cpus function in parallel
  The cluster boot benchmark has the following code:
  
  >  for vm in vms:
  >    metadata = {'machine_type': vm.machine_type, 'num_cpus': vm.num_cpus,
  >               'machine_instance': vm_number}
  >   value = vm.TimeToBoot()
  
  This looks great until you realize vm.num_cpus is a method on the virtual machine which in turn calls RemoteCommand leading to an ssh.  When large number of VM's boot the result is a long set of serially run ssh's to each VM.  This could be done a lot faster by moving the code into a method and then using RunThreaded.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `perfkitbenchmarker/benchmarks/cluster_boot_benchmark.py`
  Content:
  ```
  1 # Copyright 2014 Google Inc. All rights reserved.
  2 #
  3 # Licensed under the Apache License, Version 2.0 (the "License");
  4 # you may not use this file except in compliance with the License.
  5 # You may obtain a copy of the License at
  6 #
  7 #   http://www.apache.org/licenses/LICENSE-2.0
  8 #
  9 # Unless required by applicable law or agreed to in writing, software
  10 # distributed under the License is distributed on an "AS IS" BASIS,
  11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 # See the License for the specific language governing permissions and
  13 # limitations under the License.
  14 
  15 """Runs a cluster boot benchmark."""
  16 
  17 import logging
  18 
  19 from perfkitbenchmarker import flags
  20 
  21 FLAGS = flags.FLAGS
  22 BENCHMARK_INFO = {'name': 'cluster boot',
  23                   'description': 'Create a cluster, record all times to boot',
  24                   'scratch_disk': False,
  25                   'num_machines': None}  # Set in GetInfo()
  26 
  27 
  28 def GetInfo():
  29   BENCHMARK_INFO['num_machines'] = FLAGS.num_vms
  30   return BENCHMARK_INFO
  31 
  32 
  33 def Prepare(unused_benchmark_spec):
  34   pass
  35 
  36 
  37 def Run(benchmark_spec):
  38   """Measure the boot time for all VMs.
  39 
  40   Args:
  41     benchmark_spec: The benchmark specification. Contains all data that is
  42         required to run the benchmark.
  43 
  44   Returns:
  45     A list of samples in the form of 3 or 4 tuples. The tuples contain
  46         the sample metric (string), value (float), and unit (string).
  47         If a 4th element is included, it is a dictionary of sample
  48         metadata.
  49   """
  50 
  51   samples = []
  52   vm_number = 0
  53   logging.info('Boot Results:')
  54   vms = benchmark_spec.vms
  55   for vm in vms:
  56     metadata = {'machine_type': vm.machine_type, 'num_cpus': vm.num_cpus,
  57                 'machine_instance': vm_number}
  58     value = vm.TimeToBoot()
  59     assert value is not None
  60     samples.append(('Boot Time', value, 'seconds', metadata))
  61     vm_number += 1
  62   logging.info(samples)
  63   assert vm_number == benchmark_spec.num_vms
  64   return samples
  65 
  66 
  67 def Cleanup(unused_benchmark_spec):
  68   pass
  69
  ```
  --- 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/perfkitbenchmarker/benchmarks/cluster_boot_benchmark.py b/perfkitbenchmarker/benchmarks/cluster_boot_benchmark.py
  --- a/perfkitbenchmarker/benchmarks/cluster_boot_benchmark.py
  +++ b/perfkitbenchmarker/benchmarks/cluster_boot_benchmark.py
  @@ -17,6 +17,7 @@
   import logging
   
   from perfkitbenchmarker import flags
  +from perfkitbenchmarker import vm_util
   
   FLAGS = flags.FLAGS
   BENCHMARK_INFO = {'name': 'cluster boot',
  @@ -34,6 +35,14 @@
     pass
   
   
  +def _GetTimeToBoot(vm, vm_index, result_list):
  +  metadata = {'machine_type': vm.machine_type, 'num_cpus': vm.num_cpus,
  +              'machine_instance': vm_index}
  +  value = vm.TimeToBoot()
  +  assert value is not None
  +  result_list.append(('Boot Time', value, 'seconds', metadata))
  +
  +
   def Run(benchmark_spec):
     """Measure the boot time for all VMs.
   
  @@ -49,18 +58,12 @@
     """
   
     samples = []
  -  vm_number = 0
     logging.info('Boot Results:')
     vms = benchmark_spec.vms
  -  for vm in vms:
  -    metadata = {'machine_type': vm.machine_type, 'num_cpus': vm.num_cpus,
  -                'machine_instance': vm_number}
  -    value = vm.TimeToBoot()
  -    assert value is not None
  -    samples.append(('Boot Time', value, 'seconds', metadata))
  -    vm_number += 1
  +  params = [((vm, i, samples), {}) for i, vm in enumerate(vms)]
  +  vm_util.RunThreaded(_GetTimeToBoot, params)
     logging.info(samples)
  -  assert vm_number == benchmark_spec.num_vms
  +  assert len(samples) == benchmark_spec.num_vms
     return samples
  
verification_info: {"golden_diff": "diff --git a/perfkitbenchmarker/benchmarks/cluster_boot_benchmark.py b/perfkitbenchmarker/benchmarks/cluster_boot_benchmark.py\n--- a/perfkitbenchmarker/benchmarks/cluster_boot_benchmark.py\n+++ b/perfkitbenchmarker/benchmarks/cluster_boot_benchmark.py\n@@ -17,6 +17,7 @@\n import logging\n \n from perfkitbenchmarker import flags\n+from perfkitbenchmarker import vm_util\n \n FLAGS = flags.FLAGS\n BENCHMARK_INFO = {'name': 'cluster boot',\n@@ -34,6 +35,14 @@\n   pass\n \n \n+def _GetTimeToBoot(vm, vm_index, result_list):\n+  metadata = {'machine_type': vm.machine_type, 'num_cpus': vm.num_cpus,\n+              'machine_instance': vm_index}\n+  value = vm.TimeToBoot()\n+  assert value is not None\n+  result_list.append(('Boot Time', value, 'seconds', metadata))\n+\n+\n def Run(benchmark_spec):\n   \"\"\"Measure the boot time for all VMs.\n \n@@ -49,18 +58,12 @@\n   \"\"\"\n \n   samples = []\n-  vm_number = 0\n   logging.info('Boot Results:')\n   vms = benchmark_spec.vms\n-  for vm in vms:\n-    metadata = {'machine_type': vm.machine_type, 'num_cpus': vm.num_cpus,\n-                'machine_instance': vm_number}\n-    value = vm.TimeToBoot()\n-    assert value is not None\n-    samples.append(('Boot Time', value, 'seconds', metadata))\n-    vm_number += 1\n+  params = [((vm, i, samples), {}) for i, vm in enumerate(vms)]\n+  vm_util.RunThreaded(_GetTimeToBoot, params)\n   logging.info(samples)\n-  assert vm_number == benchmark_spec.num_vms\n+  assert len(samples) == benchmark_spec.num_vms\n   return samples\n", "issue": "The cluster boot benchmark should the num_cpus function in parallel\nThe cluster boot benchmark has the following code:\n\n>  for vm in vms:\n>    metadata = {'machine_type': vm.machine_type, 'num_cpus': vm.num_cpus,\n>               'machine_instance': vm_number}\n>   value = vm.TimeToBoot()\n\nThis looks great until you realize vm.num_cpus is a method on the virtual machine which in turn calls RemoteCommand leading to an ssh.  When large number of VM's boot the result is a long set of serially run ssh's to each VM.  This could be done a lot faster by moving the code into a method and then using RunThreaded.\n\n", "before_files": [{"content": "# Copyright 2014 Google Inc. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"Runs a cluster boot benchmark.\"\"\"\n\nimport logging\n\nfrom perfkitbenchmarker import flags\n\nFLAGS = flags.FLAGS\nBENCHMARK_INFO = {'name': 'cluster boot',\n                  'description': 'Create a cluster, record all times to boot',\n                  'scratch_disk': False,\n                  'num_machines': None}  # Set in GetInfo()\n\n\ndef GetInfo():\n  BENCHMARK_INFO['num_machines'] = FLAGS.num_vms\n  return BENCHMARK_INFO\n\n\ndef Prepare(unused_benchmark_spec):\n  pass\n\n\ndef Run(benchmark_spec):\n  \"\"\"Measure the boot time for all VMs.\n\n  Args:\n    benchmark_spec: The benchmark specification. Contains all data that is\n        required to run the benchmark.\n\n  Returns:\n    A list of samples in the form of 3 or 4 tuples. The tuples contain\n        the sample metric (string), value (float), and unit (string).\n        If a 4th element is included, it is a dictionary of sample\n        metadata.\n  \"\"\"\n\n  samples = []\n  vm_number = 0\n  logging.info('Boot Results:')\n  vms = benchmark_spec.vms\n  for vm in vms:\n    metadata = {'machine_type': vm.machine_type, 'num_cpus': vm.num_cpus,\n                'machine_instance': vm_number}\n    value = vm.TimeToBoot()\n    assert value is not None\n    samples.append(('Boot Time', value, 'seconds', metadata))\n    vm_number += 1\n  logging.info(samples)\n  assert vm_number == benchmark_spec.num_vms\n  return samples\n\n\ndef Cleanup(unused_benchmark_spec):\n  pass\n", "path": "perfkitbenchmarker/benchmarks/cluster_boot_benchmark.py"}], "after_files": [{"content": "# Copyright 2014 Google Inc. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"Runs a cluster boot benchmark.\"\"\"\n\nimport logging\n\nfrom perfkitbenchmarker import flags\nfrom perfkitbenchmarker import vm_util\n\nFLAGS = flags.FLAGS\nBENCHMARK_INFO = {'name': 'cluster boot',\n                  'description': 'Create a cluster, record all times to boot',\n                  'scratch_disk': False,\n                  'num_machines': None}  # Set in GetInfo()\n\n\ndef GetInfo():\n  BENCHMARK_INFO['num_machines'] = FLAGS.num_vms\n  return BENCHMARK_INFO\n\n\ndef Prepare(unused_benchmark_spec):\n  pass\n\n\ndef _GetTimeToBoot(vm, vm_index, result_list):\n  metadata = {'machine_type': vm.machine_type, 'num_cpus': vm.num_cpus,\n              'machine_instance': vm_index}\n  value = vm.TimeToBoot()\n  assert value is not None\n  result_list.append(('Boot Time', value, 'seconds', metadata))\n\n\ndef Run(benchmark_spec):\n  \"\"\"Measure the boot time for all VMs.\n\n  Args:\n    benchmark_spec: The benchmark specification. Contains all data that is\n        required to run the benchmark.\n\n  Returns:\n    A list of samples in the form of 3 or 4 tuples. The tuples contain\n        the sample metric (string), value (float), and unit (string).\n        If a 4th element is included, it is a dictionary of sample\n        metadata.\n  \"\"\"\n\n  samples = []\n  logging.info('Boot Results:')\n  vms = benchmark_spec.vms\n  params = [((vm, i, samples), {}) for i, vm in enumerate(vms)]\n  vm_util.RunThreaded(_GetTimeToBoot, params)\n  logging.info(samples)\n  assert len(samples) == benchmark_spec.num_vms\n  return samples\n\n\ndef Cleanup(unused_benchmark_spec):\n  pass\n", "path": "perfkitbenchmarker/benchmarks/cluster_boot_benchmark.py"}]}