Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 38 additions & 17 deletions examples/openvino/executor_runner/openvino_executor_runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@
#include <executorch/runtime/platform/log.h>
#include <executorch/runtime/platform/runtime.h>

// Define a fixed-size memory pool for the method allocator (4 MB)
static uint8_t method_allocator_pool[4 * 1024U * 1024U]; // 4 MB

// Define command-line flags for model path and the number of iterations
DEFINE_string(
model_path,
"/home/icx-6338/ynimmaga/delegate.pte", //"model.pte",
"Model serialized in flatbuffer format.");
DEFINE_int32(iteration, 1, "Iterations of inference.");
"",
"Path to the model serialized in flatbuffer format (required).");
DEFINE_int32(
num_iter,
1,
"Number of inference iterations (default is 1).");

using executorch::extension::FileDataLoader;
using executorch::extension::prepare_input_tensors;
Expand All @@ -35,32 +40,42 @@ using executorch::runtime::Result;
using executorch::runtime::Span;

int main(int argc, char** argv) {
// Initialize the runtime environment
executorch::runtime::runtime_init();

// Parse command-line arguments and flags
gflags::ParseCommandLineFlags(&argc, &argv, true);
if (argc != 1) {
std::string msg = "Extra commandline args:";
for (int i = 1; i < argc; i++) {
msg += " " + std::string(argv[i]);
}
ET_LOG(Error, "%s", msg.c_str());

// Check if the model path is provided
if (FLAGS_model_path.empty()) {
std::cerr << "Error: --model_path is required." << std::endl;
std::cerr << "Usage: " << argv[0]
<< " --model_path=<path_to_model> --num_iter=<iterations>" << std::endl;
return 1;
}

// Retrieve the model path and number of iterations
const char* model_path = FLAGS_model_path.c_str();
int num_iterations = FLAGS_num_iter;
std::cout << "Model path: " << model_path << std::endl;
std::cout << "Number of iterations: " << num_iterations << std::endl;

// Load the model using FileDataLoader
Result<FileDataLoader> loader = FileDataLoader::from(model_path);
ET_CHECK_MSG(
loader.ok(),
"FileDataLoader::from() failed: 0x%" PRIx32,
static_cast<uint32_t>(loader.error()));

// Load the program from the loaded model
Result<Program> program = Program::load(&loader.get());
if (!program.ok()) {
ET_LOG(Error, "Failed to parse model file %s", model_path);
return 1;
}
ET_LOG(Info, "Model file %s is loaded.", model_path);

// 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);
Expand All @@ -69,16 +84,19 @@ int main(int argc, char** argv) {
}
ET_LOG(Info, "Using method %s", method_name);

// Retrieve metadata about the method
Result<MethodMeta> method_meta = program->method_meta(method_name);
ET_CHECK_MSG(
method_meta.ok(),
"Failed to get method_meta for %s: 0x%" PRIx32,
method_name,
static_cast<uint32_t>(method_meta.error()));

// Set up a memory allocator for the method
MemoryAllocator method_allocator{
MemoryAllocator(sizeof(method_allocator_pool), method_allocator_pool)};

// Prepare planned buffers for memory planning
std::vector<std::unique_ptr<uint8_t[]>> planned_buffers;
std::vector<Span<uint8_t>> planned_spans;
size_t num_memory_planned_buffers = method_meta->num_memory_planned_buffers();
Expand All @@ -92,8 +110,10 @@ int main(int argc, char** argv) {
HierarchicalAllocator planned_memory(
{planned_spans.data(), planned_spans.size()});

// Set up a memory manager using the method allocator and planned memory
MemoryManager memory_manager(&method_allocator, &planned_memory);

// Load the method into the program
Result<Method> method = program->load_method(method_name, &memory_manager);
ET_CHECK_MSG(
method.ok(),
Expand All @@ -102,44 +122,45 @@ int main(int argc, char** argv) {
static_cast<uint32_t>(method.error()));
ET_LOG(Info, "Method loaded.");

// Prepare the input tensors for the method
auto inputs = prepare_input_tensors(*method);
ET_CHECK_MSG(
inputs.ok(),
"Could not prepare inputs: 0x%" PRIx32,
static_cast<uint32_t>(inputs.error()));
ET_LOG(Info, "Inputs prepared.");

// Measure execution time for inference
auto before_exec = std::chrono::high_resolution_clock::now();
Error status = Error::Ok;
for (int i = 0; i < FLAGS_iteration; ++i) {
for (int i = 0; i < num_iterations; ++i) {
status = method->execute();
}
auto after_exec = std::chrono::high_resolution_clock::now();
double elapsed_time = std::chrono::duration_cast<std::chrono::microseconds>(
after_exec - before_exec)
.count() / 1000.0;

// Log execution time and average time per iteration
ET_LOG(
Info,
"%d inference took %f ms, avg %f ms",
FLAGS_iteration,
num_iterations,
elapsed_time,
elapsed_time / static_cast<float>(FLAGS_iteration));
elapsed_time / static_cast<float>(num_iterations));
ET_CHECK_MSG(
status == Error::Ok,
"Execution of method %s failed with status 0x%" PRIx32,
method_name,
static_cast<uint32_t>(status));
ET_LOG(Info, "Model executed successfully.");

// Retrieve and print the method outputs
std::vector<EValue> outputs(method->outputs_size());
ET_LOG(Info, "%zu outputs: ", outputs.size());
ET_LOG(Info, "%zu Number of outputs: ", outputs.size());
status = method->get_outputs(outputs.data(), outputs.size());
ET_CHECK(status == Error::Ok);
//std::cout << executorch::extension::evalue_edge_items(100);
//for (int i = 0; i < outputs.size(); ++i) {
// std::cout << "Output " << i << ": " << outputs[i] << std::endl;
//}

return 0;
}