Skip to content

Commit 18fff93

Browse files
committed
Merge branch 'unify-benchmark-ci' of https://github.com/intel/llvm into unify-benchmark-ci
2 parents 68ed0c4 + ad13e93 commit 18fff93

File tree

12 files changed

+169
-86
lines changed

12 files changed

+169
-86
lines changed

devops/scripts/benchmarks/benches/compute.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ def run(self, env_vars) -> list[Result]:
170170
env=env_vars,
171171
stdout=result,
172172
unit=parse_unit_type(unit),
173-
description=self.description()
173+
description=self.description(),
174174
)
175175
)
176176
return ret

devops/scripts/benchmarks/benches/llamacpp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ def run(self, env_vars) -> list[Result]:
139139
env=env_vars,
140140
stdout=result,
141141
unit="token/s",
142-
description=self.description()
142+
description=self.description(),
143143
)
144144
)
145145
return results

devops/scripts/benchmarks/benches/syclbench.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ def __init__(self, bench, name, test):
105105
self.bench = bench
106106
self.bench_name = name
107107
self.test = test
108-
self.done = False
109108

110109
def bin_args(self) -> list[str]:
111110
return []
@@ -119,8 +118,6 @@ def setup(self):
119118
)
120119

121120
def run(self, env_vars) -> list[Result]:
122-
if self.done:
123-
return
124121
self.outputfile = os.path.join(self.bench.directory, self.test + ".csv")
125122

126123
command = [
@@ -152,17 +149,17 @@ def run(self, env_vars) -> list[Result]:
152149
unit="ms",
153150
)
154151
)
155-
self.done = True
156-
return res_list
157152

158-
def teardown(self):
159-
print(f"Removing {self.outputfile}...")
160153
os.remove(self.outputfile)
161-
return
154+
155+
return res_list
162156

163157
def name(self):
164158
return f"{self.bench.name()} {self.test}"
165159

160+
def teardown(self):
161+
return
162+
166163

167164
# multi benchmarks
168165
class Blocked_transform(SyclBenchmark):

devops/scripts/benchmarks/benches/velocity.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def run(self, env_vars) -> list[Result]:
136136
env=env_vars,
137137
stdout=result,
138138
unit=self.unit,
139-
description=self.description()
139+
description=self.description(),
140140
)
141141
]
142142

devops/scripts/benchmarks/history.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,12 @@ def extract_index(file_path: Path) -> int:
6161

6262
def create_run(self, name: str, results: list[Result]) -> BenchmarkRun:
6363
try:
64-
result = run("git rev-parse --short HEAD")
64+
script_dir = os.path.dirname(os.path.abspath(__file__))
65+
result = run("git rev-parse --short HEAD", cwd=script_dir)
6566
git_hash = result.stdout.decode().strip()
6667

6768
# Get the GitHub repo URL from git remote
68-
remote_result = run("git remote get-url origin")
69+
remote_result = run("git remote get-url origin", cwd=script_dir)
6970
remote_url = remote_result.stdout.decode().strip()
7071

7172
# Convert SSH or HTTPS URL to owner/repo format
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,2 @@
1-
const config = {
2-
remoteDataUrl: ''
3-
};
4-
// defaultCompareNames = [];
5-
// suiteNames = [];
1+
//remoteDataUrl = 'https://example.com/data.json';
2+
//defaultCompareNames = ['baseline'];

devops/scripts/benchmarks/html/scripts.js

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -114,14 +114,12 @@ function createChart(data, containerId, type) {
114114

115115
const chartConfig = {
116116
type: type === 'time' ? 'line' : 'bar',
117-
data: type === 'time' ?
118-
{
119-
datasets: createTimeseriesDatasets(data)
120-
} :
121-
{
122-
labels: data.labels,
123-
datasets: data.datasets
124-
},
117+
data: type === 'time' ? {
118+
datasets: createTimeseriesDatasets(data)
119+
} : {
120+
labels: data.labels,
121+
datasets: data.datasets
122+
},
125123
options: options
126124
};
127125

@@ -221,10 +219,12 @@ function createChartContainer(data, canvasId) {
221219
summary.appendChild(downloadButton);
222220
details.appendChild(summary);
223221

222+
latestRunsLookup = createLatestRunsLookup(benchmarkRuns);
223+
224224
// Create and append extra info
225225
const extraInfo = document.createElement('div');
226226
extraInfo.className = 'extra-info';
227-
extraInfo.innerHTML = generateExtraInfo(data);
227+
extraInfo.innerHTML = generateExtraInfo(latestRunsLookup, data);
228228
details.appendChild(extraInfo);
229229

230230
container.appendChild(details);
@@ -252,9 +252,8 @@ function createLatestRunsLookup(benchmarkRuns) {
252252

253253
return latestRunsMap;
254254
}
255-
const latestRunsLookup = createLatestRunsLookup(benchmarkRuns);
256255

257-
function generateExtraInfo(data) {
256+
function generateExtraInfo(latestRunsLookup, data) {
258257
const labels = data.datasets ? data.datasets.map(dataset => dataset.label) : [data.label];
259258

260259
return labels.map(label => {
@@ -283,7 +282,7 @@ function downloadChart(canvasId, label) {
283282
const chart = chartInstances.get(canvasId);
284283
if (chart) {
285284
const link = document.createElement('a');
286-
link.href = chart.toBase64Image('image/jpeg', 1)
285+
link.href = chart.toBase64Image('image/png', 1)
287286
link.download = `${label}.png`;
288287
link.click();
289288
}
@@ -445,6 +444,13 @@ function setupRunSelector() {
445444
function setupSuiteFilters() {
446445
suiteFiltersContainer = document.getElementById('suite-filters');
447446

447+
const suiteNames = new Set();
448+
benchmarkRuns.forEach(run => {
449+
run.results.forEach(result => {
450+
suiteNames.add(result.suite);
451+
});
452+
});
453+
448454
suiteNames.forEach(suite => {
449455
const label = document.createElement('label');
450456
const checkbox = document.createElement('input');
@@ -530,16 +536,18 @@ function loadData() {
530536
const loadingIndicator = document.getElementById('loading-indicator');
531537
loadingIndicator.style.display = 'block'; // Show loading indicator
532538

533-
if (config.remoteDataUrl && config.remoteDataUrl !== '') {
539+
if (typeof remoteDataUrl !== 'undefined' && remoteDataUrl !== '') {
534540
// Fetch data from remote URL
535-
fetch(config.remoteDataUrl)
536-
.then(response => response.text())
537-
.then(scriptContent => {
538-
// Evaluate the script content
539-
eval(scriptContent);
541+
fetch(remoteDataUrl)
542+
.then(response => response.json())
543+
.then(data => {
544+
benchmarkRuns = data;
540545
initializeCharts();
541546
})
542-
.catch(error => console.error('Error fetching remote data:', error))
547+
.catch(error => {
548+
console.error('Error fetching remote data:', error);
549+
loadingIndicator.textContent = 'Fetching remote data failed.';
550+
})
543551
.finally(() => {
544552
loadingIndicator.style.display = 'none'; // Hide loading indicator
545553
});

devops/scripts/benchmarks/main.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from history import BenchmarkHistory
1818
from utils.utils import prepare_workdir
1919
from utils.compute_runtime import *
20+
from presets import preset_get_by_name, presets
2021

2122
import argparse
2223
import re
@@ -153,7 +154,7 @@ def main(directory, additional_env_vars, save_name, compare_names, filter):
153154
SyclBench(directory),
154155
LlamaCppBench(directory),
155156
UMFSuite(directory),
156-
# TestSuite()
157+
TestSuite(),
157158
]
158159
if not options.dry_run
159160
else []
@@ -163,6 +164,9 @@ def main(directory, additional_env_vars, save_name, compare_names, filter):
163164
failures = {}
164165

165166
for s in suites:
167+
if s.name() not in options.preset.suites():
168+
continue
169+
166170
suite_benchmarks = s.benchmarks()
167171
if filter:
168172
suite_benchmarks = [
@@ -182,14 +186,13 @@ def main(directory, additional_env_vars, save_name, compare_names, filter):
182186
print(f"{type(s).__name__} setup complete.")
183187
benchmarks += suite_benchmarks
184188

185-
for b in benchmarks:
186-
print(b.name())
187-
188189
for benchmark in benchmarks:
189190
try:
190-
print(f"Setting up {benchmark.name()}... ")
191+
if options.verbose:
192+
print(f"Setting up {benchmark.name()}... ")
191193
benchmark.setup()
192-
print(f"{benchmark.name()} setup complete.")
194+
if options.verbose:
195+
print(f"{benchmark.name()} setup complete.")
193196

194197
except Exception as e:
195198
if options.exit_on_failure:
@@ -279,8 +282,6 @@ def main(directory, additional_env_vars, save_name, compare_names, filter):
279282
if options.output_html:
280283
generate_html(history.runs, compare_names)
281284

282-
print(f"See {os.getcwd()}/html/index.html for the results.")
283-
284285

285286
def validate_and_parse_env_args(env_args):
286287
env_vars = {}
@@ -362,12 +363,6 @@ def validate_and_parse_env_args(env_args):
362363
help="Regex pattern to filter benchmarks by name.",
363364
default=None,
364365
)
365-
parser.add_argument(
366-
"--epsilon",
367-
type=float,
368-
help="Threshold to consider change of performance significant",
369-
default=options.epsilon,
370-
)
371366
parser.add_argument(
372367
"--verbose", help="Print output of all the commands.", action="store_true"
373368
)
@@ -394,7 +389,11 @@ def validate_and_parse_env_args(env_args):
394389
help="Specify whether markdown output should fit the content size limit for request validation",
395390
)
396391
parser.add_argument(
397-
"--output-html", help="Create HTML output", action="store_true", default=False
392+
"--output-html",
393+
help="Create HTML output. Local output is for direct local viewing of the html file, remote is for server deployment.",
394+
nargs="?",
395+
const=options.output_html,
396+
choices=["local", "remote"],
398397
)
399398
parser.add_argument(
400399
"--dry-run",
@@ -438,6 +437,13 @@ def validate_and_parse_env_args(env_args):
438437
help="Directory for cublas library",
439438
default=None,
440439
)
440+
parser.add_argument(
441+
"--preset",
442+
type=str,
443+
choices=[p.name() for p in presets],
444+
help="Benchmark preset to run.",
445+
default=options.preset.name(),
446+
)
441447

442448
args = parser.parse_args()
443449
additional_env_vars = validate_and_parse_env_args(args.env)
@@ -449,7 +455,6 @@ def validate_and_parse_env_args(env_args):
449455
options.sycl = args.sycl
450456
options.iterations = args.iterations
451457
options.timeout = args.timeout
452-
options.epsilon = args.epsilon
453458
options.ur = args.ur
454459
options.ur_adapter = args.adapter
455460
options.exit_on_failure = args.exit_on_failure
@@ -464,6 +469,7 @@ def validate_and_parse_env_args(env_args):
464469
options.current_run_name = args.relative_perf
465470
options.cudnn_directory = args.cudnn_directory
466471
options.cublas_directory = args.cublas_directory
472+
options.preset = preset_get_by_name(args.preset)
467473

468474
if args.build_igc and args.compute_runtime is None:
469475
parser.error("--build-igc requires --compute-runtime to be set")

devops/scripts/benchmarks/options.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from dataclasses import dataclass, field
22
from enum import Enum
3+
from presets import Preset, presets
34

45

56
class Compare(Enum):
@@ -29,18 +30,17 @@ class Options:
2930
compare: Compare = Compare.LATEST
3031
compare_max: int = 10 # average/median over how many results
3132
output_markdown: MarkdownSize = MarkdownSize.SHORT
32-
output_html: bool = False
33+
output_html: str = "local"
3334
dry_run: bool = False
34-
# these two should probably be merged into one setting
3535
stddev_threshold: float = 0.02
36-
epsilon: float = 0.02
3736
iterations_stddev: int = 5
3837
build_compute_runtime: bool = False
3938
extra_ld_libraries: list[str] = field(default_factory=list)
4039
extra_env_vars: dict = field(default_factory=dict)
41-
compute_runtime_tag: str = "25.05.32567.12"
40+
compute_runtime_tag: str = "25.05.32567.18"
4241
build_igc: bool = False
4342
current_run_name: str = "This PR"
43+
preset: Preset = presets[0]
4444

4545

4646
options = Options()

devops/scripts/benchmarks/output_html.py

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,43 @@
55

66
import json
77
import os
8+
from options import options
89

910

1011
def generate_html(benchmark_runs: list, compare_names: list[str]):
11-
12-
# Get unique suite names
13-
suite_names = {result.suite for run in benchmark_runs for result in run.results}
14-
1512
# create path to data.js in html folder
16-
data_path = os.path.join(os.path.dirname(__file__), "html", "data.js")
17-
18-
# Write data to js file
19-
# We can't store this as a standalone json file because it needs to be inline in the html
20-
with open(data_path, "w") as f:
21-
f.write("const benchmarkRuns = [\n")
22-
# it might be tempting to just to create a list and convert
23-
# that to a json, but that leads to json being serialized twice.
24-
for i, run in enumerate(benchmark_runs):
25-
if i > 0:
26-
f.write(",\n")
27-
f.write(run.to_json())
28-
29-
f.write("\n];\n\n") # terminates benchmarkRuns
30-
31-
# these are not const because they might be modified
32-
# in config.js
33-
f.write("defaultCompareNames = ")
34-
json.dump(compare_names, f)
35-
f.write(";\n\n") # terminates defaultCompareNames
36-
f.write("suiteNames = ")
37-
json.dump(list(suite_names), f)
38-
f.write(";") # terminates suiteNames
13+
html_path = os.path.join(os.path.dirname(__file__), "html")
14+
15+
if options.output_html == "local":
16+
data_path = os.path.join(html_path, "data.js")
17+
# Write data to js file
18+
# We can't store this as a standalone json file because it needs to be inline in the html
19+
with open(data_path, "w") as f:
20+
f.write("benchmarkRuns = [\n")
21+
# it might be tempting to just to create a list and convert
22+
# that to a json, but that leads to json being serialized twice.
23+
for i, run in enumerate(benchmark_runs):
24+
if i > 0:
25+
f.write(",\n")
26+
f.write(run.to_json())
27+
28+
f.write("\n];\n\n") # terminates benchmarkRuns
29+
30+
f.write("defaultCompareNames = ")
31+
json.dump(compare_names, f)
32+
f.write(";\n") # terminates defaultCompareNames
33+
34+
print(f"See {os.getcwd()}/html/index.html for the results.")
35+
else:
36+
data_path = os.path.join(html_path, "data.json")
37+
with open(data_path, "w") as f:
38+
f.write("[\n")
39+
for i, run in enumerate(benchmark_runs):
40+
if i > 0:
41+
f.write(",\n")
42+
f.write(run.to_json())
43+
f.write("\n];\n")
44+
45+
print(
46+
f"Upload {data_path} to a location set in config.js remoteDataUrl argument."
47+
)

0 commit comments

Comments
 (0)