e2a5e228cb10a997308dd966c941771d2023b0fa
[platform/upstream/hailort.git] /
1 /**
2  * Copyright (c) 2020-2023 Hailo Technologies Ltd. All rights reserved.
3  * Distributed under the MIT license (https://opensource.org/licenses/MIT)
4  **/
5 /**
6  * @file async_infer_functionality_example.cpp
7  * This example demonstrates the Async Infer API usage with a specific model with multiple inputs and outputs
8  * and changes configutrations of the streams.
9  **/
10
11 #include "hailo/hailort.hpp"
12
13 #include <iostream>
14
15 #if defined(__unix__)
16 #include <sys/mman.h>
17 #endif
18
19 #define FRAMES_COUNT (100)
20
21 using namespace hailort;
22
23 static std::shared_ptr<uint8_t> page_aligned_alloc(size_t size)
24 {
25 #if defined(__unix__)
26     auto addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
27     if (MAP_FAILED == addr) throw std::bad_alloc();
28     return std::shared_ptr<uint8_t>(reinterpret_cast<uint8_t*>(addr), [size](void *addr) { munmap(addr, size); });
29 #elif defined(_MSC_VER)
30     auto addr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
31     if (!addr) throw std::bad_alloc();
32     return std::shared_ptr<uint8_t>(reinterpret_cast<uint8_t*>(addr), [](void *addr){ VirtualFree(addr, 0, MEM_RELEASE); });
33 #else
34 #pragma error("Aligned alloc not supported")
35 #endif
36 }
37
38 int main()
39 {
40     auto vdevice = VDevice::create();
41     if (!vdevice) {
42         std::cerr << "Failed create vdevice, status = " << vdevice.status() << std::endl;
43         return vdevice.status();
44     }
45
46     auto infer_model_exp = vdevice.value()->create_infer_model("hefs/multi_network_shortcut_net.hef");
47     if (!infer_model_exp) {
48         std::cerr << "Failed to create infer model, status = " << infer_model_exp.status() << std::endl;
49         return infer_model_exp.status();
50     }
51     auto infer_model = infer_model_exp.release();
52
53     infer_model->input("multi_network_shortcut_net_scope1/input_layer_0")->set_format_type(HAILO_FORMAT_TYPE_FLOAT32);
54     infer_model->output("multi_network_shortcut_net_scope1/shortcut0")->set_format_type(HAILO_FORMAT_TYPE_FLOAT32);
55     infer_model->input("multi_network_shortcut_net_scope2/input_layer_1")->set_format_type(HAILO_FORMAT_TYPE_FLOAT32);
56     infer_model->output("multi_network_shortcut_net_scope2/shortcut1")->set_format_type(HAILO_FORMAT_TYPE_FLOAT32);
57
58     auto configured_infer_model = infer_model->configure();
59     if (!configured_infer_model) {
60         std::cerr << "Failed to create configured infer model, status = " << configured_infer_model.status() << std::endl;
61         return configured_infer_model.status();
62     }
63
64     // We store buffers vector here as a guard for the memory. The buffer will be freed only after
65     // configured_infer_model will be released.
66     std::vector<std::shared_ptr<uint8_t>> buffer_guards;
67
68     auto bindings = configured_infer_model->create_bindings();
69     if (!bindings) {
70         std::cerr << "Failed to create infer bindings, status = " << bindings.status() << std::endl;
71         return bindings.status();
72     }
73
74     for (const auto &input_name : infer_model->get_input_names()) {
75         size_t input_frame_size = infer_model->input(input_name)->get_frame_size();
76         auto input_buffer = page_aligned_alloc(input_frame_size);
77         auto status = bindings->input(input_name)->set_buffer(MemoryView(input_buffer.get(), input_frame_size));
78         if (HAILO_SUCCESS != status) {
79             std::cerr << "Failed to set infer input buffer, status = " << status << std::endl;
80             return status;
81         }
82
83         buffer_guards.push_back(input_buffer);
84     }
85
86     for (const auto &output_name : infer_model->get_output_names()) {
87         size_t output_frame_size = infer_model->output(output_name)->get_frame_size();
88         auto output_buffer = page_aligned_alloc(output_frame_size);
89         auto status = bindings->output(output_name)->set_buffer(MemoryView(output_buffer.get(), output_frame_size));
90         if (HAILO_SUCCESS != status) {
91             std::cerr << "Failed to set infer output buffer, status = " << status << std::endl;
92             return status;
93         }
94
95         buffer_guards.push_back(output_buffer);
96     }
97
98     AsyncInferJob last_infer_job;
99     for (uint32_t i = 0; i < FRAMES_COUNT; i++) {
100         // Waiting for available requests in the pipeline
101         auto status = configured_infer_model->wait_for_async_ready(std::chrono::milliseconds(1000));
102         if (HAILO_SUCCESS != status) {
103             std::cerr << "Failed to wait for async ready, status = " << status << std::endl;
104             return status;
105         }
106
107         auto job = configured_infer_model->run_async(bindings.value(), [] (const AsyncInferCompletionInfo &/*completion_info*/) {
108             // Use completion_info to get the job status and the corresponding bindings
109         });
110         if (!job) {
111             std::cerr << "Failed to start async infer job, status = " << job.status() << std::endl;
112             return job.status();
113         }
114         job->detach();
115
116         if (i == FRAMES_COUNT - 1) {
117             last_infer_job = job.release();
118         }
119     }
120
121     // Wait for last infer to finish
122     auto status = last_infer_job.wait(std::chrono::milliseconds(1000));
123     if (HAILO_SUCCESS != status) {
124         std::cerr << "Failed to wait for infer to finish, status = " << status << std::endl;
125         return status;
126     }
127     
128     return HAILO_SUCCESS;
129 }