// // RemoveCopy.cpp // MNNConverter // // Created by MNN on 2019/09/05. // Copyright © 2018, Alibaba Group Holding Limited // #include "../PostTreatUtils.hpp" #include "config.hpp" #include "../Global.hpp" class RemoveCopy : public PostConverter { public: virtual bool onExecute(std::unique_ptr& net) const override { std::set netOutputNames; for (auto& t : net->outputName) { netOutputNames.insert(t); } for (auto iter = net->oplists.begin(); iter != net->oplists.end(); iter++) { auto& op = *iter; if (op->type == MNN::OpType_Input) { for (auto o : op->outputIndexes) { netOutputNames.insert(net->tensorName[o]); } } } std::map> desmap; for (auto&& iter : net->extraTensorDescribe) { desmap.insert(std::make_pair(iter->index, std::move(iter))); } auto config = Global::Get(); for (auto iter = net->oplists.begin(); iter != net->oplists.end();) { auto& op = *iter; if (op->type != MNN::OpType_Identity || op->inputIndexes.size() != op->outputIndexes.size()) { iter++; continue; } bool hasOutputName = false; for (auto o : op->outputIndexes) { if (netOutputNames.find(net->tensorName[o]) != netOutputNames.end()) { hasOutputName = true; break; } } bool hasOutputFromInput = false; for (auto o : op->inputIndexes) { if (netOutputNames.find(net->tensorName[o]) != netOutputNames.end()) { hasOutputFromInput = true; break; } } if (hasOutputFromInput && hasOutputName) { iter++; continue; } auto originInput = op->inputIndexes; auto originOutputs = op->outputIndexes; MNN_ASSERT(originInput.size() == originOutputs.size()); if (hasOutputName) { bool valid = true; for (int i=0; iinputIndexes.size(); ++i) { auto o = op->outputIndexes[i]; auto originInput = op->inputIndexes[i]; if (netOutputNames.find(net->tensorName[o]) != netOutputNames.end()) { if (netOutputNames.find(net->tensorName[originInput]) != netOutputNames.end()) { valid = false; break; } auto originName = net->tensorName[originInput]; net->tensorName[originInput] = net->tensorName[o]; net->tensorName[o] = originName; } } if (!valid) { continue; } } std::map replaceIndexes; for (int i=0; iinputIndexes.size();++i) { replaceIndexes.insert(std::make_pair(op->outputIndexes[i], op->inputIndexes[i])); } for (auto& replaceIter : replaceIndexes) { auto desIter = desmap.find(replaceIter.first); if (desIter != desmap.end()) { desIter->second->index = replaceIter.second; desIter->second->name = net->tensorName[replaceIter.second]; desmap[replaceIter.second] = std::move(desIter->second); desmap.erase(desIter); } } for (auto subIter = net->oplists.begin(); subIter != net->oplists.end(); subIter++) { auto& subOp = *subIter; for (int v = 0; v < subOp->inputIndexes.size(); ++v) { if (replaceIndexes.find(subOp->inputIndexes[v]) != replaceIndexes.end()) { subOp->inputIndexes[v] = replaceIndexes[subOp->inputIndexes[v]]; } } } iter = net->oplists.erase(iter); } net->extraTensorDescribe.clear(); for (auto&& iter : desmap) { net->extraTensorDescribe.emplace_back(std::move(iter.second)); } return true; } }; static PostConverterRegister __l("RemoveCopy");