Skip to content

Commit cc8c79c

Browse files
committed
add some logs
1 parent e90c71c commit cc8c79c

File tree

6 files changed

+98
-72
lines changed

6 files changed

+98
-72
lines changed

devops/scripts/benchmarks/main.py

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from utils.compute_runtime import *
2727
from utils.validate import Validate
2828
from utils.detect_versions import DetectVersion
29-
from utils.logger import log, LogLevel
29+
from utils.logger import log
3030
from presets import enabled_suites, presets
3131

3232

@@ -160,6 +160,9 @@ def collect_metadata(suites):
160160
def main(directory, additional_env_vars, save_name, compare_names, filter):
161161
prepare_workdir(directory, INTERNAL_WORKDIR_VERSION)
162162

163+
if options.dry_run:
164+
log.info("Dry run mode enabled. No benchmarks will be executed.")
165+
163166
if options.build_compute_runtime:
164167
log.info(f"Setting up Compute Runtime {options.compute_runtime_tag}")
165168
cr = get_compute_runtime()
@@ -231,6 +234,10 @@ def main(directory, additional_env_vars, save_name, compare_names, filter):
231234
log.error(f"failed: {e}")
232235

233236
results = []
237+
if benchmarks:
238+
log.info(f"Running {len(benchmarks)} benchmarks...")
239+
elif not options.dry_run:
240+
log.warning("No benchmarks to run.")
234241
for benchmark in benchmarks:
235242
try:
236243
merged_env_vars = {**additional_env_vars}
@@ -275,19 +282,22 @@ def main(directory, additional_env_vars, save_name, compare_names, filter):
275282
history = BenchmarkHistory(results_dir)
276283
# limit how many files we load.
277284
# should this be configurable?
285+
log.info(f"Loading benchmark history from {results_dir}...")
278286
history.load(1000)
279-
280-
# remove duplicates. this can happen if e.g., --compare baseline is specified manually.
281-
compare_names = (
282-
list(dict.fromkeys(compare_names)) if compare_names is not None else []
283-
)
284-
285-
for name in compare_names:
286-
compare_result = history.get_compare(name)
287-
if compare_result:
288-
chart_data[name] = compare_result.results
287+
log.info(f"Loaded {len(history.runs)} benchmark runs.")
288+
289+
if compare_names:
290+
log.info(f"Comparing against {len(compare_names)} previous runs...")
291+
# remove duplicates. this can happen if e.g., --compare baseline is specified manually.
292+
compare_names = list(dict.fromkeys(compare_names))
293+
for name in compare_names:
294+
compare_result = history.get_compare(name)
295+
if compare_result:
296+
chart_data[name] = compare_result.results
297+
log.info(f"Comparison complete.")
289298

290299
if options.output_markdown:
300+
log.info("Generating markdown with benchmark results...")
291301
markdown_content = generate_markdown(
292302
this_name, chart_data, failures, options.output_markdown, metadata
293303
)
@@ -309,16 +319,21 @@ def main(directory, additional_env_vars, save_name, compare_names, filter):
309319
# we calculate historical averages or get latest results for compare.
310320
# Otherwise we might be comparing the results to themselves.
311321
if not options.dry_run:
322+
log.info(f"Saving benchmark results...")
312323
history.save(saved_name, results, save_name is not None)
313324
if saved_name not in compare_names:
314325
compare_names.append(saved_name)
326+
log.info(f"Benchmark results saved.")
315327

316328
if options.output_html:
317329
html_path = options.output_directory
318330
if options.output_directory is None:
319-
html_path = os.path.join(os.path.dirname(__file__), "html")
320-
331+
html_path = os.path.normpath(
332+
os.path.join(os.path.dirname(__file__), "html")
333+
)
334+
log.info(f"Generating HTML with benchmark results in {html_path}...")
321335
generate_html(history.runs, compare_names, html_path, metadata)
336+
log.info(f"HTML with benchmark results has been generated")
322337

323338

324339
def validate_and_parse_env_args(env_args):
@@ -376,6 +391,7 @@ def validate_and_parse_env_args(env_args):
376391
type=str,
377392
help="Compare results against previously saved data.",
378393
action="append",
394+
default=[],
379395
)
380396
parser.add_argument(
381397
"--iterations",
@@ -574,7 +590,6 @@ def validate_and_parse_env_args(env_args):
574590
additional_env_vars = validate_and_parse_env_args(args.env)
575591

576592
options.workdir = args.benchmark_directory
577-
options.verbose = args.verbose
578593
options.rebuild = not args.no_rebuild
579594
options.redownload = args.redownload
580595
options.sycl = args.sycl
@@ -599,15 +614,8 @@ def validate_and_parse_env_args(env_args):
599614
options.build_jobs = args.build_jobs
600615
options.hip_arch = args.hip_arch
601616

602-
# Set the log level
603-
log_level = (
604-
LogLevel.DEBUG.value
605-
if args.verbose
606-
else LogLevel.from_string(args.log_level).value
607-
)
608-
log.logger.setLevel(log_level)
609-
for handler in log.logger.handlers:
610-
handler.setLevel(log_level)
617+
# Initialize logger with command line arguments
618+
log.initialize(args.verbose, args.log_level)
611619

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

devops/scripts/benchmarks/options.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
from enum import Enum
33
import multiprocessing
44

5-
from presets import presets
6-
75

86
class Compare(Enum):
97
LATEST = "latest"
@@ -41,6 +39,7 @@ class DetectVersionsOptions:
4139
# Max amount of api calls permitted on each run of the benchmark scripts
4240
max_api_calls = 4
4341

42+
4443
@dataclass
4544
class Options:
4645
workdir: str = None
@@ -53,7 +52,6 @@ class Options:
5352
benchmark_cwd: str = "INVALID"
5453
timeout: float = 600
5554
iterations: int = 3
56-
verbose: bool = False
5755
compare: Compare = Compare.LATEST
5856
compare_max: int = 10 # average/median over how many results
5957
output_markdown: MarkdownSize = MarkdownSize.SHORT

devops/scripts/benchmarks/output_html.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def generate_html(
4949
json.dump(output.default_compare_names, f, indent=2)
5050
f.write(";\n")
5151

52-
log.info(f"See {os.getcwd()}/html/index.html for the results.")
52+
log.info(f"See {html_path}/index.html for the results.")
5353
else:
5454
# For remote format, we write a single JSON file
5555
data_path = os.path.join(html_path, "data.json")

devops/scripts/benchmarks/utils/compute_runtime.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import re
88
import yaml
99

10-
from pathlib import Path
1110
from .utils import *
1211
from options import options
1312

@@ -51,6 +50,7 @@ def env_vars(self) -> dict:
5150
}
5251

5352
def build_gmmlib(self, repo, commit):
53+
log.info("Building GMMLib...")
5454
self.gmmlib_repo = git_clone(options.workdir, "gmmlib-repo", repo, commit)
5555
self.gmmlib_build = os.path.join(options.workdir, "gmmlib-build")
5656
self.gmmlib_install = os.path.join(options.workdir, "gmmlib-install")
@@ -64,9 +64,11 @@ def build_gmmlib(self, repo, commit):
6464
run(configure_command)
6565
run(f"cmake --build {self.gmmlib_build} -j {options.build_jobs}")
6666
run(f"cmake --install {self.gmmlib_build}")
67+
log.info("GMMLib build complete.")
6768
return self.gmmlib_install
6869

6970
def build_level_zero(self, repo, commit):
71+
log.info("Building Level Zero...")
7072
self.level_zero_repo = git_clone(
7173
options.workdir, "level-zero-repo", repo, commit
7274
)
@@ -89,9 +91,11 @@ def build_level_zero(self, repo, commit):
8991
run(configure_command)
9092
run(f"cmake --build {self.level_zero_build} -j {options.build_jobs}")
9193
run(f"cmake --install {self.level_zero_build}")
94+
log.info("Level Zero build complete.")
9295
return self.level_zero_install
9396

9497
def build_igc(self, repo, commit):
98+
log.info("Building IGC...")
9599
self.igc_repo = git_clone(options.workdir, "igc", repo, commit)
96100
self.vc_intr = git_clone(
97101
options.workdir,
@@ -151,6 +155,7 @@ def build_igc(self, repo, commit):
151155
)
152156
# cmake --install doesn't work...
153157
run("make install", cwd=self.igc_build)
158+
log.info("IGC build complete.")
154159
return self.igc_install
155160

156161
def read_manifest(self, manifest_path):
@@ -204,6 +209,7 @@ def build_compute_runtime(self):
204209
# Remove -Werror...
205210
replace_in_file(cmakelists_path, r"\s-Werror(?:=[a-zA-Z]*)?", "")
206211

212+
log.info("Building Compute Runtime...")
207213
configure_command = [
208214
"cmake",
209215
f"-B {self.compute_runtime_build}",
@@ -220,6 +226,7 @@ def build_compute_runtime(self):
220226

221227
run(configure_command)
222228
run(f"cmake --build {self.compute_runtime_build} -j {options.build_jobs}")
229+
log.info("Compute Runtime build complete.")
223230
return self.compute_runtime_build
224231

225232

devops/scripts/benchmarks/utils/logger.py

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,80 +5,90 @@
55

66
import logging
77
import sys
8-
from enum import Enum
8+
from typing import Optional, Type, Any
99

1010

11-
class LogLevel(Enum):
12-
DEBUG = logging.DEBUG
13-
INFO = logging.INFO
14-
WARNING = logging.WARNING
15-
ERROR = logging.ERROR
16-
CRITICAL = logging.CRITICAL
17-
18-
@staticmethod
19-
def from_string(level_str):
20-
level_map = {
21-
"debug": LogLevel.DEBUG,
22-
"info": LogLevel.INFO,
23-
"warning": LogLevel.WARNING,
24-
"error": LogLevel.ERROR,
25-
"critical": LogLevel.CRITICAL,
26-
}
27-
return level_map.get(level_str.lower(), LogLevel.INFO)
11+
# Define log level mapping as a module-level function
12+
def _get_log_level(level_str: str) -> int:
13+
"""Convert a string log level to a logging module level constant."""
14+
level_map = {
15+
"debug": logging.DEBUG,
16+
"info": logging.INFO,
17+
"warning": logging.WARNING,
18+
"error": logging.ERROR,
19+
"critical": logging.CRITICAL,
20+
}
21+
return level_map.get(level_str.lower(), logging.INFO)
2822

2923

3024
class BenchmarkLogger:
31-
"""Logger for the Unified Runtime Benchmark Runner.
25+
"""Logger for the Benchmark Runner.
3226
3327
This logger provides different log levels (DEBUG, INFO, WARNING, ERROR, CRITICAL)
34-
that can be controlled via command-line arguments.
28+
that can be controlled via command-line arguments. Call initialize() with the
29+
appropriate parameters after parsing command line arguments.
3530
"""
3631

37-
_instance = None
32+
_instance: Optional["BenchmarkLogger"] = None
3833

39-
def __new__(cls):
34+
def __new__(cls: Type["BenchmarkLogger"]) -> "BenchmarkLogger":
4035
if cls._instance is None:
4136
cls._instance = super(BenchmarkLogger, cls).__new__(cls)
42-
cls._instance._initialize_logger()
4337
return cls._instance
4438

45-
def _initialize_logger(self):
46-
"""Initialize the logger with the appropriate log level."""
47-
self.logger = logging.getLogger("ur_benchmarks")
39+
def __init__(self) -> None:
40+
"""Create logger but don't configure it until initialize() is called."""
41+
self._logger: logging.Logger = logging.getLogger("ur_benchmarks")
42+
43+
def initialize(self, verbose: bool = False, log_level: str = "info") -> None:
44+
"""Configure the logger with the appropriate log level.
45+
46+
Args:
47+
verbose: If True, sets the log level to DEBUG regardless of log_level
48+
log_level: One of "debug", "info", "warning", "error", "critical"
49+
50+
Note:
51+
This method will only initialize the logger once. Subsequent calls will be ignored.
52+
"""
53+
# Return early if logger is already initialized (has handlers)
54+
if self._logger.handlers:
55+
return
4856

49-
# Create console handler
5057
console_handler = logging.StreamHandler(sys.stdout)
5158

52-
# Set default log level (INFO)
53-
self.logger.setLevel(logging.INFO)
54-
console_handler.setLevel(logging.INFO)
59+
level = logging.DEBUG if verbose else _get_log_level(log_level)
60+
self._logger.setLevel(level)
61+
console_handler.setLevel(level)
5562

56-
# Create formatter
5763
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
5864
console_handler.setFormatter(formatter)
5965

60-
# Add the handler to the logger
61-
self.logger.addHandler(console_handler)
66+
self._logger.addHandler(console_handler)
6267

63-
def debug(self, message):
68+
def debug(self, message: Any) -> None:
6469
"""Log a debug message."""
65-
self.logger.debug(message)
70+
if self._logger.handlers:
71+
self._logger.debug(message)
6672

67-
def info(self, message):
73+
def info(self, message: Any) -> None:
6874
"""Log an info message."""
69-
self.logger.info(message)
75+
if self._logger.handlers:
76+
self._logger.info(message)
7077

71-
def warning(self, message):
78+
def warning(self, message: Any) -> None:
7279
"""Log a warning message."""
73-
self.logger.warning(message)
80+
if self._logger.handlers:
81+
self._logger.warning(message)
7482

75-
def error(self, message):
83+
def error(self, message: Any) -> None:
7684
"""Log an error message."""
77-
self.logger.error(message)
85+
if self._logger.handlers:
86+
self._logger.error(message)
7887

79-
def critical(self, message):
88+
def critical(self, message: Any) -> None:
8089
"""Log a critical message."""
81-
self.logger.critical(message)
90+
if self._logger.handlers:
91+
self._logger.critical(message)
8292

8393

8494
# Global logger instance

devops/scripts/benchmarks/utils/utils.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ def run(
7979

8080
def git_clone(dir, name, repo, commit):
8181
repo_path = os.path.join(dir, name)
82+
log.debug(f"Cloning {repo} into {repo_path} at commit {commit}")
8283

8384
if os.path.isdir(repo_path) and os.path.isdir(os.path.join(repo_path, ".git")):
8485
run("git fetch", cwd=repo_path)
@@ -91,6 +92,7 @@ def git_clone(dir, name, repo, commit):
9192
raise Exception(
9293
f"The directory {repo_path} exists but is not a git repository."
9394
)
95+
log.debug(f"Cloned {repo} into {repo_path} at commit {commit}")
9496
return repo_path
9597

9698

@@ -118,7 +120,8 @@ def prepare_workdir(dir, version):
118120
shutil.rmtree(dir)
119121
else:
120122
raise Exception(
121-
f"The directory {dir} exists but is not a benchmark work directory."
123+
f"The directory {dir} exists but is not a benchmark work directory. "
124+
f"A BENCH_WORKDIR_VERSION file is expected with version {version} but not found at {version_file_path}."
122125
)
123126

124127
os.makedirs(dir)

0 commit comments

Comments
 (0)