Skip to content

Commit c018b49

Browse files
authored
[Benchmarks] Add benchmarks logger (#19158)
1 parent a028eed commit c018b49

File tree

17 files changed

+321
-148
lines changed

17 files changed

+321
-148
lines changed

devops/scripts/benchmarks/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,27 @@ are stored [here](https://oneapi-src.github.io/unified-runtime/performance/).
4545
## Output formats
4646
You can display the results in the form of a HTML file by using `--ouptut-html` and a markdown file by using `--output-markdown`. Due to character limits for posting PR comments, the final content of the markdown file might be reduced. In order to obtain the full markdown output, use `--output-markdown full`.
4747

48+
## Logging
49+
50+
The benchmark runner uses a configurable logging system with different log levels that can be set using the `--log-level` command-line option.
51+
52+
Available log levels:
53+
- `debug`
54+
- `info` (default)
55+
- `warning`
56+
- `error`
57+
- `critical`
58+
59+
To set the log level, use the `--log-level` option:
60+
```bash
61+
./main.py ~/benchmarks_workdir/ --sycl ~/llvm/build/ --log-level debug
62+
```
63+
64+
You can also use the `--verbose` flag, which sets the log level to `debug` and overrides any `--log-level` setting:
65+
```bash
66+
./main.py ~/benchmarks_workdir/ --sycl ~/llvm/build/ --verbose
67+
```
68+
4869
## Requirements
4970

5071
### Python

devops/scripts/benchmarks/benches/benchdnn.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
# See LICENSE.TXT
44
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
55

6+
67
from pathlib import Path
8+
79
from .base import Suite, Benchmark
810
from options import options
911
from utils.utils import git_clone, run, create_build_path
1012
from utils.result import Result
1113
from utils.oneapi import get_oneapi
14+
from utils.logger import log
1215
from .benchdnn_list import get_bench_dnn_list
1316

1417

@@ -151,8 +154,7 @@ def run(self, env_vars):
151154
)
152155
result_value = self._extract_time(output)
153156

154-
if options.verbose:
155-
print(f"[{self.name()}] Output: {output}")
157+
log.debug(f"[{self.name()}] Output: {output}")
156158

157159
return [
158160
Result(

devops/scripts/benchmarks/benches/gromacs.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
55

66
import os
7-
import subprocess
87
from pathlib import Path
8+
import re
9+
910
from .base import Suite, Benchmark
1011
from options import options
1112
from utils.utils import git_clone, download, run, create_build_path
1213
from utils.result import Result
1314
from utils.oneapi import get_oneapi
14-
import re
15+
from utils.logger import log
1516

1617

1718
class GromacsBench(Suite):
@@ -210,8 +211,7 @@ def run(self, env_vars):
210211

211212
time = self._extract_execution_time(mdrun_output)
212213

213-
if options.verbose:
214-
print(f"[{self.name()}] Time: {time:.3f} seconds")
214+
log.debug(f"[{self.name()}] Time: {time:.3f} seconds")
215215

216216
return [
217217
Result(
@@ -259,7 +259,7 @@ def _validate_correctness(self, log_file):
259259
drift_value = float(match.group(1))
260260
return abs(drift_value) <= threshold
261261
except ValueError:
262-
print(
262+
log.warning(
263263
f"Parsed drift value: {drift_value} exceeds threshold"
264264
)
265265
return False

devops/scripts/benchmarks/benches/umf.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,17 @@
33
# See LICENSE.TXT
44
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
55

6-
import random
7-
from utils.utils import git_clone
8-
from .base import Benchmark, Suite
9-
from utils.result import Result
10-
from utils.utils import run, create_build_path
11-
from options import options
12-
from utils.oneapi import get_oneapi
136
import os
147
import csv
158
import io
169
import re
1710

11+
from .base import Benchmark, Suite
12+
from utils.result import Result
13+
from options import options
14+
from utils.oneapi import get_oneapi
15+
from utils.logger import log
16+
1817

1918
def isUMFAvailable():
2019
return options.umf is not None
@@ -93,7 +92,7 @@ def extra_env_vars(self) -> dict:
9392

9493
def setup(self):
9594
if not isUMFAvailable():
96-
print("UMF prefix path not provided")
95+
log.warning("UMF prefix path not provided")
9796
return
9897

9998
self.oneapi = get_oneapi()

devops/scripts/benchmarks/compare.py

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
1-
from utils.aggregate import Aggregator, SimpleMedian, EWMA
2-
from utils.validate import Validate
3-
from utils.result import Result, BenchmarkRun
4-
from options import options
1+
# Copyright (C) 2024-2025 Intel Corporation
2+
# Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions.
3+
# See LICENSE.TXT
4+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
55

6-
import os
76
import re
8-
import sys
97
import json
108
import argparse
119
from datetime import datetime, timezone
1210
from pathlib import Path
1311
from dataclasses import dataclass, asdict
1412

13+
from utils.aggregate import Aggregator, SimpleMedian, EWMA
14+
from utils.validate import Validate
15+
from utils.result import BenchmarkRun
16+
from utils.logger import log
17+
from options import options
18+
1519

1620
verbose = False
1721

22+
1823
@dataclass
1924
class BenchmarkHistoricAverage:
2025
"""Contains historic average information for 1 benchmark"""
@@ -115,8 +120,8 @@ def validate_benchmark_result(result: BenchmarkRun) -> bool:
115120
if result.hostname != hostname:
116121
return False
117122
if result.name != result_name:
118-
print(
119-
f"Warning: Result file {result_path} does not match specified result name {result.name}."
123+
log.warning(
124+
f"Result file {result_path} does not match specified result name {result.name}."
120125
)
121126
return False
122127
if result.date < datetime.strptime(cutoff, "%Y%m%d_%H%M%S").replace(
@@ -227,10 +232,9 @@ def perf_diff_entry() -> dict:
227232
elif halfway_round(delta, 2) < -options.regression_threshold:
228233
regression.append(perf_diff_entry())
229234

230-
if verbose:
231-
print(
232-
f"{test.name}: expect {hist_avg[test.name].value}, got {test.value}"
233-
)
235+
log.debug(
236+
f"{test.name}: expect {hist_avg[test.name].value}, got {test.value}"
237+
)
234238

235239
return improvement, regression
236240

@@ -267,24 +271,24 @@ def to_hist(
267271
elif avg_type == "EWMA":
268272
aggregator_type = EWMA
269273
else:
270-
print("Error: Unsupported avg_type f{avg_type}.")
274+
log.error("Unsupported avg_type f{avg_type}.")
271275
exit(1)
272276

273277
try:
274278
with open(compare_file, "r") as compare_f:
275279
compare_result = BenchmarkRun.from_json(json.load(compare_f))
276280
except:
277-
print(f"Unable to open {compare_file}.")
281+
log.error(f"Unable to open {compare_file}.")
278282
exit(1)
279283

280284
# Sanity checks:
281285
if compare_result.hostname == "Unknown":
282-
print(
286+
log.error(
283287
"Hostname for results in {compare_file} unknown, unable to build a historic average: Refusing to continue."
284288
)
285289
exit(1)
286290
if not Validate.timestamp(cutoff):
287-
print("Invalid timestamp provided, please follow YYYYMMDD_HHMMSS.")
291+
log.error("Invalid timestamp provided, please follow YYYYMMDD_HHMMSS.")
288292
exit(1)
289293

290294
# Build historic average and compare results against historic average:
@@ -348,13 +352,13 @@ def to_hist(
348352

349353
if args.verbose:
350354
verbose = True
351-
print("-- Compare.py --")
355+
log.info("-- Compare.py --")
352356

353357
if args.operation == "to_hist":
354358
if not Validate.timestamp(args.cutoff):
355359
raise ValueError("Timestamp must be provided as YYYYMMDD_HHMMSS.")
356360
if args.avg_type not in ["median", "EWMA"]:
357-
print("Only median, EWMA is currently supported: exiting.")
361+
log.error("Only median, EWMA is currently supported: exiting.")
358362
exit(1)
359363

360364
improvements, regressions = Compare.to_hist(
@@ -373,28 +377,34 @@ def to_hist(
373377
else:
374378
regressions_ignored.append(test)
375379

376-
def print_regression(entry: dict):
377-
"""Print an entry outputted from Compare.to_hist"""
378-
print(f"Test: {entry['name']}")
379-
print(f"-- Historic {entry['avg_type']}: {entry['hist_avg']}")
380-
print(f"-- Run result: {entry['value']}")
381-
print(f"-- Delta: {entry['delta']}")
382-
print("")
380+
def print_regression(entry: dict, is_warning: bool = False):
381+
"""Print an entry outputted from Compare.to_hist
382+
383+
Args:
384+
entry (dict): The entry to print
385+
is_warning (bool): If True, use log.warning instead of log.info
386+
"""
387+
log_func = log.warning if is_warning else log.info
388+
log_func(f"Test: {entry['name']}")
389+
log_func(f"-- Historic {entry['avg_type']}: {entry['hist_avg']}")
390+
log_func(f"-- Run result: {entry['value']}")
391+
log_func(f"-- Delta: {entry['delta']}")
392+
log_func("")
383393

384394
if improvements:
385-
print("#\n# Improvements:\n#\n")
395+
log.info("#\n# Improvements:\n#\n")
386396
for test in improvements:
387397
print_regression(test)
388398
if regressions_ignored:
389-
print("#\n# Regressions (filtered out by regression-filter):\n#\n")
399+
log.info("#\n# Regressions (filtered out by regression-filter):\n#\n")
390400
for test in regressions_ignored:
391401
print_regression(test)
392402
if regressions_of_concern:
393-
print("#\n# Regressions:\n#\n")
403+
log.warning("#\n# Regressions:\n#\n")
394404
for test in regressions_of_concern:
395-
print_regression(test)
405+
print_regression(test, is_warning=True)
396406
exit(1) # Exit 1 to trigger github test failure
397-
print("\nNo unexpected regressions found!")
407+
log.info("\nNo unexpected regressions found!")
398408
else:
399-
print("Unsupported operation: exiting.")
409+
log.error("Unsupported operation: exiting.")
400410
exit(1)

devops/scripts/benchmarks/history.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
import json
88
from pathlib import Path
99
import socket
10+
1011
from utils.result import Result, BenchmarkRun
1112
from options import Compare, options
1213
from datetime import datetime, timezone, timedelta
1314
from utils.utils import run
1415
from utils.validate import Validate
15-
16+
from utils.logger import log
1617
from utils.detect_versions import DetectVersion
1718

1819

@@ -33,8 +34,8 @@ def load_result(self, file_path: Path) -> BenchmarkRun:
3334
def load(self, n: int):
3435
results_dir = Path(self.dir) / "results"
3536
if not results_dir.exists() or not results_dir.is_dir():
36-
print(
37-
f"Warning: {results_dir} is not a valid directory: no historic results loaded."
37+
log.warning(
38+
f"{results_dir} is not a valid directory: no historic results loaded."
3839
)
3940
return
4041

@@ -97,7 +98,7 @@ def git_info_from_path(path: Path) -> (str, str):
9798

9899
if options.git_commit_override is None or options.github_repo_override is None:
99100
if options.detect_versions.sycl:
100-
print(f"Auto-detecting sycl version...")
101+
log.info(f"Auto-detecting sycl version...")
101102
github_repo, git_hash = DetectVersion.instance().get_dpcpp_git_info()
102103
else:
103104
git_hash, github_repo = git_info_from_path(
@@ -129,12 +130,12 @@ def git_info_from_path(path: Path) -> (str, str):
129130
if options.build_compute_runtime:
130131
compute_runtime = options.compute_runtime_tag
131132
elif options.detect_versions.compute_runtime:
132-
print(f"Auto-detecting compute_runtime version...")
133+
log.info(f"Auto-detecting compute_runtime version...")
133134
detect_res = DetectVersion.instance()
134135
compute_runtime = detect_res.get_compute_runtime_ver()
135136
if detect_res.get_compute_runtime_ver_cached() is None:
136-
print(
137-
"Warning: Could not find compute_runtime version via github tags API."
137+
log.warning(
138+
"Could not find compute_runtime version via github tags API."
138139
)
139140
else:
140141
compute_runtime = "unknown"
@@ -169,7 +170,7 @@ def save(self, save_name, results: list[Result], to_file=True):
169170
file_path = Path(os.path.join(results_dir, f"{save_name}_{timestamp}.json"))
170171
with file_path.open("w") as file:
171172
json.dump(serialized, file, indent=4)
172-
print(f"Benchmark results saved to {file_path}")
173+
log.info(f"Benchmark results saved to {file_path}")
173174

174175
def find_first(self, name: str) -> BenchmarkRun:
175176
for r in self.runs:

0 commit comments

Comments
 (0)