Skip to content

Commit 8794ce2

Browse files
committed
Separated visualization from reporting
1 parent acbfce6 commit 8794ce2

File tree

2 files changed

+229
-148
lines changed

2 files changed

+229
-148
lines changed
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
"""Report results of the experiment without requiring visualization."""
2+
3+
from pathlib import Path
4+
5+
import numpy as np
6+
7+
from autotuning_methodology.baseline import (
8+
Baseline,
9+
ExecutedStrategyBaseline,
10+
RandomSearchCalculatedBaseline,
11+
)
12+
from autotuning_methodology.curves import Curve, StochasticOptimizationAlgorithm
13+
from autotuning_methodology.searchspace_statistics import SearchspaceStatistics
14+
15+
16+
def get_aggregation_data_key(gpu_name: str, kernel_name: str):
17+
"""Utility function to get the key for data in the aggregation data dictionary.
18+
19+
Args:
20+
gpu_name: the GPU name
21+
kernel_name: the kernel name
22+
23+
Returns:
24+
The key as a string.
25+
"""
26+
return f"{gpu_name}+{kernel_name}"
27+
28+
29+
def get_aggregation_data(
30+
experiment_folderpath: Path,
31+
experiment: dict,
32+
strategies: dict,
33+
results_descriptions: dict,
34+
cutoff_percentile: float,
35+
cutoff_percentile_start=0.01,
36+
confidence_level=0.95,
37+
minimization: bool = True,
38+
time_resolution: int = 1e4,
39+
use_strategy_as_baseline=None,
40+
):
41+
"""Function to collect the aggregation data after the experiments have ran.
42+
43+
Args:
44+
experiment_folderpath: _description_
45+
experiment: _description_
46+
strategies: _description_
47+
results_descriptions: _description_
48+
cutoff_percentile: _description_
49+
minimization: _description_. Defaults to True.
50+
cutoff_percentile_start: _description_. Defaults to 0.01.
51+
confidence_level: _description_. Defaults to 0.95.
52+
time_resolution: _description_. Defaults to 1e4.
53+
use_strategy_as_baseline: _description_. Defaults to None.
54+
55+
Returns:
56+
The aggregation data in a dictionary, with `get_aggregation_data_key` as key and a tuple as value.
57+
"""
58+
if int(time_resolution) != time_resolution:
59+
raise ValueError(f"The resolution must be an integer, yet is {time_resolution}.")
60+
time_resolution = int(time_resolution)
61+
62+
aggregation_data: dict[str, tuple[Baseline, list[Curve], SearchspaceStatistics, np.ndarray]] = dict()
63+
for gpu_name in experiment["GPUs"]:
64+
for kernel_name in experiment["kernels"]:
65+
# get the statistics
66+
searchspace_stats = SearchspaceStatistics(
67+
kernel_name=kernel_name,
68+
device_name=gpu_name,
69+
minimization=minimization,
70+
objective_time_keys=experiment["objective_time_keys"],
71+
objective_performance_keys=experiment["objective_performance_keys"],
72+
bruteforced_caches_path=experiment_folderpath / experiment["bruteforced_caches_path"],
73+
)
74+
75+
# get the cached strategy results as curves
76+
strategies_curves: list[Curve] = list()
77+
baseline_executed_strategy = None
78+
for strategy in strategies:
79+
results_description = results_descriptions[gpu_name][kernel_name][strategy["name"]]
80+
if results_description is None:
81+
raise ValueError(
82+
f"""Strategy {strategy['display_name']} not in results_description,
83+
make sure execute_experiment() has ran first"""
84+
)
85+
curve = StochasticOptimizationAlgorithm(results_description)
86+
strategies_curves.append(curve)
87+
if use_strategy_as_baseline is not None and strategy["name"] == use_strategy_as_baseline:
88+
baseline_executed_strategy = curve
89+
if use_strategy_as_baseline is not None and baseline_executed_strategy is None:
90+
raise ValueError(f"Could not find '{use_strategy_as_baseline}' in executed strategies")
91+
92+
# set the x-axis range
93+
_, cutoff_point_fevals, cutoff_point_time = searchspace_stats.cutoff_point_fevals_time(cutoff_percentile)
94+
_, cutoff_point_fevals_start, cutoff_point_time_start = searchspace_stats.cutoff_point_fevals_time(
95+
cutoff_percentile_start
96+
)
97+
fevals_range = np.arange(start=cutoff_point_fevals_start, stop=cutoff_point_fevals)
98+
time_range = np.linspace(start=cutoff_point_time_start, stop=cutoff_point_time, num=time_resolution)
99+
100+
# get the random baseline
101+
random_baseline = (
102+
RandomSearchCalculatedBaseline(searchspace_stats)
103+
if baseline_executed_strategy is None
104+
else ExecutedStrategyBaseline(
105+
searchspace_stats, strategy=baseline_executed_strategy, confidence_level=confidence_level
106+
)
107+
)
108+
109+
# collect aggregatable data
110+
aggregation_data[get_aggregation_data_key(gpu_name, kernel_name)] = tuple(
111+
[random_baseline, strategies_curves, searchspace_stats, time_range, fevals_range]
112+
)
113+
114+
return aggregation_data
115+
116+
117+
def get_strategies_aggregated_performance(
118+
aggregation_data: list[tuple[Baseline, list[Curve], SearchspaceStatistics, np.ndarray]],
119+
confidence_level: float,
120+
) -> tuple[list[np.ndarray], list[np.ndarray], list[np.ndarray], list[int]]:
121+
"""Combines the performances across searchspaces into a single metric.
122+
123+
Args:
124+
aggregation_data: the aggregated data from the various searchspaces.
125+
confidence_level: the confidence interval used for the confidence / prediction interval.
126+
127+
Returns:
128+
The aggregated relative performances of each strategy.
129+
Tuple of [performance, lower error, upper error, stopping point fraction].
130+
"""
131+
# for each strategy, collect the relative performance in each search space
132+
strategies_performance = [list() for _ in aggregation_data[0][1]]
133+
strategies_performance_lower_err = [list() for _ in aggregation_data[0][1]]
134+
strategies_performance_upper_err = [list() for _ in aggregation_data[0][1]]
135+
strategies_performance_real_stopping_point_fraction = [list() for _ in range(len(aggregation_data[0][1]))]
136+
for random_baseline, strategies_curves, searchspace_stats, time_range in aggregation_data:
137+
dist = searchspace_stats.objective_performances_total_sorted
138+
for strategy_index, strategy_curve in enumerate(strategies_curves):
139+
# get the real and fictional performance curves
140+
(
141+
real_stopping_point_index,
142+
x_axis_range_real,
143+
curve_real,
144+
curve_lower_err_real,
145+
curve_upper_err_real,
146+
x_axis_range_fictional,
147+
curve_fictional,
148+
curve_lower_err_fictional,
149+
curve_upper_err_fictional,
150+
) = strategy_curve.get_curve_over_time(time_range, dist=dist, confidence_level=confidence_level)
151+
# combine the real and fictional parts to get the full curve
152+
combine = x_axis_range_fictional.ndim > 0
153+
x_axis_range = np.concatenate([x_axis_range_real, x_axis_range_fictional]) if combine else x_axis_range_real
154+
assert np.array_equal(time_range, x_axis_range, equal_nan=True), "time_range != x_axis_range"
155+
curve = np.concatenate([curve_real, curve_fictional]) if combine else curve_real
156+
curve_lower_err = (
157+
np.concatenate([curve_lower_err_real, curve_lower_err_fictional]) if combine else curve_lower_err_real
158+
)
159+
curve_upper_err = (
160+
np.concatenate([curve_upper_err_real, curve_upper_err_fictional]) if combine else curve_upper_err_real
161+
)
162+
# get the standardised curves and write them to the collector
163+
curve, curve_lower_err, curve_upper_err = random_baseline.get_standardised_curves(
164+
time_range, [curve, curve_lower_err, curve_upper_err], x_type="time"
165+
)
166+
strategies_performance[strategy_index].append(curve)
167+
strategies_performance_lower_err[strategy_index].append(curve_lower_err)
168+
strategies_performance_upper_err[strategy_index].append(curve_upper_err)
169+
strategies_performance_real_stopping_point_fraction[strategy_index].append(
170+
real_stopping_point_index / x_axis_range.shape[0]
171+
)
172+
173+
# for each strategy, get the mean performance per step in time_range
174+
strategies_aggregated_performance: list[np.ndarray] = list()
175+
strategies_aggregated_lower_err: list[np.ndarray] = list()
176+
strategies_aggregated_upper_err: list[np.ndarray] = list()
177+
strategies_aggregated_real_stopping_point_fraction: list[float] = list()
178+
for index, value in enumerate(strategies_performance):
179+
strategies_aggregated_performance.append(np.mean(np.array(value), axis=0))
180+
strategies_aggregated_lower_err.append(np.mean(np.array(strategies_performance_lower_err[index]), axis=0))
181+
strategies_aggregated_upper_err.append(np.mean(np.array(strategies_performance_upper_err[index]), axis=0))
182+
strategies_aggregated_real_stopping_point_fraction.append(
183+
np.median(strategies_performance_real_stopping_point_fraction[index])
184+
)
185+
186+
return (
187+
strategies_aggregated_performance,
188+
strategies_aggregated_lower_err,
189+
strategies_aggregated_upper_err,
190+
strategies_aggregated_real_stopping_point_fraction,
191+
)

0 commit comments

Comments
 (0)