From d05501fad91bec44612d6c8e58ed1af7bffa4b0f Mon Sep 17 00:00:00 2001 From: "Efimov Alexander/AI Tools Lab/./Samsung Electronics" Date: Wed, 11 Jul 2018 13:54:18 +0300 Subject: [PATCH] Basic model analyzer info gathering (#560) Basic model analyzer info gathering Save inputs, outputs and operation names. Signed-off-by: Efimov Alexander --- .../nnc/libs/backend/soft/include/model_analyzer.h | 51 +++++++++++------ contrib/nnc/libs/backend/soft/src/generator.cpp | 34 +++++++++++- .../nnc/libs/backend/soft/src/model_analyzer.cpp | 64 ++++++++++++++++++---- 3 files changed, 120 insertions(+), 29 deletions(-) diff --git a/contrib/nnc/libs/backend/soft/include/model_analyzer.h b/contrib/nnc/libs/backend/soft/include/model_analyzer.h index 0ea03d0..1bcc8de 100644 --- a/contrib/nnc/libs/backend/soft/include/model_analyzer.h +++ b/contrib/nnc/libs/backend/soft/include/model_analyzer.h @@ -34,45 +34,64 @@ public: void visit(ADT::INode *node, ops::ReluOp &op) override; void visit(ADT::INode *node, ops::ReshapeOp &op) override; - // stub for operation description + struct TensorDescription + { + std::string _name; + bool _isNNOutput; // true if is it NN output tensor + }; + + // operation description struct OpDescr { - // TODO add information about operation, inputs, outputs, place model data stored + enum class Type + { + IN, + OUT, + ORDINARY + }; + + Type _type; + ADT::INode *_node; + std::string _opName; + // list of output tensors + std::vector _outputs; + size_t _paramStartOffset; }; const std::vector &getInputs() const { - // TODO return list of input tensor names - // UB here, suppress warnings - return *static_cast*>(nullptr); + return _inputs; } const std::vector &getOutputs() const { - // TODO return list of output tensor names - // UB here, suppress warnings - return *static_cast*>(nullptr); + return _outputs; } const std::vector &getInferenceSequence() const { - // TODO return sequence of operations - // UB here, suppress warnings - return *static_cast*>(nullptr); + return _inferenceSequence; } const std::vector &getPackedParameters() const { - // TODO return array containing compressed parameters for operations - // UB here, suppress warnings - return *static_cast*>(nullptr); + return _packedParameters; } uint64_t getFormatVersion() const { - // TODO return analyzer version, part of model parameters file. - return 0; + return _formatVersion; } + +private: + void addOpDescr(ADT::INode *node, const std::string &name); + + const uint64_t _formatVersion = 1; + std::vector _packedParameters; + std::vector _inferenceSequence; + size_t _localTensorsN = 0; + std::vector _inputs; + std::vector _outputs; }; } // namespace soft diff --git a/contrib/nnc/libs/backend/soft/src/generator.cpp b/contrib/nnc/libs/backend/soft/src/generator.cpp index 12dc0b0..04b6151 100644 --- a/contrib/nnc/libs/backend/soft/src/generator.cpp +++ b/contrib/nnc/libs/backend/soft/src/generator.cpp @@ -5,10 +5,12 @@ #include #include #include +#include + #include #include #include -#include +#include using namespace std; using namespace nncc::contrib; @@ -59,6 +61,21 @@ bool fillFileStats(const string &path, struct stat &s) return true; } +using ostream_ptr = unique_ptr; + +ostream_ptr getStream(const string &path) +{ + if (path.empty()) + return ostream_ptr(&cout, [](ostream *){}); + ofstream *ofs = new ofstream(path); + if (ofs->fail()) + { + delete ofs; + throw PluginException("Can not open code output file: " + path); + } + return ostream_ptr(ofs, [](ostream *ofs){delete ofs;}); +} + } // unnamed namespace BaseCodeGenerator::BaseCodeGenerator(const string &headerFile, const string &codeFile, const string &modelFile): @@ -94,7 +111,20 @@ void BaseCodeGenerator::generate(Graph *g) // visit and analyze graph ModelAnalyzer ma; g->accept(&ma); - // materialize code + // Print header + auto headerStream = getStream(_headerFile); + materializeHeader(*headerStream, ma); + headerStream.reset(); + + // Print code + auto codeStream = getStream(_codeFile); + materializeCode(*codeStream, ma); + codeStream.reset(); + + // Print model parameters + auto modelStream = getStream(_modelFile); + materializeModelParams(*modelStream, ma); + modelStream.reset(); } CCodeGenerator CCodeGenerator::create(const std::string &headerFile, diff --git a/contrib/nnc/libs/backend/soft/src/model_analyzer.cpp b/contrib/nnc/libs/backend/soft/src/model_analyzer.cpp index 1670fbd..c7cc374 100644 --- a/contrib/nnc/libs/backend/soft/src/model_analyzer.cpp +++ b/contrib/nnc/libs/backend/soft/src/model_analyzer.cpp @@ -1,4 +1,7 @@ #include "model_analyzer.h" +#include "nnc/core/IR/model/graph/ir_node.h" + +using namespace std; namespace nncc { @@ -9,59 +12,98 @@ namespace backend namespace soft { +void ModelAnalyzer::addOpDescr(ADT::INode *node, const string &opName) +{ + size_t offset = _packedParameters.size(); + OpDescr::Type type = OpDescr::Type::ORDINARY; + vector outputs; + const std::string &name = node->getName(); + if (node->getPrevNodes().empty()) + { + _inputs.push_back(name); + type = OpDescr::Type::IN; + } else + if (!name.empty()) + { + _outputs.push_back(name); + type = OpDescr::Type::OUT; + } + if (type != OpDescr::Type::ORDINARY) + { + outputs.push_back({"_" + name, type == OpDescr::Type::OUT}); + } else + { + outputs.push_back({"tensor_" + to_string(_localTensorsN++), false}); + } + _inferenceSequence.push_back({type, node, opName, std::move(outputs), offset}); + // TODO add model hashing +} + void ModelAnalyzer::visit(ADT::INode *node, ops::ConcatOp &op) { - // TODO fill appropriate fields in operations sequence and parameters + addOpDescr(node, "concat"); + // TODO add parameters dump } void ModelAnalyzer::visit(ADT::INode *node, ops::Conv2DOp &op) { - // TODO fill appropriate fields in operations sequence and parameters + addOpDescr(node, "conv2d"); + // TODO add parameters dump } void ModelAnalyzer::visit(ADT::INode *node, ops::DepthwiseConv2DOp &op) { - // TODO fill appropriate fields in operations sequence and parameters + addOpDescr(node, "depthwiseConv2d"); + // TODO add parameters dump } void ModelAnalyzer::visit(ADT::INode *node, ops::SoftmaxOp &op) { - // TODO fill appropriate fields in operations sequence and parameters + addOpDescr(node, "softmax"); + // TODO add parameters dump } void ModelAnalyzer::visit(ADT::INode *node, ops::PoolOp &op) { - // TODO fill appropriate fields in operations sequence and parameters + addOpDescr(node, "pool"); + // TODO add parameters dump } void ModelAnalyzer::visit(ADT::INode *node, ops::FullyConnectedOp &op) { - // TODO fill appropriate fields in operations sequence and parameters + addOpDescr(node, "fullConnect"); + // TODO add parameters dump } void ModelAnalyzer::visit(ADT::INode *node, ops::CappedReluOp &op) { - // TODO fill appropriate fields in operations sequence and parameters + addOpDescr(node, "cappedRelu"); + // TODO add parameters dump } void ModelAnalyzer::visit(ADT::INode *node, ops::BiasAddOp &op) { - // TODO fill appropriate fields in operations sequence and parameters + addOpDescr(node, "biasAdd"); + // TODO add parameters dump } void ModelAnalyzer::visit(ADT::INode *node, ops::VariableOp &op) { - // TODO fill appropriate fields in operations sequence and parameters + assert(node->getPrevNodes().empty()); + addOpDescr(node, "in"); + // TODO add parameters dump } void ModelAnalyzer::visit(ADT::INode *node, ops::ReluOp &op) { - // TODO fill appropriate fields in operations sequence and parameters + addOpDescr(node, "relu"); + // TODO add parameters dump } void ModelAnalyzer::visit(ADT::INode *node, ops::ReshapeOp &op) { - // TODO fill appropriate fields in operations sequence and parameters + addOpDescr(node, "reshape"); + // TODO add parameters dump } } // namespace soft -- 2.7.4