From 8302911b8085ec09a1432998ac808c32f47fb056 Mon Sep 17 00:00:00 2001 From: ynimmaga Date: Tue, 4 Feb 2025 14:16:13 -0800 Subject: [PATCH 1/3] Get openvino backend device from compile specs --- backends/openvino/preprocess.py | 3 --- backends/openvino/runtime/OpenvinoBackend.cpp | 9 ++++++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/backends/openvino/preprocess.py b/backends/openvino/preprocess.py index 96df9faba85..cd6d5150cf3 100644 --- a/backends/openvino/preprocess.py +++ b/backends/openvino/preprocess.py @@ -12,9 +12,6 @@ from executorch.exir.backend.compile_spec_schema import CompileSpec from openvino.frontend.pytorch.torchdynamo.compile import openvino_compile -SKIP_COMPILE_SPEC_KEYS = {"ImportForever"} - - @final class OpenvinoBackend(BackendDetails): diff --git a/backends/openvino/runtime/OpenvinoBackend.cpp b/backends/openvino/runtime/OpenvinoBackend.cpp index 00be8d9a323..15007b38792 100644 --- a/backends/openvino/runtime/OpenvinoBackend.cpp +++ b/backends/openvino/runtime/OpenvinoBackend.cpp @@ -77,8 +77,15 @@ Result OpenvinoBackend::init( // Wrap the data in a stream std::istringstream compiled_stream(data_string); + auto device = "CPU"; + // Get the device value, if provided in compile sepcs + for (auto& compile_spec : compile_specs) { + if (std::strcmp(compile_spec.key, "device") == 0) + device = static_cast(compile_spec.value.buffer); + } + // Import the model - auto compiled_model = core.import_model(compiled_stream, "CPU"); + auto compiled_model = core.import_model(compiled_stream, device); // Allocate an infer request std::shared_ptr infer_request = std::make_shared(compiled_model.create_infer_request()); From 2cda72b7a0176766a4993488d008ff8e0d2391e7 Mon Sep 17 00:00:00 2001 From: ynimmaga Date: Tue, 4 Feb 2025 15:34:21 -0800 Subject: [PATCH 2/3] Fixed formatting issues --- backends/openvino/CMakeLists.txt | 1 - backends/openvino/__init__.py | 2 +- backends/openvino/partitioner.py | 14 +- backends/openvino/preprocess.py | 11 +- backends/openvino/runtime/OpenvinoBackend.cpp | 223 +++++++++--------- examples/openvino/CMakeLists.txt | 2 - examples/openvino/aot/README.md | 2 - .../openvino/aot/aot_openvino_compiler.py | 48 +++- .../openvino_executor_runner.cpp | 15 +- 9 files changed, 172 insertions(+), 146 deletions(-) diff --git a/backends/openvino/CMakeLists.txt b/backends/openvino/CMakeLists.txt index 129ab0435ac..f3fda7fe5ca 100644 --- a/backends/openvino/CMakeLists.txt +++ b/backends/openvino/CMakeLists.txt @@ -68,4 +68,3 @@ target_link_options(openvino_backend PRIVATE -Wl,-rpath=${OPENVINO_LIB_PATH}) # Install the OpenVINO backend library to the lib directory install(TARGETS openvino_backend DESTINATION lib) - diff --git a/backends/openvino/__init__.py b/backends/openvino/__init__.py index dac275d3f12..7460fe46b0b 100644 --- a/backends/openvino/__init__.py +++ b/backends/openvino/__init__.py @@ -1,4 +1,4 @@ from .partitioner import OpenvinoPartitioner from .preprocess import OpenvinoBackend -__all__ = [OpenvinoBackend, OpenvinoPartitioner] +__all__ = [OpenvinoBackend, OpenvinoPartitioner] diff --git a/backends/openvino/partitioner.py b/backends/openvino/partitioner.py index b0d0e18a0d7..88e94fedb03 100644 --- a/backends/openvino/partitioner.py +++ b/backends/openvino/partitioner.py @@ -1,6 +1,7 @@ from typing import Callable, final, List, Optional, Tuple import torch +import torch.fx as fx from executorch.backends.openvino.preprocess import OpenvinoBackend from executorch.exir.backend.backend_details import CompileSpec from executorch.exir.backend.partitioner import ( @@ -9,12 +10,12 @@ PartitionResult, ) from executorch.exir.backend.utils import tag_constant_data +from openvino.frontend.pytorch.torchdynamo.op_support import OperatorSupport from torch.export.exported_program import ExportedProgram from torch.fx.passes.infra.partitioner import CapabilityBasedPartitioner from torch.fx.passes.operator_support import OperatorSupportBase -import torch.fx as fx -from openvino.frontend.pytorch.torchdynamo.op_support import OperatorSupport + class OpenvinoOperatorsSupport(OperatorSupportBase): @@ -38,10 +39,10 @@ def is_node_supported(self, _, node: torch.fx.Node) -> bool: options = [] op_type = node.target.__name__ supported_ops = OperatorSupport(options)._support_dict - if (op_type == "getitem"): + if op_type == "getitem": return True - if ("torch.ops." + str(op_type) in supported_ops): + if "torch.ops." + str(op_type) in supported_ops: return True else: print("Op not supported: ", "torch.ops." + str(op_type)) @@ -52,7 +53,7 @@ def is_node_supported(self, _, node: torch.fx.Node) -> bool: ) return False - return False + return False @final @@ -82,13 +83,12 @@ def ops_to_not_decompose( return (ops_not_decompose, None) def partition(self, exported_program: ExportedProgram) -> PartitionResult: - options = {} gm = fx.symbolic_trace(exported_program.graph_module) partitioner = CapabilityBasedPartitioner( exported_program.graph_module, OpenvinoOperatorsSupport(self._op_types_to_skip, self._op_names_to_skip), - allows_single_node_partition=True + allows_single_node_partition=True, ) partition_list = partitioner.propose_partitions() diff --git a/backends/openvino/preprocess.py b/backends/openvino/preprocess.py index cd6d5150cf3..e2aefe7d729 100644 --- a/backends/openvino/preprocess.py +++ b/backends/openvino/preprocess.py @@ -1,7 +1,7 @@ import contextlib import struct -from typing import final, List, cast +from typing import cast, final, List import torch from executorch.exir.backend.backend_details import ( @@ -12,6 +12,7 @@ from executorch.exir.backend.compile_spec_schema import CompileSpec from openvino.frontend.pytorch.torchdynamo.compile import openvino_compile + @final class OpenvinoBackend(BackendDetails): @@ -25,8 +26,8 @@ def preprocess( output_names = edge_program.graph_signature.user_outputs args = [] for node in edge_program.graph.nodes: - if (node.target in input_names): - args.append( node.meta["val"]) + if node.target in input_names: + args.append(node.meta["val"]) input_shapes = [] output_shapes = [] @@ -35,7 +36,9 @@ def preprocess( for spec in module_compile_spec: compile_options[spec.key] = spec.value.decode() - compiled = openvino_compile(edge_program.module(), *args, options=compile_options) + compiled = openvino_compile( + edge_program.module(), *args, options=compile_options + ) model_bytes = compiled.export_model() return PreprocessResult(processed_bytes=model_bytes) diff --git a/backends/openvino/runtime/OpenvinoBackend.cpp b/backends/openvino/runtime/OpenvinoBackend.cpp index 15007b38792..f9c7a67ef78 100644 --- a/backends/openvino/runtime/OpenvinoBackend.cpp +++ b/backends/openvino/runtime/OpenvinoBackend.cpp @@ -1,6 +1,6 @@ #include -#include #include +#include #include @@ -31,150 +31,159 @@ namespace backends { namespace openvino { OpenvinoBackend::OpenvinoBackend() { - if (!is_available()) { - //ET_LOG(Error, "OpenVINO runtime is not available. Initialization failed."); - throw std::runtime_error("OpenVINO runtime not available"); - } + if (!is_available()) { + // ET_LOG(Error, "OpenVINO runtime is not available. Initialization + // failed."); + throw std::runtime_error("OpenVINO runtime not available"); + } - //ET_LOG(Info, "OpenVINO runtime successfully verified and initialized."); + // ET_LOG(Info, "OpenVINO runtime successfully verified and initialized."); } bool OpenvinoBackend::is_available() const { - try { - // Create an OpenVINO Core object to verify runtime availability - ov::Core core; - - // Check if at least one device is available - auto devices = core.get_available_devices(); - if (!devices.empty()) { - return true; // OpenVINO is available - } - } catch (const std::exception& e) { - // Log the exception if OpenVINO runtime is not available - ET_LOG(Error, "OpenVINO is not available: %s", e.what()); - } catch (...) { - // Handle any unexpected errors - ET_LOG(Error, "OpenVINO availability check failed due to an unknown error."); - } + try { + // Create an OpenVINO Core object to verify runtime availability + ov::Core core; - return false; // OpenVINO is not available + // Check if at least one device is available + auto devices = core.get_available_devices(); + if (!devices.empty()) { + return true; // OpenVINO is available + } + } catch (const std::exception& e) { + // Log the exception if OpenVINO runtime is not available + ET_LOG(Error, "OpenVINO is not available: %s", e.what()); + } catch (...) { + // Handle any unexpected errors + ET_LOG( + Error, "OpenVINO availability check failed due to an unknown error."); + } + + return false; // OpenVINO is not available } Result OpenvinoBackend::init( BackendInitContext& context, FreeableBuffer* processed, ArrayRef compile_specs) const { + ET_LOG(Info, "OpenvinoBackend::init %p", processed->data()); - ET_LOG(Info, "OpenvinoBackend::init %p", processed->data()); + ov::Core core; + const char* data_ptr = static_cast(processed->data()); + size_t data_size = processed->size(); - ov::Core core; - const char* data_ptr = static_cast(processed->data()); - size_t data_size = processed->size(); - - // Copy data to a string or vector - std::string data_string(data_ptr, data_size); + // Copy data to a string or vector + std::string data_string(data_ptr, data_size); - // Wrap the data in a stream - std::istringstream compiled_stream(data_string); + // Wrap the data in a stream + std::istringstream compiled_stream(data_string); - auto device = "CPU"; - // Get the device value, if provided in compile sepcs - for (auto& compile_spec : compile_specs) { - if (std::strcmp(compile_spec.key, "device") == 0) - device = static_cast(compile_spec.value.buffer); - } + auto device = "CPU"; + // Get the device value, if provided in compile sepcs + for (auto& compile_spec : compile_specs) { + if (std::strcmp(compile_spec.key, "device") == 0) + device = static_cast(compile_spec.value.buffer); + } - // Import the model - auto compiled_model = core.import_model(compiled_stream, device); + // Import the model + auto compiled_model = core.import_model(compiled_stream, device); - // Allocate an infer request - std::shared_ptr infer_request = std::make_shared(compiled_model.create_infer_request()); + // Allocate an infer request + std::shared_ptr infer_request = + std::make_shared(compiled_model.create_infer_request()); - // Allocate execution handle - MemoryAllocator* allocator = context.get_runtime_allocator(); - ExecutionHandle* handle = ET_ALLOCATE_INSTANCE_OR_RETURN_ERROR(allocator, ExecutionHandle); - handle->compiled_model = std::make_shared(compiled_model); - handle->infer_request = infer_request; + // Allocate execution handle + MemoryAllocator* allocator = context.get_runtime_allocator(); + ExecutionHandle* handle = + ET_ALLOCATE_INSTANCE_OR_RETURN_ERROR(allocator, ExecutionHandle); + handle->compiled_model = std::make_shared(compiled_model); + handle->infer_request = infer_request; - return handle; + return handle; } Error OpenvinoBackend::execute( BackendExecutionContext& context, DelegateHandle* input_handle, EValue** args) const { + ExecutionHandle* execution_handle = (ExecutionHandle*)input_handle; - ExecutionHandle* execution_handle = (ExecutionHandle*)input_handle; + auto infer_request = execution_handle->infer_request; - auto infer_request = execution_handle->infer_request; + size_t num_inputs = infer_request->get_compiled_model().inputs().size(); + size_t num_outputs = infer_request->get_compiled_model().outputs().size(); - size_t num_inputs = infer_request->get_compiled_model().inputs().size(); - size_t num_outputs = infer_request->get_compiled_model().outputs().size(); + // Set inputs + for (size_t i = 0; i < num_inputs; i++) { + auto input_tensor = args[i]->toTensor(); + ov::Shape input_shape( + input_tensor.sizes().begin(), input_tensor.sizes().end()); - // Set inputs - for (size_t i = 0; i < num_inputs; i++) { - auto input_tensor = args[i]->toTensor(); - ov::Shape input_shape(input_tensor.sizes().begin(), input_tensor.sizes().end()); + // Convert input tensor to OpenVINO tensor + ov::element::Type ov_type = + convert_to_openvino_type(input_tensor.scalar_type()); + ov::Tensor ov_input_tensor( + ov_type, input_shape, input_tensor.mutable_data_ptr()); - // Convert input tensor to OpenVINO tensor - ov::element::Type ov_type = convert_to_openvino_type(input_tensor.scalar_type()); - ov::Tensor ov_input_tensor(ov_type, input_shape, input_tensor.mutable_data_ptr()); - - infer_request->set_input_tensor(i, ov_input_tensor); - } + infer_request->set_input_tensor(i, ov_input_tensor); + } - // Set outputs - for (size_t i = 0; i < num_outputs; i++) { - auto output_tensor = args[num_inputs+i]->toTensor(); - ov::Shape output_shape(output_tensor.sizes().begin(), output_tensor.sizes().end()); + // Set outputs + for (size_t i = 0; i < num_outputs; i++) { + auto output_tensor = args[num_inputs + i]->toTensor(); + ov::Shape output_shape( + output_tensor.sizes().begin(), output_tensor.sizes().end()); - // Convert input tensor to OpenVINO tensor - ov::element::Type ov_type = convert_to_openvino_type(output_tensor.scalar_type()); - ov::Tensor ov_output_tensor(ov_type, output_shape, output_tensor.mutable_data_ptr()); + // Convert input tensor to OpenVINO tensor + ov::element::Type ov_type = + convert_to_openvino_type(output_tensor.scalar_type()); + ov::Tensor ov_output_tensor( + ov_type, output_shape, output_tensor.mutable_data_ptr()); - infer_request->set_output_tensor(i, ov_output_tensor); - } + infer_request->set_output_tensor(i, ov_output_tensor); + } - // Execute the inference - infer_request->infer(); + // Execute the inference + infer_request->infer(); - return Error::Ok; + return Error::Ok; } void OpenvinoBackend::destroy(DelegateHandle* handle) const { - if (!handle) { - ET_LOG(Info, "Attempted to destroy a null handle."); - return; - } - - // Cast the handle to the appropriate type - ExecutionHandle* execution_handle = static_cast(handle); - - // Clean up resources - if (execution_handle->infer_request) { - execution_handle->infer_request.reset(); // Release the infer request - ET_LOG(Info, "Infer request successfully destroyed."); - } - - if (execution_handle->compiled_model) { - execution_handle->compiled_model.reset(); // Release the compiled model - ET_LOG(Info, "Compiled model successfully destroyed."); - } - - ET_LOG(Info, "Delegate handle destroyed successfully."); + if (!handle) { + ET_LOG(Info, "Attempted to destroy a null handle."); + return; + } + + // Cast the handle to the appropriate type + ExecutionHandle* execution_handle = static_cast(handle); + + // Clean up resources + if (execution_handle->infer_request) { + execution_handle->infer_request.reset(); // Release the infer request + ET_LOG(Info, "Infer request successfully destroyed."); + } + + if (execution_handle->compiled_model) { + execution_handle->compiled_model.reset(); // Release the compiled model + ET_LOG(Info, "Compiled model successfully destroyed."); + } + + ET_LOG(Info, "Delegate handle destroyed successfully."); } -ov::element::Type OpenvinoBackend::convert_to_openvino_type(ScalarType scalar_type) const { - switch (scalar_type) { - case ScalarType::Float: - return ov::element::f32; - case ScalarType::Int: - return ov::element::i32; - case ScalarType::Char: - return ov::element::i8; - default: - throw std::runtime_error("Unsupported scalar type"); - } +ov::element::Type OpenvinoBackend::convert_to_openvino_type( + ScalarType scalar_type) const { + switch (scalar_type) { + case ScalarType::Float: + return ov::element::f32; + case ScalarType::Int: + return ov::element::i32; + case ScalarType::Char: + return ov::element::i8; + default: + throw std::runtime_error("Unsupported scalar type"); + } } } // namespace openvino @@ -184,7 +193,5 @@ ov::element::Type OpenvinoBackend::convert_to_openvino_type(ScalarType scalar_ty namespace { auto backend = executorch::backends::openvino::OpenvinoBackend(); executorch::runtime::Backend backend_id{"OpenvinoBackend", &backend}; -static auto registered = executorch::runtime::register_backend(backend_id); +static auto registered = executorch::runtime::register_backend(backend_id); } // namespace - - diff --git a/examples/openvino/CMakeLists.txt b/examples/openvino/CMakeLists.txt index 961b34efd41..af626ae56d9 100644 --- a/examples/openvino/CMakeLists.txt +++ b/examples/openvino/CMakeLists.txt @@ -94,5 +94,3 @@ set_target_properties( get_filename_component( EXECUTORCH_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE ) - - diff --git a/examples/openvino/aot/README.md b/examples/openvino/aot/README.md index 6c59f1dad41..873f380810c 100644 --- a/examples/openvino/aot/README.md +++ b/examples/openvino/aot/README.md @@ -84,5 +84,3 @@ python aot_openvino_compiler.py --suite huggingface --model bert-base-uncased -- - **Unsupported Input Shape**: Ensure `--input_shape` is provided as a valid list or tuple. - - diff --git a/examples/openvino/aot/aot_openvino_compiler.py b/examples/openvino/aot/aot_openvino_compiler.py index f2f26b03951..9a413380f56 100644 --- a/examples/openvino/aot/aot_openvino_compiler.py +++ b/examples/openvino/aot/aot_openvino_compiler.py @@ -1,15 +1,18 @@ +import argparse + import executorch import timm import torch import torchvision.models as torchvision_models -from transformers import AutoModel -from executorch.exir.backend.backend_details import CompileSpec -from executorch.backends.openvino.preprocess import OpenvinoBackend from executorch.backends.openvino.partitioner import OpenvinoPartitioner +from executorch.backends.openvino.preprocess import OpenvinoBackend from executorch.exir import EdgeProgramManager, to_edge +from executorch.exir.backend.backend_details import CompileSpec from torch.export import export, ExportedProgram + from torch.export.exported_program import ExportedProgram -import argparse +from transformers import AutoModel + # Function to load a model based on the selected suite def load_model(suite: str, model_name: str): @@ -24,6 +27,7 @@ def load_model(suite: str, model_name: str): else: raise ValueError(f"Unsupported model suite: {suite}") + def main(suite: str, model_name: str, input_shape, device: str): # Ensure input_shape is a tuple if isinstance(input_shape, list): @@ -36,7 +40,7 @@ def main(suite: str, model_name: str, input_shape, device: str): model = model.eval() # Provide input - example_args = (torch.randn(*input_shape), ) + example_args = (torch.randn(*input_shape),) # Export to aten dialect using torch.export aten_dialect: ExportedProgram = export(model, example_args) @@ -50,23 +54,41 @@ def main(suite: str, model_name: str, input_shape, device: str): lowered_module = edge_program.to_backend(OpenvinoPartitioner(compile_spec)) # Apply backend-specific passes - exec_prog = lowered_module.to_executorch(config=executorch.exir.ExecutorchBackendConfig()) + exec_prog = lowered_module.to_executorch( + config=executorch.exir.ExecutorchBackendConfig() + ) # Serialize and save it to a file with open(f"{model_name}.pte", "wb") as file: exec_prog.write_to_file(file) print(f"Model exported and saved as {model_name}.pte on {device}.") + if __name__ == "__main__": # Argument parser for dynamic inputs parser = argparse.ArgumentParser(description="Export models with executorch.") - parser.add_argument("--suite", type=str, required=True, choices=["timm", "torchvision", "huggingface"], - help="Select the model suite (timm, torchvision, huggingface).") - parser.add_argument("--model", type=str, required=True, help="Model name to be loaded.") - parser.add_argument("--input_shape", type=eval, required=True, - help="Input shape for the model as a list or tuple (e.g., [1, 3, 224, 224] or (1, 3, 224, 224)).") - parser.add_argument("--device", type=str, default="CPU", - help="Target device for compiling the model (e.g., CPU, GPU). Default is CPU.") + parser.add_argument( + "--suite", + type=str, + required=True, + choices=["timm", "torchvision", "huggingface"], + help="Select the model suite (timm, torchvision, huggingface).", + ) + parser.add_argument( + "--model", type=str, required=True, help="Model name to be loaded." + ) + parser.add_argument( + "--input_shape", + type=eval, + required=True, + help="Input shape for the model as a list or tuple (e.g., [1, 3, 224, 224] or (1, 3, 224, 224)).", + ) + parser.add_argument( + "--device", + type=str, + default="CPU", + help="Target device for compiling the model (e.g., CPU, GPU). Default is CPU.", + ) args = parser.parse_args() diff --git a/examples/openvino/executor_runner/openvino_executor_runner.cpp b/examples/openvino/executor_runner/openvino_executor_runner.cpp index 67bb35d9701..27b5bf6568f 100644 --- a/examples/openvino/executor_runner/openvino_executor_runner.cpp +++ b/examples/openvino/executor_runner/openvino_executor_runner.cpp @@ -21,10 +21,7 @@ DEFINE_string( model_path, "", "Path to the model serialized in flatbuffer format (required)."); -DEFINE_int32( - num_iter, - 1, - "Number of inference iterations (default is 1)."); +DEFINE_int32(num_iter, 1, "Number of inference iterations (default is 1)."); using executorch::extension::FileDataLoader; using executorch::extension::prepare_input_tensors; @@ -50,7 +47,8 @@ int main(int argc, char** argv) { if (FLAGS_model_path.empty()) { std::cerr << "Error: --model_path is required." << std::endl; std::cerr << "Usage: " << argv[0] - << " --model_path= --num_iter=" << std::endl; + << " --model_path= --num_iter=" + << std::endl; return 1; } @@ -75,7 +73,8 @@ int main(int argc, char** argv) { } ET_LOG(Info, "Model file %s is loaded.", model_path); - // Retrieve the method name from the program (assumes the first method is used) + // Retrieve the method name from the program (assumes the first method is + // used) const char* method_name = nullptr; { const auto method_name_result = program->get_method_name(0); @@ -139,7 +138,8 @@ int main(int argc, char** argv) { auto after_exec = std::chrono::high_resolution_clock::now(); double elapsed_time = std::chrono::duration_cast( after_exec - before_exec) - .count() / 1000.0; + .count() / + 1000.0; // Log execution time and average time per iteration ET_LOG( @@ -163,4 +163,3 @@ int main(int argc, char** argv) { return 0; } - From f7dc3e3b2a4d9053f9697a6b15cf6f29b9ef9fd4 Mon Sep 17 00:00:00 2001 From: ynimmaga Date: Tue, 4 Feb 2025 15:42:36 -0800 Subject: [PATCH 3/3] Fixed formatting issues --- backends/openvino/preprocess.py | 2 +- examples/openvino/aot/aot_openvino_compiler.py | 6 ++++++ .../openvino/executor_runner/openvino_executor_runner.cpp | 8 ++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/backends/openvino/preprocess.py b/backends/openvino/preprocess.py index e2aefe7d729..c2e69883c3b 100644 --- a/backends/openvino/preprocess.py +++ b/backends/openvino/preprocess.py @@ -37,7 +37,7 @@ def preprocess( compile_options[spec.key] = spec.value.decode() compiled = openvino_compile( - edge_program.module(), *args, options=compile_options + edge_program.module(), *args, options=compile_options, executorch=True ) model_bytes = compiled.export_model() diff --git a/examples/openvino/aot/aot_openvino_compiler.py b/examples/openvino/aot/aot_openvino_compiler.py index 9a413380f56..eebc39e89de 100644 --- a/examples/openvino/aot/aot_openvino_compiler.py +++ b/examples/openvino/aot/aot_openvino_compiler.py @@ -1,3 +1,9 @@ +# Copyright (c) Intel Corporation +# +# Licensed under the BSD License (the "License"); you may not use this file +# except in compliance with the License. See the license file in the root +# directory of this source tree for more details. + import argparse import executorch diff --git a/examples/openvino/executor_runner/openvino_executor_runner.cpp b/examples/openvino/executor_runner/openvino_executor_runner.cpp index 27b5bf6568f..1886e4f7847 100644 --- a/examples/openvino/executor_runner/openvino_executor_runner.cpp +++ b/examples/openvino/executor_runner/openvino_executor_runner.cpp @@ -22,6 +22,14 @@ DEFINE_string( "", "Path to the model serialized in flatbuffer format (required)."); DEFINE_int32(num_iter, 1, "Number of inference iterations (default is 1)."); +DEFINE_string( + input_list_path, + "", + "Path to the input list file which includes the list of raw input tensor files (optional)."); +DEFINE_string( + output_folder_path, + "", + "Path to the output folder to save raw output tensor files (optional)."); using executorch::extension::FileDataLoader; using executorch::extension::prepare_input_tensors;