2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "compiler/Compiler.h"
19 #include "ExecutorFactory.h"
20 #include "ShapeValidator.h"
21 #include "pass/ConstantOutputPass.h"
22 #include "pass/OddOutputPass.h"
23 #include "pass/PassRunner.h"
24 #include "pass/UnusedOperandEliminationPass.h"
25 #include "../dumper/dot/DotDumper.h"
26 #include "../exec/SingleModelExecutors.h"
27 #include "../ir/OperationDumper.h"
28 #include "../ir/verifier/Verifier.h"
30 #include "compiler/StaticShapeInferer.h"
32 #include <misc/string_helpers.h>
39 Compiler::Compiler(const std::shared_ptr<ir::Model> &model, CompilerOptions &copt)
40 : _model{model}, _options{&copt}
45 Compiler::Compiler(const std::shared_ptr<ir::NNPkg> &nnpkg,
46 std::vector<std::unique_ptr<CompilerOptions>> &copts)
47 : _model{nnpkg->primary_model()}, _options{copts[0].get()}
49 // Use for single model only
50 assert(nnpkg->model_count() == 1);
53 std::shared_ptr<CompilerArtifact> Compiler::compile(void)
55 /***************************************************
56 * Prepare compilation phase
57 ***************************************************/
59 throw std::runtime_error{"Empty compile option"};
62 // TODO handle option for each model
63 if (_options->he_profiling_mode)
65 if (!_options->he_scheduler)
66 throw std::runtime_error("Heterogeneous scheduler must be enabled during profiling.");
68 if (_options->executor != "Dataflow")
69 throw std::runtime_error("Profiling mode works only with 'Dataflow' executor");
72 _options->forceInternalOptions();
73 _options->verboseOptions();
75 _model->iterate([&](const ir::SubgraphIndex &, ir::Graph &subg) {
78 .append(std::make_unique<pass::ConstantOutputPass>(subg))
79 .append(std::make_unique<pass::OddOutputPass>(subg))
83 pass::PassRunner{}.append(std::make_unique<pass::UnusedOperandEliminationPass>(subg)).run();
86 /***************************************************
87 * Backend independent analysis & optimization phase
88 ***************************************************/
89 // TODO Handle dump level for each model
90 auto dump_level = static_cast<dumper::dot::DotDumper::Level>(_options->graph_dump_level);
91 onert::dumper::dot::DotDumper dot_dumper(dump_level);
94 auto tracing_ctx = std::make_unique<util::TracingCtx>();
96 // Lower: Assign backend
97 std::unordered_map<ir::SubgraphIndex, std::unique_ptr<compiler::LoweredGraph>> lowered_subgs;
99 _model->iterate([&](const ir::SubgraphIndex &subg_index, ir::Graph &subg) {
100 // Lower: Assign backend
101 lowered_subgs[subg_index] = std::make_unique<compiler::LoweredGraph>(subg, *_options);
102 // Set tracing_ctx for copied graph
103 if (tracing_ctx != nullptr)
104 tracing_ctx->setSubgraphIndex(&(lowered_subgs[subg_index]->graph()), subg_index.value());
110 for (const auto &pair : lowered_subgs)
112 const auto &subg_index = pair.first;
113 const auto &lowered_subg = pair.second;
114 dot_dumper.dump(*lowered_subg, nnfw::misc::str("after_lower_subg-", subg_index.value()));
119 // Run the StaticShapeInfer of primary subg. All child StaticShapeInferers are called
121 std::unordered_map<ir::SubgraphIndex, std::unique_ptr<StaticShapeInferer>> inferers =
122 StaticShapeInferer::createStaticShapeInferers(lowered_subgs);
124 const auto primary_subg_idx = ir::SubgraphIndex{0};
125 inferers.at(primary_subg_idx)->infer();
127 for (const auto &pair_inferer : inferers)
129 const auto inferer = pair_inferer.second.get();
135 // TODO Move shape independent feature check from ShapeValidator to OperationValidator
136 // TODO Move ShapeValidator into shape inference
137 // - Check input tensor shape validation
138 // - Check parameter value validation which valid value is depend on input tensor shape
139 // - Output tensor shape validation check is needless because
140 // static/dynamic shape inferer will make valid output shape
141 for (const auto &pair : lowered_subgs)
143 auto &lowered_subg = pair.second;
144 compiler::ShapeValidator{lowered_subg->graph()}();
147 /*************************************************************
148 * Backend independent analysis & optimization phase finished
149 *************************************************************/
150 auto executors = std::make_shared<exec::SingleModelExecutors>();
151 for (auto &&pair : lowered_subgs)
153 auto const model_index = ir::ModelIndex{0};
154 auto const subg_index = pair.first;
155 auto &lowered_subg = pair.second;
156 auto const indexed_ranks = lowered_subg->indexed_ranks();
158 ir::OperationDumper dumper("Executor generation of Subgraph " +
159 std::to_string(subg_index.value()));
160 lowered_subg->graph().operations().iterate(
161 [&](const ir::OperationIndex &, const ir::Operation &op) { op.accept(dumper); });
163 auto executor = std::unique_ptr<exec::IExecutor>{ExecutorFactory::get().create(
164 std::move(lowered_subg), tracing_ctx.get(), *_options, executors, model_index)};
165 executor->setIndexedRanks(indexed_ranks);
166 executors->emplace(model_index, subg_index, std::move(executor));
169 /********************************
170 * Code generation phase finished
171 ********************************/
172 return std::make_shared<CompilerArtifact>(executors, std::move(tracing_ctx));
175 } // namespace compiler