ONE - On-device Neural Engine
Loading...
Searching...
No Matches
Driver.cpp
Go to the documentation of this file.
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 "pass/PassData.h"
18
21
26
33
34#include "support/CommandLine.h"
35#include "Definitions.h"
36#include "Options.h"
37#include "Driver.h"
38
39#ifdef NNC_FRONTEND_CAFFE2_ENABLED
40#include <caffe2_importer.h>
41#endif // NNC_FRONTEND_CAFFE2_ENABLED
42#ifdef NNC_FRONTEND_CAFFE_ENABLED
43#include <caffe_importer.h>
44#endif // NNC_FRONTEND_CAFFE_ENABLED
45#ifdef NNC_FRONTEND_TFLITE_ENABLED
46#include <tflite_importer.h>
47#endif // NNC_FRONTEND_TFLITE_ENABLED
48#ifdef NNC_FRONTEND_ONNX_ENABLED
49#include <ONNXImporterImpl.h>
50#endif // NNC_FRONTEND_ONNX_ENABLED
51
52#include <memory>
53
54namespace nnc
55{
56
57static std::string getFrontendOptionsString()
58{
59 std::string res;
60
61 if (!cli::caffeFrontend.isDisabled())
62 res += "'" + cli::caffeFrontend.getNames()[0] + "' ";
63
64 if (!cli::caffe2Frontend.isDisabled())
65 res += "'" + cli::caffe2Frontend.getNames()[0] + "' ";
66
67 if (!cli::onnxFrontend.isDisabled())
68 res += "'" + cli::onnxFrontend.getNames()[0] + "' ";
69
70 if (!cli::tflFrontend.isDisabled())
71 res += "'" + cli::tflFrontend.getNames()[0] + "'";
72
73 return res;
74}
75
76static std::unique_ptr<mir::Graph> importModel()
77{
78 // For bool, the value false is converted to zero and the value true is converted to one
80 throw DriverException("One and only one of the following options are allowed and have to be set"
81 "in the same time: " +
82 getFrontendOptionsString());
83
85 {
86#ifdef NNC_FRONTEND_CAFFE_ENABLED
87 return mir_caffe::loadModel(cli::inputFile.getRawValue());
88#endif // NNC_FRONTEND_CAFFE_ENABLED
89 }
90 else if (cli::caffe2Frontend)
91 {
92#ifdef NNC_FRONTEND_CAFFE2_ENABLED
93 // FIXME: caffe2 input shapes are not provided by model and must be set from cli
94 // current 'inputShapes' could provide only one shape, while model could has several inputs
95 return mir_caffe2::loadModel(cli::inputFile.getRawValue(), cli::initNet.getRawValue(),
96 {cli::inputShapes.getRawValue()});
97#endif // NNC_FRONTEND_CAFFE2_ENABLED
98 }
99 else if (cli::onnxFrontend)
100 {
101#ifdef NNC_FRONTEND_ONNX_ENABLED
102 return mir_onnx::loadModel(cli::inputFile.getRawValue());
103#endif // NNC_FRONTEND_ONNX_ENABLED
104 }
105 else if (cli::tflFrontend)
106 {
107#ifdef NNC_FRONTEND_TFLITE_ENABLED
108 return mir_tflite::loadModel(cli::inputFile.getRawValue());
109#endif // NNC_FRONTEND_TFLITE_ENABLED
110 }
111
112 assert(false);
113 return nullptr;
114}
115
116static void backend(mir::Graph *graph)
117{
119 {
120 CPPCodeGenerator(cli::artifactDir, cli::artifactName).run(graph);
121 }
123 {
124 AclCppCodeGenerator(cli::artifactDir, cli::artifactName).run(graph);
125 }
127 {
128 InterpreterBackend(cli::interInputDataDir, cli::artifactDir).run(graph);
129 }
130 else
131 {
132 assert(false && "invalid option value");
133 }
134}
135
140void Driver::runPasses()
141{
142 auto graph = importModel();
143 PassData pass_data(graph.get());
144
145 for (const auto &pass : _passManager.getPasses())
146 {
147 pass_data = pass->run(pass_data);
148 if (cli::dumpGraph && static_cast<mir::Graph *>(pass_data))
149 {
150 DumperPass d(pass->getName());
151 d.run(pass_data);
152 }
153 }
154
155 backend(pass_data);
156
157 // NOTE. Now we destroy data of all passes when PassManager is destroyed.
158 // In future to reduce memory consumption we can destory it when passes are being performed
159
160} // runPasses
161
166void Driver::registerBackendSpecificPasses()
167{
168 std::unique_ptr<Pass> data_format_pass;
169
171 {
172 _passManager.registerPass(std::make_unique<LowerConv2D>());
173 _passManager.registerPass(std::make_unique<DataFormatSwitcher>(mir::DataFormat::NHWC));
174 }
176 {
177 _passManager.registerPass(std::make_unique<LowerConv2D>());
178 _passManager.registerPass(std::make_unique<ConstantFoldTranspose>());
179 // TODO Change to DataFormat::NCHW when fix it in ACL
180 _passManager.registerPass(std::make_unique<DataFormatSwitcher>(mir::DataFormat::NHWC));
181 }
183 {
184 _passManager.registerPass(std::make_unique<DataFormatSwitcher>(mir::DataFormat::NHWC));
185 }
186 else
187 {
188 assert(false && "invalid option value");
189 }
190}
191
192void Driver::registerOptimizationPass()
193{
195 {
196 // TODO: maybe we should start managing the optimizations more intelligently?
197 _passManager.registerPass(std::unique_ptr<Pass>(new CombineTransposes()));
198 _passManager.registerPass(std::unique_ptr<Pass>(new SinkTranspose()));
199 _passManager.registerPass(std::unique_ptr<Pass>(new SinkRelu()));
200#if 0
201 // TODO Support broadcasting.
202 _passManager.registerPass(std::unique_ptr<Pass>(new FuseArithmeticOps()));
203#endif
204 _passManager.registerPass(std::unique_ptr<Pass>(new DeadCodeElimination()));
205 }
206} // registerOptimizationPass
207
209{
210 registerOptimizationPass();
211 registerBackendSpecificPasses();
212
213 runPasses();
214}
215
216} // namespace nnc
#define NNC_TARGET_ARM_CPP
Definition Options.h:43
#define NNC_TARGET_ARM_GPU_CPP
Definition Options.h:45
#define NNC_TARGET_INTERPRETER
Definition Options.h:46
#define NNC_TARGET_X86_CPP
Definition Options.h:44
void runDriver()
main method to run compiler driver
Definition Driver.cpp:208
void registerPass(std::unique_ptr< Pass > pass)
register pass in pass manager
std::unique_ptr< mir::Graph > loadModel(std::string predict_net, std::string init_net, const std::vector< std::vector< int > > &input_shapes)
std::unique_ptr< mir::Graph > loadModel(const std::string &filename)
std::unique_ptr< mir::Graph > loadModel(const std::string &filename)
std::unique_ptr< mir::Graph > loadModel(std::string filename)
Option< bool > onnxFrontend(optname("--onnx"), overview("treat input file as ONNX model"), false, optional(true), optvalues(""), nullptr, separators(""), showopt(false))
Definition Options.h:37
Option< std::string > artifactName(optname("--output, -o"), overview("specify name for output files"), "nnmodel", optional(true), optvalues(""), checkOutFile)
Definition Options.h:58
Option< std::string > inputFile(optname("--nnmodel, -m"), overview("specify input file with serialized NN models"), std::string(), optional(false), optvalues(""), checkInFile)
Definition Options.h:52
Option< std::vector< int > > inputShapes(optname("--input-shape"), overview("Shape of caffe2 input"), std::vector< int >{}, optional(false), optvalues(""), nullptr, separators(""), showopt(false), IOption::Group::caffe2)
Definition Options.h:32
Option< bool > caffe2Frontend(optname("--caffe2"), overview("treat input file as Caffe2 model (predict_net.pb)"), false, optional(false), optvalues(""), nullptr, separators(""), showopt(false), IOption::Group::caffe2)
Definition Options.h:31
Option< bool > doOptimizationPass(optname("-O"), overview("whether to optimize model or not"), false, optional(true), optvalues(""), nullptr, separators(""), showopt(true))
Definition Options.h:39
Option< std::string > artifactDir(optname("--output-dir, -d"), overview("specify directory for output files"), ".", optional(true), optvalues(""), checkOutDir, separators("="))
Definition Options.h:57
Option< bool > caffeFrontend(optname("--caffe"), overview("treat input file as Caffe model"), false, optional(true), optvalues(""), nullptr, separators(""), showopt(false))
Definition Options.h:35
Option< bool > tflFrontend(optname("--tflite"), overview("treat input file as Tensor Flow Lite model"), false, optional(true), optvalues(""), nullptr, separators(""), showopt(false))
Definition Options.h:36
Option< bool > dumpGraph(optname("--dump, -D"), overview("dump graph to dot files after optimization passes"), false, optional(true), optvalues(""), nullptr, separators(""), showopt(true))
Definition Options.h:40
Option< std::string > initNet(optname("--init-net"), overview("path to Caffe2 model weights (init_net.pb)"), std::string(), optional(false), optvalues(""), checkInFile, separators(""), showopt(false), IOption::Group::caffe2)
Definition Options.h:33
Option< std::string > interInputDataDir(optname("--input-data-dir"), overview("specify directory with binary files " "containing the input data for the model " "(one file for each input with the same name)"), ".", optional(true), optvalues(""), checkInDir)
Definition Options.h:63
Option< std::string > target(optname("--target"), overview("select target language to emit for given architecture." "Valid values are '" NNC_TARGET_ARM_CPP "', '" NNC_TARGET_X86_CPP "', '" NNC_TARGET_ARM_GPU_CPP "', '" NNC_TARGET_INTERPRETER "'"), std::string(), optional(false), optvalues(NNC_TARGET_ARM_CPP "," NNC_TARGET_X86_CPP "," NNC_TARGET_ARM_GPU_CPP "," NNC_TARGET_INTERPRETER), nullptr, separators("="))
Definition Options.h:47