holobench 1.3.6__py2.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 +41 -0
- bencher/bench_cfg.py +462 -0
- bencher/bench_plot_server.py +100 -0
- bencher/bench_report.py +268 -0
- bencher/bench_runner.py +136 -0
- bencher/bencher.py +805 -0
- bencher/caching.py +51 -0
- bencher/example/__init__.py +0 -0
- bencher/example/benchmark_data.py +200 -0
- bencher/example/example_all.py +45 -0
- bencher/example/example_categorical.py +99 -0
- bencher/example/example_custom_sweep.py +59 -0
- bencher/example/example_docs.py +34 -0
- bencher/example/example_float3D.py +101 -0
- bencher/example/example_float_cat.py +98 -0
- bencher/example/example_floats.py +89 -0
- bencher/example/example_floats2D.py +93 -0
- bencher/example/example_holosweep.py +104 -0
- bencher/example/example_holosweep_objects.py +111 -0
- bencher/example/example_holosweep_tap.py +144 -0
- bencher/example/example_image.py +82 -0
- bencher/example/example_levels.py +181 -0
- bencher/example/example_pareto.py +53 -0
- bencher/example/example_sample_cache.py +85 -0
- bencher/example/example_sample_cache_context.py +116 -0
- bencher/example/example_simple.py +134 -0
- bencher/example/example_simple_bool.py +34 -0
- bencher/example/example_simple_cat.py +47 -0
- bencher/example/example_simple_float.py +38 -0
- bencher/example/example_strings.py +46 -0
- bencher/example/example_time_event.py +62 -0
- bencher/example/example_video.py +124 -0
- bencher/example/example_workflow.py +189 -0
- bencher/example/experimental/example_bokeh_plotly.py +38 -0
- bencher/example/experimental/example_hover_ex.py +45 -0
- bencher/example/experimental/example_hvplot_explorer.py +39 -0
- bencher/example/experimental/example_interactive.py +75 -0
- bencher/example/experimental/example_streamnd.py +49 -0
- bencher/example/experimental/example_streams.py +36 -0
- bencher/example/experimental/example_template.py +40 -0
- bencher/example/experimental/example_updates.py +84 -0
- bencher/example/experimental/example_vector.py +84 -0
- bencher/example/meta/example_meta.py +171 -0
- bencher/example/meta/example_meta_cat.py +25 -0
- bencher/example/meta/example_meta_float.py +23 -0
- bencher/example/meta/example_meta_levels.py +26 -0
- bencher/example/optuna/example_optuna.py +78 -0
- bencher/example/shelved/example_float2D_scatter.py +109 -0
- bencher/example/shelved/example_float3D_cone.py +96 -0
- bencher/example/shelved/example_kwargs.py +63 -0
- bencher/job.py +184 -0
- bencher/optuna_conversions.py +168 -0
- bencher/plotting/__init__.py +0 -0
- bencher/plotting/plot_filter.py +110 -0
- bencher/plotting/plt_cnt_cfg.py +74 -0
- bencher/results/__init__.py +0 -0
- bencher/results/bench_result.py +80 -0
- bencher/results/bench_result_base.py +405 -0
- bencher/results/float_formatter.py +44 -0
- bencher/results/holoview_result.py +592 -0
- bencher/results/optuna_result.py +354 -0
- bencher/results/panel_result.py +113 -0
- bencher/results/plotly_result.py +65 -0
- bencher/utils.py +148 -0
- bencher/variables/inputs.py +193 -0
- bencher/variables/parametrised_sweep.py +206 -0
- bencher/variables/results.py +176 -0
- bencher/variables/sweep_base.py +167 -0
- bencher/variables/time.py +74 -0
- bencher/video_writer.py +30 -0
- bencher/worker_job.py +40 -0
- holobench-1.3.6.dist-info/METADATA +85 -0
- holobench-1.3.6.dist-info/RECORD +74 -0
- holobench-1.3.6.dist-info/WHEEL +5 -0
@@ -0,0 +1,167 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import List, Any, Tuple
|
3
|
+
from copy import deepcopy
|
4
|
+
|
5
|
+
import numpy as np
|
6
|
+
import param
|
7
|
+
from param import Parameterized
|
8
|
+
import holoviews as hv
|
9
|
+
import panel as pn
|
10
|
+
from bencher.utils import hash_sha1
|
11
|
+
|
12
|
+
# slots that are shared across all Sweep classes
|
13
|
+
# param and slots don't work easily with multiple inheritance so define here
|
14
|
+
shared_slots = ["units", "samples", "samples_debug"]
|
15
|
+
|
16
|
+
|
17
|
+
def describe_variable(
|
18
|
+
v: Parameterized, debug: bool, include_samples: bool, value=None
|
19
|
+
) -> List[str]:
|
20
|
+
"""Generate a string description of a variable
|
21
|
+
|
22
|
+
Args:
|
23
|
+
v (param.Parameterized): parameter to describe
|
24
|
+
debug (bool): Generate a reduced number of samples from the variable
|
25
|
+
include_samples (bool): Include a description of the samples
|
26
|
+
|
27
|
+
Returns:
|
28
|
+
str: String description of the variable
|
29
|
+
"""
|
30
|
+
indent = " "
|
31
|
+
sampling_str = []
|
32
|
+
sampling_str.append(f"{v.name}:")
|
33
|
+
if include_samples:
|
34
|
+
# sampling_str.append(f"{indent}{v.sampling_str(debug)}")
|
35
|
+
sampling_str.append(f"{indent}number of samples: {len(v.values(debug))}")
|
36
|
+
sampling_str.append(f"{indent}sample values: {[str(v) for v in v.values(debug)]}")
|
37
|
+
|
38
|
+
if value is not None:
|
39
|
+
sampling_str.append(f"{indent}value: {value}")
|
40
|
+
if hasattr(v, "units"):
|
41
|
+
if v.units != "ul" and len(v.units) > 0:
|
42
|
+
sampling_str.append(f"{indent}units: [{v.units}]")
|
43
|
+
if v.doc is not None:
|
44
|
+
sampling_str.append(f"{indent}docs: {v.doc}")
|
45
|
+
for i in range(len(sampling_str)):
|
46
|
+
sampling_str[i] = f"{indent}{sampling_str[i]}"
|
47
|
+
return sampling_str
|
48
|
+
|
49
|
+
|
50
|
+
class SweepBase(param.Parameter):
|
51
|
+
# def __init__(self, **params):
|
52
|
+
# super().__init__(**params)
|
53
|
+
# self.units = ""
|
54
|
+
# slots = ["units", "samples", "samples_debug"]
|
55
|
+
# __slots__ = shared_slots
|
56
|
+
|
57
|
+
def values(self, debug: bool) -> List[Any]:
|
58
|
+
"""All sweep classes must implement this method. This generates sample values from based on the parameters bounds and sample number.
|
59
|
+
|
60
|
+
Args:
|
61
|
+
debug (bool): Return a reduced set of samples to enable fast debugging of a data generation and plotting pipeline. Ideally when debug is true, 2 samples will be returned
|
62
|
+
|
63
|
+
Returns:
|
64
|
+
List[Any]: A list of samples from the variable
|
65
|
+
"""
|
66
|
+
raise NotImplementedError
|
67
|
+
|
68
|
+
def hash_persistent(self) -> str:
|
69
|
+
"""A hash function that avoids the PYTHONHASHSEED 'feature' which returns a different hash value each time the program is run"""
|
70
|
+
return hash_sha1(
|
71
|
+
(self.units, self.samples, self.samples_debug) # pylint: disable=no-member
|
72
|
+
)
|
73
|
+
|
74
|
+
def sampling_str(self, debug=False) -> str:
|
75
|
+
"""Generate a string representation of the of the sampling procedure
|
76
|
+
|
77
|
+
Args:
|
78
|
+
debug (bool): If true then self.samples_debug is used
|
79
|
+
"""
|
80
|
+
|
81
|
+
samples = self.values(debug)
|
82
|
+
object_str = ",".join([str(i) for i in samples])
|
83
|
+
return f"Taking {len(samples)} samples from {self.name} with values: [{object_str}]"
|
84
|
+
|
85
|
+
def as_slider(self, debug=False) -> pn.widgets.slider.DiscreteSlider:
|
86
|
+
"""given a sweep variable (self), return the range of values as a panel slider
|
87
|
+
|
88
|
+
Args:
|
89
|
+
debug (bool, optional): pass to the sweepvar to produce a full set of varaibles, or when debug=True, a reduces number of sweep vars. Defaults to False.
|
90
|
+
|
91
|
+
Returns:
|
92
|
+
pn.widgets.slider.DiscreteSlider: A panel slider with the values() of the sweep variable
|
93
|
+
"""
|
94
|
+
return pn.widgets.slider.DiscreteSlider(name=self.name, options=list(self.values(debug)))
|
95
|
+
|
96
|
+
def as_dim(self, compute_values=False, debug=False) -> hv.Dimension:
|
97
|
+
"""Takes a sweep variable and turns it into a holoview dimension
|
98
|
+
|
99
|
+
Returns:
|
100
|
+
hv.Dimension:
|
101
|
+
"""
|
102
|
+
name_tuple = (self.name, self.name)
|
103
|
+
|
104
|
+
params = {}
|
105
|
+
if hasattr(self, "bounds"):
|
106
|
+
if compute_values:
|
107
|
+
params["values"] = self.values(debug)
|
108
|
+
# params["range"] = tuple(self.bounds)
|
109
|
+
else:
|
110
|
+
params["range"] = tuple(self.bounds)
|
111
|
+
params["default"] = self.default
|
112
|
+
|
113
|
+
else:
|
114
|
+
params["values"] = self.values(debug)
|
115
|
+
params["default"] = self.default
|
116
|
+
|
117
|
+
if hasattr(self, "step"):
|
118
|
+
params["step"] = getattr(self, "step")
|
119
|
+
|
120
|
+
return hv.Dimension(name_tuple, unit=self.units, **params) # pylint: disable=no-member
|
121
|
+
|
122
|
+
def indices_to_samples(self, desires_num_samples, sample_values):
|
123
|
+
indices = [
|
124
|
+
int(i) for i in np.linspace(0, len(sample_values) - 1, desires_num_samples, dtype=int)
|
125
|
+
]
|
126
|
+
|
127
|
+
if len(indices) > len(sample_values):
|
128
|
+
return sample_values
|
129
|
+
|
130
|
+
return [sample_values[i] for i in indices]
|
131
|
+
|
132
|
+
def with_samples(self, samples: int) -> SweepBase:
|
133
|
+
output = deepcopy(self)
|
134
|
+
# TODO set up class properly. Slightly complicated due to slots
|
135
|
+
output.samples = samples # pylint: disable = attribute-defined-outside-init
|
136
|
+
if hasattr(output, "step"):
|
137
|
+
# hack TODO fix this
|
138
|
+
output.step = None # pylint: disable = attribute-defined-outside-init
|
139
|
+
return output
|
140
|
+
|
141
|
+
def with_sample_values(self, sample_values: int) -> SweepBase:
|
142
|
+
output = deepcopy(self)
|
143
|
+
# TODO set up class properly. Slightly complicated due to slots
|
144
|
+
try:
|
145
|
+
output.sample_values = sample_values # pylint: disable = attribute-defined-outside-init
|
146
|
+
except AttributeError:
|
147
|
+
output.objects = sample_values # pylint: disable = attribute-defined-outside-init
|
148
|
+
output.samples = len(sample_values) # pylint: disable = attribute-defined-outside-init
|
149
|
+
return output
|
150
|
+
|
151
|
+
def with_const(self, const_value: Any) -> Tuple[SweepBase, Any]:
|
152
|
+
"""Create a new instance of SweepBase with a constant value.
|
153
|
+
|
154
|
+
Args:
|
155
|
+
const_value (Any): The constant value to be associated with the new instance.
|
156
|
+
|
157
|
+
Returns:
|
158
|
+
Tuple[SweepBase, Any]: A tuple containing the new instance of SweepBase and the constant value.
|
159
|
+
"""
|
160
|
+
return (deepcopy(self), const_value)
|
161
|
+
|
162
|
+
def with_level(self, level: int = 1, max_level: int = 12) -> SweepBase:
|
163
|
+
assert level >= 1
|
164
|
+
# TODO work out if the order can be returned in level order always
|
165
|
+
samples = [0, 1, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049]
|
166
|
+
out = self.with_sample_values(self.with_samples(samples[min(max_level, level)]).values())
|
167
|
+
return out
|
@@ -0,0 +1,74 @@
|
|
1
|
+
from datetime import datetime
|
2
|
+
from typing import List
|
3
|
+
|
4
|
+
from pandas import Timestamp
|
5
|
+
from param import Selector
|
6
|
+
from bencher.variables.sweep_base import SweepBase, shared_slots
|
7
|
+
|
8
|
+
|
9
|
+
class TimeBase(SweepBase, Selector):
|
10
|
+
"""A class to capture a time snapshot of benchmark values. Time is reprented as a continous value i.e a datetime which is converted into a np.datetime64. To represent time as a discrete value use the TimeEvent class. The distinction is because holoview and plotly code makes different assumptions about discrete vs continous variables"""
|
11
|
+
|
12
|
+
__slots__ = shared_slots
|
13
|
+
|
14
|
+
def values(self, debug=False) -> List[str]:
|
15
|
+
"""return all the values for a parameter sweep. If debug is true return a reduced list"""
|
16
|
+
# print(self.sampling_str(debug))
|
17
|
+
return self.objects
|
18
|
+
|
19
|
+
|
20
|
+
class TimeSnapshot(TimeBase):
|
21
|
+
"""A class to capture a time snapshot of benchmark values. Time is reprented as a continous value i.e a datetime which is converted into a np.datetime64. To represent time as a discrete value use the TimeEvent class. The distinction is because holoview and plotly code makes different assumptions about discrete vs continous variables"""
|
22
|
+
|
23
|
+
__slots__ = shared_slots
|
24
|
+
|
25
|
+
def __init__(
|
26
|
+
self,
|
27
|
+
datetime_src: datetime | str,
|
28
|
+
units: str = "time",
|
29
|
+
samples: int = None,
|
30
|
+
samples_debug: int = 2,
|
31
|
+
**params,
|
32
|
+
):
|
33
|
+
if isinstance(datetime_src, str):
|
34
|
+
TimeBase.__init__(self, [datetime_src], instantiate=True, **params)
|
35
|
+
else:
|
36
|
+
TimeBase.__init__(
|
37
|
+
self,
|
38
|
+
objects=[Timestamp(datetime_src)],
|
39
|
+
instantiate=True,
|
40
|
+
**params,
|
41
|
+
)
|
42
|
+
self.units = units
|
43
|
+
if samples is None:
|
44
|
+
self.samples = len(self.objects)
|
45
|
+
else:
|
46
|
+
self.samples = samples
|
47
|
+
self.samples_debug = min(self.samples, samples_debug)
|
48
|
+
|
49
|
+
|
50
|
+
class TimeEvent(TimeBase):
|
51
|
+
"""A class to represent a discrete event in time where the data was captured i.e a series of pull requests. Here time is discrete and can't be interpolated, to represent time as a continous value use the TimeSnapshot class. The distinction is because holoview and plotly code makes different assumptions about discrete vs continous variables"""
|
52
|
+
|
53
|
+
__slots__ = shared_slots
|
54
|
+
|
55
|
+
def __init__(
|
56
|
+
self,
|
57
|
+
time_event: str,
|
58
|
+
units: str = "event",
|
59
|
+
samples: int = None,
|
60
|
+
samples_debug: int = 2,
|
61
|
+
**params,
|
62
|
+
):
|
63
|
+
TimeBase.__init__(
|
64
|
+
self,
|
65
|
+
objects=[time_event],
|
66
|
+
instantiate=True,
|
67
|
+
**params,
|
68
|
+
)
|
69
|
+
self.units = units
|
70
|
+
if samples is None:
|
71
|
+
self.samples = len(self.objects)
|
72
|
+
else:
|
73
|
+
self.samples = samples
|
74
|
+
self.samples_debug = min(self.samples, samples_debug)
|
bencher/video_writer.py
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
from bencher import gen_video_path, gen_image_path
|
2
|
+
from PIL import Image
|
3
|
+
import numpy as np
|
4
|
+
|
5
|
+
|
6
|
+
class VideoWriter:
|
7
|
+
def __init__(self, filename: str = "vid") -> None:
|
8
|
+
self.images = []
|
9
|
+
self.filename = gen_video_path(filename)
|
10
|
+
|
11
|
+
def append(self, img):
|
12
|
+
self.images.append(img)
|
13
|
+
|
14
|
+
def write(self, bitrate: int = 1500) -> str:
|
15
|
+
import moviepy.video.io.ImageSequenceClip
|
16
|
+
|
17
|
+
# todo
|
18
|
+
# if len(self.images[0.shape) == 2:
|
19
|
+
# for i in range(len(self.images)):
|
20
|
+
# self.images[i] = np.expand_dims(self.images[i], 2)
|
21
|
+
|
22
|
+
clip = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(self.images, fps=30)
|
23
|
+
clip.write_videofile(self.filename, bitrate=f"{bitrate}k", logger=None)
|
24
|
+
return self.filename
|
25
|
+
|
26
|
+
|
27
|
+
def add_image(np_array: np.ndarray, name: str = "img"):
|
28
|
+
filename = gen_image_path(name)
|
29
|
+
Image.fromarray(np_array).save(filename)
|
30
|
+
return filename
|
bencher/worker_job.py
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
from typing import List, Tuple, Any
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from sortedcontainers import SortedDict
|
4
|
+
from .utils import hash_sha1
|
5
|
+
from bencher.utils import hmap_canonical_input
|
6
|
+
|
7
|
+
|
8
|
+
@dataclass
|
9
|
+
class WorkerJob:
|
10
|
+
function_input_vars: List
|
11
|
+
index_tuple: Tuple[int]
|
12
|
+
dims_name: List[str]
|
13
|
+
constant_inputs: dict
|
14
|
+
bench_cfg_sample_hash: str
|
15
|
+
tag: str
|
16
|
+
|
17
|
+
function_input: SortedDict = None
|
18
|
+
canonical_input: Tuple[Any] = None
|
19
|
+
fn_inputs_sorted: List[str] = None
|
20
|
+
function_input_signature_pure: str = None
|
21
|
+
function_input_signature_benchmark_context: str = None
|
22
|
+
found_in_cache: bool = False
|
23
|
+
msgs: List[str] = field(default_factory=list)
|
24
|
+
|
25
|
+
def setup_hashes(self) -> None:
|
26
|
+
self.function_input = SortedDict(zip(self.dims_name, self.function_input_vars))
|
27
|
+
|
28
|
+
self.canonical_input = hmap_canonical_input(self.function_input)
|
29
|
+
|
30
|
+
if self.constant_inputs is not None:
|
31
|
+
self.function_input = self.function_input | self.constant_inputs
|
32
|
+
|
33
|
+
# store a tuple of the inputs as keys for a holomap
|
34
|
+
# the signature is the hash of the inputs to to the function + meta variables such as repeat and time + the hash of the benchmark sweep as a whole (without the repeats hash)
|
35
|
+
self.fn_inputs_sorted = list(SortedDict(self.function_input).items())
|
36
|
+
self.function_input_signature_pure = hash_sha1((self.fn_inputs_sorted, self.tag))
|
37
|
+
|
38
|
+
self.function_input_signature_benchmark_context = hash_sha1(
|
39
|
+
(self.function_input_signature_pure, self.bench_cfg_sample_hash)
|
40
|
+
)
|
@@ -0,0 +1,85 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: holobench
|
3
|
+
Version: 1.3.6
|
4
|
+
Summary: A package for benchmarking the performance of arbitrary functions
|
5
|
+
Author-email: Austin Gregg-Smith <blooop@gmail.com>
|
6
|
+
Description-Content-Type: text/markdown
|
7
|
+
Requires-Dist: holoviews>=1.15,<=1.18.1
|
8
|
+
Requires-Dist: numpy>=1.0,<=1.26.2
|
9
|
+
Requires-Dist: param>=1.13.0,<=2.0.1
|
10
|
+
Requires-Dist: hvplot>=0.8,<=0.9.1
|
11
|
+
Requires-Dist: matplotlib>=3.6.3,<=3.8.2
|
12
|
+
Requires-Dist: panel>=1.3.6,<=1.3.6
|
13
|
+
Requires-Dist: diskcache>=5.6,<=5.6.3
|
14
|
+
Requires-Dist: optuna>=3.2,<=3.5.0
|
15
|
+
Requires-Dist: xarray>=2023.7,<=2023.12.0
|
16
|
+
Requires-Dist: plotly>=5.15,<=5.18.0
|
17
|
+
Requires-Dist: sortedcontainers>=2.4,<=2.4
|
18
|
+
Requires-Dist: pandas>=2.0,<=2.1.4
|
19
|
+
Requires-Dist: strenum>=0.4.0,<=0.4.15
|
20
|
+
Requires-Dist: scikit-learn>=1.2,<=1.3.2
|
21
|
+
Requires-Dist: str2bool>=1.1,<=1.1
|
22
|
+
Requires-Dist: scoop>=0.7.0,<=0.7.2.0
|
23
|
+
Requires-Dist: moviepy>=1.0.3,<=1.0.3
|
24
|
+
Requires-Dist: black>=23,<=23.12.1 ; extra == "test"
|
25
|
+
Requires-Dist: pylint>=2.16,<=3.0.3 ; extra == "test"
|
26
|
+
Requires-Dist: pytest-cov>=4.1,<=4.1 ; extra == "test"
|
27
|
+
Requires-Dist: pytest>=7.4,<=7.4.4 ; extra == "test"
|
28
|
+
Requires-Dist: hypothesis>=6.82,<=6.92.2 ; extra == "test"
|
29
|
+
Requires-Dist: ruff>=0.0.280,<=0.1.9 ; extra == "test"
|
30
|
+
Requires-Dist: coverage>=7.2.7,<=7.4.0 ; extra == "test"
|
31
|
+
Project-URL: Documentation, https://bencher.readthedocs.io/en/latest/
|
32
|
+
Project-URL: Home, https://github.com/dyson-ai/bencher
|
33
|
+
Project-URL: Repository, https://github.com/dyson-ai/bencher
|
34
|
+
Provides-Extra: test
|
35
|
+
|
36
|
+
# Bencher
|
37
|
+
|
38
|
+
## Continuous Integration Status
|
39
|
+
|
40
|
+
[](https://github.com/dyson-ai/bencher/actions/workflows/ci.yml?query=branch%3Amain)
|
41
|
+

|
42
|
+
[](https://codecov.io/gh/dyson-ai/bencher)
|
43
|
+
[](https://GitHub.com/dyson-ai/bencher/issues/)
|
44
|
+
[](https://github.com/dyson-ai/bencher/pulls?q=is%3Amerged)
|
45
|
+
[](https://pypi.org/project/holobench/)
|
46
|
+
[](https://GitHub.com/dyson-ai/bencher/releases/)
|
47
|
+
[](https://opensource.org/license/mit/)
|
48
|
+
[](https://www.python.org/downloads/release/python-310/)
|
49
|
+
|
50
|
+
|
51
|
+
## Intro
|
52
|
+
|
53
|
+
Bencher is a tool to make it easy to benchmark the interactions between the input parameters to your algorithm and its resulting performance on a set of metrics.
|
54
|
+
|
55
|
+
Parameters for bencher are defined using the param library https://param.holoviz.org/ as a config class with extra metadata that describes the bounds of the search space you want to measure. You must define a benchmarking function that accepts an instance of the config class and return a dictionary with string metric names and float values.
|
56
|
+
|
57
|
+
Parameters are benchmarked by passing in a list N parameters, and an N-Dimensional tensor is returned. You can optionally sample each point multiple times to get back a distribution and also track its value over time. By default the data will be plotted automatically based on the types of parameters you are sampling (e.g, continous, discrete), but you can also pass in a callback to customize plotting.
|
58
|
+
|
59
|
+
The data is stored in a persistent database so that past performance is tracked.
|
60
|
+
|
61
|
+
## Assumptions
|
62
|
+
|
63
|
+
The input types should also be of one of the basic datatypes (bool, int, float, str, enum, datetime) so that the data can be easily hashed, cached and stored in the database and processed with seaborn and xarray plotting functions. You can use class inheritance to define hierarchical parameter configuration class types that can be reused in a bigger configuration classes.
|
64
|
+
|
65
|
+
Bencher is designed to work with stochastic pure functions with no side effects. It assumes that when the objective function is given the same inputs, it will return the same output +- random noise. This is because the function must be called multiple times to get a good statistical distribution of it and so each call must not be influenced by anything or the results will be corrupted.
|
66
|
+
|
67
|
+
### Pseudocode of bencher
|
68
|
+
|
69
|
+
Enumerate a list of all input parameter combinations
|
70
|
+
for each set of input parameters:
|
71
|
+
pass the inputs to the objective function and store results in the N-D array
|
72
|
+
|
73
|
+
get unique hash for the set of inputs parameters
|
74
|
+
look up previous results for that hash
|
75
|
+
if it exists:
|
76
|
+
load historical data
|
77
|
+
combine latest data with historical data
|
78
|
+
|
79
|
+
store the results using the input hash as a key
|
80
|
+
deduce the type of plot based on the input types
|
81
|
+
return data and plot
|
82
|
+
|
83
|
+
### Example Output
|
84
|
+
|
85
|
+
https://dyson-ai.github.io/bencher/
|
@@ -0,0 +1,74 @@
|
|
1
|
+
bencher/__init__.py,sha256=lw9moEkY3rb3kQVS3_SM9L0LsOAXRSM1JUJ_mm16tMQ,1236
|
2
|
+
bencher/bench_cfg.py,sha256=0dIF_JrvWYiugNDi28wh_8a8ejm99cnw3RrlMIDI2Ww,18714
|
3
|
+
bencher/bench_plot_server.py,sha256=HnW6XpmARweMCd-koqzu1lxuj0gA4_fP-72D3Yfy-0M,4087
|
4
|
+
bencher/bench_report.py,sha256=b9jLksrXzBhSmvI7KetO1i0hsHknE7qk4b4k0MGGtNw,10484
|
5
|
+
bencher/bench_runner.py,sha256=TLJGn-NO4BBBZMG8W5E6u7IPyij67Yk3S4B29ONClnk,6049
|
6
|
+
bencher/bencher.py,sha256=jYOkqs5F6vIL9_KLygVgi0O_vj-xspBVlipduNMtt1Y,32012
|
7
|
+
bencher/caching.py,sha256=AusaNrzGGlj5m6zcwcqnTn55Mam2mQdF--oqelO806M,1627
|
8
|
+
bencher/job.py,sha256=Q2zpia95Ibukk8EeFq5IBbpo2PMRe7o5keelJCJlGnI,5927
|
9
|
+
bencher/optuna_conversions.py,sha256=9nLVPAydSQ8PyJlyhzs__Em6_Rx8l8Ld94UNJZxy6cY,5303
|
10
|
+
bencher/utils.py,sha256=oKUtD3Uw76n82ZeyWRBleneYKrZuuNE8pb7Gswlhwjc,5034
|
11
|
+
bencher/video_writer.py,sha256=L_RVrHU4C6hj9BhbEPelgPgtGZeHH4PYYW4CHjGXgJ0,937
|
12
|
+
bencher/worker_job.py,sha256=FREi0yWQACFmH86R1j-LH72tALEFkKhLDmmoGQY9Jh4,1571
|
13
|
+
bencher/example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
+
bencher/example/benchmark_data.py,sha256=D9yUg_KKtqqEkAiLceodDwsv6sh7xEFWZNp6P6Y3pj4,6989
|
15
|
+
bencher/example/example_all.py,sha256=iiKV2poYWu4SUIQkpoX4qT1zTm574QfuNHpYww3meFA,1952
|
16
|
+
bencher/example/example_categorical.py,sha256=3BeOQN58nCGx6xzB0YvkgaBFInzJ5L3XsIYKfKOs0gM,3684
|
17
|
+
bencher/example/example_custom_sweep.py,sha256=-y8mYuXYD91j8kcCEe9c6Gx6g1dK-bvHM9sbXqHL2gA,1916
|
18
|
+
bencher/example/example_docs.py,sha256=aUi33O543JBPoOGlpHaY2eA74GR7cHH_6-hcC8xf3z0,1174
|
19
|
+
bencher/example/example_float3D.py,sha256=pwi3YlDad3NL4IrfMK2V5yV1CRpqfmUO-zUnGmVYxDs,3425
|
20
|
+
bencher/example/example_float_cat.py,sha256=RZiKEACZyGDnubxhaUcabI43AYvm3h7qt0SCUp5Yuso,3810
|
21
|
+
bencher/example/example_floats.py,sha256=HcQgfwldTVeFBmBTMtZ0yRy17ZJ4cfJeI_t8TxY2iOI,4269
|
22
|
+
bencher/example/example_floats2D.py,sha256=D0kljoUCinMKCEW-Zg-cQ8sYu_yPCZqzKJ9tRtt-Ono,3697
|
23
|
+
bencher/example/example_holosweep.py,sha256=d9g5aWCAUb7FMZahb4t3xNs344EshPhA-8-K6K1SBXg,3180
|
24
|
+
bencher/example/example_holosweep_objects.py,sha256=vHuAtkM1VrJelHOazn_SJfzxNywKyaMzN-DE8W7Ricc,3228
|
25
|
+
bencher/example/example_holosweep_tap.py,sha256=3ayQ0bTj_XWP_92ifQJAhe1whwPAj_xWHPkzC7fvqAY,4540
|
26
|
+
bencher/example/example_image.py,sha256=DBB7oe-67XoxPBPhUJNSr45U8t8xJvi9KiC3ptZkAHE,2713
|
27
|
+
bencher/example/example_levels.py,sha256=rpSNB571yfMnT7iO66Ds-DPGHWzOTM9FLMNfSetJdHY,6896
|
28
|
+
bencher/example/example_pareto.py,sha256=yyAg8Vb-5sgsS6LkYKT7T5Evcfg69FlCqCakUippSmU,2687
|
29
|
+
bencher/example/example_sample_cache.py,sha256=7gf1BJ63VAgdqNuNXkbL9-jeTeC3kXA_PY9yG3ulTz0,4200
|
30
|
+
bencher/example/example_sample_cache_context.py,sha256=IAUBbL78QM20R8evaq7L8I-xPxFDFykF1Gk1y2Ru1W0,4063
|
31
|
+
bencher/example/example_simple.py,sha256=Nn2ixNx29jbgvwH2K5vDGhSFcqKLMNaP1occPxhHoU0,11703
|
32
|
+
bencher/example/example_simple_bool.py,sha256=36KMSHyXZhzS1cp2TZnDLn7-GpShLdQ7mycuT0M3le8,1247
|
33
|
+
bencher/example/example_simple_cat.py,sha256=YFccE84g37U2M3ByWYIcGNLXWdW_ktJbbZvGL0D6oHA,1759
|
34
|
+
bencher/example/example_simple_float.py,sha256=X4vsH0F4fZAoO0EKB1xIzFMY0f0Wyk8LV2plPlSEsbI,1323
|
35
|
+
bencher/example/example_strings.py,sha256=BdsEZgLT9mOxLkBKNHz2XpPwwe4SzNTdjnY1WVlOmNM,1570
|
36
|
+
bencher/example/example_time_event.py,sha256=y1vpK7UDrObEu0Z1x3e4OQzvGCQ7pF5GZvpKLegMbYk,2158
|
37
|
+
bencher/example/example_video.py,sha256=w2NtsDL-afZWGlScrrHxr9vdCrxTvyzqOUhIeDOHjvU,4079
|
38
|
+
bencher/example/example_workflow.py,sha256=00QnUuViMfX_PqzqkXmg1wPX6yAq7IS7mCL_RFKwrMM,6806
|
39
|
+
bencher/example/experimental/example_bokeh_plotly.py,sha256=3jUKh8eKIAlpklKnp8UopIHhUDw1A0_5CwjeyTzbi7o,846
|
40
|
+
bencher/example/experimental/example_hover_ex.py,sha256=qszw4FkIfqQkVviPSpmUoFOoi6PGotGbsc7Ojyx8EtU,1052
|
41
|
+
bencher/example/experimental/example_hvplot_explorer.py,sha256=B9u-kh6D_8J0wAtkYu2w8kML8eL3DkOZg0p91n_nBT4,1815
|
42
|
+
bencher/example/experimental/example_interactive.py,sha256=MM1A2EVsKTy95RERTNnld0tUmZmCy8N41_jGm2wlG7U,2619
|
43
|
+
bencher/example/experimental/example_streamnd.py,sha256=LqkTtdY4NhnP5dEB1Ifv7RQ5Vq4dLkp5E3aWnWuzniA,1414
|
44
|
+
bencher/example/experimental/example_streams.py,sha256=rrTmcmxDlirGoyTbJ4LT4fBIAc1k28qjnjy5JxGKyhg,1030
|
45
|
+
bencher/example/experimental/example_template.py,sha256=XdIVS9RtLdE5GNnerWiZMXvP7n17lzuc_YTLqJTwb6Q,1172
|
46
|
+
bencher/example/experimental/example_updates.py,sha256=rF4UgWY-CW6ohNtOpQklTuwbwVRvEM5j6edZOiMkspQ,1835
|
47
|
+
bencher/example/experimental/example_vector.py,sha256=3o_1dA4dc2HL6uIEvDAcvLPVJB8jgkq1QZ3BQIL-LEo,3118
|
48
|
+
bencher/example/meta/example_meta.py,sha256=P71Q-3G8B44DYaZQe5eFmFxUsjbViSat3DcUvgdSSuw,5605
|
49
|
+
bencher/example/meta/example_meta_cat.py,sha256=YKVUiZ7M1tFFYgUTVQZeOe-1bnmxOjLdWy3nmCoyEe0,693
|
50
|
+
bencher/example/meta/example_meta_float.py,sha256=f3OcORsRUt9Bnd1M1hOjmgxulxcalwdQHSQ0Psx1rY8,650
|
51
|
+
bencher/example/meta/example_meta_levels.py,sha256=O77D4gAGYf7uZo7-Kj2ZwyNmpnc4paoQXE_DQtKKWKo,1488
|
52
|
+
bencher/example/optuna/example_optuna.py,sha256=-RIuDrdPjfXz1c1hOAmWeJNdmGICiWnyJfAavRsiMuk,2370
|
53
|
+
bencher/example/shelved/example_float2D_scatter.py,sha256=z8ranMq8IcJ1yoVSFDncp3gw-yWG7X9lXLimXKpy5Ks,3372
|
54
|
+
bencher/example/shelved/example_float3D_cone.py,sha256=T3-IapccLYX3BM9sGDyOTLhZVEmzkeMsXzQMT5msnNQ,2966
|
55
|
+
bencher/example/shelved/example_kwargs.py,sha256=Bgxkd7qeHdySBE24amdP-VNFRRgK_enyzprlxBwY9Ko,2461
|
56
|
+
bencher/plotting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
57
|
+
bencher/plotting/plot_filter.py,sha256=Zff02hEcRffiqDEoXUHVZQJK5kW4HbMxe2GYCrxI8jg,4688
|
58
|
+
bencher/plotting/plt_cnt_cfg.py,sha256=BkiAsgHm35Mqb5OsjULGVK0Q6pGZ0WSsJxxwSOrbaQs,3124
|
59
|
+
bencher/results/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
60
|
+
bencher/results/bench_result.py,sha256=NiJ8UIYrw5QBksltIHAOh-4CaIMYI8YA-cEcWgfwZ70,2838
|
61
|
+
bencher/results/bench_result_base.py,sha256=-c46om4Gulzxn3PPvQAsQF9qzT7rQLtX6hsO65f9N2A,15767
|
62
|
+
bencher/results/float_formatter.py,sha256=sX6HNCyaXdHDxC8ybVUHwCJ3qOKbPUkBOplVIHtKWjM,1746
|
63
|
+
bencher/results/holoview_result.py,sha256=nfXYTaGQkXwLqJ_gEB3TYJxHfKAQCN1E60D9Tfbkxos,22254
|
64
|
+
bencher/results/optuna_result.py,sha256=jtsWJGdCS0L98EzxTxXU_AyarCL5CkXRLOVuSvs048M,13437
|
65
|
+
bencher/results/panel_result.py,sha256=SpVHHdTdlNHh1pGcK3DYLw6BClDRJ_37TNTkicnErTU,3936
|
66
|
+
bencher/results/plotly_result.py,sha256=wkgfL38qJp6RviekXBYpNPeU4HCf0nbtKDAhu5QZhUg,2132
|
67
|
+
bencher/variables/inputs.py,sha256=XtUko3qNYB1xk7fwM9teVGRU0MNCW673n2teGtoyFGU,6393
|
68
|
+
bencher/variables/parametrised_sweep.py,sha256=3ioxqm8xg9WYIH-eRFRhDSn_YphGD-269gZ_FaxuEv8,7029
|
69
|
+
bencher/variables/results.py,sha256=omENIr_Y3RxRG8sr4RQKD1Y_vTyMJUoA7P-fV1uSX5Y,6015
|
70
|
+
bencher/variables/sweep_base.py,sha256=I1LEeG1y5Jsw0a-Ik03t0tSzcfENht2GmBECJ3KNs28,6559
|
71
|
+
bencher/variables/time.py,sha256=Le7s8_oUYJD4wCqwQw-a_FRDpYQOi8CqMbGYsBF07jg,2860
|
72
|
+
holobench-1.3.6.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
|
73
|
+
holobench-1.3.6.dist-info/METADATA,sha256=LyfizZKUZi92A3pYWd_faXDRH-fpfDsNyv_4NThnHWo,4996
|
74
|
+
holobench-1.3.6.dist-info/RECORD,,
|