kernel-tuner 1.2.0__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/PKG-INFO +2 -2
  2. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/backends/cupy.py +0 -1
  3. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/backends/hypertuner.py +82 -27
  4. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/core.py +5 -2
  5. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/file_utils.py +24 -1
  6. kernel_tuner-1.3.0/kernel_tuner/hyper.py +215 -0
  7. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/integration.py +4 -4
  8. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/interface.py +95 -43
  9. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/runners/simulation.py +22 -3
  10. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/schema/T1/1.0.0/input-schema.json +2 -1
  11. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/schema/T4/1.0.0/results-schema.json +5 -1
  12. kernel_tuner-1.3.0/kernel_tuner/searchspace.py +1509 -0
  13. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/basinhopping.py +2 -2
  14. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/bayes_opt.py +1 -1
  15. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/brute_force.py +1 -1
  16. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/common.py +117 -37
  17. kernel_tuner-1.3.0/kernel_tuner/strategies/diff_evo.py +409 -0
  18. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/dual_annealing.py +6 -5
  19. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/firefly_algorithm.py +10 -8
  20. kernel_tuner-1.3.0/kernel_tuner/strategies/genetic_algorithm.py +252 -0
  21. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/greedy_ils.py +9 -4
  22. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/greedy_mls.py +2 -2
  23. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/minimize.py +2 -2
  24. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/pso.py +20 -14
  25. kernel_tuner-1.3.0/kernel_tuner/strategies/pyatf_strategies.py +125 -0
  26. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/random_sample.py +2 -2
  27. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/simulated_annealing.py +72 -22
  28. kernel_tuner-1.3.0/kernel_tuner/strategies/wrapper.py +56 -0
  29. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/util.py +39 -16
  30. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/pyproject.toml +5 -3
  31. kernel_tuner-1.3.0/test/conftest.py +7 -0
  32. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/context.py +27 -5
  33. kernel_tuner-1.3.0/test/strategies/test_cache_file.json +394 -0
  34. kernel_tuner-1.3.0/test/strategies/test_diff_evo.py +189 -0
  35. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/strategies/test_genetic_algorithm.py +9 -4
  36. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/strategies/test_strategies.py +55 -17
  37. kernel_tuner-1.3.0/test/test_cache_file_T1_input.json +82 -0
  38. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_compiler_functions.py +2 -2
  39. kernel_tuner-1.3.0/test/test_custom_optimizer.py +174 -0
  40. kernel_tuner-1.3.0/test/test_hyper.py +39 -0
  41. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_integration.py +6 -6
  42. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_kernelbuilder.py +2 -2
  43. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_runners.py +10 -4
  44. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_searchspace.py +154 -0
  45. kernel_tuner-1.3.0/test/utils/__init__.py +0 -0
  46. kernel_tuner-1.3.0/test/vector_add.cu +6 -0
  47. kernel_tuner-1.2.0/kernel_tuner/hyper.py +0 -98
  48. kernel_tuner-1.2.0/kernel_tuner/searchspace.py +0 -839
  49. kernel_tuner-1.2.0/kernel_tuner/strategies/diff_evo.py +0 -42
  50. kernel_tuner-1.2.0/kernel_tuner/strategies/genetic_algorithm.py +0 -181
  51. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/LICENSE +0 -0
  52. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/README.md +0 -0
  53. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/__init__.py +0 -0
  54. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/accuracy.py +0 -0
  55. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/backends/__init__.py +0 -0
  56. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/backends/backend.py +0 -0
  57. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/backends/compiler.py +0 -0
  58. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/backends/hip.py +0 -0
  59. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/backends/nvcuda.py +0 -0
  60. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/backends/opencl.py +0 -0
  61. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/backends/pycuda.py +0 -0
  62. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/energy/__init__.py +0 -0
  63. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/energy/energy.py +0 -0
  64. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/kernelbuilder.py +0 -0
  65. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/observers/__init__.py +0 -0
  66. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/observers/compiler.py +0 -0
  67. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/observers/cupy.py +0 -0
  68. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/observers/hip.py +0 -0
  69. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/observers/ncu.py +0 -0
  70. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/observers/nvcuda.py +0 -0
  71. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/observers/nvml.py +0 -0
  72. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/observers/observer.py +0 -0
  73. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/observers/opencl.py +0 -0
  74. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/observers/pmt.py +0 -0
  75. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/observers/powersensor.py +0 -0
  76. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/observers/pycuda.py +0 -0
  77. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/observers/register.py +0 -0
  78. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/observers/tegra.py +0 -0
  79. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/runners/__init__.py +0 -0
  80. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/runners/runner.py +0 -0
  81. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/runners/sequential.py +0 -0
  82. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/schema/T4/1.0.0/metadata-schema.json +0 -0
  83. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/__init__.py +0 -0
  84. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/hillclimbers.py +0 -0
  85. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/mls.py +0 -0
  86. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/strategies/ordered_greedy_mls.py +0 -0
  87. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/utils/__init__.py +0 -0
  88. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/kernel_tuner/utils/directives.py +0 -0
  89. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/__init__.py +0 -0
  90. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/convolution.cu +0 -0
  91. {kernel_tuner-1.2.0/test/utils → kernel_tuner-1.3.0/test/strategies}/__init__.py +0 -0
  92. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/strategies/test_bayesian_optimization.py +0 -0
  93. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/strategies/test_common.py +0 -0
  94. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/synthetic_fp32_cache_NVIDIA_RTX_A4000.json +0 -0
  95. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_T1_input.json +0 -0
  96. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_accuracy.py +0 -0
  97. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_backend.py +0 -0
  98. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_cache_file.json +0 -0
  99. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_common.py +0 -0
  100. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_core.py +0 -0
  101. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_cuda_functions.py +0 -0
  102. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_cupy_functions.py +0 -0
  103. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_energy.py +0 -0
  104. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_file_utils.py +0 -0
  105. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_hip_functions.py +0 -0
  106. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_nvml_mocked.py +0 -0
  107. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_observers.py +0 -0
  108. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_opencl_functions.py +0 -0
  109. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_pycuda_functions.py +0 -0
  110. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_pycuda_mocked.py +0 -0
  111. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_time_budgets.py +0 -0
  112. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_toml_file.py +0 -0
  113. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/test_util_functions.py +0 -0
  114. {kernel_tuner-1.2.0 → kernel_tuner-1.3.0}/test/utils/test_directives.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: kernel_tuner
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: An easy to use CUDA/OpenCL kernel tuner in Python
5
5
  License: Apache-2.0
6
6
  Keywords: auto-tuning,gpu,computing,pycuda,cuda,pyopencl,opencl
@@ -43,7 +43,7 @@ Requires-Dist: pycuda (>=2025.1) ; extra == "cuda"
43
43
  Requires-Dist: pynvml (>=11.4.1) ; extra == "cuda"
44
44
  Requires-Dist: pyopencl ; extra == "cuda-opencl"
45
45
  Requires-Dist: pyopencl ; extra == "opencl"
46
- Requires-Dist: python-constraint2 (>=2.3.1)
46
+ Requires-Dist: python-constraint2 (>=2.4.0)
47
47
  Requires-Dist: scikit-learn (>=1.0.2)
48
48
  Requires-Dist: scipy (>=1.14.1)
49
49
  Requires-Dist: xmltodict
@@ -1,6 +1,5 @@
1
1
  """This module contains all Cupy specific kernel_tuner functions."""
2
2
  from __future__ import print_function
3
- from warnings import warn
4
3
 
5
4
  import numpy as np
6
5
 
@@ -17,6 +17,8 @@ except ImportError:
17
17
 
18
18
 
19
19
  class ScoreObserver(BenchmarkObserver):
20
+ """BenchmarkObserver subclass for registering the hyperparameter tuning score."""
21
+
20
22
  def __init__(self, dev):
21
23
  self.dev = dev
22
24
  self.scores = []
@@ -33,13 +35,70 @@ class HypertunerFunctions(Backend):
33
35
  """Class for executing hyperparameter tuning."""
34
36
  units = {}
35
37
 
36
- def __init__(self, iterations):
38
+ def __init__(self, iterations, compiler_options=None):
37
39
  self.iterations = iterations
40
+ self.compiler_options = compiler_options
38
41
  self.observers = [ScoreObserver(self)]
39
42
  self.name = platform.processor()
40
43
  self.max_threads = 1024
41
44
  self.last_score = None
42
45
 
46
+ # set the defaults
47
+ self.gpus = ["A100", "A4000", "MI250X"]
48
+ folder = "../autotuning_methodology/benchmark_hub/kernels"
49
+ self.applications = [
50
+ {
51
+ "name": "dedispersion_milo",
52
+ "folder": folder,
53
+ "input_file": "dedispersion_milo.json",
54
+ "objective_performance_keys": ["time"]
55
+ },
56
+ {
57
+ "name": "hotspot_milo",
58
+ "folder": folder,
59
+ "input_file": "hotspot_milo.json",
60
+ "objective_performance_keys": ["GFLOP/s"]
61
+ },
62
+ {
63
+ "name": "convolution_milo",
64
+ "folder": folder,
65
+ "input_file": "convolution_milo.json",
66
+ "objective_performance_keys": ["time"]
67
+ },
68
+ {
69
+ "name": "gemm_milo",
70
+ "folder": folder,
71
+ "input_file": "gemm_milo.json",
72
+ "objective_performance_keys": ["time"]
73
+ }
74
+ ]
75
+ # any additional settings
76
+ self.override = {
77
+ "experimental_groups_defaults": {
78
+ "repeats": 25,
79
+ "samples": self.iterations,
80
+ "minimum_fraction_of_budget_valid": 0.1,
81
+ "minimum_number_of_valid_search_iterations": 3,
82
+ },
83
+ "statistics_settings": {
84
+ "cutoff_percentile": 0.95,
85
+ "cutoff_percentile_start": 0.01,
86
+ "cutoff_type": "time",
87
+ "objective_time_keys": [
88
+ "all"
89
+ ]
90
+ }
91
+ }
92
+
93
+ # override the defaults with compiler options if provided
94
+ if self.compiler_options is not None:
95
+ if "gpus" in self.compiler_options:
96
+ self.gpus = self.compiler_options["gpus"]
97
+ if "applications" in self.compiler_options:
98
+ self.applications = self.compiler_options["applications"]
99
+ if "override" in self.compiler_options:
100
+ self.override = self.compiler_options["override"]
101
+
43
102
  # set the environment options
44
103
  env = dict()
45
104
  env["iterations"] = self.iterations
@@ -60,22 +119,6 @@ class HypertunerFunctions(Backend):
60
119
  path = Path(__file__).parent.parent.parent / "hyperparamtuning"
61
120
  path.mkdir(exist_ok=True)
62
121
 
63
- # TODO get applications & GPUs args from benchmark
64
- gpus = ["RTX_3090", "RTX_2080_Ti"]
65
- applications = None
66
- # applications = [
67
- # {
68
- # "name": "convolution",
69
- # "folder": "./cached_data_used/kernels",
70
- # "input_file": "convolution.json"
71
- # },
72
- # {
73
- # "name": "pnpoly",
74
- # "folder": "./cached_data_used/kernels",
75
- # "input_file": "pnpoly.json"
76
- # }
77
- # ]
78
-
79
122
  # strategy settings
80
123
  strategy: str = kernel_instance.arguments[0]
81
124
  hyperparams = [{'name': k, 'value': v} for k, v in kernel_instance.params.items()]
@@ -88,16 +131,9 @@ class HypertunerFunctions(Backend):
88
131
  'search_method_hyperparameters': hyperparams
89
132
  }]
90
133
 
91
- # any additional settings
92
- override = {
93
- "experimental_groups_defaults": {
94
- "samples": self.iterations
95
- }
96
- }
97
-
98
134
  name = kernel_instance.name if len(kernel_instance.name) > 0 else kernel_instance.kernel_source.kernel_name
99
- experiments_filepath = generate_experiment_file(name, path, searchspace_strategies, applications, gpus,
100
- override=override, overwrite_existing_file=True)
135
+ experiments_filepath = generate_experiment_file(name, path, searchspace_strategies, self.applications, self.gpus,
136
+ override=self.override, generate_unique_file=True, overwrite_existing_file=True)
101
137
  return str(experiments_filepath)
102
138
 
103
139
  def start_event(self):
@@ -114,12 +150,27 @@ class HypertunerFunctions(Backend):
114
150
  return super().synchronize()
115
151
 
116
152
  def run_kernel(self, func, gpu_args=None, threads=None, grid=None, stream=None):
153
+ # from cProfile import Profile
154
+
155
+ # # generate the experiments file
156
+ # experiments_filepath = Path(func)
157
+
158
+ # # run the methodology to get a fitness score for this configuration
159
+ # with Profile() as pr:
160
+ # scores = get_strategy_scores(str(experiments_filepath), full_validate_on_load=False)
161
+ # pr.dump_stats('diff_evo_hypertune_hotspot.prof')
162
+ # self.last_score = scores[list(scores.keys())[0]]['score']
163
+ # raise ValueError(scores)
164
+
117
165
  # generate the experiments file
118
166
  experiments_filepath = Path(func)
119
167
 
120
168
  # run the methodology to get a fitness score for this configuration
121
- scores = get_strategy_scores(str(experiments_filepath))
169
+ scores = get_strategy_scores(str(experiments_filepath), full_validate_on_load=False)
122
170
  self.last_score = scores[list(scores.keys())[0]]['score']
171
+
172
+ # remove the experiments file
173
+ experiments_filepath.unlink()
123
174
 
124
175
  def memset(self, allocation, value, size):
125
176
  return super().memset(allocation, value, size)
@@ -129,3 +180,7 @@ class HypertunerFunctions(Backend):
129
180
 
130
181
  def memcpy_htod(self, dest, src):
131
182
  return super().memcpy_htod(dest, src)
183
+
184
+ def refresh_memory(self, device_memory, host_arguments, should_sync):
185
+ """This is a no-op for the hypertuner backend, as it does not manage memory directly."""
186
+ pass
@@ -315,10 +315,13 @@ class DeviceInterface(object):
315
315
  observers=observers,
316
316
  )
317
317
  elif lang.upper() == "HYPERTUNER":
318
- dev = HypertunerFunctions(iterations=iterations)
318
+ dev = HypertunerFunctions(
319
+ iterations=iterations,
320
+ compiler_options=compiler_options
321
+ )
319
322
  self.requires_warmup = False
320
323
  else:
321
- raise ValueError(
324
+ raise NotImplementedError(
322
325
  "Sorry, support for languages other than CUDA, OpenCL, HIP, C, and Fortran is not implemented yet"
323
326
  )
324
327
  self.dev = dev
@@ -3,6 +3,7 @@
3
3
  import json
4
4
  import subprocess
5
5
  from importlib.metadata import PackageNotFoundError, requires, version
6
+ from importlib.util import spec_from_file_location, module_from_spec
6
7
  from pathlib import Path
7
8
  from sys import platform
8
9
 
@@ -152,7 +153,7 @@ def get_t4_results(results, tune_params, objective="time"):
152
153
 
153
154
  # write output_data to a JSON file
154
155
  version, _ = output_file_schema("results")
155
- output_json = dict(results=output_data, schema_version=version, metadata={'timeunit': 'miliseconds'})
156
+ output_json = dict(results=output_data, schema_version=version, metadata={'timeunit': 'milliseconds'})
156
157
  return output_json
157
158
 
158
159
  def store_output_file(output_filename: str, results, tune_params, objective="time"):
@@ -302,3 +303,25 @@ def store_metadata_file(metadata_filename: str):
302
303
  with open(metadata_filenamepath, "w+") as fh:
303
304
  json.dump(metadata_json, fh, indent=" ")
304
305
 
306
+ def import_class_from_file(file_path: Path, class_name):
307
+ """Import a class from a file."""
308
+
309
+ def load_module(module_name):
310
+ spec = spec_from_file_location(module_name, file_path)
311
+ if spec is None:
312
+ raise ImportError(f"Could not load spec from {file_path}")
313
+
314
+ # create a module from the spec and execute it
315
+ module = module_from_spec(spec)
316
+ spec.loader.exec_module(module)
317
+ if not hasattr(module, class_name):
318
+ raise ImportError(f"Module '{module_name}' has no class '{class_name}'")
319
+ return module
320
+
321
+ try:
322
+ module = load_module(file_path.stem)
323
+ except ImportError:
324
+ module = load_module(f"{file_path.parent.stem}.{file_path.stem}")
325
+
326
+ # return the class from the module
327
+ return getattr(module, class_name)
@@ -0,0 +1,215 @@
1
+ """Module for functions related to hyperparameter optimization."""
2
+
3
+
4
+ from pathlib import Path
5
+ from random import randint
6
+ from argparse import ArgumentParser
7
+
8
+ import numpy as np
9
+
10
+ import kernel_tuner
11
+
12
+
13
+ def get_random_unique_filename(prefix = '', suffix=''):
14
+ """Get a random, unique filename that does not yet exist."""
15
+ def randpath():
16
+ return Path(f"{prefix}{randint(1000, 9999)}{suffix}")
17
+ path = randpath()
18
+ while path.exists():
19
+ path = randpath()
20
+ return path
21
+
22
+ def tune_hyper_params(target_strategy: str, hyper_params: dict, restrictions: list, *args, **kwargs):
23
+ """Tune hyperparameters for a given strategy and kernel.
24
+
25
+ This function is to be called just like tune_kernel, except that you specify a strategy
26
+ and a dictionary with hyperparameters in front of the arguments you pass to tune_kernel.
27
+
28
+ The arguments to tune_kernel should contain a cachefile. To compute the optimum the hyperparameter
29
+ tuner first tunes the kernel with a brute force search. If your cachefile is not yet complete
30
+ this may take very long.
31
+
32
+ :param target_strategy: Specify the strategy for which to tune hyperparameters
33
+ :type target_strategy: string
34
+
35
+ :param hyper_params: A dictionary containing the hyperparameters as keys and
36
+ lists the possible values per key
37
+ :type hyper_params: dict(string: list)
38
+
39
+ :param args: all positional arguments used to call tune_kernel
40
+ :type args: various
41
+
42
+ :param kwargs: other keyword arguments to pass to tune_kernel
43
+ :type kwargs: dict
44
+
45
+ """
46
+ # v Have the methodology as a dependency
47
+ # - User inputs:
48
+ # - a set of bruteforced cachefiles / template experiments file
49
+ # - an optimization algorithm
50
+ # - the hyperparameter values to try
51
+ # - overarching optimization algorithm (meta-strategy)
52
+ # - At each round:
53
+ # - The meta-strategy selects a hyperparameter configuration to try
54
+ # - Kernel Tuner generates an experiments file with the hyperparameter configuration
55
+ # - Kernel Tuner executes this experiments file using the methodology
56
+ # - The methodology returns the fitness metric
57
+ # - The fitness metric is fed back into the meta-strategy
58
+
59
+ iterations = 1
60
+ if "iterations" in kwargs:
61
+ iterations = kwargs['iterations']
62
+ del kwargs['iterations']
63
+
64
+ # pass a temporary cache file to avoid duplicate execution
65
+ if 'cache' not in kwargs:
66
+ cachefile = get_random_unique_filename('temp_', '.json')
67
+ cachefile = Path(f"hyperparamtuning_paper_bruteforce_{target_strategy}.json")
68
+ kwargs['cache'] = str(cachefile)
69
+
70
+ def put_if_not_present(target_dict, key, value):
71
+ target_dict[key] = value if key not in target_dict else target_dict[key]
72
+
73
+ # set default arguments if not provided
74
+ put_if_not_present(kwargs, "verbose", True)
75
+ put_if_not_present(kwargs, "quiet", False)
76
+ put_if_not_present(kwargs, "simulation_mode", False)
77
+ put_if_not_present(kwargs, "strategy", 'brute_force')
78
+ put_if_not_present(kwargs, 'verify', None)
79
+ arguments = [target_strategy]
80
+
81
+ # IMPORTANT when running this script in parallel, always make sure the below name is unique among your runs!
82
+ # e.g. when parallalizing over the hypertuning of multiple strategies, use the strategy name
83
+ name = f"hyperparamtuning_{target_strategy.lower()}"
84
+
85
+ # execute the hyperparameter tuning
86
+ result, env = kernel_tuner.tune_kernel(name, None, [], arguments, hyper_params, restrictions=restrictions, *args, lang='Hypertuner',
87
+ objective='score', objective_higher_is_better=True, iterations=iterations, **kwargs)
88
+
89
+ # remove the temporary cachefile and return only unique results in order
90
+ # cachefile.unlink()
91
+ result_unique = dict()
92
+ for r in result:
93
+ config_id = ",".join(str(r[k]) for k in hyper_params.keys())
94
+ if config_id not in result_unique:
95
+ result_unique[config_id] = r
96
+ return list(result_unique.values()), env
97
+
98
+ if __name__ == "__main__":
99
+ """Main function to run the hyperparameter tuning. Run with `python hyper.py strategy_to_tune=`."""
100
+
101
+ parser = ArgumentParser()
102
+ parser.add_argument("strategy_to_tune", type=str, help="The strategy to tune hyperparameters for.")
103
+ parser.add_argument("--meta_strategy", nargs='?', default="dual_annealing", type=str, help="The meta-strategy to use for hyperparameter tuning.")
104
+ parser.add_argument("--max_time", nargs='?', default=60*60*24, type=int, help="The maximum time in seconds for the hyperparameter tuning.")
105
+ args = parser.parse_args()
106
+ strategy_to_tune = args.strategy_to_tune
107
+
108
+ kwargs = dict(
109
+ verbose=True,
110
+ quiet=False,
111
+ simulation_mode=False,
112
+ strategy=args.meta_strategy,
113
+ cache=f"hyperparamtuning_t={strategy_to_tune}_m={args.meta_strategy}.json",
114
+ strategy_options=dict(
115
+ time_limit=args.max_time,
116
+ )
117
+ )
118
+
119
+ # select the hyperparameter parameters for the selected optimization algorithm
120
+ restrictions = []
121
+ if strategy_to_tune.lower() == "pso":
122
+ # exhaustive search for PSO hyperparameters
123
+ # hyperparams = {
124
+ # 'popsize': [10, 20, 30],
125
+ # 'maxiter': [50, 100, 150],
126
+ # # 'w': [0.25, 0.5, 0.75], # disabled due to low influence according to KW-test (H=0.0215) and mutual information
127
+ # 'c1': [1.0, 2.0, 3.0],
128
+ # 'c2': [0.5, 1.0, 1.5]
129
+ # }
130
+ hyperparams = {
131
+ 'popsize': list(range(2, 50+1, 2)),
132
+ 'maxiter': list(range(10, 200, 10)),
133
+ # 'w': [0.25, 0.5, 0.75], # disabled due to low influence according to KW-test (H=0.0215) and mutual information
134
+ 'c1': [round(n, 2) for n in np.arange(1.0, 3.5+0.25, 0.25).tolist()],
135
+ 'c2': [round(n, 2) for n in np.arange(0.5, 2.0+0.25, 0.25).tolist()]
136
+ }
137
+ elif strategy_to_tune.lower() == "firefly_algorithm":
138
+ hyperparams = {
139
+ 'popsize': [10, 20, 30],
140
+ 'maxiter': [50, 100, 150],
141
+ 'B0': [0.5, 1.0, 1.5],
142
+ 'gamma': [0.1, 0.25, 0.5],
143
+ 'alpha': [0.1, 0.2, 0.3]
144
+ }
145
+ elif strategy_to_tune.lower() == "greedy_ils":
146
+ hyperparams = {
147
+ 'neighbor': ['Hamming', 'adjacent'],
148
+ 'restart': [True, False],
149
+ 'no_improvement': [10, 25, 50, 75],
150
+ 'random_walk': [0.1, 0.2, 0.3, 0.4, 0.5]
151
+ }
152
+ elif strategy_to_tune.lower() == "dual_annealing":
153
+ hyperparams = {
154
+ 'method': ['COBYLA', 'L-BFGS-B', 'SLSQP', 'CG', 'Powell', 'Nelder-Mead', 'BFGS', 'trust-constr'],
155
+ }
156
+ elif strategy_to_tune.lower() == "diff_evo":
157
+ hyperparams = {
158
+ 'method': ["best1bin", "rand1bin", "best2bin", "rand2bin", "best1exp", "rand1exp", "best2exp", "rand2exp", "currenttobest1bin", "currenttobest1exp", "randtobest1bin", "randtobest1exp"], # best1bin
159
+ 'popsize': list(range(2, 50+1, 2)), # 50
160
+ 'popsize_times_dimensions': [True, False], # False
161
+ 'F': [round(n, 2) for n in np.arange(0.1, 2.0+0.1, 0.1).tolist()], # 1.3
162
+ 'CR': [round(n, 2) for n in np.arange(0.05, 1.0+0.05, 0.05).tolist()] # 0.9
163
+ }
164
+ elif strategy_to_tune.lower() == "basinhopping":
165
+ hyperparams = {
166
+ 'method': ["Nelder-Mead", "Powell", "CG", "BFGS", "L-BFGS-B", "TNC", "COBYLA", "SLSQP"],
167
+ 'T': [0.1, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5],
168
+ }
169
+ elif strategy_to_tune.lower() == "genetic_algorithm":
170
+ # hyperparams = {
171
+ # 'method': ["single_point", "two_point", "uniform", "disruptive_uniform"],
172
+ # 'popsize': [10, 20, 30],
173
+ # 'maxiter': [50, 100, 150],
174
+ # 'mutation_chance': [5, 10, 20]
175
+ # }
176
+ hyperparams = {
177
+ 'method': ["single_point", "two_point", "uniform", "disruptive_uniform"],
178
+ 'popsize': list(range(2, 50+1, 2)),
179
+ 'maxiter': list(range(10, 200, 10)),
180
+ 'mutation_chance': list(range(5, 100, 5))
181
+ }
182
+ elif strategy_to_tune.lower() == "greedy_mls":
183
+ hyperparams = {
184
+ 'neighbor': ["Hamming", "adjacent"],
185
+ 'restart': [True, False],
186
+ 'randomize': [True, False]
187
+ }
188
+ elif strategy_to_tune.lower() == "simulated_annealing":
189
+ # hyperparams = {
190
+ # 'T': [0.5, 1.0, 1.5],
191
+ # 'T_min': [0.0001, 0.001, 0.01],
192
+ # 'alpha': [0.9925, 0.995, 0.9975],
193
+ # 'maxiter': [1, 2, 3]
194
+ # }
195
+ hyperparams = {
196
+ 'T': [round(n, 2) for n in np.arange(0.1, 2.0+0.1, 0.1).tolist()],
197
+ 'T_min': [round(n, 4) for n in np.arange(0.0001, 0.1, 0.001).tolist()],
198
+ 'alpha': [0.9925, 0.995, 0.9975],
199
+ 'maxiter': list(range(1, 10, 1))
200
+ }
201
+ elif strategy_to_tune.lower() == "bayes_opt":
202
+ hyperparams = {
203
+ # 'covariancekernel': ["constantrbf", "rbf", "matern32", "matern52"],
204
+ 'covariancelengthscale': [1.0, 1.5, 2.0],
205
+ 'method': ["poi", "ei", "lcb", "lcb-srinivas", "multi", "multi-advanced", "multi-fast", "multi-ultrafast"],
206
+ 'samplingmethod': ["random", "LHS"],
207
+ 'popsize': [10, 20, 30]
208
+ }
209
+ else:
210
+ raise ValueError(f"Invalid argument {strategy_to_tune=}")
211
+
212
+ # run the hyperparameter tuning
213
+ result, env = tune_hyper_params(strategy_to_tune.lower(), hyperparams, restrictions=restrictions, **kwargs)
214
+ print(result)
215
+ print(env['best_config'])
@@ -4,7 +4,7 @@ import json
4
4
 
5
5
  from jsonschema import validate
6
6
 
7
- from kernel_tuner import util
7
+ from kernel_tuner.util import get_instance_string, looks_like_a_filename, read_file
8
8
 
9
9
  #specifies for a number of pre-defined objectives whether
10
10
  #the objective should be minimized or maximized (boolean value denotes higher is better)
@@ -208,8 +208,8 @@ def store_results(results_filename, kernel_name, kernel_string, tune_params, pro
208
208
  meta["version_number"] = "1.0"
209
209
  meta["kernel_name"] = kernel_name
210
210
  if kernel_string and not callable(kernel_string) and not isinstance(kernel_string, list):
211
- if util.looks_like_a_filename(kernel_string):
212
- meta["kernel_string"] = util.read_file(kernel_string)
211
+ if looks_like_a_filename(kernel_string):
212
+ meta["kernel_string"] = read_file(kernel_string)
213
213
  else:
214
214
  meta["kernel_string"] = kernel_string
215
215
  meta["objective"] = objective
@@ -340,7 +340,7 @@ def _select_best_common_config(results, objective, objective_higher_is_better):
340
340
  for config in results:
341
341
  params = config["tunable_parameters"]
342
342
 
343
- config_str = util.get_instance_string(params)
343
+ config_str = get_instance_string(params)
344
344
  #count occurances
345
345
  results_table[config_str] = results_table.get(config_str,0) + 1
346
346
  #add to performance