From: 윤현식/동작제어Lab(SR)/Principal Engineer/삼성전자 Date: Wed, 31 Oct 2018 07:34:29 +0000 (+0900) Subject: [enco] tool to dump IR (initial version) (#2034) X-Git-Tag: nncc_backup~1443 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ce9f203337d70291bf0efe3adb365ab4d74c227c;p=platform%2Fcore%2Fml%2Fnnfw.git [enco] tool to dump IR (initial version) (#2034) This tool prints IR info of caffe frontend. Signed-off-by: Hyun Sik Yoon --- diff --git a/contrib/encodump/.FORMATCHECKED b/contrib/encodump/.FORMATCHECKED new file mode 100644 index 0000000..e69de29 diff --git a/contrib/encodump/CMakeLists.txt b/contrib/encodump/CMakeLists.txt new file mode 100644 index 0000000..04e2fc3 --- /dev/null +++ b/contrib/encodump/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE SOURCES "src/*.cpp") + +add_executable(encodump ${SOURCES}) +target_include_directories(encodump PRIVATE src) +target_link_libraries(encodump enco_intf_frontend) +target_link_libraries(encodump enco_core) +target_link_libraries(encodump dl) diff --git a/contrib/encodump/src/Driver.cpp b/contrib/encodump/src/Driver.cpp new file mode 100644 index 0000000..3cf3f0a --- /dev/null +++ b/contrib/encodump/src/Driver.cpp @@ -0,0 +1,230 @@ +/* + * 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 + +#include +#include + +#include + +#include "Dump.h" + +namespace cmdline +{ + +// TODO Extract this helper class +class Vector : public cmdline::View +{ +public: + uint32_t size(void) const { return _args.size(); } + +public: + const char *at(uint32_t nth) const { return _args.at(nth).c_str(); } + +public: + Vector &append(const std::string &arg) + { + _args.emplace_back(arg); + return (*this); + } + +private: + std::vector _args; +}; + +} // namespace cmdline + +namespace +{ + +class Zone +{ +public: + Zone() = default; + +public: + const cmdline::View *args(void) const { return &_args; } + +public: + void append(const std::string &arg) { _args.append(arg); } + +private: + cmdline::Vector _args; +}; + +} // namespace + +#include + +namespace +{ + +class FrontendFactory +{ +public: + FrontendFactory(const std::string &path) + { + _handle = dlopen(path.c_str(), RTLD_LAZY); + assert(_handle != nullptr); + } + +public: + // Copy is not allowed to avoid double close + FrontendFactory(const FrontendFactory &) = delete; + FrontendFactory(FrontendFactory &&) = delete; + +public: + ~FrontendFactory() { dlclose(_handle); } + +private: + using Entry = std::unique_ptr (*)(const cmdline::View &); + +private: + Entry entry(void) const + { + auto entry = reinterpret_cast(dlsym(_handle, "make_frontend")); + assert(entry != nullptr); + return entry; + } + +public: + std::unique_ptr make(const cmdline::View *args) const + { + auto fn = entry(); + return fn(*args); + } + +private: + void *_handle; +}; + +} // namespace + +namespace +{ + +class FrontendZone : public Zone +{ +public: + FrontendZone(const std::string &path) : _factory{path} + { + // DO NOTHING + } + +public: + const FrontendFactory *factory(void) const { return &_factory; } + +private: + FrontendFactory _factory; +}; + +} // namespace + +#include + +#include + +#include +#include + +/** + * @brief Dump IR for given arguments + * + * Call example: + * $ ./build/contrib/encodump/encodump \ + * --frontend build/contrib/enco/frontend/caffe/libenco_caffe_frontend.so \ + * --frontend-arg build/contrib/enco/test/caffe/003.prototxt \ + * --frontend-arg build/contrib/enco/test/caffe/003.caffemodel + */ +static int entry(int argc, char **argv) +{ + // Usage: + // [Command] --frontend [Frontend .so path] --frontend-arg ... + std::unique_ptr frontend_zone; + + // Simple argument parser (based on map) + std::map> argparse; + + argparse["--frontend"] = [&](const std::string &path) { + frontend_zone = nncc::foundation::make_unique(path); + }; + + argparse["--frontend-arg"] = [&](const std::string &arg) { frontend_zone->append(arg); }; + + if (argc < 2) + { + std::cerr << "Usage:" << std::endl; + std::cerr << "[Command] --frontend [.so path]" << std::endl; + std::cerr << " --frontend-arg [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); + } + + assert(frontend_zone != nullptr); + + auto frontend = frontend_zone->factory()->make(frontend_zone->args()); + + auto bundle = frontend->load(); + + // dump + dump(bundle.module()); + + // todo : dump data + + return 0; +} + +#ifdef NDEBUG +int main(int argc, char **argv) +{ + try + { + return entry(argc, argv); + } + catch (const std::exception &e) + { + std::cerr << "ERROR: " << e.what() << std::endl; + } + + return 255; +} +#else // NDEBUG +int main(int argc, char **argv) +{ + // NOTE main does not catch internal exceptions for debug build to make it easy to + // check the stacktrace with a debugger + return entry(argc, argv); +} +#endif // !NDEBUG diff --git a/contrib/encodump/src/Dump.cpp b/contrib/encodump/src/Dump.cpp new file mode 100644 index 0000000..7e1e5f9 --- /dev/null +++ b/contrib/encodump/src/Dump.cpp @@ -0,0 +1,197 @@ +/* + * 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 "Dump.h" + +#include + +std::string tab(int n) { return std::string(n * 2, ' '); } + +struct OpPrinter final : public coco::Op::Visitor +{ +public: + OpPrinter(std::ostream &os) : _os(os) {} + +public: + void visit(const coco::Load *op) override { _os << "; Load(" << op->object() << ")"; } + + void visit(const coco::PadF *op) override + { + op->arg()->accept(this); + _os << "; PadF"; + } + + void visit(const coco::Conv2D *op) override + { + op->arg()->accept(this); + const coco::Padding2D *pad = op->pad(); + const coco::Stride2D *stride = op->stride(); + + _os << "; Conv2D(ker: " << op->ker() << ", padding [T/B/L/R=" << pad->top() << "," + << pad->bottom() << "," << pad->left() << "," << pad->right() << "]" + << ", stride [V/H = " << stride->vertical() << "," << stride->horizontal() << "]" + << ")"; + } + + void visit(const coco::MaxPool2D *op) override + { + op->arg()->accept(this); + _os << "; MaxPool2D"; + } + + void visit(const coco::AvgPool2D *op) override + { + op->arg()->accept(this); + _os << "; AvgPool2D"; + } + + void visit(const coco::Add *op) override + { + op->left()->accept(this); + op->right()->accept(this); + _os << "; Add"; + } + + void visit(const coco::Mul *op) override + { + op->left()->accept(this); + op->right()->accept(this); + _os << "; Mul"; + } + + void visit(const coco::ReLU *op) override + { + op->arg()->accept(this); + _os << "; ReLU"; + } + +private: + std::ostream &_os; +}; + +struct InstrPrinter final : public coco::Instr::Visitor +{ +public: + InstrPrinter() = delete; + + InstrPrinter(int indent) : _indent(indent) {} + + void visit(const coco::Eval *ins) override + { + std::cout << tab(_indent) << "Eval" << std::endl; + std::cout << tab(_indent) << " out: " << ins->out() << std::endl; + std::cout << tab(_indent) << " op: "; + { + OpPrinter prn(std::cout); + ins->op()->accept(prn); + } + std::cout << std::endl; + } + + void visit(const coco::Copy *ins) override + { + std::cout << tab(_indent) << "Copy" << std::endl; + std::cout << tab(_indent) << " from: " << ins->from() << std::endl; + std::cout << tab(_indent) << " into: " << ins->into() << std::endl; + } + + void visit(const coco::Shuffle *ins) override + { + std::cout << tab(_indent) << "Shuffle" << std::endl; + std::cout << tab(_indent) << " from: " << ins->from() << std::endl; + std::cout << tab(_indent) << " into: " << ins->into() << std::endl; + } + +private: + int _indent; +}; + +void dump(const coco::Op *op) +{ + OpPrinter prn(std::cout); + op->accept(prn); +} + +void dump(const coco::Instr *ins, int indent) +{ + std::cout << tab(indent) << "Inst:" << std::endl; + + static InstrPrinter prn(indent + 1); + + ins->accept(prn); +} + +void dump(const coco::Block *B, int indent) +{ + std::cout << tab(indent) << "Block (index: " << B->index().value() << ")" << std::endl; + for (auto I = B->instr()->head(); I != nullptr; I = I->next()) + { + dump(I, indent + 1); + } +} + +void dump(const coco::BlockList *L, int indent) +{ + for (auto B = L->head(); B != nullptr; B = B->next()) + { + dump(B, indent); + } +} + +void dump(const coco::BagManager *l, int indent) +{ + for (auto n = 0; n < l->size(); ++n) + { + auto bag = l->at(n); + std::cout << tab(indent) << "%" << bag << " = Bag(size: " << bag->size() << ")" << std::endl; + } +} +void dump(const coco::ObjectManager *l, int indent) +{ + for (auto n = 0; n < l->size(); ++n) + { + auto obj = l->at(n); + std::cout << tab(indent) << "%" << obj << " = Object(bag: " << obj->bag() << ")" << std::endl; + } +} + +template void head(int indent); + +template <> void head(int indent) { std::cout << tab(indent) << "Input: "; } + +template <> void head(int indent) { std::cout << tab(indent) << "Output: "; } + +template void dump(const coco::PtrList *list, int indent) +{ + head(indent); + for (int n = 0; n < list->size(); n++) + { + const PtrItemT *item = list->at(n); + if (n != 0) + std::cout << ", "; + std::cout << "#" << n + 1 << ". name=" << item->name(); + } + std::cout << std::endl; +} + +void dump(const coco::Module *module) +{ + std::cout << "Module" << std::endl; + + dump(module->block(), 1); + dump(module->input(), 1); + dump(module->output(), 1); +} diff --git a/contrib/encodump/src/Dump.h b/contrib/encodump/src/Dump.h new file mode 100644 index 0000000..e7ea7d1 --- /dev/null +++ b/contrib/encodump/src/Dump.h @@ -0,0 +1,8 @@ +#ifndef __DUMP_H__ +#define __DUMP_H__ + +#include + +void dump(const coco::Module *module); + +#endif // __DUMP_H__