| 33 | } |
| 34 | |
| 35 | static std::vector<std::shared_ptr<BufferStorage>> preRearrangeWeights( // NOLINT |
| 36 | Schedule::ScheduleInfo& scheduleInfo, Backend* firstbackend, Backend* backupBackend, const Module* base = nullptr) { |
| 37 | std::map<const std::string, std::shared_ptr<Execution>> base_executions; |
| 38 | if (base != nullptr) { |
| 39 | // has base module |
| 40 | auto static_module = getStaticModule(base); |
| 41 | if (static_module) { |
| 42 | auto session = static_module->getSession(); |
| 43 | std::vector<Schedule::OpCacheInfo> op_caches = session->getPipelineInfo(0).second; |
| 44 | for (auto& op_cache : op_caches) { |
| 45 | const auto& exe_cache = op_cache.executionCache; |
| 46 | for (const auto& exe_item : exe_cache) { |
| 47 | if (exe_item.first->name()) { |
| 48 | base_executions.insert(std::make_pair(exe_item.first->name()->str(), exe_item.second)); |
| 49 | } |
| 50 | } |
| 51 | } |
| 52 | } |
| 53 | } |
| 54 | FileLoader loader(scheduleInfo.externalWeightPath.c_str()); |
| 55 | auto&& pipelineInfo = scheduleInfo.pipelineInfo[0].second; |
| 56 | std::vector<std::shared_ptr<BufferStorage>> splitOps(pipelineInfo.size()); |
| 57 | // KV Cache sharing: registry of Attention executions by layer_index for clone-based reuse |
| 58 | std::map<int, std::shared_ptr<Execution>> kvAttentionRegistry; |
| 59 | for (int i = 0; i < pipelineInfo.size(); ++i) { |
| 60 | auto& info = pipelineInfo[i]; |
| 61 | auto op = pipelineInfo[i].op; |
| 62 | std::unique_ptr<OpT> op_table(op->UnPack()); |
| 63 | std::shared_ptr<Execution> exe; |
| 64 | Backend* backend = firstbackend; |
| 65 | if (info.type == Schedule::CONSTANT) { |
| 66 | backend = backupBackend; |
| 67 | } |
| 68 | switch (op->type()) { |
| 69 | case MNN::OpType_DepthwiseConvInt8: |
| 70 | case MNN::OpType_ConvInt8: |
| 71 | case MNN::OpType_ConvolutionDepthwise: |
| 72 | case MNN::OpType_Convolution: { |
| 73 | if (!base_executions.empty() && op->name()) { |
| 74 | auto iter = base_executions.find(op->name()->str()); |
| 75 | if (iter != base_executions.end()) { |
| 76 | auto base_exe = iter->second.get(); |
| 77 | Execution* copyExecution = nullptr; |
| 78 | base_exe->onClone(backend, op, ©Execution); |
| 79 | if (copyExecution == nullptr) { |
| 80 | base_exe->onClone(backupBackend, op, ©Execution); |
| 81 | } |
| 82 | if (copyExecution != nullptr && copyExecution->onClone(nullptr, op, nullptr)) { |
| 83 | exe.reset(copyExecution); |
| 84 | } |
| 85 | } |
| 86 | } |
| 87 | if (exe == nullptr) { |
| 88 | DataType type = DataType_DT_FLOAT; |
| 89 | auto conv2d = op->main_as_Convolution2D(); |
| 90 | // Create Default Inputs and Outputs |
| 91 | auto tempInput = info.inputs[0]; |
| 92 | auto tempOutput = info.outputs[0]; |
no test coverage detected