Engine实现接口(C++语言)
Engine::Init
初始化Engine实例的相关配置。该接口在engine.h中定义。
该Init接口是可选的,用户根据实际情况决定是否需要重载实现。
函数格式
HIAI_StatusT Engine::Init(const AIConfig &config, const vector<AIModelDescription> &modelDesc)
参数说明
参数 |
说明 |
取值范围 |
---|---|---|
config |
Engine配置项。 |
- |
modelDesc |
模型描述。 |
- |
返回值
返回的错误码是由用户提前注册的,具体注册方式见错误码注册。
错误码示例
本API(Application Programming Interface)的错误码由用户进行注册。
重载实现示例
初始化推理Engine,在初始化过程中通过模型管家(AIModelManager)的AIModelManager::Init接口加载模型。
HIAI_StatusT FrameworkerEngine::Init(const hiai::AIConfig& config, const std::vector<hiai::AIModelDescription>& model_desc) { hiai::AIStatus ret = hiai::SUCCESS; // init ai_model_manager_ if (nullptr == ai_model_manager_) { ai_model_manager_ = std::make_shared<hiai::AIModelManager>(); } std::cout<<"FrameworkerEngine Init"<<std::endl; HIAI_ENGINE_LOG("FrameworkerEngine Init"); for (int index = 0; index < config.items_size(); ++index) { const ::hiai::AIConfigItem& item = config.items(index); // loading model if(item.name() == "model_path") { const char* model_path = item.value().data(); std::vector<hiai::AIModelDescription> model_desc_vec; hiai::AIModelDescription model_desc_; model_desc_.set_path(model_path); model_desc_vec.push_back(model_desc_); ret = ai_model_manager_->Init(config, model_desc_vec); if (hiai::SUCCESS != ret) { HIAI_ENGINE_LOG(this, HIAI_AI_MODEL_MANAGER_INIT_FAIL, "[DEBUG] fail to init ai_model"); return HIAI_AI_MODEL_MANAGER_INIT_FAIL; } } } HIAI_ENGINE_LOG("FrameworkerEngine Init success"); return HIAI_OK; }
宏:HIAI_DEFINE_PROCESS
用户直接调用该宏定义Engine的输入与输出端口数。该宏在engine.h中定义。
本宏封装用到了以下函数:
HIAI_StatusT Engine::InitQueue(const uint32_t& in_port_num, const uint32_t& out_port_num);
相关宏:
在HIAI_IMPL_ENGINE_PROCESS(name, engineClass, inPortNum)之前调用此宏。
宏格式
HIAI_DEFINE_PROCESS(inputPortNum, outputPortNum)
参数说明
参数 |
说明 |
取值范围 |
---|---|---|
inputPortNum |
Engine的输入端口数。 |
- |
outputPortNum |
Engine的输出端口数。 |
- |
调用示例
#define FRAMEWORK_ENGINE_INPUT_SIZE 1 #define FRAMEWORK_ENGINE_OUTPUT_SIZE 1 * @[in]: 定义一个输入端口,一个输出端口*/ HIAI_DEFINE_PROCESS(FRAMEWORK_ENGINE_INPUT_SIZE, FRAMEWORK_ENGINE_OUTPUT_SIZE)
宏:HIAI_IMPL_ENGINE_PROCESS
用户需要重载实现该宏,用于定义Engine的具体实现。该宏在engine.h中定义。
本宏封装用到了以下函数:
static HIAIEngineFactory* GetInstance(); HIAI_StatusT HIAIEngineFactory::RegisterEngineCreator(const std::string& engine_name,HIAI_ENGINE_FUNCTOR_CREATOR engineCreatorFunc); HIAI_StatusT HIAIEngineFactory::UnRegisterEngineCreator(const std::string& engine_name);
相关宏:
在HIAI_DEFINE_PROCESS(inputPortNum, outputPortNum)之后调用本宏。
宏格式
HIAI_IMPL_ENGINE_PROCESS(name, engineClass, inPortNum)
参数说明
参数 |
说明 |
取值范围 |
---|---|---|
name |
Config的Engine名称。 |
- |
engineClass |
Engine的实现类名称。 |
- |
inPortNum |
输入的端口数。 |
- |
返回值
返回的错误码由用户提前注册。
错误码示例
该API的错误码由用户进行注册。
重载实现样例
定义推理Engine的实现,在实现过程中通过模型管家(AIModelManager)的AIModelManager::Process接口执行模型推理。
HIAI_IMPL_ENGINE_PROCESS("FrameworkerEngine", FrameworkerEngine, FRAMEWORK_ENGINE_INPUT_SIZE) { hiai::AIStatus ret = hiai::SUCCESS; HIAI_StatusT hiai_ret = HIAI_OK; // receive data //arg0表示Engine的输入端口(编号为0),如果有多个输入端口,可依次通过arg1(编号为1的输入端口)、arg2(编号为2的输入端口)等来对应输入端口。通过输入端口获取上一个Engine发送的数据。 std::shared_ptr<std::string> input_arg = std::static_pointer_cast<std::string>(arg0); if (nullptr == input_arg) { HIAI_ENGINE_LOG(this, HIAI_INVALID_INPUT_MSG, "[DEBUG] input arg is invalid"); return HIAI_INVALID_INPUT_MSG; } std::cout<<"FrameworkerEngine Process"<<std::endl; // prapare for calling the process of ai_model_manager_ std::vector<std::shared_ptr<hiai::IAITensor>> input_data_vec; uint32_t len = 75264; HIAI_ENGINE_LOG("FrameworkerEngine:Go to Process"); std::cout << "HIAIAippOp::Go to process" << std::endl; std::shared_ptr<hiai::AINeuralNetworkBuffer> neural_buffer = std::shared_ptr<hiai::AINeuralNetworkBuffer>(new hiai::AINeuralNetworkBuffer());//std::static_pointer_cast<hiai::AINeuralNetworkBuffer>(input_data); neural_buffer->SetBuffer((void*)(input_arg->c_str()), (uint32_t)(len)); std::shared_ptr<hiai::IAITensor> input_data = std::static_pointer_cast<hiai::IAITensor>(neural_buffer); input_data_vec.push_back(input_data); // call Process and inference hiai::AIContext ai_context; std::vector<std::shared_ptr<hiai::IAITensor>> output_data_vec; ret = ai_model_manager_->CreateOutputTensor(input_data_vec, output_data_vec); if (hiai::SUCCESS != ret) { HIAI_ENGINE_LOG(this, HIAI_AI_MODEL_MANAGER_PROCESS_FAIL, "[DEBUG] fail to process ai_model"); return HIAI_AI_MODEL_MANAGER_PROCESS_FAIL; } ret = ai_model_manager_->Process(ai_context, input_data_vec, output_data_vec, 0); if (hiai::SUCCESS != ret) { HIAI_ENGINE_LOG(this, HIAI_AI_MODEL_MANAGER_PROCESS_FAIL, "[DEBUG] fail to process ai_model"); return HIAI_AI_MODEL_MANAGER_PROCESS_FAIL; } std::cout<<"[DEBUG] output_data_vec size is "<< output_data_vec.size()<<std::endl; for (uint32_t index = 0; index < output_data_vec.size(); index++) { // send data of inference to destEngine std::shared_ptr<hiai::AINeuralNetworkBuffer> output_data = std::static_pointer_cast<hiai::AINeuralNetworkBuffer>(output_data_vec[index]); std::shared_ptr<std::string> output_string_ptr = std::shared_ptr<std::string>(new std::string((char*)output_data->GetBuffer(), output_data->GetSize())); hiai_ret = SendData(0, "string", std::static_pointer_cast<void>(output_string_ptr)); if (HIAI_OK != hiai_ret) { HIAI_ENGINE_LOG(this, HIAI_SEND_DATA_FAIL, "fail to send data"); return HIAI_SEND_DATA_FAIL; } } return HIAI_OK; }
Engine::SetDataRecvFunctor
设置Engine接收消息的回调函数。该接口在engine.h中定义。
该接口需要与DataRecvInterface::RecvData接口配合使用,详细原理如下:
- 定义一个DataRecvInterface类的子类(例如DdkDataRecvInterface),初始化一个子类的对象。
- 调用Engine::SetDataRecvFunctor接口将DdkDataRecvInterface类的对象设置成回调函数。
- 调用Engine::SendData函数将对应的输入数据发送到对应的输出端口。
- 调用DdkDataRecvInterface类的RecvData函数返回数据。
函数格式
HIAI_StatusT Engine::SetDataRecvFunctor(const uint32_t portId, const shared_ptr<DataRecvInterface>& userDefineDataRecv)
参数说明
参数 |
说明 |
取值范围 |
---|---|---|
portId |
端口ID。 |
- |
userDefineDataRecv |
用户自定义的数据接收回调函数。 |
- |
返回值
返回的部分错误码请参见“错误码示例”中的“错误码”列。
错误码示例
序号 |
错误码 |
错误码描述 |
---|---|---|
1 |
HIAI_OK |
running ok |
2 |
HIAI_PORT_ID_ERROR |
port id error |
Engine::SendData
将数据从本Engine发送到指定port_id。该接口在engine.h中定义。
在跨侧(Host->Device或Device->Host)传输数据时,该接口采用DMA(Direct Memory Access)传送方式,可能会影响CPU对中断请求的及时响应与处理,例如影响调用new或者malloc分配内存时的性能。
函数格式
HIAI_StatusT Engine::SendData(uint32_t portId, const std::string& messageName, const shared_ptr<void>& dataPtr, uint32_t timeOut = TIME_OUT_VALUE);
参数说明
参数 |
说明 |
取值范围 |
---|---|---|
portId |
Engine的输出端口号。 |
- |
messageName |
当前发送的消息名(该消息必须已经调用HiAI提供的宏已经注册过)。 |
- |
dataPtr |
指向具体的消息指针。 |
- |
timeOut |
调用该接口发送数据时的一次超时时间,不指定timeout参数时,默认的一次超时时间为500ms。 若发送数据超时,系统后台会再次尝试发送数据,最大尝试16次。 |
- |
返回值
返回的部分错误码请参见“错误码示例”中的“错误码”列。
错误码示例
序号 |
错误码 |
错误码描述 |
---|---|---|
1 |
HIAI_OK |
running ok |
2 |
HIAI_ENGINE_NULL_POINTER |
null pointer |
3 |
HIAI_GRAPH_ENGINE_NOT_EXIST |
engine not exist |
4 |
HIAI_GRAPH_SRC_PORT_NOT_EXIST |
src port not exist |
调用示例
/** * @file multi_input_output_engine_example.h * * Copyright(c)<2018>, <Huawei Technologies Co.,Ltd> * * @version 1.0 * * @date 2018-4-25 */ #ifndef MULTI_INPUT_OUTPUT_ENGINE_EXAMPLE_H_ #define MULTI_INPUT_OUTPUT_ENGINE_EXAMPLE_H_ #include "hiaiengine/engine.h" #include "hiaiengine/data_type.h" #include "hiaiengine/multitype_queue.h" #define MULTI_INPUT_OUTPUT_ENGINE_EXAMPLE_INPUT_SIZE 3 #define MULTI_INPUT_OUTPUT_ENGINE_EXAMPLE_OUTPUT_SIZE 2 namespace hiai { // Define New Engine class HIAIMultiEngineExample : public Engine { public: HIAIMultiEngineExample() : input_que_(MULTI_INPUT_OUTPUT_ENGINE_EXAMPLE_INPUT_SIZE) {} // 重载父类Engine的Init HIAI_StatusT Init(const AIConfig& config, const std::vector<AIModelDescription>& model_desc) { return HIAI_OK; } /** * @ingroup hiaiengine * @brief HIAI_DEFINE_PROCESS * @[in]: 定义一个输入端口,一个输出端口 */ HIAI_DEFINE_PROCESS(MULTI_INPUT_OUTPUT_ENGINE_EXAMPLE_INPUT_SIZE, MULTI_INPUT_OUTPUT_ENGINE_EXAMPLE_OUTPUT_SIZE) private: // 私有实现一个成员变量,用来缓存输入队列 hiai::MultiTypeQueue input_que_; }; } #endif //MULTI_INPUT_OUTPUT_ENGINE_EXAMPLE_H_
/** * @file multi_input_output_engine_example.h * * Copyright(c)<2018>, <Huawei Technologies Co.,Ltd> * * @version 1.0 * * @date 2018-4-25 */ #include "multi_input_output_engine_example.h" #include "use_def_data_type.h" #include "use_def_errorcode.h" namespace hiai { /** * @ingroup hiaiengine * @brief HIAI_DEFINE_PROCESS : 实现多端口输入输出处理流程 * @[in]: 定义一个输入端口,一个输出端口, * 并该Engine注册,其名为“HIAIMultiEngineExample” */ HIAI_IMPL_ENGINE_PROCESS("HIAIMultiEngineExample", HIAIMultiEngineExample, MULTI_INPUT_OUTPUT_ENGINE_EXAMPLE_INPUT_SIZE) { // This Engine has three input args and two output // 每个端口接收到的数据可能不是同一个时刻,因此某些输入端口可能是空的 input_que_.PushData(0,arg0); input_que_.PushData(1,arg1); input_que_.PushData(2,arg2); std::shared_ptr<void> input_arg1; std::shared_ptr<void> input_arg2; std::shared_ptr<void> input_arg3; // 仅当三个端口都有输入数据时才继续后续处理,方式一 if (!input_que_.PopAllData(input_arg1, input_arg2, input_arg3)) { HIAI_ENGINE_LOG(this, HIAI_INVALID_INPUT_MSG, "fail to process"); return HIAI_INVALID_INPUT_MSG; } // 仅当三个端口都有输入数据时才继续后续处理,方式二 /* if (!(input_que_.FrontData(0, input_arg1) && input_que_.FrontData(1, input_arg2) && input_que_.FrontData(2, input_arg3))) { HIAI_ENGINE_LOG(this, HIAI_INVALID_INPUT_MSG, "fail to process"); return HIAI_INVALID_INPUT_MSG; } else { input_que_.PopData(0, input_arg1); input_que_.PopData(1, input_arg2); input_que_.PopData(2, input_arg3); } */ // // 中间业务逻辑可以直接调用 DVPP API或AIModelManger API 处理。 // // 分配内存用来保存结果 std::shared_ptr<UseDefDataTypeT> output1 = std::make_shared<UseDefDataTypeT>(); std::shared_ptr<UseDefTemplateDataType<uint64_t, uint64_t, uint64_t>> output2 = std::make_shared<UseDefTemplateDataType<uint64_t, uint64_t, uint64_t>>(); // 填充输出数据结构,例如简单赋值 *output1 = *input_arg2; *output2 = *input_arg3; // 将输出端口发送到端口0 hiai::Engine::SendData(0, "UseDefDataTypeT", std::static_pointer_cast<void>(output1)); // 将输出端口发送到端口1 hiai::Engine::SendData(1, "UseDefTemplateDataType_uint64_t_uint64_t_uint64_t", std::static_pointer_cast<void>(output2)); return HIAI_OK; } }