|  | #!/usr/bin/env python3 | 
|  | # Copyright 2022 The IREE Authors | 
|  | # | 
|  | # Licensed under the Apache License v2.0 with LLVM Exceptions. | 
|  | # See https://llvm.org/LICENSE.txt for license information. | 
|  | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  |  | 
|  | import glob | 
|  | import os | 
|  | import argparse | 
|  | import pathlib | 
|  | from typing import List, Optional, Sequence | 
|  |  | 
|  |  | 
|  | def _check_dir_path(path): | 
|  | path = pathlib.Path(path) | 
|  | if path.is_dir(): | 
|  | return path | 
|  | else: | 
|  | raise argparse.ArgumentTypeError(path) | 
|  |  | 
|  |  | 
|  | def _check_file_path(path): | 
|  | path = pathlib.Path(path) | 
|  | if path.is_file(): | 
|  | return path | 
|  | else: | 
|  | raise argparse.ArgumentTypeError(f"'{path}' is not found") | 
|  |  | 
|  |  | 
|  | def _check_exe_path(path): | 
|  | path = pathlib.Path(path) | 
|  | if os.access(path, os.X_OK): | 
|  | return path | 
|  | else: | 
|  | raise argparse.ArgumentTypeError(f"'{path}' is not an executable") | 
|  |  | 
|  |  | 
|  | class Parser(argparse.ArgumentParser): | 
|  | """Argument parser that includes common arguments and does validation.""" | 
|  |  | 
|  | def __init__(self, *args, **kwargs): | 
|  | super().__init__(*args, **kwargs) | 
|  |  | 
|  | artifacts_dir_group = self.add_mutually_exclusive_group(required=True) | 
|  | # TODO(#11076): Replace build-dir argument with e2e-test-artifacts-dir. | 
|  | artifacts_dir_group.add_argument( | 
|  | "build_dir", | 
|  | metavar="<build-dir>", | 
|  | type=_check_dir_path, | 
|  | default=None, | 
|  | nargs="?", | 
|  | help="Path to the build directory containing benchmark suites") | 
|  | artifacts_dir_group.add_argument( | 
|  | "--e2e_test_artifacts_dir", | 
|  | metavar="<e2e-test-artifacts-dir>", | 
|  | type=_check_dir_path, | 
|  | default=None, | 
|  | help=( | 
|  | "Path to the IREE e2e test artifacts directory. This will override " | 
|  | "<build-dir> and eventually replace it. For now must use with " | 
|  | "--run_config")) | 
|  |  | 
|  | self.add_argument( | 
|  | "--normal_benchmark_tool_dir", | 
|  | "--normal-benchmark-tool-dir", | 
|  | type=_check_dir_path, | 
|  | default=None, | 
|  | help="Path to the normal (non-tracing) iree tool directory") | 
|  | self.add_argument("--traced_benchmark_tool_dir", | 
|  | "--traced-benchmark-tool-dir", | 
|  | type=_check_dir_path, | 
|  | default=None, | 
|  | help="Path to the tracing-enabled iree tool directory") | 
|  | self.add_argument("--trace_capture_tool", | 
|  | "--trace-capture-tool", | 
|  | type=_check_exe_path, | 
|  | default=None, | 
|  | help="Path to the tool for collecting captured traces") | 
|  | self.add_argument( | 
|  | "--driver-filter-regex", | 
|  | "--driver_filter_regex", | 
|  | type=str, | 
|  | default=None, | 
|  | help="Only run benchmarks matching the given driver regex") | 
|  | self.add_argument( | 
|  | "--model-name-regex", | 
|  | "--model_name_regex", | 
|  | type=str, | 
|  | default=None, | 
|  | help="Only run benchmarks matching the given model name regex") | 
|  | self.add_argument( | 
|  | "--mode-regex", | 
|  | "--mode_regex", | 
|  | type=str, | 
|  | default=None, | 
|  | help="Only run benchmarks matching the given benchmarking mode regex") | 
|  | self.add_argument("--output", | 
|  | "-o", | 
|  | default=None, | 
|  | type=pathlib.Path, | 
|  | help="Path to the output file") | 
|  | self.add_argument("--capture_tarball", | 
|  | "--capture-tarball", | 
|  | default=None, | 
|  | type=pathlib.Path, | 
|  | help="Path to the tarball for captures") | 
|  | self.add_argument("--no-clean", | 
|  | action="store_true", | 
|  | help="Do not clean up the temporary directory used for " | 
|  | "benchmarking on the Android device") | 
|  | self.add_argument("--verbose", | 
|  | action="store_true", | 
|  | help="Print internal information during execution") | 
|  | self.add_argument( | 
|  | "--pin-cpu-freq", | 
|  | "--pin_cpu_freq", | 
|  | action="store_true", | 
|  | help="Pin CPU frequency for all cores to the maximum. Requires root") | 
|  | self.add_argument("--pin-gpu-freq", | 
|  | "--pin_gpu_freq", | 
|  | action="store_true", | 
|  | help="Pin GPU frequency to the maximum. Requires root") | 
|  | self.add_argument( | 
|  | "--keep_going", | 
|  | "--keep-going", | 
|  | action="store_true", | 
|  | help="Continue running after a failed benchmark. The overall exit status" | 
|  | " will still indicate failure and all errors will be reported at the end." | 
|  | ) | 
|  | self.add_argument( | 
|  | "--tmp_dir", | 
|  | "--tmp-dir", | 
|  | "--tmpdir", | 
|  | default=pathlib.Path("/tmp/iree-benchmarks"), | 
|  | type=_check_dir_path, | 
|  | help="Base directory in which to store temporary files. A subdirectory" | 
|  | " with a name matching the git commit hash will be created.") | 
|  | self.add_argument( | 
|  | "--continue_from_directory", | 
|  | "--continue-from-directory", | 
|  | default=None, | 
|  | type=_check_dir_path, | 
|  | help="Path to directory with previous benchmark temporary files. This" | 
|  | " should be for the specific commit (not the general tmp-dir). Previous" | 
|  | " benchmark and capture results from here will not be rerun and will be" | 
|  | " combined with the new runs.") | 
|  | self.add_argument( | 
|  | "--benchmark_min_time", | 
|  | "--benchmark-min-time", | 
|  | default=0, | 
|  | type=float, | 
|  | help="If specified, this will be passed as --benchmark_min_time to the" | 
|  | "iree-benchmark-module (minimum number of seconds to repeat running " | 
|  | "for). In that case, no --benchmark_repetitions flag will be passed." | 
|  | " If not specified, a --benchmark_repetitions will be passed " | 
|  | "instead.") | 
|  | self.add_argument("--run_config", | 
|  | type=_check_file_path, | 
|  | default=None, | 
|  | help="JSON file of the run config") | 
|  |  | 
|  | def parse_args( | 
|  | self, arg_strs: Optional[Sequence[str]] = None) -> argparse.Namespace: | 
|  | args = super().parse_args(arg_strs) | 
|  |  | 
|  | if args.e2e_test_artifacts_dir is not None and args.run_config is None: | 
|  | raise self.error("--e2e_test_artifacts_dir requires --run_config.") | 
|  |  | 
|  | return args | 
|  |  | 
|  |  | 
|  | def expand_and_check_file_paths(paths: Sequence[str]) -> List[pathlib.Path]: | 
|  | """Expands the wildcards in the paths and check if they are files. | 
|  | Returns: | 
|  | List of expanded paths. | 
|  | """ | 
|  |  | 
|  | expanded_paths = [] | 
|  | for path in paths: | 
|  | expanded_paths += [pathlib.Path(path) for path in glob.glob(path)] | 
|  |  | 
|  | for path in expanded_paths: | 
|  | if not path.is_file(): | 
|  | raise ValueError(f"{path} is not a file.") | 
|  |  | 
|  | return expanded_paths |