#include <iostream>#include "hobot/dnn/hb_dnn.h"#include "hobot/hb_ucp.h"#include "hobot/hb_ucp_sys.h"int main(int argc, char **argv) { // Step 1: Load the model hbDNNPackedHandle_t packed_dnn_handle; const char* model_file_name= "./mobilenetv1/mobilenetv1_224x224_nv12.hbm"; hbDNNInitializeFromFiles(&packed_dnn_handle, &model_file_name, 1); // Step 2: Get model names const char **model_name_list; int model_count = 0; hbDNNGetModelNameList(&model_name_list, &model_count, packed_dnn_handle); // Step 3: Get dnn_handle hbDNNHandle_t dnn_handle; hbDNNGetModelHandle(&dnn_handle, packed_dnn_handle, model_name_list[0]); // Step 4: Prepare input data int input_count = 0; hbDNNGetInputCount(&input_count, dnn_handle); std::vector<hbDNNTensor> input(input_count); for (int i = 0; i < input_count; i++) { hbDNNGetInputTensorProperties(&input[i].properties, dnn_handle, i); auto &mem = input[i].sysMem; /* 1. For dynamic input, you need to set the corresponding dynamic parameters in input[i].properties. 2. Call hbUCPMalloc/hbUCPMallocCached to apply for the corresponding memory size based on the model input. such as hbUCPMallocCached(&mem, size, 0); 3. Determine whether the input needs quantization or padding based on properties, then fill the input data into mem. 4. If the memory is a cacheable, you must actively perform a flush operation after writing. such as hbUCPMemFlush(&mem, HB_SYS_MEM_CACHE_CLEAN); */ } // Step 5: Prepare storage space for the output data of the model int output_count = 0; hbDNNGetOutputCount(&output_count, dnn_handle); std::vector<hbDNNTensor> output(output_count); for (int i = 0; i < output_count; i++) { hbDNNTensorProperties &output_properties = output[i].properties; hbDNNGetOutputTensorProperties(&output_properties, dnn_handle, i); int out_aligned_size = output_properties.alignedByteSize; hbUCPSysMem &mem = output[i].sysMem; hbUCPMallocCached(&mem, out_aligned_size, 0); } // Step 6: Create the asynchronous inference task hbUCPTaskHandle_t task_handle{nullptr}; hbDNNInferV2(&task_handle, output.data(), input.data(), dnn_handle); // Step 7: Submit the task hbUCPSchedParam infer_sched_param; HB_UCP_INITIALIZE_SCHED_PARAM(&infer_sched_param); hbUCPSubmitTask(task_handle, &infer_sched_param); // Step 8: Wait for the task to end hbUCPWaitTaskDone(task_handle, 0); // Step 9: Parse model output, here we take the classification model as an example to get the top1 result for (int i = 0; i < output_count; i++) { // For output memory that applies for the cacheable attribute, it needs to be actively flushed before reading. hbUCPMemFlush(&(output[i].sysMem), HB_SYS_MEM_CACHE_INVALIDATE); /* 1. Determine whether the output data has padding, whether inverse quantization is required, and the quantization parameter information required for inverse quantization, etc. 2. parsing process. */ } // Release the task hbUCPReleaseTask(task_handle); // Release the memory for (int i = 0; i < input_count; i++) { hbUCPFree(&(input[i].sysMem)); } for (int i = 0; i < output_count; i++) { hbUCPFree(&(output[i].sysMem)); } // Release the model hbDNNRelease(packed_dnn_handle); return 0;}