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> bufferif (!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;}// 解析Scheduleauto 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,为推理做准备。
