|  | # 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 |