blob: 3e098314b0258e10966e420aac2089d70ea5f56c [file] [log] [blame]
# 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
"""Utilities for handling the benchmark suite.
Benchmark artifacts should be generated by building the `iree-benchmark-suites`
CMake target, which put them in the following directory structure:
<root-build-dir>/benchmark_suites
└── <benchmark-category> (e.g., TFLite)
├── <benchmark-suite> (e.g., MobileBertSquad-fp32)
│ ├── <benchmark-case> (e.g., iree-vulkan__GPU-Mali-Valhall__kernel-execution)
│ │ ├── compilation_statistics.json
│ │ ├── tool
│ │ └── flagfile
│ ├── ...
│ │ ├── compilation_statistics.json
│ │ ├── tool
│ │ └── flagfile
│ └── <benchmark_case>
│ │ ├── compilation_statistics.json
│ ├── tool
│ └── flagfile
└── vmfb
├── <compiled-iree-model>-<sha1>.vmfb
├── ...
└── <compiled-iree-model>-<sha1>.vmfb
"""
import re
import os
from typing import List, Optional, Sequence
from .benchmark_definition import AndroidDeviceInfo, BenchmarkInfo
# All benchmarks' relative path against root build directory.
BENCHMARK_SUITE_REL_PATH = "benchmark_suites"
def compose_info_object(device_info: AndroidDeviceInfo,
benchmark_category_dir: str,
benchmark_case_dir: str) -> BenchmarkInfo:
"""Creates an BenchmarkInfo object to describe the benchmark.
Args:
device_info: an AndroidDeviceInfo object.
benchmark_category_dir: the directory to a specific benchmark category.
benchmark_case_dir: a directory containing the benchmark case.
Returns:
A BenchmarkInfo object.
"""
# Extract the model name from the directory path. This uses the relative
# path under the root model directory. If there are multiple segments,
# additional ones will be placed in parentheses.
model_name = os.path.relpath(benchmark_case_dir, benchmark_category_dir)
# Now we have <model-name>/.../<iree-driver>__<target-arch>__<bench_mode>,
# Remove the last segment.
model_name = os.path.dirname(model_name)
main, rest = os.path.split(model_name)
if main:
# Tags coming from directory structure.
model_name = main
model_tags = [re.sub(r"\W+", "-", rest)]
else:
# Tags coming from the name itself.
model_name, rest = rest.split("-", 1)
model_tags = rest.split(",")
# Extract benchmark info from the directory path following convention:
# <iree-driver>__<target-architecture>__<benchmark_mode>
root_immediate_dir = os.path.basename(benchmark_case_dir)
iree_driver, target_arch, bench_mode = root_immediate_dir.split("__")
model_source = os.path.basename(benchmark_category_dir)
return BenchmarkInfo(model_name=model_name,
model_tags=model_tags,
model_source=model_source,
bench_mode=bench_mode.split(","),
runner=iree_driver,
device_info=device_info)
def filter_benchmarks_for_category(benchmark_category_dir: str,
cpu_target_arch_filter: str,
gpu_target_arch_filter: str,
available_drivers: Sequence[str],
driver_filter: Optional[str],
mode_filter: Optional[str],
model_name_filter: Optional[str],
verbose: bool = False) -> Sequence[str]:
"""Filters benchmarks in a specific category for the given device.
Args:
benchmark_category_dir: the directory to a specific benchmark category.
cpu_target_arch_filter: CPU target architecture filter regex.
gpu_target_arch_filter: GPU target architecture filter regex.
available_drivers: list of drivers supported by the tools in this build dir.
driver_filter: driver filter regex.
mode_filter: benchmark mode regex.
model_name_filter: model name regex.
verbose: whether to print additional debug info.
Returns:
A list containing all matched benchmark cases' directories.
"""
matched_benchmarks = []
# Go over all benchmarks in the model directory to find those matching the
# current Android device's CPU/GPU architecture.
for root, dirs, _ in os.walk(benchmark_category_dir):
# Take the immediate directory name and try to see if it contains compiled
# models and flagfiles. This relies on the following directory naming
# convention:
# <iree-driver>__<target-architecture>__<benchmark_mode>
root_immediate_dir = os.path.basename(root)
segments = root_immediate_dir.split("__")
if len(segments) != 3 or not segments[0].startswith("iree-"):
continue
model_name = os.path.relpath(root, benchmark_category_dir)
iree_driver, target_arch, bench_mode = segments
iree_driver = iree_driver[len("iree-"):].lower()
target_arch = target_arch.lower()
# We can choose this benchmark if it matches the driver and CPU/GPU
# architecture.
matched_driver = (iree_driver in available_drivers) and (
driver_filter is None or
re.match(driver_filter, iree_driver) is not None)
matched_arch = (re.match(cpu_target_arch_filter, target_arch) is not None or
re.match(gpu_target_arch_filter, target_arch) is not None)
matched_model_name = (model_name_filter is None or
re.match(model_name_filter, model_name) is not None)
matched_mode = (mode_filter is None or
re.match(mode_filter, bench_mode) is not None)
chosen = False
if matched_driver and matched_arch and matched_model_name and matched_mode:
matched_benchmarks.append(root)
chosen = True
if verbose:
print(f"dir: {root}")
print(f" model_name: {model_name}")
print(f" iree_driver: {iree_driver}")
print(f" target_arch: {target_arch}")
print(f" bench_mode: {bench_mode}")
print(f" chosen: {chosen}")
return matched_benchmarks