holobench 1.3.5__py3-none-any.whl → 1.23.0__py3-none-any.whl
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.
- bencher/__init__.py +12 -0
- bencher/bench_cfg.py +29 -33
- bencher/bench_plot_server.py +5 -1
- bencher/bench_report.py +14 -14
- bencher/bench_runner.py +3 -2
- bencher/bencher.py +80 -53
- bencher/class_enum.py +52 -0
- bencher/job.py +6 -4
- bencher/optuna_conversions.py +4 -3
- bencher/utils.py +55 -4
- bencher/video_writer.py +48 -11
- holobench-1.23.0.data/data/share/bencher/package.xml +33 -0
- holobench-1.23.0.dist-info/LICENSE +21 -0
- {holobench-1.3.5.dist-info → holobench-1.23.0.dist-info}/METADATA +41 -31
- holobench-1.23.0.dist-info/RECORD +20 -0
- {holobench-1.3.5.dist-info → holobench-1.23.0.dist-info}/WHEEL +2 -1
- holobench-1.23.0.dist-info/top_level.txt +1 -0
- bencher/example/benchmark_data.py +0 -200
- bencher/example/example_all.py +0 -45
- bencher/example/example_categorical.py +0 -99
- bencher/example/example_custom_sweep.py +0 -59
- bencher/example/example_docs.py +0 -34
- bencher/example/example_float3D.py +0 -101
- bencher/example/example_float_cat.py +0 -98
- bencher/example/example_floats.py +0 -89
- bencher/example/example_floats2D.py +0 -93
- bencher/example/example_holosweep.py +0 -104
- bencher/example/example_holosweep_objects.py +0 -111
- bencher/example/example_holosweep_tap.py +0 -144
- bencher/example/example_image.py +0 -82
- bencher/example/example_levels.py +0 -181
- bencher/example/example_pareto.py +0 -53
- bencher/example/example_sample_cache.py +0 -85
- bencher/example/example_sample_cache_context.py +0 -116
- bencher/example/example_simple.py +0 -134
- bencher/example/example_simple_bool.py +0 -34
- bencher/example/example_simple_cat.py +0 -47
- bencher/example/example_simple_float.py +0 -38
- bencher/example/example_strings.py +0 -46
- bencher/example/example_time_event.py +0 -62
- bencher/example/example_video.py +0 -124
- bencher/example/example_workflow.py +0 -189
- bencher/example/experimental/example_bokeh_plotly.py +0 -38
- bencher/example/experimental/example_hover_ex.py +0 -45
- bencher/example/experimental/example_hvplot_explorer.py +0 -39
- bencher/example/experimental/example_interactive.py +0 -75
- bencher/example/experimental/example_streamnd.py +0 -49
- bencher/example/experimental/example_streams.py +0 -36
- bencher/example/experimental/example_template.py +0 -40
- bencher/example/experimental/example_updates.py +0 -84
- bencher/example/experimental/example_vector.py +0 -84
- bencher/example/meta/example_meta.py +0 -171
- bencher/example/meta/example_meta_cat.py +0 -25
- bencher/example/meta/example_meta_float.py +0 -23
- bencher/example/meta/example_meta_levels.py +0 -26
- bencher/example/optuna/example_optuna.py +0 -78
- bencher/example/shelved/example_float2D_scatter.py +0 -109
- bencher/example/shelved/example_float3D_cone.py +0 -96
- bencher/example/shelved/example_kwargs.py +0 -63
- bencher/plotting/__init__.py +0 -0
- bencher/plotting/plot_filter.py +0 -110
- bencher/plotting/plt_cnt_cfg.py +0 -74
- bencher/results/__init__.py +0 -0
- bencher/results/bench_result.py +0 -80
- bencher/results/bench_result_base.py +0 -405
- bencher/results/float_formatter.py +0 -44
- bencher/results/holoview_result.py +0 -592
- bencher/results/optuna_result.py +0 -354
- bencher/results/panel_result.py +0 -113
- bencher/results/plotly_result.py +0 -65
- bencher/variables/inputs.py +0 -193
- bencher/variables/parametrised_sweep.py +0 -206
- bencher/variables/results.py +0 -176
- bencher/variables/sweep_base.py +0 -167
- bencher/variables/time.py +0 -74
- holobench-1.3.5.dist-info/RECORD +0 -74
- /bencher/example/__init__.py → /holobench-1.23.0.data/data/share/ament_index/resource_index/packages/bencher +0 -0
bencher/__init__.py
CHANGED
@@ -11,6 +11,7 @@ from .variables.results import (
|
|
11
11
|
ResultVar,
|
12
12
|
ResultVec,
|
13
13
|
ResultHmap,
|
14
|
+
ResultPath,
|
14
15
|
ResultVideo,
|
15
16
|
ResultImage,
|
16
17
|
ResultString,
|
@@ -21,6 +22,15 @@ from .variables.results import (
|
|
21
22
|
curve,
|
22
23
|
)
|
23
24
|
|
25
|
+
from .results.composable_container.composable_container_base import (
|
26
|
+
ComposeType,
|
27
|
+
ComposableContainerBase,
|
28
|
+
)
|
29
|
+
from .results.composable_container.composable_container_video import (
|
30
|
+
ComposableContainerVideo,
|
31
|
+
RenderCfg,
|
32
|
+
)
|
33
|
+
|
24
34
|
from .plotting.plot_filter import VarRange, PlotFilter
|
25
35
|
from .utils import (
|
26
36
|
hmap_canonical_input,
|
@@ -30,6 +40,7 @@ from .utils import (
|
|
30
40
|
gen_image_path,
|
31
41
|
gen_video_path,
|
32
42
|
lerp,
|
43
|
+
tabs_in_markdown,
|
33
44
|
)
|
34
45
|
from .variables.parametrised_sweep import ParametrizedSweep
|
35
46
|
from .caching import CachedParams
|
@@ -39,3 +50,4 @@ from .results.holoview_result import ReduceType, HoloviewResult
|
|
39
50
|
from .bench_report import BenchReport
|
40
51
|
from .job import Executors
|
41
52
|
from .video_writer import VideoWriter, add_image
|
53
|
+
from .class_enum import ClassEnum, ExampleEnum
|
bencher/bench_cfg.py
CHANGED
@@ -38,10 +38,6 @@ class BenchRunCfg(BenchPlotSrvCfg):
|
|
38
38
|
doc="If true each time the function is called it will plot a timeseries of historical and the latest result.",
|
39
39
|
)
|
40
40
|
|
41
|
-
debug: bool = param.Boolean(
|
42
|
-
False, doc="Debug the sampling faster by reducing the dimension sampling resolution"
|
43
|
-
)
|
44
|
-
|
45
41
|
use_optuna: bool = param.Boolean(False, doc="show optuna plots")
|
46
42
|
|
47
43
|
summarise_constant_inputs = param.Boolean(
|
@@ -303,6 +299,11 @@ class BenchCfg(BenchRunCfg):
|
|
303
299
|
doc="store the hash value of the config to avoid having to hash multiple times",
|
304
300
|
)
|
305
301
|
|
302
|
+
plot_callbacks = param.List(
|
303
|
+
None,
|
304
|
+
doc="A callable that takes a BenchResult and returns panel representation of the results",
|
305
|
+
)
|
306
|
+
|
306
307
|
def __init__(self, **params):
|
307
308
|
super().__init__(**params)
|
308
309
|
self.plot_lib = None
|
@@ -328,7 +329,6 @@ class BenchCfg(BenchRunCfg):
|
|
328
329
|
hash_sha1(str(self.title)),
|
329
330
|
hash_sha1(self.over_time),
|
330
331
|
repeats_hash,
|
331
|
-
hash_sha1(self.debug),
|
332
332
|
hash_sha1(self.tag),
|
333
333
|
)
|
334
334
|
)
|
@@ -344,9 +344,13 @@ class BenchCfg(BenchRunCfg):
|
|
344
344
|
def inputs_as_str(self) -> List[str]:
|
345
345
|
return [i.name for i in self.input_vars]
|
346
346
|
|
347
|
-
def describe_sweep(self, width: int = 800) -> pn.pane.Markdown:
|
347
|
+
def describe_sweep(self, width: int = 800, accordion=True) -> pn.pane.Markdown:
|
348
348
|
"""Produce a markdown summary of the sweep settings"""
|
349
|
-
|
349
|
+
|
350
|
+
desc = pn.pane.Markdown(self.describe_benchmark(), width=width)
|
351
|
+
if accordion:
|
352
|
+
return pn.Accordion(("Data Collection Parameters", desc))
|
353
|
+
return desc
|
350
354
|
|
351
355
|
def describe_benchmark(self) -> str:
|
352
356
|
"""Generate a string summary of the inputs and results from a BenchCfg
|
@@ -359,37 +363,30 @@ class BenchCfg(BenchRunCfg):
|
|
359
363
|
|
360
364
|
benchmark_sampling_str.append("Input Variables:")
|
361
365
|
for iv in self.input_vars:
|
362
|
-
benchmark_sampling_str.extend(describe_variable(iv,
|
366
|
+
benchmark_sampling_str.extend(describe_variable(iv, True))
|
363
367
|
|
364
368
|
if self.const_vars and (self.summarise_constant_inputs):
|
365
369
|
benchmark_sampling_str.append("\nConstants:")
|
366
370
|
for cv in self.const_vars:
|
367
|
-
benchmark_sampling_str.extend(describe_variable(cv[0], False,
|
371
|
+
benchmark_sampling_str.extend(describe_variable(cv[0], False, cv[1]))
|
368
372
|
|
369
373
|
benchmark_sampling_str.append("\nResult Variables:")
|
370
374
|
for rv in self.result_vars:
|
371
|
-
benchmark_sampling_str.extend(describe_variable(rv,
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
benchmark_sampling_str.append(f" use_cache: {self.use_cache}")
|
387
|
-
benchmark_sampling_str.append(f" use_sample_cache: {self.use_sample_cache}")
|
388
|
-
benchmark_sampling_str.append(f" only_hash_tag: {self.only_hash_tag}")
|
389
|
-
benchmark_sampling_str.append(f" parallel: {self.executor}")
|
390
|
-
|
391
|
-
for mv in self.meta_vars:
|
392
|
-
benchmark_sampling_str.extend(describe_variable(mv, self.debug, True))
|
375
|
+
benchmark_sampling_str.extend(describe_variable(rv, False))
|
376
|
+
|
377
|
+
benchmark_sampling_str.append("\nMeta Variables:")
|
378
|
+
benchmark_sampling_str.append(f" run date: {self.run_date}")
|
379
|
+
if self.run_tag:
|
380
|
+
benchmark_sampling_str.append(f" run tag: {self.run_tag}")
|
381
|
+
if self.level is not None:
|
382
|
+
benchmark_sampling_str.append(f" bench level: {self.level}")
|
383
|
+
benchmark_sampling_str.append(f" use_cache: {self.use_cache}")
|
384
|
+
benchmark_sampling_str.append(f" use_sample_cache: {self.use_sample_cache}")
|
385
|
+
benchmark_sampling_str.append(f" only_hash_tag: {self.only_hash_tag}")
|
386
|
+
benchmark_sampling_str.append(f" executor: {self.executor}")
|
387
|
+
|
388
|
+
for mv in self.meta_vars:
|
389
|
+
benchmark_sampling_str.extend(describe_variable(mv, True))
|
393
390
|
|
394
391
|
benchmark_sampling_str.append("```")
|
395
392
|
|
@@ -427,7 +424,6 @@ class BenchCfg(BenchRunCfg):
|
|
427
424
|
if self.description is not None and description:
|
428
425
|
col.append(self.to_description())
|
429
426
|
if describe_sweep:
|
430
|
-
col.append(pn.pane.Markdown("## Data Collection Parameters:"))
|
431
427
|
col.append(self.describe_sweep())
|
432
428
|
if results_suffix:
|
433
429
|
col.append(pn.pane.Markdown("## Results:"))
|
@@ -451,7 +447,7 @@ class DimsCfg:
|
|
451
447
|
self.dims_name = [i.name for i in bench_cfg.all_vars]
|
452
448
|
|
453
449
|
self.dim_ranges = []
|
454
|
-
self.dim_ranges = [i.values(
|
450
|
+
self.dim_ranges = [i.values() for i in bench_cfg.all_vars]
|
455
451
|
self.dims_size = [len(p) for p in self.dim_ranges]
|
456
452
|
self.dim_ranges_index = [list(range(i)) for i in self.dims_size]
|
457
453
|
self.dim_ranges_str = [f"{s}\n" for s in self.dim_ranges]
|
bencher/bench_plot_server.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
"""A server for display plots of benchmark results"""
|
2
|
+
|
2
3
|
import logging
|
3
4
|
import os
|
4
5
|
from typing import List, Tuple
|
@@ -86,6 +87,10 @@ class BenchPlotServer:
|
|
86
87
|
port (int): use a fixed port to lauch the server
|
87
88
|
"""
|
88
89
|
|
90
|
+
# suppress verbose tornado and bokeh output
|
91
|
+
for logger in ["tornado", "bokeh"]:
|
92
|
+
logging.getLogger(logger).setLevel(logging.WARNING)
|
93
|
+
|
89
94
|
if port is not None:
|
90
95
|
return pn.serve(
|
91
96
|
plots_instance,
|
@@ -96,5 +101,4 @@ class BenchPlotServer:
|
|
96
101
|
show=show,
|
97
102
|
)
|
98
103
|
|
99
|
-
logging.getLogger().setLevel(logging.WARNING)
|
100
104
|
return pn.serve(plots_instance, title=bench_name, threaded=True, show=show)
|
bencher/bench_report.py
CHANGED
@@ -3,7 +3,8 @@ from typing import Callable
|
|
3
3
|
import os
|
4
4
|
import panel as pn
|
5
5
|
from pathlib import Path
|
6
|
-
import
|
6
|
+
import tempfile
|
7
|
+
|
7
8
|
from threading import Thread
|
8
9
|
|
9
10
|
from bencher.results.bench_result import BenchResult
|
@@ -47,7 +48,7 @@ class BenchReport(BenchPlotServer):
|
|
47
48
|
self.pane.append(col)
|
48
49
|
|
49
50
|
def append_result(self, bench_res: BenchResult) -> None:
|
50
|
-
self.append_tab(bench_res.
|
51
|
+
self.append_tab(bench_res.plot(), bench_res.bench_cfg.title)
|
51
52
|
|
52
53
|
def append_tab(self, pane: pn.panel, name: str = None) -> None:
|
53
54
|
if pane is not None:
|
@@ -137,24 +138,23 @@ class BenchReport(BenchPlotServer):
|
|
137
138
|
|
138
139
|
remote, publish_url = remote_callback(branch_name)
|
139
140
|
|
140
|
-
|
141
|
-
|
142
|
-
|
141
|
+
with tempfile.TemporaryDirectory() as td:
|
142
|
+
directory = td
|
143
|
+
report_path = self.save(directory, filename="index.html", in_html_folder=False)
|
144
|
+
logging.info(f"created report at: {report_path.absolute()}")
|
143
145
|
|
144
|
-
|
146
|
+
cd_dir = f"cd {directory} &&"
|
145
147
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
148
|
+
os.system(f"{cd_dir} git init")
|
149
|
+
os.system(f"{cd_dir} git checkout -b {branch_name}")
|
150
|
+
os.system(f"{cd_dir} git add index.html")
|
151
|
+
os.system(f'{cd_dir} git commit -m "publish {branch_name}"')
|
152
|
+
os.system(f"{cd_dir} git remote add origin {remote}")
|
153
|
+
os.system(f"{cd_dir} git push --set-upstream origin {branch_name} -f")
|
152
154
|
|
153
155
|
logging.info("Published report @")
|
154
156
|
logging.info(publish_url)
|
155
157
|
|
156
|
-
shutil.rmtree(directory)
|
157
|
-
|
158
158
|
return publish_url
|
159
159
|
|
160
160
|
|
bencher/bench_runner.py
CHANGED
@@ -103,7 +103,7 @@ class BenchRunner:
|
|
103
103
|
for r in range(1, repeats + 1):
|
104
104
|
for lvl in range(min_level, max_level + 1):
|
105
105
|
if grouped:
|
106
|
-
report_level = BenchReport(self.name)
|
106
|
+
report_level = BenchReport(f"{run_cfg.run_tag}_{self.name}")
|
107
107
|
|
108
108
|
for bch_fn in self.bench_fns:
|
109
109
|
run_lvl = deepcopy(run_cfg)
|
@@ -114,13 +114,14 @@ class BenchRunner:
|
|
114
114
|
res = bch_fn(run_lvl, report_level)
|
115
115
|
else:
|
116
116
|
res = bch_fn(run_lvl, BenchReport())
|
117
|
+
res.report.bench_name = f"{run_cfg.run_tag}_{res.report.bench_name}"
|
117
118
|
self.show_publish(res.report, show, publish, save, debug)
|
118
119
|
self.results.append(res)
|
119
120
|
if grouped:
|
120
121
|
self.show_publish(report_level, show, publish, save, debug)
|
121
122
|
return self.results
|
122
123
|
|
123
|
-
def show_publish(self, report, show, publish, save, debug):
|
124
|
+
def show_publish(self, report: BenchReport, show: bool, publish: bool, save: bool, debug: bool):
|
124
125
|
if save:
|
125
126
|
report.save_index()
|
126
127
|
if publish and self.publisher is not None:
|
bencher/bencher.py
CHANGED
@@ -10,6 +10,7 @@ import xarray as xr
|
|
10
10
|
from diskcache import Cache
|
11
11
|
from contextlib import suppress
|
12
12
|
from functools import partial
|
13
|
+
import panel as pn
|
13
14
|
|
14
15
|
from bencher.worker_job import WorkerJob
|
15
16
|
|
@@ -23,6 +24,7 @@ from bencher.variables.results import (
|
|
23
24
|
ResultVar,
|
24
25
|
ResultVec,
|
25
26
|
ResultHmap,
|
27
|
+
ResultPath,
|
26
28
|
ResultVideo,
|
27
29
|
ResultImage,
|
28
30
|
ResultString,
|
@@ -32,6 +34,7 @@ from bencher.variables.results import (
|
|
32
34
|
from bencher.results.bench_result import BenchResult
|
33
35
|
from bencher.variables.parametrised_sweep import ParametrizedSweep
|
34
36
|
from bencher.job import Job, FutureCache, JobFuture, Executors
|
37
|
+
from bencher.utils import params_to_str
|
35
38
|
|
36
39
|
# Customize the formatter
|
37
40
|
formatter = logging.Formatter("%(levelname)s: %(message)s")
|
@@ -164,6 +167,23 @@ class Bench(BenchPlotServer):
|
|
164
167
|
|
165
168
|
self.cache_size = int(100e9) # default to 100gb
|
166
169
|
|
170
|
+
# self.bench_cfg = BenchCfg()
|
171
|
+
|
172
|
+
# Maybe put this in SweepCfg
|
173
|
+
self.input_vars = None
|
174
|
+
self.result_vars = None
|
175
|
+
self.const_vars = None
|
176
|
+
self.plot_callbacks = []
|
177
|
+
self.plot = True
|
178
|
+
|
179
|
+
def add_plot_callback(self, callback: Callable[[BenchResult], pn.panel], **kwargs) -> None:
|
180
|
+
"""Add a plotting callback that will be called on any result produced when calling a sweep funciton. You can pass additional arguments to the plotting function with kwargs. e.g. add_plot_callback(bch.BenchResult.to_video_grid,)
|
181
|
+
|
182
|
+
Args:
|
183
|
+
callback (Callable[[BenchResult], pn.panel]): _description_
|
184
|
+
"""
|
185
|
+
self.plot_callbacks.append(partial(callback, **kwargs))
|
186
|
+
|
167
187
|
def set_worker(self, worker: Callable, worker_input_cfg: ParametrizedSweep = None) -> None:
|
168
188
|
"""Set the benchmark worker function and optionally the type the worker expects
|
169
189
|
|
@@ -187,34 +207,6 @@ class Bench(BenchPlotServer):
|
|
187
207
|
logging.info(f"setting worker {worker}")
|
188
208
|
self.worker_input_cfg = worker_input_cfg
|
189
209
|
|
190
|
-
def sweep(
|
191
|
-
self,
|
192
|
-
input_vars: List[ParametrizedSweep] = None,
|
193
|
-
result_vars: List[ParametrizedSweep] = None,
|
194
|
-
const_vars: List[ParametrizedSweep] = None,
|
195
|
-
time_src: datetime = None,
|
196
|
-
description: str = None,
|
197
|
-
post_description: str = None,
|
198
|
-
pass_repeat: bool = False,
|
199
|
-
tag: str = "",
|
200
|
-
run_cfg: BenchRunCfg = None,
|
201
|
-
plot: bool = False,
|
202
|
-
) -> BenchResult:
|
203
|
-
title = "Sweeping " + " vs ".join([self.get_name(i) for i in input_vars])
|
204
|
-
return self.plot_sweep(
|
205
|
-
title,
|
206
|
-
input_vars=input_vars,
|
207
|
-
result_vars=result_vars,
|
208
|
-
const_vars=const_vars,
|
209
|
-
time_src=time_src,
|
210
|
-
description=description,
|
211
|
-
post_description=post_description,
|
212
|
-
pass_repeat=pass_repeat,
|
213
|
-
tag=tag,
|
214
|
-
run_cfg=run_cfg,
|
215
|
-
plot=plot,
|
216
|
-
)
|
217
|
-
|
218
210
|
def sweep_sequential(
|
219
211
|
self,
|
220
212
|
title="",
|
@@ -226,15 +218,16 @@ class Bench(BenchPlotServer):
|
|
226
218
|
group_size: int = 1,
|
227
219
|
iterations: int = 1,
|
228
220
|
relationship_cb=None,
|
221
|
+
plot_callbacks: List | bool = None,
|
229
222
|
) -> List[BenchResult]:
|
230
|
-
results = []
|
231
223
|
if relationship_cb is None:
|
232
224
|
relationship_cb = combinations
|
225
|
+
if input_vars is None:
|
226
|
+
input_vars = self.worker_class_instance.get_inputs_only()
|
227
|
+
results = []
|
233
228
|
for it in range(iterations):
|
234
229
|
for input_group in relationship_cb(input_vars, group_size):
|
235
|
-
title_gen = (
|
236
|
-
title + "Sweeping " + " vs ".join([self.get_name(i) for i in input_group])
|
237
|
-
)
|
230
|
+
title_gen = title + "Sweeping " + " vs ".join(params_to_str(input_group))
|
238
231
|
if iterations > 1:
|
239
232
|
title_gen += f" iteration:{it}"
|
240
233
|
res = self.plot_sweep(
|
@@ -243,8 +236,9 @@ class Bench(BenchPlotServer):
|
|
243
236
|
result_vars=result_vars,
|
244
237
|
const_vars=const_vars,
|
245
238
|
run_cfg=run_cfg,
|
246
|
-
|
239
|
+
plot_callbacks=plot_callbacks,
|
247
240
|
)
|
241
|
+
|
248
242
|
if optimise_var is not None:
|
249
243
|
const_vars = res.get_optimal_inputs(optimise_var, True)
|
250
244
|
results.append(res)
|
@@ -262,7 +256,7 @@ class Bench(BenchPlotServer):
|
|
262
256
|
pass_repeat: bool = False,
|
263
257
|
tag: str = "",
|
264
258
|
run_cfg: BenchRunCfg = None,
|
265
|
-
|
259
|
+
plot_callbacks: List | bool = None,
|
266
260
|
) -> BenchResult:
|
267
261
|
"""The all in 1 function benchmarker and results plotter.
|
268
262
|
|
@@ -277,7 +271,8 @@ class Bench(BenchPlotServer):
|
|
277
271
|
pass_repeat (bool,optional) By default do not pass the kwarg 'repeat' to the benchmark function. Set to true if
|
278
272
|
you want the benchmark function to be passed the repeat number
|
279
273
|
tag (str,optional): Use tags to group different benchmarks together.
|
280
|
-
run_cfg: (BenchRunCfg, optional): A config for storing how the benchmarks and run
|
274
|
+
run_cfg: (BenchRunCfg, optional): A config for storing how the benchmarks and run
|
275
|
+
plot_callbacks: (List | bool) A list of plot callbacks to call on the results. Pass false or an empty list to turn off plotting
|
281
276
|
Raises:
|
282
277
|
ValueError: If a result variable is not set
|
283
278
|
|
@@ -290,18 +285,26 @@ class Bench(BenchPlotServer):
|
|
290
285
|
logging.info(
|
291
286
|
"No input variables passed, using all param variables in bench class as inputs"
|
292
287
|
)
|
293
|
-
input_vars
|
288
|
+
if self.input_vars is None:
|
289
|
+
input_vars = self.worker_class_instance.get_inputs_only()
|
290
|
+
else:
|
291
|
+
input_vars = self.input_vars
|
294
292
|
for i in input_vars:
|
295
293
|
logging.info(f"input var: {i.name}")
|
296
294
|
if result_vars is None:
|
297
295
|
logging.info(
|
298
296
|
"No results variables passed, using all result variables in bench class:"
|
299
297
|
)
|
300
|
-
result_vars
|
301
|
-
|
302
|
-
|
298
|
+
if self.result_vars is None:
|
299
|
+
result_vars = self.worker_class_instance.get_results_only()
|
300
|
+
else:
|
301
|
+
result_vars = self.result_vars
|
302
|
+
|
303
303
|
if const_vars is None:
|
304
|
-
const_vars
|
304
|
+
if self.const_vars is None:
|
305
|
+
const_vars = self.worker_class_instance.get_input_defaults()
|
306
|
+
else:
|
307
|
+
const_vars = self.const_vars
|
305
308
|
else:
|
306
309
|
if input_vars is None:
|
307
310
|
input_vars = []
|
@@ -317,6 +320,9 @@ class Bench(BenchPlotServer):
|
|
317
320
|
for i in range(len(result_vars)):
|
318
321
|
result_vars[i] = self.convert_vars_to_params(result_vars[i], "result")
|
319
322
|
|
323
|
+
for r in result_vars:
|
324
|
+
logging.info(f"result var: {r.name}")
|
325
|
+
|
320
326
|
if isinstance(const_vars, dict):
|
321
327
|
const_vars = list(const_vars.items())
|
322
328
|
|
@@ -380,6 +386,14 @@ class Bench(BenchPlotServer):
|
|
380
386
|
"## Results Description\nPlease set post_description to explain these results"
|
381
387
|
)
|
382
388
|
|
389
|
+
if plot_callbacks is None:
|
390
|
+
if self.plot_callbacks is not None and len(self.plot_callbacks) == 0:
|
391
|
+
plot_callbacks = [BenchResult.to_auto_plots]
|
392
|
+
else:
|
393
|
+
plot_callbacks = self.plot_callbacks
|
394
|
+
elif isinstance(plot_callbacks, bool):
|
395
|
+
plot_callbacks = [BenchResult.to_auto_plots] if plot_callbacks else []
|
396
|
+
|
383
397
|
bench_cfg = BenchCfg(
|
384
398
|
input_vars=input_vars,
|
385
399
|
result_vars=result_vars_only,
|
@@ -391,7 +405,13 @@ class Bench(BenchPlotServer):
|
|
391
405
|
title=title,
|
392
406
|
pass_repeat=pass_repeat,
|
393
407
|
tag=run_cfg.run_tag + tag,
|
408
|
+
plot_callbacks=plot_callbacks,
|
394
409
|
)
|
410
|
+
return self.run_sweep(bench_cfg, run_cfg, time_src)
|
411
|
+
|
412
|
+
def run_sweep(
|
413
|
+
self, bench_cfg: BenchCfg, run_cfg: BenchRunCfg, time_src: datetime
|
414
|
+
) -> BenchResult:
|
395
415
|
print("tag", bench_cfg.tag)
|
396
416
|
|
397
417
|
bench_cfg.param.update(run_cfg.param.values())
|
@@ -446,16 +466,12 @@ class Bench(BenchPlotServer):
|
|
446
466
|
|
447
467
|
bench_res.post_setup()
|
448
468
|
|
449
|
-
if
|
469
|
+
if bench_cfg.auto_plot:
|
450
470
|
self.report.append_result(bench_res)
|
471
|
+
|
451
472
|
self.results.append(bench_res)
|
452
473
|
return bench_res
|
453
474
|
|
454
|
-
def get_name(self, var):
|
455
|
-
if isinstance(var, param.Parameter):
|
456
|
-
return var.name
|
457
|
-
return var
|
458
|
-
|
459
475
|
def convert_vars_to_params(self, variable: param.Parameter, var_type: str):
|
460
476
|
"""check that a variable is a subclass of param
|
461
477
|
|
@@ -544,7 +560,7 @@ class Bench(BenchPlotServer):
|
|
544
560
|
time_src (datetime | str): a representation of the sample time
|
545
561
|
|
546
562
|
Returns:
|
547
|
-
|
563
|
+
tuple[BenchResult, List, List]: bench_result, function intputs, dimension names
|
548
564
|
"""
|
549
565
|
|
550
566
|
if time_src is None:
|
@@ -552,13 +568,11 @@ class Bench(BenchPlotServer):
|
|
552
568
|
bench_cfg.meta_vars = self.define_extra_vars(bench_cfg, bench_cfg.repeats, time_src)
|
553
569
|
|
554
570
|
bench_cfg.all_vars = bench_cfg.input_vars + bench_cfg.meta_vars
|
555
|
-
|
556
571
|
# bench_cfg.all_vars = bench_cfg.iv_time + bench_cfg.input_vars +[ bench_cfg.iv_repeat]
|
557
|
-
|
558
572
|
# bench_cfg.all_vars = [ bench_cfg.iv_repeat] +bench_cfg.input_vars + bench_cfg.iv_time
|
559
573
|
|
560
574
|
for i in bench_cfg.all_vars:
|
561
|
-
logging.info(i.sampling_str(
|
575
|
+
logging.info(i.sampling_str())
|
562
576
|
|
563
577
|
dims_cfg = DimsCfg(bench_cfg)
|
564
578
|
function_inputs = list(
|
@@ -574,7 +588,9 @@ class Bench(BenchPlotServer):
|
|
574
588
|
if isinstance(rv, ResultReference):
|
575
589
|
result_data = np.full(dims_cfg.dims_size, -1, dtype=int)
|
576
590
|
data_vars[rv.name] = (dims_cfg.dims_name, result_data)
|
577
|
-
if isinstance(
|
591
|
+
if isinstance(
|
592
|
+
rv, (ResultPath, ResultVideo, ResultImage, ResultString, ResultContainer)
|
593
|
+
):
|
578
594
|
result_data = np.full(dims_cfg.dims_size, "NAN", dtype=object)
|
579
595
|
data_vars[rv.name] = (dims_cfg.dims_name, result_data)
|
580
596
|
elif type(rv) == ResultVec:
|
@@ -616,7 +632,6 @@ class Bench(BenchPlotServer):
|
|
616
632
|
default=repeats,
|
617
633
|
bounds=[1, repeats],
|
618
634
|
samples=repeats,
|
619
|
-
samples_debug=2 if repeats > 2 else 1,
|
620
635
|
units="repeats",
|
621
636
|
doc="The number of times a sample was measured",
|
622
637
|
)
|
@@ -712,7 +727,15 @@ class Bench(BenchPlotServer):
|
|
712
727
|
logging.info(f"{rv.name}: {result_value}")
|
713
728
|
|
714
729
|
if isinstance(
|
715
|
-
rv,
|
730
|
+
rv,
|
731
|
+
(
|
732
|
+
ResultVar,
|
733
|
+
ResultVideo,
|
734
|
+
ResultImage,
|
735
|
+
ResultString,
|
736
|
+
ResultContainer,
|
737
|
+
ResultPath,
|
738
|
+
),
|
716
739
|
):
|
717
740
|
set_xarray_multidim(bench_res.ds[rv.name], worker_job.index_tuple, result_value)
|
718
741
|
elif isinstance(rv, ResultReference):
|
@@ -803,3 +826,7 @@ class Bench(BenchPlotServer):
|
|
803
826
|
|
804
827
|
def get_result(self, index: int = -1) -> BenchResult:
|
805
828
|
return self.results[index]
|
829
|
+
|
830
|
+
def publish(self, remote_callback: Callable) -> str:
|
831
|
+
branch_name = f"{self.bench_name}_{self.run_cfg.run_tag}"
|
832
|
+
return self.report.publish(remote_callback, branch_name=branch_name)
|
bencher/class_enum.py
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from strenum import StrEnum
|
3
|
+
from typing import Any
|
4
|
+
import importlib
|
5
|
+
from abc import abstractmethod
|
6
|
+
from dataclasses import dataclass
|
7
|
+
from enum import auto
|
8
|
+
|
9
|
+
|
10
|
+
class ClassEnum(StrEnum):
|
11
|
+
"""A ClassEnum is a pattern to make it easier to create factory a factory method that converts from an enum to a corresponding class. Subclasses should implement to_class(enum_instance:EnumType) which takes an enum returns the corresponding instance of that class."""
|
12
|
+
|
13
|
+
@classmethod
|
14
|
+
def to_class_generic(cls, module_import: str, class_name: str) -> Any:
|
15
|
+
"""Create an instance of the class referred to by this enum
|
16
|
+
|
17
|
+
Returns:
|
18
|
+
Any: instance of the class
|
19
|
+
"""
|
20
|
+
|
21
|
+
class_def = getattr(importlib.import_module(module_import), class_name)
|
22
|
+
return class_def()
|
23
|
+
|
24
|
+
@classmethod
|
25
|
+
@abstractmethod
|
26
|
+
def to_class(cls, enum_val: ClassEnum) -> Any:
|
27
|
+
"""Subclasses should overrides this method to take an enum returns the corresponding instance of that class."""
|
28
|
+
raise NotImplementedError()
|
29
|
+
|
30
|
+
|
31
|
+
@dataclass
|
32
|
+
class BaseClass:
|
33
|
+
baseclassname: str = "class0"
|
34
|
+
|
35
|
+
|
36
|
+
@dataclass
|
37
|
+
class Class1(BaseClass):
|
38
|
+
classname: str = "class1"
|
39
|
+
|
40
|
+
|
41
|
+
@dataclass
|
42
|
+
class Class2(BaseClass):
|
43
|
+
classname: str = "class2"
|
44
|
+
|
45
|
+
|
46
|
+
class ExampleEnum(ClassEnum):
|
47
|
+
Class1 = auto()
|
48
|
+
Class2 = auto()
|
49
|
+
|
50
|
+
@classmethod
|
51
|
+
def to_class(cls, enum_val: ExampleEnum) -> BaseClass:
|
52
|
+
return cls.to_class_generic("bencher.class_enum", enum_val)
|
bencher/job.py
CHANGED
@@ -80,7 +80,8 @@ class FutureCache:
|
|
80
80
|
size_limit: int = int(20e9), # 20 GB
|
81
81
|
use_cache=True,
|
82
82
|
):
|
83
|
-
self.
|
83
|
+
self.executor_type = executor
|
84
|
+
self.executor = None
|
84
85
|
if use_cache:
|
85
86
|
self.cache = Cache(f"cachedir/{cache_name}", tag_index=tag_index, size_limit=size_limit)
|
86
87
|
logging.info(f"cache dir: {self.cache.directory}")
|
@@ -110,6 +111,9 @@ class FutureCache:
|
|
110
111
|
|
111
112
|
self.worker_fn_call_count += 1
|
112
113
|
|
114
|
+
if self.executor_type is not Executors.SERIAL:
|
115
|
+
if self.executor is None:
|
116
|
+
self.executor = Executors.factory(self.executor_type)
|
113
117
|
if self.executor is not None:
|
114
118
|
self.overwrite_msg(job, " starting parallel job...")
|
115
119
|
return JobFuture(
|
@@ -148,9 +152,7 @@ class FutureCache:
|
|
148
152
|
self.cache.close()
|
149
153
|
if self.executor:
|
150
154
|
self.executor.shutdown()
|
151
|
-
|
152
|
-
# def __del__(self):
|
153
|
-
# self.close()
|
155
|
+
self.executor = None
|
154
156
|
|
155
157
|
def stats(self) -> str:
|
156
158
|
logging.info(f"job calls: {self.worker_wrapper_call_count}")
|
bencher/optuna_conversions.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
from typing import List
|
2
|
+
import logging
|
2
3
|
|
3
4
|
import optuna
|
4
5
|
import panel as pn
|
@@ -30,7 +31,7 @@ def optuna_grid_search(bench_cfg: BenchCfg) -> optuna.Study:
|
|
30
31
|
"""
|
31
32
|
search_space = {}
|
32
33
|
for iv in bench_cfg.all_vars:
|
33
|
-
search_space[iv.name] = iv.values(
|
34
|
+
search_space[iv.name] = iv.values()
|
34
35
|
directions = []
|
35
36
|
for rv in bench_cfg.optuna_targets(True):
|
36
37
|
directions.append(rv.direction)
|
@@ -158,8 +159,8 @@ def summarise_optuna_study(study: optuna.study.Study) -> pn.pane.panel:
|
|
158
159
|
row.append(plot_param_importances(study))
|
159
160
|
try:
|
160
161
|
row.append(plot_pareto_front(study))
|
161
|
-
except Exception:
|
162
|
-
|
162
|
+
except Exception as e: # pylint: disable=broad-except
|
163
|
+
logging.exception(e)
|
163
164
|
|
164
165
|
row.append(
|
165
166
|
pn.pane.Markdown(f"```\nBest value: {study.best_value}\nParams: {study.best_params}```")
|