样例代码解析
本实践采用模块化设计,基于C++语言结合GE图引擎 API与acl(Ascend Computing Language)API实现,完整代码请单击Link获取,核心组件构成如下:
- ModelInference::Builder:构建器,配置模型参数;封装ModelInference对象的构建过程,提供链式配置接口。
- ModelInference:核心类,提供模型初始化、资源管理、任务调度等核心能力。
- ModelInference::GraphWorker:工作线程,执行异步推理任务的线程单元。
- ModelInference::GraphTask:任务单元,封装单次推理请求(输入/输出和回调)的完整生命周期。
图1为各个组件的UML(Unified Modeling Language)类图:
接口调用流程
样例代码主要执行流程以及涉及接口如下:

- 调用aclInit接口,初始化acl,调用aclrtSetDevice指定运行的Device。
- 构建ModelInference实例并初始化特性开关:开启批量H2D功能、配置AICore控核策略、使用多实例并行。
- ModelInference初始化:
- 提交推理任务到工作线程。下面以一个线程为例,描述工作线程的执行流程:
- 调用GEFinalize,释放系统资源;调用aclFinalize释放acl相关资源。
开发示例
- 包含的头文件,包括acl、C或C++标准库、GE、样例ModelInference的头文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#include <acl.h> #include <acl_rt.h> #include <sstream> #include <random> #include <unordered_map> #include <chrono> #include <atomic> #include <complex> #include <iostream> #include <vector> #include <map> #include "model_inference.h" #include <getopt.h> #include <string>
- acl资源初始化,设置Device。
1 2 3 4 5 6 7 8 9 10 11 12 13
// 初始化acl aclError aerr = aclInit(nullptr); if (aerr != ACL_ERROR_NONE) { std::cerr << "Failed to init ACL, error=" << aerr << std::endl; return -1; } // 指定用于运算的Device aerr = aclrtSetDevice(0); if (aerr != ACL_ERROR_NONE) { std::cerr << "aclrtSetDevice failed, ret=" << aerr << std::endl; aclFinalize(); return -1; }
- 设置推理参数。
1 2 3 4
// 模型文件路径 const std::string model_path = "../data/DCN_v2.pb"; // 模型文件类型 const std::string model_type = "TensorFlow";
- 指定构造模型解析参数,样例模型输入数量为27个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
std::stringstream ss; // 定义输入节点的数量 int input_size = 27; for (int i = 1; i < input_size; ++i) ss << "Input_" << i << ":" << batchSize << ";"; ss << "Input:" << batchSize << ",8"; // 构建一个map,用于配置模型的解析参数 std::map<ge::AscendString, ge::AscendString> parser = { // 设置输出节点 {ge::AscendString(ge::ir_option::OUT_NODES), ge::AscendString("Identity:0")}, // 设置输入shape {ge::AscendString(ge::ir_option::INPUT_SHAPE), ge::AscendString(ss.str().c_str())} };
- 构建ModelInference实例并初始化。
1 2 3 4 5 6 7 8 9 10 11
// 创建 ModelInference实例 auto model_inference = gerec::ModelInference::Builder(cfg.model_path, cfg.model_type) .InputBatchCopy(enableBatchH2D) // 开启批量H2D功能 .AiCoreNum(aiCoreNum) // 配置AICore控核 .MultiInstanceNum(multiInstanceNum) // 多实例并行 .GraphParserParams(cfg.parser_params) // 设置图解析参数 .Build(); if (model_inference->Init() != ge::SUCCESS) { std::cerr << "Init ModelInference failed" << std::endl; return ge::FAILED; }
- 提交推理任务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// 回调函数,用于在异步推理完成后执行清理和统计工作 auto callback = [&](std::shared_ptr<std::vector<gert::Tensor>> outputs, std::shared_ptr<std::vector<gert::Tensor>> inputs, bool status, long long exec_us) { if (status) { // 如果推理成功,更新成功计数和执行时间总和 success_count.fetch_add(1, std::memory_order_relaxed); // 成功次数增加 total_exec_us.fetch_add(exec_us, std::memory_order_relaxed); // 累加执行时间(微秒) } // 释放输出/输入Tensor占用的内存 FreeHostTensors(outputs); FreeHostTensors(inputs); }; // 执行多次异步推理 for (int i = 0; i < num_runs; ++i) { if (model_inference->RunGraphAsync(all_inputs[i], all_outputs[i], callback) != ge::SUCCESS) { std::cerr << "RunGraphAsync failed at " << i << std::endl; return ge::FAILED; } }
RunGraphAsync接口采用异步执行模式,需绑定回调函数(Callback)以处理推理结果。回调函数需满足以下签名规范:
using Callback = std::function<void( std::shared_ptr<std::vector<gert::Tensor>> outputs, // 输出Tensor列表 std::shared_ptr<std::vector<gert::Tensor>> inputs, // 输入Tensor列表 bool status, // 操作执行状态 long long exec_us // 执行时延(微秒) // 执行时延(微秒) )>; - 释放资源。
1 2
// acl去初始化 ret = aclFinalize();
父主题: 推荐网络推理优秀实践
