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
#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;
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):
// 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,
#include "model_analyzer.h"
+#include "nnc/core/IR/model/graph/ir_node.h"
+
+using namespace std;
namespace nncc
{
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