struct Content
{
AutoStorage<uint8_t> buffer;
const Net *net = nullptr;
std::vector<std::unique_ptr<Session>> sessions;
std::map<const Tensor *, const Session *> tensorMap;
};
Interpreter *Interpreter::createFromFile(const char *file)
{
if (nullptr == file)
{
MNN_PRINT("NULL file for create interpreter\n");
return nullptr;
}
std::unique_ptr<FileLoader> loader(new FileLoader(file));
if (!loader->valid())
{
MNN_PRINT("Create interpreter failed, open %s error\n", file);
return nullptr;
}
bool result = loader->read(); // 读取文件
if (!result)
{
MNN_PRINT("Read file error\n");
return nullptr;
}
if (loader->size() == 0)
{
MNN_PRINT("Create interpreter failed, %s is empty\n", file);
return nullptr;
}
auto net = new Content;
bool success = loader->merge(net->buffer); //合并到AutoStorage<uint8_t> buffer
if (!success)
{
return nullptr;
}
loader.reset();
return createFromBufferInternal(net);
}
Interpreter *Interpreter::createFromBufferInternal(Content *net)
{
if (nullptr == net)
{
MNN_PRINT("Buffer is null for create interpreter\n");
return nullptr;
}
flatbuffers::Verifier verify((const uint8_t *)(net->buffer.get()), net->buffer.size());
if (false == VerifyNetBuffer(verify)) // 验证内存是否符合flatbuffer格式
{
MNN_PRINT("Invalidate buffer to create interpreter\n");
delete net;
return nullptr;
}
net->net = GetNet(net->buffer.get()); // 获取网络
if (nullptr == net->net->oplists())
{
MNN_ERROR("Model has no oplist\n");
delete net;
return nullptr;
}
int opSize = net->net->oplists()->size();
for (int i = 0; i < opSize; ++i)
{
auto op = net->net->oplists()->GetAs<Op>(i); // 验证网络op是否合格
if (nullptr == op || nullptr == op->outputIndexes())
{
MNN_ERROR("Invalid Model, the %d op is empty\n", i);
delete net;
return nullptr;
}
}
return new Interpreter(net);
}
MNN使用FlatBuffers存储模型,这是一个注重性能和资源使用的序列化类库。相较于Protocol Buffers,其更适用于移动设备,FlatBuffers提供更高的性能以及更低的资源需求。
深入浅出 FlatBuffers
Session *Interpreter::createMultiPathSession(const std::vector<ScheduleConfig> &configs)
{
if (nullptr == mNet->buffer.get())
{
MNN_ERROR("The model buffer has been released. Can't create session\n");
return nullptr;
}
// 解析Schedule
auto info = Schedule::schedule(mNet->net, configs);
auto newSession = std::unique_ptr<Session>(new Session(info));
if (!newSession->valid())
{
MNN_PRINT("Invalid Session!!\n");
return nullptr;
}
auto result = newSession.get();
if (info.validForResize)
{
result->resize(); // 做resize,为推理做准备工作
}
mNet->sessions.emplace_back(std::move(newSession));
return result;
}
通过Schedule创建Session,同时对Session进行resize,为推理做准备。