// // Pass.cpp // MNNConverter // // Created by MNN on b'2020/12/07'. // Copyright © 2018, Alibaba Group Holding Limited // #include "MNN/expr/Expr.hpp" #include "converter/source/optimizer/passes/Pass.hpp" #include "converter/source/optimizer/passes/PassRegistry.hpp" #include "converter/source/optimizer/SubGraphComplete.hpp" #include "converter/source/optimizer/Program.hpp" #include "converter/source/optimizer/Global.hpp" namespace MNN { namespace passes { NestedPass::NestedPass(const std::string& pass_name, PassContext *context) : Pass(pass_name), pass_manager_(new PassManager(context)) {} PassManager& NestedPass::OwningPassManager() const { return *(pass_manager_.get()); } bool NestedPass::Run(PassContext *context) { return pass_manager_->RunOnOperation(context); } PassManager::PassManager(const PassManager& other) { for (const auto& pass : other.passes_) { passes_.push_back(pass->Clone()); } } void PassManager::AddPass(std::unique_ptr&& pass) { passes_.push_back(std::move(pass)); } void PassManager::AddPass(const std::string& pass_name) { std::unique_ptr pass = PassRegistry::GetPass(pass_name)->Clone(); AddPass(std::move(pass)); } void PassManager::AddNestedPass(std::unique_ptr&& pass) { PassManager& pm = AddNest(); pm.AddPass(std::move(pass)); } void PassManager::AddNestedPass(const std::string& pass_name) { std::unique_ptr pass = PassRegistry::GetPass(pass_name)->Clone(); AddNestedPass(std::move(pass)); } PassManager& PassManager::AddNest() { std::unique_ptr nest(new NestedPass("nested", context_)); passes_.push_back(std::move(nest)); return reinterpret_cast( // NOLINT passes_.back().get())->OwningPassManager(); } std::unique_ptr PassManager::RunAllPasses( // NOLINT std::unique_ptr& originNet, // NOLINT const std::unordered_map& inputs) { auto program = MNN::Express::Program::create(originNet.get(), true); program->input(inputs); auto operations = Express::Variable::getExecuteOrder(program->outputs()); for (auto op : operations) { PassContext ctx(*context_); ctx.node = op; RunOnOperation(&ctx); } std::unique_ptr newNet(new MNN::NetT); newNet->sourceType = originNet->sourceType; newNet->bizCode = originNet->bizCode; newNet->outputName = originNet->outputName; Express::Variable::save(program->outputs(), newNet.get()); return std::move(newNet); } std::unique_ptr PassManager::Run(std::unique_ptr& net) { std::vector subgraphs; for (auto& subgraph : net->subgraphs) { subgraphs.push_back(subgraph.get()); } auto RunAllPassesImpl = [this]( std::unique_ptr& originNet, const std::unordered_map& inputs) { return this->RunAllPasses(originNet, inputs); }; Express::OptimizeContext ctx; ctx.subgraphs = subgraphs; ctx.is_training = context_->is_training; ctx.verbose = context_->verbose; ctx.source = context_->source; ctx.completed_subgraphs = {}; ctx.RunOptimize = RunAllPassesImpl; Global::Reset(&ctx); std::unordered_map inputs; std::unique_ptr result = ctx.RunOptimize(net, inputs); for (auto* subgraph : ctx.completed_subgraphs) { result->subgraphs.emplace_back(subgraph); } return std::move(result); } bool PassManager::RunOnOperation(PassContext *context) { bool status = false; while (1) { bool iterable = false; for (auto& pass : passes_) { iterable = iterable || pass->Run(context); } if (!iterable) { break; } else { status = true; } } return status; } bool RewritePass::Run(PassContext *context) { return VerifyAndRewrite(context); } bool RewritePass::VerifyAndRewrite(PassContext* context) { if (!verify_fn_(context)) { return false; } return rewrite_fn_(context); } } // namespace passes } // namespace MNN