当前位置:   article > 正文

使用Runtime执行推理(C++)_c++runtime

c++runtime

使用Runtime执行推理(C++)
概述
通过MindSpore Lite模型转换后,需在Runtime中完成模型的推理执行流程。本教程介绍如何使用C++接口编写推理代码。
Runtime总体使用流程如下图所示:
在这里插入图片描述

包含的组件及功能如下所述:
Model:MindSpore Lite使用的模型,通过用户构图或直接加载网络,来实例化算子原型的列表。
• Lite Session:提供图编译的功能,并调用图执行器进行推理。
Scheduler:算子异构调度器,根据异构调度策略,为每一个算子选择合适的kernel,构造kernel list,并切分子图。
• Executor:图执行器,执行kernel list,动态分配和释放Tensor。
• Operator:算子原型,包含算子的属性,以及shape、data type和format的推导方法。
• Kernel:算子库提供算子的具体实现,提供算子forward的能力。
• Tensor:MindSpore Lite使用的Tensor,提供了Tensor内存操作的功能和接口。
更多C++ API说明,请参考 API文档。
读取模型
在MindSpore Lite中,模型文件是从模型转换工具转换得到的.ms文件。进行模型推理时,需要从文件系统加载模型,并进行模型解析,这部分操作主要在Model中实现。Model持有权重数据、算子属性等模型数据。
模型通过Model类的静态Import方法从内存数据中创建。函数返回的Model实例是一个指针,通过new创建,不再需要时,需要用户通过delete释放。
如果对运行时内存有较大的限制,可以在Model被图编译以后,使用Free接口来降低内存占用。但一旦调用了某个Model的Free接口,该Model就不能再进行图编译了。
创建会话
使用MindSpore Lite执行推理时,LiteSession是推理的主入口,通过LiteSession我们可以进行图编译、图执行。
创建上下文
上下文会保存会话所需的一些基本配置参数,用于指导图编译和图执行,其定义如下:
MindSpore Lite支持异构推理,推理时的后端配置信息由Context中的device_list_指定,默认存放CPU的DeviceContext。在进行图编译时,会根据device_list_中不同的后端配置信息进行算子选型调度。目前仅支持两种异构,CPU和GPU异构或者CPU和NPU异构。 当配置GPU的DeviceContext时,优先使用GPU推理;当配置NPU的DeviceContext时,优先使用NPU推理。
device_list_[0]必须是CPU的DeviceContext, device_list_[1]是GPU的DeviceContext或者NPU的DeviceContext。暂时不支持同时设置CPU, GPU和NPU三个DeviceContext。
MindSpore Lite内置一个进程共享的线程池,推理时通过thread_num_指定线程池的最大线程数,默认为2线程,推荐最多不超过4个线程,否则可能会影响性能。
MindSpore Lite支持动态内存分配和释放,如果没有指定allocator,推理时会生成一个默认的allocator,也可以通过Context方法在多个Context中共享内存分配器。
如果用户通过new创建Context,不再需要时,需要用户通过delete释放。一般在创建完LiteSession后,Context即可释放。
创建会话
有两种方式可以创建会话:
• 第一种方法是使用上一步创建得到的Context,调用LiteSession的静态static LiteSession *CreateSession(const lite::Context *context)方法来创建LiteSession。函数返回的LiteSession实例是一个指针,通过new创建,不再需要时,需要用户通过delete释放。
• 第二种方法是使用上一步创建得到的Context,以及已经从文件读入的模型buffer和buffer的size,通过调用LiteSession的静态static LiteSession *CreateSession(const char *model_buf, size_t size, const lite::Context *context)方法来创建LiteSession。函数返回的LiteSession实例是一个指针,通过new创建,不再需要时,需要用户通过delete释放。
第二种方法中使用的CreateSession接口是一个简化流程的接口,使用这个接口可以简化调用流程。该接口的功能实现了三个接口的功能:单入参的CreateSession接口,Import接口和CompileGraph接口。
使用示例
下面示例代码演示了Context的创建,以及在两个LiteSession间共享内存池的功能:
auto context = new (std::nothrow) lite::Context;
if (context == nullptr) {
MS_LOG(ERROR) << “New context failed while running %s”, modelName.c_str();
return RET_ERROR;
}

// CPU device context has default values.
auto &cpu_decice_info = context->device_list_[0].device_info_.cpu_device_info_;
// The large core takes priority in thread and core binding methods. This parameter will work in the BindThread interface. For specific binding effect, see the “Run Graph” section.
cpu_decice_info.cpu_bind_mode_ = HIGHER_CPU;
// If GPU device context is set. The preferred backend is GPU, which means, if there is a GPU operator, it will run on the GPU first, otherwise it will run on the CPU.
DeviceContext gpu_device_ctx{DT_GPU, {false}};
// The GPU device context needs to be push_back into device_list to work.
context->device_list_.push_back(gpu_device_ctx);
// Configure the number of worker threads in the thread pool to 2, including the main thread.
context->thread_num_ = 2;
// Allocators can be shared across multiple Contexts.
auto *context2 = new Context();
context2->thread_num_ = context->thread_num_;
context2->allocator = context->allocator;
auto &cpu_decice_info2 = context2->device_list_[0].device_info_.cpu_device_info_;
cpu_decice_info2.cpu_bind_mode_ = cpu_decice_info->cpu_bind_mode_;

// Use Context to create Session.
auto session1 = session::LiteSession::CreateSession(context);
// After the LiteSession is created, the Context can be released.
delete (context);
if (session1 == nullptr) {
MS_LOG(ERROR) << “CreateSession failed while running %s”, modelName.c_str();
return RET_ERROR;
}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/467144
推荐阅读
相关标签
  

闽ICP备14008679号