45124556b4784a2a2321522dda92568d7f88d582
[platform/core/ml/nnfw.git] / runtime / onert / core / src / compiler / Compiler.cc
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "compiler/Compiler.h"
18
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"
29
30 #include "compiler/StaticShapeInferer.h"
31
32 #include <misc/string_helpers.h>
33
34 namespace onert
35 {
36 namespace compiler
37 {
38
39 Compiler::Compiler(const std::shared_ptr<ir::Model> &model, CompilerOptions &copt)
40   : _model{model}, _options{&copt}
41 {
42   // DO NOTHING
43 }
44
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()}
48 {
49   // Use for single model only
50   assert(nnpkg->model_count() == 1);
51 }
52
53 std::shared_ptr<CompilerArtifact> Compiler::compile(void)
54 {
55   /***************************************************
56    * Prepare compilation phase
57    ***************************************************/
58   if (!_options)
59     throw std::runtime_error{"Empty compile option"};
60
61   // Mode check
62   // TODO handle option for each model
63   if (_options->he_profiling_mode)
64   {
65     if (!_options->he_scheduler)
66       throw std::runtime_error("Heterogeneous scheduler must be enabled during profiling.");
67
68     if (_options->executor != "Dataflow")
69       throw std::runtime_error("Profiling mode works only with 'Dataflow' executor");
70   }
71
72   _options->forceInternalOptions();
73   _options->verboseOptions();
74
75   _model->iterate([&](const ir::SubgraphIndex &, ir::Graph &subg) {
76     // Mandatory passes
77     pass::PassRunner{}
78       .append(std::make_unique<pass::ConstantOutputPass>(subg))
79       .append(std::make_unique<pass::OddOutputPass>(subg))
80       .run();
81
82     // Optimizations
83     pass::PassRunner{}.append(std::make_unique<pass::UnusedOperandEliminationPass>(subg)).run();
84   });
85
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);
92
93   // Tracing context
94   auto tracing_ctx = std::make_unique<util::TracingCtx>();
95
96   // Lower: Assign backend
97   std::unordered_map<ir::SubgraphIndex, std::unique_ptr<compiler::LoweredGraph>> lowered_subgs;
98   {
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());
105     });
106   }
107
108   _model.reset();
109
110   for (const auto &pair : lowered_subgs)
111   {
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()));
115   }
116
117   // Shape inference.
118   {
119     // Run the StaticShapeInfer of primary subg. All child StaticShapeInferers are called
120     // recursively
121     std::unordered_map<ir::SubgraphIndex, std::unique_ptr<StaticShapeInferer>> inferers =
122       StaticShapeInferer::createStaticShapeInferers(lowered_subgs);
123
124     const auto primary_subg_idx = ir::SubgraphIndex{0};
125     inferers.at(primary_subg_idx)->infer();
126
127     for (const auto &pair_inferer : inferers)
128     {
129       const auto inferer = pair_inferer.second.get();
130       inferer->dump();
131     }
132   }
133
134   // Shape validation
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)
142   {
143     auto &lowered_subg = pair.second;
144     compiler::ShapeValidator{lowered_subg->graph()}();
145   }
146
147   /*************************************************************
148    *  Backend independent analysis & optimization phase finished
149    *************************************************************/
150   auto executors = std::make_shared<exec::SingleModelExecutors>();
151   for (auto &&pair : lowered_subgs)
152   {
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();
157
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); });
162
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));
167   }
168
169   /********************************
170    * Code generation phase finished
171    ********************************/
172   return std::make_shared<CompilerArtifact>(executors, std::move(tracing_ctx));
173 }
174
175 } // namespace compiler
176 } // namespace onert