文章大纲
引言
前面文章介绍了Mindspore Lite AI 的主要数据结构以及模型加载的第一个流程模型文件Buffer封装转为Model对象的核心API,这一篇接着往下介绍LiteSession处理Model对象的后续流程。
一、LiteSession 概述
LiteSession类是一个用于管理和执行计算图的类,它主要负责在执行神经网络模型时进行节点的调度和执行。在LiteSession中,通常会维护模型的上下文信息、分配内存、管理模型中的各个节点(kernels)以及执行这些节点的逻辑。LiteSession的功能和作用包括但不限于:
节点管理:维护一个计算图中的所有节点,并负责它们的创建和销毁。
执行调度:控制各个节点的执行顺序,确保数据的正确流动和计算的顺利进行。
资源管理:负责内存的分配和释放,优化运行时资源的使用。
回调机制:支持在节点执行前后注册回调函数,以便于进行日志记录、性能监控等操作。
二、LiteSession::Init(const std::shared_ptr &context)
设置并初始化一个LiteSession的执行环境,确保环境中的所有必要组件(线程池、上下文、内核插件、计算委托、GPU运行时)正常工作
int LiteSession::Init(const std::shared_ptr<InnerContext> &context) {
bool expected = false;
if (!is_running_.compare_exchange_strong(expected, true)) {
MS_LOG(ERROR) << "Not support multi-threading";
return RET_ERROR;
}
if (!PlatformInstructionSetSupportCheck()) {
MS_LOG(ERROR) << "Device not support isa";
return RET_NOT_SUPPORT;
}
//初始化线程池
auto status = InitSharedThreadPool();
...
auto ret = ContextInit(context);
...
ret = AscendInit(context);
...
ret = DelegateInit();
...
ret = InitGPURuntime();
...
is_running_.store(false);
return RET_OK;
}
1、LiteSession::ContextInit
初始化与计算相关的上下文管理,包括为后续的计算准备所需的上下文环境,以及设置与线程相关的配置。在实现过程中,函数检查了输入有效性,进行了上下文的初始化和转换,设置了线程池的参数,同时也考虑到了特定平台(如iOS)和并行计算的需求
int LiteSession::ContextInit(const std::shared_ptr<InnerContext> &context) {
...
this->context_ = context;
context_->SetBindRunnerId(runner_id_);
auto ret = this->context_->Init();
...
ms_context_ = MSContextFromContext(context);
...
#ifdef MS_COMPILE_IOS
context_->thread_pool_->SetMaxSpinCount(kDefaulLiteIosSpinCount);
context_->thread_pool_->SetMinSpinCount(kDefaulLiteIosSpinCount);
#endif
#if defined(PARALLEL_INFERENCE) && defined(ENABLE_MINDRT)
if (context_->inter_op_parallel_num_ > 1 && !runner_id_.empty() &&
ParallelThreadPoolManager::GetInstance()->GetEnableSharedThreadPool(runner_id_)) {
MS_LOG(INFO) << "Enable subgraph parallelism and enable thread pool sharing";
ParallelThreadPoolManager::GetInstance()->BindPoolToRunner(context_->thread_pool_, config_info_);
}
#endif
return RET_OK;
}
2、LiteSession::DelegateInit()
初始化模型的委托(Delegate),这里的委托可以是用于加速模型推理的计算后端,例如NPU、GPU或某些特定的API(如NNAPI和CoreML)
int LiteSession::DelegateInit() {
#ifndef DELEGATE_CLIP
int ret = RET_OK;
if (context_->delegate != nullptr) {
MS_LOG(ERROR) << "NH#context_->IsDeviceTypeEnabled(DT_NPU)";
delegate_ = context_->delegate;
delegate_device_type_ = -1;
} else if (context_->delegate_mode_ != kNoDelegate) {
switch (context_->delegate_mode_) {
case kNNAPI:
MS_LOG(ERROR) << "NH#(context_->delegate_mode_ != kNoDelegate CreateNNAPIDelegate";
ret = CreateNNAPIDelegate();
break;
case kCoreML:
MS_LOG(ERROR) << "NH#(context_->delegate_mode_ != kNoDelegate CreateCoreMLDelegate";
ret = CreateCoreMLDelegate();
break;
default:
return RET_ERROR;
}
} else {
//cpu方式的话会进到这里但是不会创建Delegate
MS_LOG(ERROR) << "NH#context_->IsDeviceTypeEnabled(DT_NPU)";
if (context_->IsDeviceTypeEnabled(DT_NPU)) {
MS_LOG(ERROR) << "NH#context_->IsDeviceTypeEnabled(DT_NPU) DT_NPU";
ret = CreateNPUDelegate();
} else if (context_->IsDeviceTypeEnabled(DT_GPU)) {
MS_LOG(ERROR) << "NH#context_->IsDeviceTypeEnabled(DT_NPU) DT_GPU";
ret = CreateTensorRTDelegate();
} else if (context_->IsDeviceTypeEnabled(DT_NNRT)) {
//nnrt方式,都需要创建delegate,
MS_LOG(ERROR) << "NH#context_->IsDeviceTypeEnabled(DT_NPU) DT_NNRT";
ret = CreateNNRTDelegate();
}
}
if (ret != RET_OK) {
return ret;
}
if (delegate_ != nullptr) {
auto delegate_ret = delegate_->Init();
if (delegate_ret == mindspore::kLiteNotSupport) {
MS_LOG(DEBUG) << "Delegate is unsupported";
delegate_.reset();
delegate_ = nullptr;
} else if (delegate_ret == mindspore::kSuccess) {
MS_LOG(INFO) << "Delegate init successfully";
} else {
MS_LOG(ERROR) << "Delegate init failed";
return RET_ERROR;
}
}
#endif
return RET_OK;
}
Mindspore 本身提供了所谓的“委托机制”,可以把模型加载和推理的工作委托给其他第三方进行,比如NNRT,以上仅仅是LiteSession 的部分Init工作,未完待续。