Basic model analyzer info gathering (#560)
authorEfimov Alexander/AI Tools Lab/./Samsung Electronics <a.efimov@samsung.com>
Wed, 11 Jul 2018 10:54:18 +0000 (13:54 +0300)
committerSergey Vostokov/AI Tools Lab /SRR/Staff Engineer/삼성전자 <s.vostokov@samsung.com>
Wed, 11 Jul 2018 10:54:18 +0000 (19:54 +0900)
Basic model analyzer info gathering

Save inputs, outputs and operation names.

Signed-off-by: Efimov Alexander <a.efimov@samsung.com>
contrib/nnc/libs/backend/soft/include/model_analyzer.h
contrib/nnc/libs/backend/soft/src/generator.cpp
contrib/nnc/libs/backend/soft/src/model_analyzer.cpp

index 0ea03d0..1bcc8de 100644 (file)
@@ -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<TensorDescription> _outputs;
+    size_t _paramStartOffset;
   };
 
   const std::vector<std::string> &getInputs() const
   {
-    // TODO return list of input tensor names
-    // UB here, suppress warnings
-    return *static_cast<std::vector<std::string>*>(nullptr);
+    return _inputs;
   }
 
   const std::vector<std::string> &getOutputs() const
   {
-    // TODO return list of output tensor names
-    // UB here, suppress warnings
-    return *static_cast<std::vector<std::string>*>(nullptr);
+    return _outputs;
   }
 
   const std::vector<OpDescr> &getInferenceSequence() const
   {
-    // TODO return sequence of operations
-    // UB here, suppress warnings
-    return *static_cast<std::vector<OpDescr>*>(nullptr);
+    return _inferenceSequence;
   }
 
   const std::vector<char> &getPackedParameters() const
   {
-    // TODO return array containing compressed parameters for operations
-    // UB here, suppress warnings
-    return *static_cast<std::vector<char>*>(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<char> _packedParameters;
+  std::vector<OpDescr> _inferenceSequence;
+  size_t _localTensorsN = 0;
+  std::vector<std::string> _inputs;
+  std::vector<std::string> _outputs;
 };
 
 } // namespace soft
index 12dc0b0..04b6151 100644 (file)
@@ -5,10 +5,12 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <fcntl.h>
+
 #include <cerrno>
 #include <cstring>
 #include <fstream>
-#include <fcntl.h>
+#include <memory>
 
 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, void (*)(ostream *)>;
+
+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,
index 1670fbd..c7cc374 100644 (file)
@@ -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<TensorDescription> 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