| # 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 os |
| from typing import Optional |
| |
| from common.benchmark_command import * |
| from common.benchmark_command_factory import BenchmarkCommandFactory |
| |
| _DEFAULT_NUM_BENCHMARK_RUNS = 50 |
| _DEFAULT_NUM_THREADS = 1 |
| |
| |
| class TfliteWrapper(TFLiteBenchmarkCommand): |
| """Specializes the benchmark command to use TFLite.""" |
| |
| def __init__(self, |
| benchmark_binary: str, |
| model_name: str, |
| model_path: str, |
| input_layer: Optional[str] = None, |
| input_shape: Optional[str] = None, |
| driver: str = "cpu", |
| num_threads: int = _DEFAULT_NUM_THREADS, |
| num_runs: int = _DEFAULT_NUM_BENCHMARK_RUNS, |
| taskset: Optional[str] = None): |
| super().__init__(benchmark_binary, |
| model_name, |
| model_path, |
| num_threads, |
| num_runs, |
| taskset=taskset) |
| self.driver = driver |
| if input_layer and input_shape: |
| self.args.append("--input_layer=%s" % input_layer) |
| self.args.append("--input_layer_shape=%s" % input_shape) |
| |
| |
| class IreeWrapper(IreeBenchmarkCommand): |
| """Specializes the benchmark command to use IREE.""" |
| |
| def __init__(self, |
| benchmark_binary: str, |
| model_name: str, |
| model_path: str, |
| function_input: str, |
| driver: str = "local-task", |
| num_threads: int = _DEFAULT_NUM_THREADS, |
| num_runs: int = _DEFAULT_NUM_BENCHMARK_RUNS, |
| taskset: Optional[str] = None): |
| super().__init__(benchmark_binary, |
| model_name, |
| model_path, |
| num_threads, |
| num_runs, |
| taskset=taskset) |
| self.driver = driver |
| self.args.append("--function=main") |
| self.args.append('--input="%s"' % function_input) |
| |
| |
| class SimpleCommandFactory(BenchmarkCommandFactory): |
| """ |
| Generates `BenchmarkCommand` objects specific to running series of simple models. |
| |
| A model is considered simple if its inputs can be generically generated based |
| on expected signature only without affecting behavior. |
| """ |
| |
| def __init__(self, |
| base_dir: str, |
| model_name: str, |
| function_input: str, |
| input_name: Optional[str] = None, |
| input_layer: Optional[str] = None): |
| self._model_name = model_name |
| self._function_input = function_input |
| self._input_name = input_name |
| self._input_layer = input_layer |
| self._base_dir = base_dir |
| self._iree_benchmark_binary_path = os.path.join(base_dir, |
| "iree-benchmark-module") |
| self._tflite_benchmark_binary_path = os.path.join(base_dir, |
| "benchmark_model") |
| # Required to be set, but no test data used yet. |
| self._tflite_test_data_dir = os.path.join(self._base_dir, "test_data") |
| |
| def generate_benchmark_commands(self, device: str, |
| driver: str) -> list[BenchmarkCommand]: |
| if device == "desktop" and driver == "cpu": |
| return self._generate_cpu(device) |
| elif device == "desktop" and driver == "gpu": |
| return self._generate_gpu("cuda") |
| elif device == "mobile" and driver == "cpu": |
| return self._generate_cpu(device) |
| elif device == "mobile" and driver == "gpu": |
| return self._generate_gpu("vulkan") |
| else: |
| print("Warning! Not a valid configuration.") |
| return [] |
| |
| def _generate_cpu(self, device: str): |
| commands = [] |
| # Generate TFLite benchmarks. |
| tflite_model_path = os.path.join(self._base_dir, "models", "tflite", |
| self._model_name + ".tflite") |
| tflite = TfliteWrapper(self._tflite_benchmark_binary_path, |
| self._model_name, |
| tflite_model_path, |
| self._input_name, |
| driver="cpu") |
| commands.append(tflite) |
| |
| tflite_noxnn = TfliteWrapper(self._tflite_benchmark_binary_path, |
| self._model_name + "_noxnn", |
| tflite_model_path, |
| self._input_name, |
| driver="cpu") |
| tflite_noxnn.args.append("--use_xnnpack=false") |
| commands.append(tflite_noxnn) |
| |
| # Generate IREE benchmarks. |
| driver = "local-task" |
| backend = "llvm-cpu" |
| |
| iree_model_path = os.path.join(self._base_dir, "models", "iree", backend, |
| self._model_name + ".vmfb") |
| iree = IreeWrapper(self._iree_benchmark_binary_path, |
| self._model_name, |
| iree_model_path, |
| self._function_input, |
| driver=driver) |
| commands.append(iree) |
| |
| model_padfuse_name = self._model_name + "_padfuse" |
| iree_padfuse_model_path = os.path.join(self._base_dir, "models", "iree", |
| backend, |
| model_padfuse_name + ".vmfb") |
| iree_padfuse = IreeWrapper(self._iree_benchmark_binary_path, |
| model_padfuse_name, |
| iree_padfuse_model_path, |
| self._function_input, |
| driver=driver) |
| commands.append(iree_padfuse) |
| |
| # Test mmt4d only on mobile. |
| if device == "mobile": |
| model_mmt4d_name = self._model_name + "_mmt4d" |
| iree_mmt4d_model_path = os.path.join(self._base_dir, "models", "iree", |
| backend, model_mmt4d_name + ".vmfb") |
| iree_mmt4d = IreeWrapper(self._iree_benchmark_binary_path, |
| model_mmt4d_name, |
| iree_mmt4d_model_path, |
| self._function_input, |
| driver=driver) |
| commands.append(iree_mmt4d) |
| |
| model_im2col_mmt4d_name = self._model_name + "_im2col_mmt4d" |
| iree_im2col_mmt4d_model_path = os.path.join( |
| self._base_dir, "models", "iree", backend, |
| model_im2col_mmt4d_name + ".vmfb") |
| iree_im2col_mmt4d = IreeWrapper(self._iree_benchmark_binary_path, |
| model_im2col_mmt4d_name, |
| iree_im2col_mmt4d_model_path, |
| self._function_input, |
| driver=driver) |
| commands.append(iree_im2col_mmt4d) |
| |
| return commands |
| |
| def _generate_gpu(self, driver: str): |
| commands = [] |
| tflite_model_path = os.path.join(self._base_dir, "models", "tflite", |
| self._model_name + ".tflite") |
| tflite = TfliteWrapper(self._tflite_benchmark_binary_path, |
| self._model_name, |
| tflite_model_path, |
| self._input_name, |
| self._input_layer, |
| driver="gpu") |
| tflite.args.append("--gpu_precision_loss_allowed=false") |
| commands.append(tflite) |
| |
| tflite_noxnn = TfliteWrapper(self._tflite_benchmark_binary_path, |
| self._model_name + "_noxnn", |
| tflite_model_path, |
| self._input_name, |
| self._input_layer, |
| driver="gpu") |
| tflite.args.append("--use_xnnpack=false") |
| commands.append(tflite_noxnn) |
| |
| tflite_fp16 = TfliteWrapper(self._tflite_benchmark_binary_path, |
| self._model_name + "_fp16", |
| tflite_model_path, |
| self._input_name, |
| self._input_layer, |
| driver="gpu") |
| tflite.args.append("--gpu_precision_loss_allowed=true") |
| commands.append(tflite_fp16) |
| |
| iree_model_path = os.path.join(self._base_dir, "models", "iree", driver, |
| self._model_name + ".vmfb") |
| iree = IreeWrapper(self._iree_benchmark_binary_path, |
| self._model_name, |
| iree_model_path, |
| self._function_input, |
| driver=driver) |
| commands.append(iree) |
| |
| iree_model_path = os.path.join(self._base_dir, "models", "iree", driver, |
| self._model_name + "_fp16.vmfb") |
| iree = IreeWrapper(self._iree_benchmark_binary_path, |
| self._model_name + "_fp16", |
| iree_model_path, |
| self._function_input, |
| driver=driver) |
| commands.append(iree) |
| |
| iree_model_path = os.path.join(self._base_dir, "models", "iree", driver, |
| self._model_name + "_padfuse.vmfb") |
| iree = IreeWrapper(self._iree_benchmark_binary_path, |
| self._model_name + "_padfuse", |
| iree_model_path, |
| self._function_input, |
| driver=driver) |
| commands.append(iree) |
| return commands |