From: 박종현/동작제어Lab(SR)/Staff Engineer/삼성전자 Date: Thu, 6 Dec 2018 06:43:49 +0000 (+0900) Subject: [nnkit] Introduce nnkit-run (#2527) X-Git-Tag: nncc_backup~1176 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cf8d35927fbdd313cef16234387127d355e2873c;p=platform%2Fcore%2Fml%2Fnnfw.git [nnkit] Introduce nnkit-run (#2527) This commit introduces nnkit-run (which is a copy of nni) as the first step to removing "nni". Signed-off-by: Jonghyun Park --- diff --git a/contrib/nnkit/tools/run/CMakeLists.txt b/contrib/nnkit/tools/run/CMakeLists.txt new file mode 100644 index 0000000..1526e0a --- /dev/null +++ b/contrib/nnkit/tools/run/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(nnkit-run nnkit-run.cpp) +target_link_libraries(nnkit-run nnkit_intf_action) +target_link_libraries(nnkit-run nnkit_intf_backend) +target_link_libraries(nnkit-run nnkit_support_cmdline) +target_link_libraries(nnkit-run nnkit_support_backend) diff --git a/contrib/nnkit/tools/run/nnkit-run.cpp b/contrib/nnkit/tools/run/nnkit-run.cpp new file mode 100644 index 0000000..95830e7 --- /dev/null +++ b/contrib/nnkit/tools/run/nnkit-run.cpp @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace +{ + +class Section +{ +public: + Section() = default; + +public: + const nnkit::CmdlineArguments &args(void) const { return _args; } + +public: + void append(const std::string &arg) { _args.append(arg); } + +private: + nnkit::VectorArguments _args; +}; + +} + +namespace +{ + +class BackendSection : public Section +{ +public: + BackendSection(const std::string &path) : _plugin{path} + { + // DO NOTHING + } + +public: + std::unique_ptr initialize(void) const + { + return _plugin.create(args()); + } + +private: + nnkit::BackendPlugin _plugin; +}; + +} + +// TODO Extract Action-related helpers +#include + +#include + +#include +#include + +namespace +{ + +class ActionBinder +{ +private: + typedef std::unique_ptr (*Entry)(const nnkit::CmdlineArguments &); + +public: + ActionBinder(const std::string &path) + { + // Q: Do we need RTLD_GLOBAL here? + _handle = dlopen(path.c_str(), RTLD_LAZY); + assert(_handle != nullptr); + + _entry = reinterpret_cast(dlsym(_handle, "make_action")); + assert(_entry != nullptr); + } + +public: + // Copy is not allowed to avoid double close + ActionBinder(const ActionBinder &) = delete; + ActionBinder(ActionBinder &&binder) + { + // Handle is transferd from 'binder' instance into this instance. + _handle = binder._handle; + _entry = binder._entry; + + binder._handle = nullptr; + binder._entry = nullptr; + } + +public: + ~ActionBinder() + { + if (_handle) + { + dlclose(_handle); + } + } + +public: + std::unique_ptr make(const nnkit::CmdlineArguments &args) const + { + return _entry(args); + } + +private: + void *_handle; + Entry _entry; +}; + +} + +namespace +{ + +class ActionSection : public Section +{ +public: + ActionSection(const std::string &path) : _binder{path} + { + // DO NOTHING + } + +public: + std::unique_ptr initialize(void) const + { + return _binder.make(args()); + } + +private: + ActionBinder _binder; +}; + +} + +#include + +#include +#include + +int main(int argc, char **argv) +{ + // Usage: + // [Command] --backend [Backend module path] --backend-arg ... --backend-arg ... + // --pre [Action module path] --pre-arg ... --pre-arg ... + // --post [Action module path] --post-arg ... --post-arg ... + + // Argument sections + // + // NOTE Command-line arguments should include one backend section, and may include multiple + // pre/post action sections. + struct Sections + { + std::unique_ptr backend; + std::vector pre; + std::vector post; + }; + + Sections sections; + + // Simple argument parser (based on map) + std::map> argparse; + + argparse["--backend"] = [§ions] (const std::string &tag) + { + sections.backend = nncc::foundation::make_unique(tag); + }; + + argparse["--backend-arg"] = [§ions] (const std::string &arg) + { + sections.backend->append(arg); + }; + + argparse["--pre"] = [§ions] (const std::string &tag) + { + sections.pre.emplace_back(tag); + }; + + argparse["--pre-arg"] = [§ions] (const std::string &arg) + { + sections.pre.back().append(arg); + }; + + argparse["--post"] = [§ions] (const std::string &tag) + { + sections.post.emplace_back(tag); + }; + + argparse["--post-arg"] = [§ions] (const std::string &arg) + { + sections.post.back().append(arg); + }; + + if (argc < 2) + { + std::cerr << "Usage:" << std::endl + << "[Command] --backend [Backend module path] " + << "--backend-arg [Backend argument] ..." << std::endl + << " --pre [Pre-Action module path] " + << "--pre-arg [Pre-Action argument] ..." << std::endl + << " --post [Post-Action module path] " + << "--post-arg [Post-Action argument] ..." << std::endl; + return 255; + } + + for (int n = 1; n < argc; n += 2) + { + const std::string tag{argv[n]}; + const std::string arg{argv[n + 1]}; + + auto it = argparse.find(tag); + + if (it == argparse.end()) + { + std::cerr << "Option '" << tag << "' is not supported" << std::endl; + return 255; + } + + it->second(arg); + } + + // we need a backend + if (sections.backend == nullptr) + { + std::cerr << "Error: Backend is required. Provide with [--backend]" << std::endl; + return 255; + } + + // Initialize a backend + auto backend = sections.backend->initialize(); + + // Initialize pre actions + std::vector> pre_actions; + + for (const auto §ion : sections.pre) + { + pre_actions.emplace_back(section.initialize()); + } + + // Initialize post actions + std::vector> post_actions; + + for (const auto §ion : sections.post) + { + post_actions.emplace_back(section.initialize()); + } + + // + // Run inference + // + backend->prepare([&pre_actions] (nnkit::TensorContext &ctx) + { + // Run pre-actions on prepared tensor context + for (auto &action : pre_actions) + { + action->run(ctx); + } + }); + + backend->run(); + + backend->teardown([&post_actions] (nnkit::TensorContext &ctx) + { + // Run post-actions before teardown + for (auto &action : post_actions) + { + action->run(ctx); + } + }); + + return 0; +}