ONE - On-device Neural Engine
Loading...
Searching...
No Matches
nnkit-run.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
19#include <nnkit/BackendPlugin.h>
20
21namespace
22{
23
24class Section
25{
26public:
27 Section() = default;
28
29public:
30 const nnkit::CmdlineArguments &args(void) const { return _args; }
31
32public:
33 void append(const std::string &arg) { _args.append(arg); }
34
35private:
37};
38} // namespace
39
40namespace
41{
42
43class BackendSection : public Section
44{
45public:
46 BackendSection(const std::string &path) : _path{path}
47 {
48 // DO NOTHING
49 }
50
51public:
52 std::unique_ptr<nnkit::Backend> initialize(void)
53 {
54 _plugin = std::move(nnkit::make_backend_plugin(_path));
55 return _plugin->create(args());
56 }
57
58private:
59 std::string _path;
60 std::unique_ptr<nnkit::BackendPlugin> _plugin;
61};
62} // namespace
63
64// TODO Extract Action-related helpers
65#include <nnkit/Action.h>
66
67#include <memory>
68
69#include <dlfcn.h>
70#include <assert.h>
71
72namespace
73{
74
75class ActionBinder
76{
77private:
78 typedef std::unique_ptr<nnkit::Action> (*Entry)(const nnkit::CmdlineArguments &);
79
80public:
81 ActionBinder(const std::string &path)
82 {
83 // Q: Do we need RTLD_GLOBAL here?
84 _handle = dlopen(path.c_str(), RTLD_LAZY);
85 assert(_handle != nullptr);
86
87 _entry = reinterpret_cast<Entry>(dlsym(_handle, "make_action"));
88 assert(_entry != nullptr);
89 }
90
91public:
92 // Copy is not allowed to avoid double close
93 ActionBinder(const ActionBinder &) = delete;
94 ActionBinder(ActionBinder &&binder)
95 {
96 // Handle is transferd from 'binder' instance into this instance.
97 _handle = binder._handle;
98 _entry = binder._entry;
99
100 binder._handle = nullptr;
101 binder._entry = nullptr;
102 }
103
104public:
105 ~ActionBinder()
106 {
107 if (_handle)
108 {
109 dlclose(_handle);
110 }
111 }
112
113public:
114 std::unique_ptr<nnkit::Action> make(const nnkit::CmdlineArguments &args) const
115 {
116 return _entry(args);
117 }
118
119private:
120 void *_handle;
121 Entry _entry;
122};
123} // namespace
124
125namespace
126{
127
128class ActionSection : public Section
129{
130public:
131 ActionSection(const std::string &path) : _binder{path}
132 {
133 // DO NOTHING
134 }
135
136public:
137 std::unique_ptr<nnkit::Action> initialize(void) const { return _binder.make(args()); }
138
139private:
140 ActionBinder _binder;
141};
142} // namespace
143
144#include <memory>
145#include <map>
146#include <iostream>
147
148int main(int argc, char **argv)
149{
150 // Usage:
151 // [Command] --backend [Backend module path] --backend-arg ... --backend-arg ...
152 // --pre [Action module path] --pre-arg ... --pre-arg ...
153 // --post [Action module path] --post-arg ... --post-arg ...
154
155 // Argument sections
156 //
157 // NOTE Command-line arguments should include one backend section, and may include multiple
158 // pre/post action sections.
159 struct Sections
160 {
161 std::unique_ptr<BackendSection> backend;
162 std::vector<ActionSection> pre;
163 std::vector<ActionSection> post;
164 };
165
166 Sections sections;
167
168 // Simple argument parser (based on map)
169 std::map<std::string, std::function<void(const std::string &arg)>> argparse;
170
171 argparse["--backend"] = [&sections](const std::string &tag) {
172 sections.backend = std::make_unique<BackendSection>(tag);
173 };
174
175 argparse["--backend-arg"] = [&sections](const std::string &arg) {
176 sections.backend->append(arg);
177 };
178
179 argparse["--pre"] = [&sections](const std::string &tag) { sections.pre.emplace_back(tag); };
180
181 argparse["--pre-arg"] = [&sections](const std::string &arg) { sections.pre.back().append(arg); };
182
183 argparse["--post"] = [&sections](const std::string &tag) { sections.post.emplace_back(tag); };
184
185 argparse["--post-arg"] = [&sections](const std::string &arg) {
186 sections.post.back().append(arg);
187 };
188
189 if (argc < 2)
190 {
191 std::cerr << "Usage:" << std::endl
192 << "[Command] --backend [Backend module path] "
193 << "--backend-arg [Backend argument] ..." << std::endl
194 << " --pre [Pre-Action module path] "
195 << "--pre-arg [Pre-Action argument] ..." << std::endl
196 << " --post [Post-Action module path] "
197 << "--post-arg [Post-Action argument] ..." << std::endl;
198 return 255;
199 }
200
201 for (int n = 1; n < argc; n += 2)
202 {
203 const std::string tag{argv[n]};
204 const std::string arg{argv[n + 1]};
205
206 auto it = argparse.find(tag);
207
208 if (it == argparse.end())
209 {
210 std::cerr << "Option '" << tag << "' is not supported" << std::endl;
211 return 255;
212 }
213
214 it->second(arg);
215 }
216
217 // we need a backend
218 if (sections.backend == nullptr)
219 {
220 std::cerr << "Error: Backend is required. Provide with [--backend]" << std::endl;
221 return 255;
222 }
223
224 // Initialize a backend
225 auto backend = sections.backend->initialize();
226
227 // Initialize pre actions
228 std::vector<std::unique_ptr<nnkit::Action>> pre_actions;
229
230 for (const auto &section : sections.pre)
231 {
232 pre_actions.emplace_back(section.initialize());
233 }
234
235 // Initialize post actions
236 std::vector<std::unique_ptr<nnkit::Action>> post_actions;
237
238 for (const auto &section : sections.post)
239 {
240 post_actions.emplace_back(section.initialize());
241 }
242
243 //
244 // Run inference
245 //
246 backend->prepare([&pre_actions](nnkit::TensorContext &ctx) {
247 // Run pre-actions on prepared tensor context
248 for (auto &action : pre_actions)
249 {
250 action->run(ctx);
251 }
252 });
253
254 backend->run();
255
256 backend->teardown([&post_actions](nnkit::TensorContext &ctx) {
257 // Run post-actions before teardown
258 for (auto &action : post_actions)
259 {
260 action->run(ctx);
261 }
262 });
263
264 return 0;
265}
int main(void)
args
Definition infer.py:21
std::unique_ptr< BackendPlugin > make_backend_plugin(const std::string &path)