Reformat sources to common style.
Signed-off-by: Sergei Barannikov <s.barannikov@samsung.com>
#include "option/Options.h"
#include "Driver.h"
-namespace nnc {
+namespace nnc
+{
/**
* @brief run all registered passes
* @throw PassException, if errors occured
*/
-void Driver::runPasses() {
+void Driver::runPasses()
+{
- const auto& registered_passes = _passManager.getPasses();
+ const auto ®istered_passes = _passManager.getPasses();
PassData pass_data(nullptr);
- for (auto &pass : registered_passes) {
+ for (auto &pass : registered_passes)
+ {
pass_data = pass->run(pass_data);
- if ( cli::dumpGraph && static_cast<mir::Graph*>(pass_data)){
+ if (cli::dumpGraph && static_cast<mir::Graph *>(pass_data))
+ {
DumperPass d(pass->getName());
d.run(pass_data);
}
} // runPasses
-static std::string getFrontendOptionsString() {
+static std::string getFrontendOptionsString()
+{
std::string res;
if (!cli::caffeFrontend.isDisabled())
* @brief Register frontend pass
* @throw DriverException if errors occurred
*/
-void Driver::registerFrontendPass() {
+void Driver::registerFrontendPass()
+{
// For bool, the value false is converted to zero and the value true is converted to one
if (cli::caffeFrontend + cli::caffe2Frontend + cli::tflFrontend + cli::onnxFrontend != 1)
throw DriverException("One and only one of the following options are allowed and have to be set"
- "in the same time: " + getFrontendOptionsString());
+ "in the same time: " +
+ getFrontendOptionsString());
std::unique_ptr<Pass> pass = NNImporter::createNNImporter();
- if (pass) {
+ if (pass)
+ {
_passManager.registerPass(std::move(pass));
- } else {
- throw DriverException("One of the following options must be defined: '"
- + getFrontendOptionsString());
+ }
+ else
+ {
+ throw DriverException("One of the following options must be defined: '" +
+ getFrontendOptionsString());
}
} // registerFrontendPass
* @brief Register backend pass
* @throw DriverException if errors occurred
*/
-void Driver::registerBackendPass() {
+void Driver::registerBackendPass()
+{
std::unique_ptr<Pass> pass;
- if (cli::target == NNC_TARGET_ARM_CPP || cli::target == NNC_TARGET_X86_CPP) {
+ if (cli::target == NNC_TARGET_ARM_CPP || cli::target == NNC_TARGET_X86_CPP)
+ {
pass = std::unique_ptr<Pass>(new CPPCodeGenerator());
- } else if (cli::target == NNC_TARGET_ARM_GPU_CPP) {
+ }
+ else if (cli::target == NNC_TARGET_ARM_GPU_CPP)
+ {
pass = std::unique_ptr<Pass>(new AclCppCodeGenerator());
- } else if (cli::target == NNC_TARGET_INTERPRETER) {
+ }
+ else if (cli::target == NNC_TARGET_INTERPRETER)
+ {
pass = std::unique_ptr<Pass>(new InterpreterPass());
- } else {
+ }
+ else
+ {
assert(false && "invalid option value");
}
} // registerBackendPass
-void Driver::registerOptimizationPass() {
- if (cli::doOptimizationPass) {
+void Driver::registerOptimizationPass()
+{
+ if (cli::doOptimizationPass)
+ {
// TODO: maybe we should start managing the optimizations more intelligently?
_passManager.registerPass(std::unique_ptr<Pass>(new CombineTransposes()));
_passManager.registerPass(std::unique_ptr<Pass>(new SinkTranspose()));
}
} // registerOptimizationPass
-void Driver::runDriver() {
+void Driver::runDriver()
+{
// register passes
registerFrontendPass();
#include "pass/PassManager.h"
-namespace nnc {
+namespace nnc
+{
/**
* @brief exceptions description class for compiler driver
*/
-class DriverException : public std::exception {
+class DriverException : public std::exception
+{
public:
DriverException() = default;
explicit DriverException(std::string reason) : _msg(std::move(reason)) {}
- explicit DriverException(const char* msg) : _msg(msg) {}
+ explicit DriverException(const char *msg) : _msg(msg) {}
- const char* what() const noexcept override { return _msg.c_str(); }
+ const char *what() const noexcept override { return _msg.c_str(); }
private:
std::string _msg;
/**
* @brief Compiler Driver manages the whole pipeline compilation process
*/
-class Driver {
+class Driver
+{
public:
/**
* @brief main method to run compiler driver
} // namespace nnc
-#endif //NNCC_DRIVER_H
+#endif // NNCC_DRIVER_H
#include "option/Options.h"
#include "Definitions.h"
-namespace nnc {
-namespace cli {
+namespace nnc
+{
+namespace cli
+{
/**
* Options for *compiler driver*
*/
-Option<bool> Help(optname("--help, -h"),
- overview("print usage and exit"),
- false,
- optional(true));
-Option<bool> caffeFrontend(optname("--caffe"),
- overview("treat input file as Caffe model"),
- false,
- optional(true),
- optvalues(""),
- nullptr,
- separators(""),
+Option<bool> Help(optname("--help, -h"), overview("print usage and exit"), false, optional(true));
+Option<bool> caffeFrontend(optname("--caffe"), overview("treat input file as Caffe model"), false,
+ optional(true), optvalues(""), nullptr, separators(""),
#ifdef NNC_FRONTEND_CAFFE_ENABLED
showopt(true)
#else
showopt(false)
#endif // NNC_FRONTEND_CAFFE_ENABLED
- );
-Option<bool> onnxFrontend(optname("--onnx"),
- overview("treat input file as ONNX model"),
- false,
- optional(true),
- optvalues(""),
- nullptr,
- separators(""),
+ );
+Option<bool> onnxFrontend(optname("--onnx"), overview("treat input file as ONNX model"), false,
+ optional(true), optvalues(""), nullptr, separators(""),
#ifdef NNC_FRONTEND_ONNX_ENABLED
- showopt(true)
+ showopt(true)
#else
- showopt(false)
+ showopt(false)
#endif // NNC_FRONTEND_ONNX_ENABLED
- );
+ );
Option<bool> caffe2Frontend(optname("--caffe2"),
- overview("treat input file as Caffe2 model (predict_net.pb)"),
- false,
- optional(false),
- optvalues(""),
- nullptr,
- separators(""),
+ overview("treat input file as Caffe2 model (predict_net.pb)"), false,
+ optional(false), optvalues(""), nullptr, separators(""),
#ifdef NNC_FRONTEND_CAFFE2_ENABLED
showopt(true),
#else
showopt(false),
#endif // NNC_FRONTEND_CAFFE2_ENABLED
- IOption::Group::caffe2
- );
+ IOption::Group::caffe2);
-Option<std::vector<int>> inputShapes(optname("--input-shape"),
- overview("Shape of caffe2 input"),
- std::vector<int>{},
- optional(false),
- optvalues(""),
- nullptr,
+Option<std::vector<int>> inputShapes(optname("--input-shape"), overview("Shape of caffe2 input"),
+ std::vector<int>{}, optional(false), optvalues(""), nullptr,
separators(""),
#ifdef NNC_FRONTEND_CAFFE2_ENABLED
showopt(true),
#else
showopt(false),
#endif // NNC_FRONTEND_CAFFE2_ENABLED
- IOption::Group::caffe2
- );
+ IOption::Group::caffe2);
Option<std::string> initNet(optname("--init-net"),
- overview("path to Caffe2 model weights (init_net.pb)"),
- std::string(),
- optional(false),
- optvalues(""),
- checkInFile,
- separators(""),
+ overview("path to Caffe2 model weights (init_net.pb)"), std::string(),
+ optional(false), optvalues(""), checkInFile, separators(""),
#ifdef NNC_FRONTEND_CAFFE2_ENABLED
showopt(true),
#else
showopt(false),
#endif // NNC_FRONTEND_CAFFE2_ENABLED
- IOption::Group::caffe2
- );
+ IOption::Group::caffe2);
Option<bool> tflFrontend(optname("--tflite"),
- overview("treat input file as Tensor Flow Lite model"),
- false,
- optional(true),
- optvalues(""),
- nullptr,
- separators(""),
+ overview("treat input file as Tensor Flow Lite model"), false,
+ optional(true), optvalues(""), nullptr, separators(""),
#ifdef NNC_FRONTEND_TFLITE_ENABLED
showopt(true)
#else
showopt(false)
#endif // NNC_FRONTEND_TFLITE_ENABLED
- );
-Option<std::string> target(optname("--target"),
- overview("select target language to emit for given architecture."
- "Valid values are '"
- NNC_TARGET_ARM_CPP "', '"
- NNC_TARGET_X86_CPP "', '"
- NNC_TARGET_ARM_GPU_CPP "', '"
- NNC_TARGET_INTERPRETER "'"),
- std::string(),
- optional(false),
- optvalues(NNC_TARGET_ARM_CPP ","
- NNC_TARGET_X86_CPP ","
- NNC_TARGET_ARM_GPU_CPP ","
- NNC_TARGET_INTERPRETER),
- nullptr,
- separators("="));
+ );
+Option<std::string>
+ target(optname("--target"),
+ overview("select target language to emit for given architecture."
+ "Valid values are '" NNC_TARGET_ARM_CPP "', '" NNC_TARGET_X86_CPP
+ "', '" NNC_TARGET_ARM_GPU_CPP "', '" NNC_TARGET_INTERPRETER "'"),
+ std::string(), optional(false),
+ optvalues(NNC_TARGET_ARM_CPP "," NNC_TARGET_X86_CPP "," NNC_TARGET_ARM_GPU_CPP
+ "," NNC_TARGET_INTERPRETER),
+ nullptr, separators("="));
/**
* Options for *frontend*
*/
Option<std::string> inputFile(optname("--nnmodel, -m"),
overview("specify input file with serialized NN models"),
- std::string(),
- optional(false),
- optvalues(""),
- checkInFile);
+ std::string(), optional(false), optvalues(""), checkInFile);
/**
* Options for *optimizer*
*/
-Option<bool> doOptimizationPass(optname("-O"),
- overview("whether to optimize model or not"),
- false,
- optional(true), optvalues(""), nullptr,
- separators(""),
+Option<bool> doOptimizationPass(optname("-O"), overview("whether to optimize model or not"), false,
+ optional(true), optvalues(""), nullptr, separators(""),
showopt(true));
Option<bool> dumpGraph(optname("--dump, -D"),
- overview("dump graph to dot files after optimization passes"),
- false,
- optional(true), optvalues(""), nullptr,
- separators(""),
- showopt(true));
+ overview("dump graph to dot files after optimization passes"), false,
+ optional(true), optvalues(""), nullptr, separators(""), showopt(true));
/**
* Options for *backend*
*/
// options for soft backend
-Option<std::string> artifactName(optname("--output, -o"),
- overview("specify name for output files"),
- "nnmodel",
- optional(true),
- optvalues(""),
- checkOutFile);
+Option<std::string> artifactName(optname("--output, -o"), overview("specify name for output files"),
+ "nnmodel", optional(true), optvalues(""), checkOutFile);
Option<std::string> artifactDir(optname("--output-dir, -d"),
overview("specify directory for output files"),
".", // default is current directory
- optional(true),
- optvalues(""),
- checkOutDir,
- separators("="));
+ optional(true), optvalues(""), checkOutDir, separators("="));
/**
* Options for *interpreter*
"containing the input data for the model "
"(one file for each input with the same name)"),
".", // default is current directory
- optional(true),
- optvalues(""),
- checkInDir);
+ optional(true), optvalues(""), checkInDir);
} // namespace cli
} // namespace nnc
* Prints the explanatory string of an exception. If the exception is nested, recurses to print
* the explanatory string of the exception it holds.
*/
-static void printException(const std::exception& e, int indent = 0) {
+static void printException(const std::exception &e, int indent = 0)
+{
std::cerr << std::string(indent, ' ') << e.what() << std::endl;
- try {
+ try
+ {
std::rethrow_if_nested(e);
- } catch (const std::exception& e) {
+ }
+ catch (const std::exception &e)
+ {
printException(e, indent + 2);
}
}
-int main(int argc, const char* argv[]) {
+int main(int argc, const char *argv[])
+{
int exit_code = EXIT_FAILURE;
- try {
+ try
+ {
// Parse command line
cli::CommandLine::getParser()->parseCommandLine(argc, argv);
// errors didn't happen
exit_code = EXIT_SUCCESS;
- } catch (const DriverException& e) {
+ }
+ catch (const DriverException &e)
+ {
printException(e);
std::cerr << "use --help for more information" << std::endl;
- } catch (const PassException& e) {
+ }
+ catch (const PassException &e)
+ {
printException(e);
}
extern Option<std::vector<int>> inputShapes;
extern Option<std::string> initNet;
-extern Option<bool> caffeFrontend; // frontend for CAFFE AI framework
-extern Option<bool> tflFrontend; // frontend for TensorFlow Lite AI framework
-extern Option<bool> onnxFrontend; // frontend for ONNX AI framework
+extern Option<bool> caffeFrontend; // frontend for CAFFE AI framework
+extern Option<bool> tflFrontend; // frontend for TensorFlow Lite AI framework
+extern Option<bool> onnxFrontend; // frontend for ONNX AI framework
extern Option<bool> doOptimizationPass; // enable optimization pass
-extern Option<bool> dumpGraph; // enable Dumping graph to .dot files
+extern Option<bool> dumpGraph; // enable Dumping graph to .dot files
// valid values for target option
-#define NNC_TARGET_ARM_CPP "arm-c++"
-#define NNC_TARGET_X86_CPP "x86-c++"
-#define NNC_TARGET_ARM_GPU_CPP "arm-gpu-c++"
-#define NNC_TARGET_INTERPRETER "interpreter"
-extern Option<std::string> target; // kind of target for which compiler generates code
+#define NNC_TARGET_ARM_CPP "arm-c++"
+#define NNC_TARGET_X86_CPP "x86-c++"
+#define NNC_TARGET_ARM_GPU_CPP "arm-gpu-c++"
+#define NNC_TARGET_INTERPRETER "interpreter"
+extern Option<std::string> target; // kind of target for which compiler generates code
/**
* Frontend options
*/
-extern Option<std::string> inputFile; // files contains model of specific AI framework
+extern Option<std::string> inputFile; // files contains model of specific AI framework
/**
* Options for backend
*/
-extern Option<std::string> artifactDir; // output directory for artifact
-extern Option<std::string> artifactName; // name of artifact
+extern Option<std::string> artifactDir; // output directory for artifact
+extern Option<std::string> artifactName; // name of artifact
/**
* Options for interpreter
*/
-extern Option<std::string> interInputDataDir; // directory with input data files
+extern Option<std::string> interInputDataDir; // directory with input data files
} // namespace cli
} // namespace nnc
-#endif //NNCC_COMMANDLINEARGUMENTS_H
+#endif // NNCC_COMMANDLINEARGUMENTS_H
/**
* @brief this class represent an interface for all compiler passes like that frontend, backend etc
*/
-class Pass {
+class Pass
+{
public:
/**
* @brief run compiler pass
/**
* @brief clean compiler pass data
*/
- virtual void cleanup() {};
+ virtual void cleanup(){};
virtual ~Pass() = default;
} // namespace nnc
-#endif //NNCC_PASS_H
+#endif // NNCC_PASS_H
#include "mir/Graph.h"
#include "mir/TensorVariant.h"
-
namespace nnc
{
class PassData
{
public:
- /* implicit */ PassData(std::nullptr_t data) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
- _dataContainer{.unknown = data}, _dataType(PDT::UNKNOWN) {}
+ /* implicit */ PassData(std::nullptr_t data)
+ : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
+ _dataContainer{.unknown = data},
+ _dataType(PDT::UNKNOWN)
+ {
+ }
/**
* @brief Implicit conversion from Graph* to PassData
*/
- /* implicit */ PassData(mir::Graph *graph) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
- _dataContainer{.graph = graph}, _dataType(PDT::GRAPH) {}
+ /* implicit */ PassData(mir::Graph *graph)
+ : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
+ _dataContainer{.graph = graph},
+ _dataType(PDT::GRAPH)
+ {
+ }
/**
* @brief Implicit conversion from PassData to Graph*
*/
- /* implicit */ operator mir::Graph*() const { // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
- if ( _dataType != PDT::GRAPH )
+ /* implicit */ operator mir::Graph *() const
+ { // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
+ if (_dataType != PDT::GRAPH)
return nullptr;
return _dataContainer.graph;
}
/**
* @brief Implicit conversion from Graph* to PassData
*/
- /* implicit */ PassData(mir::TensorVariant *tv) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
- _dataContainer{.tensorVariant = tv}, _dataType(PDT::TENSOR_VARIANT) {}
+ /* implicit */ PassData(mir::TensorVariant *tv)
+ : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
+ _dataContainer{.tensorVariant = tv},
+ _dataType(PDT::TENSOR_VARIANT)
+ {
+ }
/**
* @brief Implicit conversion from PassData to Graph*
*/
- /* implicit */ operator mir::TensorVariant*() const { // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
- if ( _dataType != PDT::TENSOR_VARIANT )
+ /* implicit */ operator mir::TensorVariant *() const
+ { // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
+ if (_dataType != PDT::TENSOR_VARIANT)
return nullptr;
return _dataContainer.tensorVariant;
}
} _dataType;
// union contains all pointers to objects that can be returned from passes
- union
- {
+ union {
mir::Graph *graph;
mir::TensorVariant *tensorVariant;
void *unknown;
} // namespace nnc
-#endif //NNCC_PASSDATA_H
+#endif // NNCC_PASSDATA_H
public:
PassException() = default;
explicit PassException(std::string msg) : _msg(std::move(msg)) {}
- explicit PassException(const char* msg) : _msg(msg) {}
+ explicit PassException(const char *msg) : _msg(msg) {}
- const char* what() const noexcept override { return _msg.c_str(); }
+ const char *what() const noexcept override { return _msg.c_str(); }
private:
std::string _msg;
} // namespace nnc
-#endif //NNCC_PASSEXCEPTION_H
+#endif // NNCC_PASSEXCEPTION_H
#include <queue>
#include <memory>
-namespace nnc {
+namespace nnc
+{
// forward declaration
class Pass;
/**
* @brief pass manager class. This class manages running of passes
*/
-class PassManager {
+class PassManager
+{
public:
PassManager();
~PassManager();
* @brief get all registered passes in order in which they were registered
*/
using Passes = std::vector<std::unique_ptr<Pass>>;
- const Passes& getPasses() const { return _passes; }
+ const Passes &getPasses() const { return _passes; }
private:
// data
#include "pass/PassException.h"
-namespace nnc {
+namespace nnc
+{
/**
* @brief objects of this class are to be thrown from ACL C++ soft backend if errors are occurred.
*/
-class AclCppException : public PassException {
+class AclCppException : public PassException
+{
public:
- explicit AclCppException(const std::string& msg) : PassException(_prefix + msg) {}
+ explicit AclCppException(const std::string &msg) : PassException(_prefix + msg) {}
private:
- static constexpr const char* _prefix = "ACL C++ soft backend error: ";
+ static constexpr const char *_prefix = "ACL C++ soft backend error: ";
};
} // namespace nnc
#include "pass/Pass.h"
-
-namespace nnc {
+namespace nnc
+{
/**
* @brief Class for the ACL C++ code generator.
* It is the entry point to the ACL C++ soft backend.
*/
-class AclCppCodeGenerator: public Pass {
+class AclCppCodeGenerator : public Pass
+{
public:
/**
* @brief Method represents the generation sequence: analysis, serialization,
#include "pass/Pass.h"
#include "mir/Graph.h"
-namespace nnc {
+namespace nnc
+{
/**
* @brief Interface for all frontends. All who uses frontends must do it thought this interface
*/
-class NNImporter : public Pass {
+class NNImporter : public Pass
+{
public:
// template method pattern
- PassData run(PassData /*data*/) final {
- return importModel();
- }
+ PassData run(PassData /*data*/) final { return importModel(); }
static std::unique_ptr<NNImporter> createNNImporter();
virtual mir::Graph *importModel() = 0;
- std::string getName() override { return "importer";};
+ std::string getName() override { return "importer"; };
};
} // namespace nnc
#include "pass/PassData.h"
#include "mir/IrDotDumper.h"
-namespace nnc {
+namespace nnc
+{
/**
* @brief Dumps the graph to a dot file named %number%.dot
* where %number% is how many times the graph was dumped.
*/
-class DumperPass : public Pass {
+class DumperPass : public Pass
+{
public:
- explicit DumperPass(std::string s): _file_name(std::move(s)){};
+ explicit DumperPass(std::string s) : _file_name(std::move(s)){};
PassData run(PassData data) override;
+
private:
std::string _file_name;
static int _counter;
};
} // namespace nnc
-#endif //NNCC_DUMPERPASS_H
+#endif // NNCC_DUMPERPASS_H
#include <unordered_map>
#include <vector>
-namespace nnc {
+namespace nnc
+{
-class NNInterpreter : public mir::IVisitor {
+class NNInterpreter : public mir::IVisitor
+{
public:
explicit NNInterpreter() = default;
~NNInterpreter() override = default;
- void setInput(const std::string& name, const mir::TensorVariant& data);
+ void setInput(const std::string &name, const mir::TensorVariant &data);
- mir::TensorVariant getResult(const mir::Operation::Output* tensor);
+ mir::TensorVariant getResult(const mir::Operation::Output *tensor);
- void visit(mir::ops::AddOp& op) override;
- void visit(mir::ops::BatchNormOp& op) override;
- void visit(mir::ops::CappedReluOp& op) override;
- void visit(mir::ops::ConcatOp& op) override;
- void visit(mir::ops::ConstantOp& op) override;
- void visit(mir::ops::Conv2DOp& op) override;
- void visit(mir::ops::DeConv2DOp& op) override;
- void visit(mir::ops::DepthwiseConv2DOp& op) override;
- void visit(mir::ops::DivOp& op) override;
- void visit(mir::ops::DropoutOp& op) override;
- void visit(mir::ops::EluOp& op) override;
- void visit(mir::ops::FullyConnectedOp& op) override;
- void visit(mir::ops::GatherOp& op) override;
- void visit(mir::ops::GemmOp& op) override;
- void visit(mir::ops::InputOp& op) override;
- void visit(mir::ops::LeakyReluOp& op) override;
- void visit(mir::ops::MaxOp& op) override;
- void visit(mir::ops::MulOp& op) override;
- void visit(mir::ops::OutputOp& op) override;
- void visit(mir::ops::PadOp& op) override;
- void visit(mir::ops::PoolOp& op) override;
- void visit(mir::ops::ReduceOp& op) override;
- void visit(mir::ops::ReluOp& op) override;
- void visit(mir::ops::ReshapeOp& op) override;
- void visit(mir::ops::ResizeOp& op) override;
- void visit(mir::ops::SigmoidOp& op) override;
- void visit(mir::ops::SliceOp& op) override;
- void visit(mir::ops::SoftmaxOp& op) override;
- void visit(mir::ops::SqrtOp& op) override;
- void visit(mir::ops::SqueezeOp& op) override;
- void visit(mir::ops::SubOp& op) override;
- void visit(mir::ops::TanhOp& op) override;
- void visit(mir::ops::TransposeOp& op) override;
+ void visit(mir::ops::AddOp &op) override;
+ void visit(mir::ops::BatchNormOp &op) override;
+ void visit(mir::ops::CappedReluOp &op) override;
+ void visit(mir::ops::ConcatOp &op) override;
+ void visit(mir::ops::ConstantOp &op) override;
+ void visit(mir::ops::Conv2DOp &op) override;
+ void visit(mir::ops::DeConv2DOp &op) override;
+ void visit(mir::ops::DepthwiseConv2DOp &op) override;
+ void visit(mir::ops::DivOp &op) override;
+ void visit(mir::ops::DropoutOp &op) override;
+ void visit(mir::ops::EluOp &op) override;
+ void visit(mir::ops::FullyConnectedOp &op) override;
+ void visit(mir::ops::GatherOp &op) override;
+ void visit(mir::ops::GemmOp &op) override;
+ void visit(mir::ops::InputOp &op) override;
+ void visit(mir::ops::LeakyReluOp &op) override;
+ void visit(mir::ops::MaxOp &op) override;
+ void visit(mir::ops::MulOp &op) override;
+ void visit(mir::ops::OutputOp &op) override;
+ void visit(mir::ops::PadOp &op) override;
+ void visit(mir::ops::PoolOp &op) override;
+ void visit(mir::ops::ReduceOp &op) override;
+ void visit(mir::ops::ReluOp &op) override;
+ void visit(mir::ops::ReshapeOp &op) override;
+ void visit(mir::ops::ResizeOp &op) override;
+ void visit(mir::ops::SigmoidOp &op) override;
+ void visit(mir::ops::SliceOp &op) override;
+ void visit(mir::ops::SoftmaxOp &op) override;
+ void visit(mir::ops::SqrtOp &op) override;
+ void visit(mir::ops::SqueezeOp &op) override;
+ void visit(mir::ops::SubOp &op) override;
+ void visit(mir::ops::TanhOp &op) override;
+ void visit(mir::ops::TransposeOp &op) override;
private:
/// @brief Gets the computed inputs for the operation.
std::vector<std::reference_wrapper<const mir::TensorVariant>>
- getInputTensors(const mir::Operation& op);
+ getInputTensors(const mir::Operation &op);
/// @brief Saves the computed outputs for the operation.
- void setOutputTensors(const mir::Operation& op, std::vector<mir::TensorVariant>&& outputs);
+ void setOutputTensors(const mir::Operation &op, std::vector<mir::TensorVariant> &&outputs);
/// @brief Mapping of graph named inputs to their values.
std::unordered_map<std::string, mir::TensorVariant> _inputTensors;
/// @brief Mapping of operations to their computed results.
- std::unordered_map<const mir::Operation*, std::vector<mir::TensorVariant>> _opResults;
+ std::unordered_map<const mir::Operation *, std::vector<mir::TensorVariant>> _opResults;
};
} // namespace nnc
#include "pass/Pass.h"
#include "pass/PassData.h"
+namespace nnc
+{
-namespace nnc {
-
-class InterpreterPass : public Pass {
+class InterpreterPass : public Pass
+{
public:
~InterpreterPass() override;
} // namespace nnc
-#endif //NNCC_INTERPRETERPASS_H
+#endif // NNCC_INTERPRETERPASS_H
#include "pass/Pass.h"
#include "pass/PassData.h"
-namespace nnc {
+namespace nnc
+{
/**
* @brief This pass combines sequential transposes and removes identity transposes if
* the combination results in an identity permutation.
*/
-class CombineTransposes : public Pass {
+class CombineTransposes : public Pass
+{
public:
PassData run(PassData data) override;
- std::string getName() override {return "opt_combine_transposes";};
+ std::string getName() override { return "opt_combine_transposes"; };
private:
};
} // namespace nnc
-#endif //NNCC_COMBINE_TRANSPOSES_H
+#endif // NNCC_COMBINE_TRANSPOSES_H
#include "pass/Pass.h"
#include "pass/PassData.h"
-namespace nnc {
+namespace nnc
+{
/**
* @brief Main purpose of this pass - is to fuse 'Conv->BatchNorm' into 'Conv'
* Currently 'BatchNorm' split by NNC frontends into 'Scale->Scale->BiasAdd'
* This optimization performs in two steps (repeated while graph changing):
- * 1. Fuse two successive operations with constant weights into one (ex: 'Scale->Scale' becomes 'Scale')
+ * 1. Fuse two successive operations with constant weights into one (ex: 'Scale->Scale' becomes
+ * 'Scale')
* 2. Sink 'BiasAdd' through 'Scale' (so 'Conv->BiasAdd->Scale' becomes 'Conv->Scale->BiasAdd')
*/
-class FuseArithmeticOps : public Pass {
+class FuseArithmeticOps : public Pass
+{
public:
PassData run(PassData data) override;
std::string getName() override { return "FuseArithmeticOps"; }
};
-} // namespace nnc
+} // namespace nnc
-
-#endif // NNCC_FUSE_ARITHMETIC_OPS_H
+#endif // NNCC_FUSE_ARITHMETIC_OPS_H
#include "mir/Operation.h"
#include "mir/Graph.h"
-namespace nnc {
-namespace opt_util {
+namespace nnc
+{
+namespace opt_util
+{
/**
* @brief Swap adjacent nodes in Graph. Creates new nodes and replaces the old ones with new.
* @param g MIR Graph
* @param top Node
* @param bottom Node
*/
- void swapAdjacent(mir::Graph* g, mir::Operation* top, mir::Operation* bottom);
+void swapAdjacent(mir::Graph *g, mir::Operation *top, mir::Operation *bottom);
// TODO: this function and it's usages should be removed, after DCE optimization will be implemented
- void removeNodeIfUnused(mir::Graph* g, mir::Operation* op);
+void removeNodeIfUnused(mir::Graph *g, mir::Operation *op);
} // namespace opt_util
} // namespace nnc
-#endif //NNCC_OPTIMIZATION_UTILS_H
+#endif // NNCC_OPTIMIZATION_UTILS_H
#include "pass/Pass.h"
#include "pass/PassData.h"
-namespace nnc {
+namespace nnc
+{
/**
* @brief This pass removes operations without uses.
* Importers currently only generate `sConstantOp`s without uses.
*/
-class RemoveDeadEnds : public Pass {
+class RemoveDeadEnds : public Pass
+{
public:
PassData run(PassData data) override;
- std::string getName() override {return "RemoveDeadEnds";};
+ std::string getName() override { return "RemoveDeadEnds"; };
};
} // namespace nnc
-
-#endif //NNCC_REMOVEDEADENDS_H
+#endif // NNCC_REMOVEDEADENDS_H
#include "pass/Pass.h"
#include "pass/PassData.h"
-namespace nnc {
+namespace nnc
+{
/**
* @brief This pass sinks relu below MaxPooling and Concat nodes.
*/
-class SinkRelu : public Pass {
+class SinkRelu : public Pass
+{
public:
PassData run(PassData data) override;
} // namespace nnc
-#endif //NNCC_SINKRELU_H
+#endif // NNCC_SINKRELU_H
#include "pass/Pass.h"
#include "pass/PassData.h"
-namespace nnc {
+namespace nnc
+{
/**
* @brief This pass sinks transposes below Relu and Concat nodes (in that order).
* `concat(relu(tr(x)), relu(tr(y))) -> tr(concat'(relu(x), relu(y)))`
*/
-class SinkTranspose : public Pass {
+class SinkTranspose : public Pass
+{
public:
PassData run(PassData data) override;
} // namespace nnc
-#endif //NNCC_SINKTRANSPOSE_H
+#endif // NNCC_SINKTRANSPOSE_H
#include <string>
#include <ostream>
-
-namespace nnc {
+namespace nnc
+{
class ModelAnalyzer;
* + code file generation function: materuializeCode
* + header file generation to expose artifact inerface to user
*/
-class BaseCodeGenerator : public Pass {
+class BaseCodeGenerator : public Pass
+{
public:
/**
- * @brief Method represents base generation sequence: analysis, serialization, header/code generation, etc
+ * @brief Method represents base generation sequence: analysis, serialization, header/code
+ * generation, etc
* @param data PassData object containing Model IR
* @return returns empty PassData object
*/
PassData run(PassData data) override;
+
protected:
/**
* @brief This function processes tensor names
* @brief Derivative classes should override this function to generate implementation of artifact
* @param out Stream to write header text
* @param ma Intermediate artifact information
- * @param s Serializer holds parameters of network and various meta-information: serializer version, hashes, etc
+ * @param s Serializer holds parameters of network and various meta-information: serializer
+ * version, hashes, etc
*/
virtual void materializeCode(std::ostream &out, const ModelAnalyzer &ma, const Serializer &s) = 0;
/**
/**
* @brief CCodeGenerator implements interfaces that provides BaseCodeGenerator for C language
- * This includes header file generation, code file generation and variable renaming according to C naming requirements
+ * This includes header file generation, code file generation and variable renaming according to C
+ * naming requirements
*/
-class CCodeGenerator: public BaseCodeGenerator
+class CCodeGenerator : public BaseCodeGenerator
{
public:
static Pass &getInstance();
#include "passes/soft_backend/BaseGenerator.h"
#include "pass/Pass.h"
-namespace nnc {
+namespace nnc
+{
-namespace sir {
+namespace sir
+{
struct TensorDescriptor;
struct Action;
struct CallFunction;
struct TransposeTensor;
struct CreateTmp;
struct DestroyTmp;
-} // namespace sir
-
+} // namespace sir
/**
* @brief CPPCodeGenerator implements interfaces that provides BaseCodeGenerator for C++ language
- * This includes header file generation, code file generation and variable renaming according to C++ naming requirements
+ * This includes header file generation, code file generation and variable renaming according to C++
+ * naming requirements
*/
-class CPPCodeGenerator: public BaseCodeGenerator {
+class CPPCodeGenerator : public BaseCodeGenerator
+{
protected:
- void formatTensorNames(const ModelAnalyzer& ma) override;
- void materializeHeader(std::ostream& out, const ModelAnalyzer& ma) override;
+ void formatTensorNames(const ModelAnalyzer &ma) override;
+ void materializeHeader(std::ostream &out, const ModelAnalyzer &ma) override;
/**
* @brief Form list of function call arguments
* @param argIds List of argument variable ids
* @param args Result list of arguments transformed in form of strings
*/
- void gatherOperationArguments(const ModelAnalyzer& ma,
- const std::vector<size_t>& arg_ids,
- std::vector<std::string>& args);
+ void gatherOperationArguments(const ModelAnalyzer &ma, const std::vector<size_t> &arg_ids,
+ std::vector<std::string> &args);
/**
* @brief Prints setter of artifact
* @param out Output stream
* @param setterName Name of setter function
* @param varId id of variable that setter fills
*/
- void printSetter(std::ostream& out, const std::string& class_name,
- const std::string& setter_name, const sir::TensorDescriptor& td);
+ void printSetter(std::ostream &out, const std::string &class_name, const std::string &setter_name,
+ const sir::TensorDescriptor &td);
/**
* @brief Prints getters of artifact
* @param out Output stream
* @param setterName Name of setter function
* @param varId id of variable that getter returns
*/
- void printGetter(std::ostream& out, const std::string& class_name,
- const std::string& getter_name, const sir::TensorDescriptor& td);
+ void printGetter(std::ostream &out, const std::string &class_name, const std::string &getter_name,
+ const sir::TensorDescriptor &td);
/**
* @brief Generate code for function call action
* @param out Output stream to print
* @param ma Intermediate model representation
* @param call Action to generate code from
*/
- void materializeCall(std::ostream& out, const ModelAnalyzer& ma,
- const nnc::sir::CallFunction* call);
+ void materializeCall(std::ostream &out, const ModelAnalyzer &ma,
+ const nnc::sir::CallFunction *call);
/**
* @brief Generate code for transpose action
* @param out Output stream to print
* @param ma Intermediate model representation
* @param action Action to generate code from
*/
- void materializeTranspose(std::ostream& out, const ModelAnalyzer& ma,
- const nnc::sir::TransposeTensor* transpose);
+ void materializeTranspose(std::ostream &out, const ModelAnalyzer &ma,
+ const nnc::sir::TransposeTensor *transpose);
/**
* @brief Generate code for constructor action
* @param out Output stream to print
* @param ma Intermediate model representation
* @param action Action to generate code from
*/
- void materializeConstructor(std::ostream& out, const ModelAnalyzer& ma,
- const nnc::sir::CreateTmp* constructor);
+ void materializeConstructor(std::ostream &out, const ModelAnalyzer &ma,
+ const nnc::sir::CreateTmp *constructor);
/**
* @brief Generate code for destructor action
* @param out Output stream to print
* @param ma Intermediate model representation
* @param action Action to generate code from
*/
- void materializeDestructor(std::ostream& out, const ModelAnalyzer& ma,
- const nnc::sir::DestroyTmp* destructor);
+ void materializeDestructor(std::ostream &out, const ModelAnalyzer &ma,
+ const nnc::sir::DestroyTmp *destructor);
/**
* @brief Prints inference sequence placed in doInference method of artifact
* @param out Output stream
* @param ma Intermediate model representation
*/
- void materializeInferenceSequence(std::ostream& out, const ModelAnalyzer& ma);
- void materializeCode(std::ostream& out, const ModelAnalyzer& ma, const Serializer& s) override;
-
+ void materializeInferenceSequence(std::ostream &out, const ModelAnalyzer &ma);
+ void materializeCode(std::ostream &out, const ModelAnalyzer &ma, const Serializer &s) override;
};
} // namespace nnc
#include <limits>
#include <iostream>
-namespace nnc {
-namespace cli {
+namespace nnc
+{
+namespace cli
+{
/**
* @brief simple exception class for invalid options
*/
-class BadOption : public std::logic_error {
+class BadOption : public std::logic_error
+{
public:
- explicit BadOption(const std::string& msg, std::string optname = "", std::string value = "")
- : std::logic_error(msg), _option_name(std::move(optname)),
- _option_value(std::move(value)) {}
+ explicit BadOption(const std::string &msg, std::string optname = "", std::string value = "")
+ : std::logic_error(msg), _option_name(std::move(optname)), _option_value(std::move(value))
+ {
+ }
/**
* @brief get name for invalid option
*/
- const std::string& getName() const { return _option_name; }
+ const std::string &getName() const { return _option_name; }
/**
* @brief get value for invalid option
*/
- const std::string& getValue() const { return _option_value; }
+ const std::string &getValue() const { return _option_value; }
private:
std::string _option_name;
/**
* @brief a class models option type
*/
-template <typename T, bool isClass>
-class OptionType {
+template <typename T, bool isClass> class OptionType
+{
public:
OptionType() = default;
};
// for class type
-template <typename T>
-class OptionType<T, true> : public T {
+template <typename T> class OptionType<T, true> : public T
+{
public:
/**
* @brief set value for option
* @tparam Tval - type of value what we want to assign to value
* @param val - option value
*/
- template <typename Tval>
- void setRawValue(const Tval& val) { this->T::operator=(val); }
+ template <typename Tval> void setRawValue(const Tval &val) { this->T::operator=(val); }
/**
* @brief get option value
* @return value of option
*/
- const T& getRawValue() const { return *this; }
+ const T &getRawValue() const { return *this; }
T getRawValue() { return *this; }
};
// for scalar type
-template <typename T>
-class OptionType<T, false> {
+template <typename T> class OptionType<T, false>
+{
public:
/**
* @brief convert Option to scalar option type
*/
- /*implicit*/ operator T() const { return _value; } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
+ /*implicit*/ operator T() const
+ {
+ return _value;
+ } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
/**
* @brief set value for option
* @tparam Tval - type of value what we want to assign to value
* @param val - option value
*/
- template <typename Tval>
- void setRawValue(const Tval& val) { _value = val; }
+ template <typename Tval> void setRawValue(const Tval &val) { _value = val; }
/**
* @brief get option value
* @return value of option
*/
- const T& getRawValue() const { return _value; }
+ const T &getRawValue() const { return _value; }
T getRawValue() { return _value; }
protected:
// methods for Option
- bool convToBool(const std::string& val);
- char convToChar(const std::string& val);
- template <typename Tnum> Tnum convToNum(const std::string& val);
+ bool convToBool(const std::string &val);
+ char convToChar(const std::string &val);
+ template <typename Tnum> Tnum convToNum(const std::string &val);
// data
T _value; // option value
/**
* @brief interface for Option class
*/
-class IOption {
+class IOption
+{
public:
/**
* @brief set option value
* @param val - value of option in string format
* @todo add support for vector
*/
- virtual void setValue(const std::string& val) = 0;
+ virtual void setValue(const std::string &val) = 0;
/**
* @brief get all names of option
*/
- virtual const std::vector<std::string>& getNames() const = 0;
+ virtual const std::vector<std::string> &getNames() const = 0;
/**
* @brief get description of option
*/
- virtual const std::string& getOverview() const = 0;
+ virtual const std::string &getOverview() const = 0;
/**
* @brief may option be optional?
/**
* @brief get valid values for given option
*/
- virtual const std::vector<std::string>& getValidVals() const = 0;
+ virtual const std::vector<std::string> &getValidVals() const = 0;
/**
* @brief get separators for option
*/
- virtual const std::vector<char>& getSeparators() const = 0;
+ virtual const std::vector<char> &getSeparators() const = 0;
/**
* @brief function for option verification
virtual bool isGrouped() const = 0;
// groups for option. Each option can be put in one of these groups
- enum class Group {
+ enum class Group
+ {
none = 0,
caffe2 = 1,
- onnx = 2 // 'onnx' is currently unused
+ onnx = 2 // 'onnx' is currently unused
};
/**
protected:
// this array contains name of option groups. It must be synchronized with Group enum
- constexpr static const char* const _groupNames[] = {nullptr, "caffe2", "onnx"};
+ constexpr static const char *const _groupNames[] = {nullptr, "caffe2", "onnx"};
};
/**
* @tparam T - type of option
*/
template <typename T>
-class Option final : public OptionType<T, std::is_class<T>::value>, public IOption {
+class Option final : public OptionType<T, std::is_class<T>::value>, public IOption
+{
public:
/**
* @brief function type for option verification
*/
- using option_checker_t = void (*)(const Option<T>&);
+ using option_checker_t = void (*)(const Option<T> &);
/**
* @brief construct an option
* @param enabled - if this option is set to false then it won't be shown for users
* @param group - all options can be splitted into groups so this param sets group for option
*/
- explicit Option(const std::vector<std::string>& optnames,
- const std::string& descr,
- const T& default_val = T(),
- bool is_optional = false,
- const std::vector<std::string>& vals = std::vector<std::string>(),
+ explicit Option(const std::vector<std::string> &optnames, const std::string &descr,
+ const T &default_val = T(), bool is_optional = false,
+ const std::vector<std::string> &vals = std::vector<std::string>(),
option_checker_t checker = nullptr,
- const std::vector<char>& seps = std::vector<char>(),
- bool enabled = true,
+ const std::vector<char> &seps = std::vector<char>(), bool enabled = true,
IOption::Group group = IOption::Group::none);
// options must not be copyable and assignment
- Option(const Option&) = delete;
+ Option(const Option &) = delete;
- Option& operator=(const Option&) = delete;
+ Option &operator=(const Option &) = delete;
/**
* @brief overload assignment operator for type
*/
- template <typename Tval>
- T& operator=(const Tval& val) { // NOLINT(cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator)
+ template <typename Tval> T &operator=(const Tval &val)
+ { // NOLINT(cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator)
setRawValue(val);
return this->getRawValue(); // If not using `this` it won't work
}
// overridden methods
- void setValue(const std::string& val) override;
+ void setValue(const std::string &val) override;
- const std::vector<std::string>& getNames() const override { return _names; }
+ const std::vector<std::string> &getNames() const override { return _names; }
- const std::string& getOverview() const override { return _descr; }
+ const std::string &getOverview() const override { return _descr; }
bool isOptional() const override { return _is_optional; }
- const std::vector<std::string>& getValidVals() const override { return _valid_vals; }
+ const std::vector<std::string> &getValidVals() const override { return _valid_vals; }
- void runCheckerFunc() override {
- if (_checker) {
+ void runCheckerFunc() override
+ {
+ if (_checker)
+ {
_checker(*this);
}
}
- const std::vector<char>& getSeparators() const override { return _seps; }
+ const std::vector<char> &getSeparators() const override { return _seps; }
bool isDisabled() const override { return !_is_enabled; }
private:
// data
std::vector<std::string> _names; // names of the option
- std::string _descr; // overview of option
+ std::string _descr; // overview of option
bool _is_optional;
std::vector<std::string> _valid_vals; // option can be initialized only by these values
- option_checker_t _checker; // function verifies option and its value
- std::vector<char> _seps; // these symbols separate option name and its value
+ option_checker_t _checker; // function verifies option and its value
+ std::vector<char> _seps; // these symbols separate option name and its value
bool _is_enabled;
bool _can_have_several_vals; // can option take several values?
- IOption::Group _group; // group for option
+ IOption::Group _group; // group for option
};
/**
* @brief this class describes a common command line interface
*/
-class CommandLine { // NOLINT(cppcoreguidelines-special-member-functions, hicpp-special-member-functions)
+class CommandLine
+{ // NOLINT(cppcoreguidelines-special-member-functions, hicpp-special-member-functions)
public:
// prevent copy or assignment
- CommandLine(const CommandLine&) = delete;
+ CommandLine(const CommandLine &) = delete;
- CommandLine& operator=(const CommandLine&) = delete;
+ CommandLine &operator=(const CommandLine &) = delete;
/**
* @brief singleton method
*/
- static CommandLine* getParser();
+ static CommandLine *getParser();
/**
* @brief parse command line option
* @param argc - number of command line arguments
* @param argv - command line arguments
- * @param check_nonoptional - if true then check that all non optional declared options are presented
+ * @param check_nonoptional - if true then check that all non optional declared options are
+ * presented
*/
- void parseCommandLine(int argc, const char** argv, bool check_nonoptional = true);
+ void parseCommandLine(int argc, const char **argv, bool check_nonoptional = true);
/**
* @brief register option for parser
* @param opt - option
*/
- void registerOption(IOption* opt);
+ void registerOption(IOption *opt);
private:
/**
* @param msg - additional user message
* @param exit_code - the program is terminated with this code
*/
- [[noreturn]] void usage(const std::string& msg = "", int exit_code = EXIT_FAILURE);
+ [[noreturn]] void usage(const std::string &msg = "", int exit_code = EXIT_FAILURE);
/**
* @brief check that all non optional registered options are passed from command line
* @param cmd_args - arguments from command line
*/
- void checkRegisteredOptions(const std::set<std::string>& cmd_args);
+ void checkRegisteredOptions(const std::set<std::string> &cmd_args);
/**
* @brief call verification function, if present, for option
* @param cmd_args - arguments from command line
*/
- void checkOptions(const std::set<std::string>& cmd_args);
+ void checkOptions(const std::set<std::string> &cmd_args);
/**
* @brief find option with `optname` and set `pos` to option value
* @return pointer to option
* @throw BadOption throw exception if option not found
*/
- IOption* findOption(const char* optname);
+ IOption *findOption(const char *optname);
/**
* @brief figure out option value
* @return position in argv where option value begins or empty string if option doesn't have value
* @throw BadOption throw exception if value for option is incorrect
*/
- const char* findOptionValue(const IOption* opt, const char** argv, int cur_argv);
+ const char *findOptionValue(const IOption *opt, const char **argv, int cur_argv);
/**
* @brief figure out value for option with multiple values
* @param opt_name - option name which taken from command line
* @param argv - array of command line arguments
* @param val_argv - position in argv for current option value
- * @return position in argv where option value begins or nullptr if option doesn't have value anymore
+ * @return position in argv where option value begins or nullptr if option doesn't have value
+ * anymore
* @throw BadOption throw exception if value for option is incorrect
*/
- const char* findValueForMultOption(const IOption* opt,
- const std::string& opt_name,
- const char** argv, int cur_argv);
+ const char *findValueForMultOption(const IOption *opt, const std::string &opt_name,
+ const char **argv, int cur_argv);
// allow object constructor only for methods
CommandLine() = default;
// data
- std::map<std::string, IOption*> _options_name; // map of name -> option
- std::vector<IOption*> _options; // options
- std::map<IOption::Group, std::vector<IOption*>> _grouped_options; // map of groups: group -> vector of options
+ std::map<std::string, IOption *> _options_name; // map of name -> option
+ std::vector<IOption *> _options; // options
+ std::map<IOption::Group, std::vector<IOption *>>
+ _grouped_options; // map of groups: group -> vector of options
std::string _prog_name; // name of program
- int _args_num = 0; // number of command line arguments
+ int _args_num = 0; // number of command line arguments
};
// the following functions are helpers for users that declare new options
* @param names - name of option, if option has several names then
* `names` must be represented by a string separated by a comma
*/
-std::vector<std::string> optname(const char* names);
+std::vector<std::string> optname(const char *names);
/** @brief convert option overview for Option constructor */
-inline std::string overview(const char* descr) {
+inline std::string overview(const char *descr)
+{
std::string overview(descr);
assert(!overview.empty());
* @param vals - valid values of option, if option has several that values then
* `vals` must be represented by a string separated by a comma
*/
-std::vector<std::string> optvalues(const char* vals);
+std::vector<std::string> optvalues(const char *vals);
/**
* @brief separators that separate option name and its value
* @param seps - chars of separators separated by a comma
*/
-std::vector<char> separators(const char* seps);
+std::vector<char> separators(const char *seps);
/**
* @param is_shown - if set to false, then option won't be shown in help message
inline bool showopt(bool is_shown) { return is_shown; }
// end of helper functions
-
//
// Implementation of template functions
//
-template <typename T>
-bool OptionType<T, false>::convToBool(const std::string& val) {
- if (val.empty() || val == "TRUE" ||
- val == "True" || val == "true" || val == "1") {
+template <typename T> bool OptionType<T, false>::convToBool(const std::string &val)
+{
+ if (val.empty() || val == "TRUE" || val == "True" || val == "true" || val == "1")
+ {
return true;
}
- if (val == "FALSE" || val == "False" || val == "false" || val == "0") {
+ if (val == "FALSE" || val == "False" || val == "false" || val == "0")
+ {
return false;
}
} // convToBool
-template <typename T>
-char OptionType<T, false>::convToChar(const std::string& val) {
- if (val.length() == 1) {
+template <typename T> char OptionType<T, false>::convToChar(const std::string &val)
+{
+ if (val.length() == 1)
+ {
return val[0];
-
- } else {
+ }
+ else
+ {
throw BadOption("", val);
}
template <typename T>
template <typename Tnum>
-Tnum OptionType<T, false>::convToNum(const std::string& val) {
+Tnum OptionType<T, false>::convToNum(const std::string &val)
+{
Tnum num_val;
assert((std::is_same<Tnum, uint64_t>::value || std::is_same<Tnum, int64_t>::value));
assert((std::numeric_limits<T>::max() < std::numeric_limits<Tnum>::max()));
assert(std::numeric_limits<T>::min() >= std::numeric_limits<Tnum>::min());
- try {
+ try
+ {
num_val = std::is_same<Tnum, uint64_t>::value ? stoull(val) : stoll(val);
-
- } catch (...) {
+ }
+ catch (...)
+ {
throw BadOption("", val);
}
- if (num_val > std::numeric_limits<T>::max() ||
- num_val < std::numeric_limits<T>::min()) {
+ if (num_val > std::numeric_limits<T>::max() || num_val < std::numeric_limits<T>::min())
+ {
throw BadOption("", val);
}
} // convToNum
-
template <typename T>
-Option<T>::Option(const std::vector<std::string>& optnames,
- const std::string& descr,
- const T& default_val,
- bool is_optional,
- const std::vector<std::string>& vals,
- option_checker_t checker,
- const std::vector<char>& seps,
- bool enabled,
- IOption::Group group) {
+Option<T>::Option(const std::vector<std::string> &optnames, const std::string &descr,
+ const T &default_val, bool is_optional, const std::vector<std::string> &vals,
+ option_checker_t checker, const std::vector<char> &seps, bool enabled,
+ IOption::Group group)
+{
// save all names
- for (const auto& n : optnames) {
+ for (const auto &n : optnames)
+ {
_names.push_back(n);
assert(n[0] == '-' && "option name must start with `-`");
#ifndef NDEBUG
// check that separators are valid symbols
- for (const auto& s : _seps) {
+ for (const auto &s : _seps)
+ {
assert((s == '=' || s == ':') && "invalid option separators");
}
#endif // NDEBUG
_group = group;
- _can_have_several_vals = std::is_same<T, std::vector<std::string>>::value
- || std::is_same<T, std::vector<int>>::value;
+ _can_have_several_vals =
+ std::is_same<T, std::vector<std::string>>::value || std::is_same<T, std::vector<int>>::value;
assert(!(_can_have_several_vals && !_seps.empty()) &&
"option with several values can't have separators");
} // Option
-
//
// prototypes of option checker functions
//
-void checkInFile(const Option<std::string>& in_file);
+void checkInFile(const Option<std::string> &in_file);
-void checkOutFile(const Option<std::string>& out_file);
+void checkOutFile(const Option<std::string> &out_file);
-void checkInDir(const Option<std::string>& dir);
+void checkInDir(const Option<std::string> &dir);
-void checkOutDir(const Option<std::string>& dir);
+void checkOutDir(const Option<std::string> &dir);
} // namespace cli
} // namespace nnc
-#endif //NNCC_COMMANDLINE_H
+#endif // NNCC_COMMANDLINE_H
PassManager::PassManager() = default;
-PassManager::~PassManager() {
- for (auto& pass : _passes)
+PassManager::~PassManager()
+{
+ for (auto &pass : _passes)
pass->cleanup();
}
-void PassManager::registerPass(std::unique_ptr<Pass> pass) {
+void PassManager::registerPass(std::unique_ptr<Pass> pass)
+{
_passes.push_back(std::move(pass));
} // registerPass
#include <sys/types.h>
#include <unistd.h>
-namespace nnc {
+namespace nnc
+{
using namespace std;
-PassData AclCppCodeGenerator::run(PassData data) {
- mir::Graph* g = data;
+PassData AclCppCodeGenerator::run(PassData data)
+{
+ mir::Graph *g = data;
assert(g);
// Create a directory for generated artifact files.
- int res = mkdir(cli::artifactDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); // NOLINT(hicpp-signed-bitwise)
+ int res = mkdir(cli::artifactDir.c_str(),
+ S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); // NOLINT(hicpp-signed-bitwise)
if (res != 0 && errno != EEXIST)
throw AclCppException("Failed to create output directory");
#include <algorithm>
-namespace nnc {
+namespace nnc
+{
using namespace std;
using namespace mir;
-AclCppOpGenerator::AclCppOpGenerator(const string& name, ostream& par_out)
- : _parOut(par_out), _module(name), _constrBlock(nullptr), _infBlock(nullptr),
- _clScheduler(AF::id("arm_compute::CLScheduler")) {}
+AclCppOpGenerator::AclCppOpGenerator(const string &name, ostream &par_out)
+ : _parOut(par_out), _module(name), _constrBlock(nullptr), _infBlock(nullptr),
+ _clScheduler(AF::id("arm_compute::CLScheduler"))
+{
+}
-const ArtifactModule& AclCppOpGenerator::generate(mir::Graph* g) {
+const ArtifactModule &AclCppOpGenerator::generate(mir::Graph *g)
+{
// Including headers.
_module.addHeaderSysInclude("fstream");
_module.addHeaderInclude("arm_compute/core/Types.h");
_parIn = _parInVar->use();
string par_file_name = cli::artifactName + ".par";
_constrBlock->call("open", {AF::lit("\"" + par_file_name + "\""),
- AF::lit("std::ios_base::in | std::ios_base::binary")}, _parIn);
+ AF::lit("std::ios_base::in | std::ios_base::binary")},
+ _parIn);
auto file_fail = _constrBlock->ifCond(AF::call("fail", {}, _parIn));
auto file_fail_block = file_fail->getBlock();
- file_fail_block->addStatement(AF::lit("throw std::string(\"Failed to open file: " +
- par_file_name + " for reading\")"));
+ file_fail_block->addStatement(
+ AF::lit("throw std::string(\"Failed to open file: " + par_file_name + " for reading\")"));
// Traverse the computational graph.
g->accept(this);
return _module;
}
-void AclCppOpGenerator::visit(ops::ConcatOp& op) {
- const auto& ir_inputs = op.getInputs();
- const auto* ir_output = op.getOutput(0);
+void AclCppOpGenerator::visit(ops::ConcatOp &op)
+{
+ const auto &ir_inputs = op.getInputs();
+ const auto *ir_output = op.getOutput(0);
- static const char* axis_names[] = {"arm_compute::DataLayoutDimension::BATCHES",
- "arm_compute::DataLayoutDimension::CHANNEL",
- "arm_compute::DataLayoutDimension::HEIGHT",
- "arm_compute::DataLayoutDimension::WIDTH"};
+ static const char *axis_names[] = {
+ "arm_compute::DataLayoutDimension::BATCHES", "arm_compute::DataLayoutDimension::CHANNEL",
+ "arm_compute::DataLayoutDimension::HEIGHT", "arm_compute::DataLayoutDimension::WIDTH"};
int axis = op.getAxis();
assert(axis >= 0 && axis < static_cast<int>(sizeof(axis_names) / sizeof(axis_names[0])) &&
"axis outside this range is not supported in ACL");
- const char* axis_name = axis_names[axis];
+ const char *axis_name = axis_names[axis];
auto out = genTensor(ir_output);
auto prefix = out->name() + "_concatenate_layer";
auto inputs_var = _constrBlock->var("std::vector<arm_compute::ICLTensor*>", prefix + "_inputs");
auto inputs = inputs_var->use();
- for (const auto& ir_input : ir_inputs)
+ for (const auto &ir_input : ir_inputs)
_constrBlock->call("push_back", {AF::ref(AF::id(tensorName(ir_input.getProducer())))}, inputs);
auto layer = genLayer("arm_compute::CLConcatenateLayer", prefix,
genLayerExecution(layer);
}
-void AclCppOpGenerator::visit(ops::Conv2DOp& op) {
+void AclCppOpGenerator::visit(ops::Conv2DOp &op)
+{
genConvolution(op, "arm_compute::CLConvolutionLayer", "_convolution_layer");
}
-void AclCppOpGenerator::visit(ops::DepthwiseConv2DOp& op) {
+void AclCppOpGenerator::visit(ops::DepthwiseConv2DOp &op)
+{
genConvolution(op, "arm_compute::CLDepthwiseConvolutionLayer", "_depthwise_convolution_layer");
}
-void AclCppOpGenerator::visit(ops::SoftmaxOp& op) {
+void AclCppOpGenerator::visit(ops::SoftmaxOp &op)
+{
assert(op.getNumInputs() == 1);
- const auto* ir_input = op.getInput(0)->getProducer();
- const auto* ir_output = op.getOutput(0);
+ const auto *ir_input = op.getInput(0)->getProducer();
+ const auto *ir_output = op.getOutput(0);
auto in = AF::id(tensorName(ir_input));
assert(axis == rank - 1);
int nof_long_axes = 0;
- for (int i = 0; i < rank; ++i) {
+ for (int i = 0; i < rank; ++i)
+ {
if (ir_output->getShape().dim(i) > 1)
++nof_long_axes;
}
shared_ptr<ArtifactId> output = genTensor(ir_output);
auto layer_name_prefix = output->name();
- if (axis == 0) {
+ if (axis == 0)
+ {
// Simple version: do not need pre and post reshapes.
// Apply the softmax operation.
auto sm = genLayer("arm_compute::CLSoftmaxLayer", layer_name_prefix + "_softmax_layer",
{AF::ref(in), AF::ref(output)});
addToPersistentTensors(output);
genLayerExecution(sm);
- } else {
+ }
+ else
+ {
// TODO refactor this code, it works only with 1 batch
// Need to reshape before the Softmax application and after it.
- // Then we need two tensors for intermediate results. This is because we do a couple of auxiliary
+ // Then we need two tensors for intermediate results. This is because we do a couple of
+ // auxiliary
// reshapes: one to transform the input tensor to a unidimensional tensor and the second to
// transorm the result of the softmax operation back to the original form.
Shape sm_shape(ir_output->getShape());
// Do the input permutation.
auto transp1 = genLayer("arm_compute::CLReshapeLayer", layer_name_prefix + "_transp_layer1",
- {AF::ref(in), AF::ref(tmp)});
+ {AF::ref(in), AF::ref(tmp)});
addToPersistentTensors(tmp);
genLayerExecution(transp1);
// Reshape the output to the original form.
auto transp2 = genLayer("arm_compute::CLReshapeLayer", layer_name_prefix + "_transp_layer2",
- {AF::ref(tmp2), AF::ref(output)});
+ {AF::ref(tmp2), AF::ref(output)});
addToPersistentTensors(output);
genLayerExecution(transp2);
}
}
template <typename Op>
-shared_ptr<ArtifactVariable>
-AclCppOpGenerator::genPadStrideInfo(const Op& op, const string& prefix, ArtifactBlock* block) {
+shared_ptr<ArtifactVariable> AclCppOpGenerator::genPadStrideInfo(const Op &op, const string &prefix,
+ ArtifactBlock *block)
+{
using AF = ArtifactFactory;
- const Shape& strides = transposeShape<1, 0>(op.getStrides());
+ const Shape &strides = transposeShape<1, 0>(op.getStrides());
assert(strides.rank() == 2);
- auto& padding_before = op.getPaddingBefore();
- auto& padding_after = op.getPaddingAfter();
+ auto &padding_before = op.getPaddingBefore();
+ auto &padding_after = op.getPaddingAfter();
string type_name = "arm_compute::PadStrideInfo";
string var_name = prefix + "_pad_stride_info";
- list<std::shared_ptr<ArtifactExpr>> var_init_params =
- {AF::lit(to_string(op.getStrides().dim(1))),
- AF::lit(to_string(op.getStrides().dim(0))),
- AF::lit(to_string(padding_before.at(1))),
- AF::lit(to_string(padding_after.at(1))),
- AF::lit(to_string(padding_before.at(0))),
- AF::lit(to_string(padding_after.at(0))),
- AF::lit("arm_compute::DimensionRoundingType::FLOOR")};
+ list<std::shared_ptr<ArtifactExpr>> var_init_params = {
+ AF::lit(to_string(op.getStrides().dim(1))),
+ AF::lit(to_string(op.getStrides().dim(0))),
+ AF::lit(to_string(padding_before.at(1))),
+ AF::lit(to_string(padding_after.at(1))),
+ AF::lit(to_string(padding_before.at(0))),
+ AF::lit(to_string(padding_after.at(0))),
+ AF::lit("arm_compute::DimensionRoundingType::FLOOR")};
auto pad_stride_info_var = block->var(type_name, var_name, {}, var_init_params);
return pad_stride_info_var;
}
-shared_ptr<ArtifactId>
-AclCppOpGenerator::genTransposeMIRtoACL(const string& name,
- const Shape& input_shape,
- const shared_ptr<ArtifactId>& input) {
+shared_ptr<ArtifactId> AclCppOpGenerator::genTransposeMIRtoACL(const string &name,
+ const Shape &input_shape,
+ const shared_ptr<ArtifactId> &input)
+{
Shape transposed_shape = transposeShape<0, 3, 1, 2>(input_shape);
shared_ptr<ArtifactId> transposed_id = genTensor(name, transposed_shape, false);
const bool allocate_at_inference = true;
return transposed_id;
}
-shared_ptr<ArtifactId>
-AclCppOpGenerator::genTransposeACLtoMIR(const string& name,
- const Shape& input_shape,
- const shared_ptr<ArtifactId>& input) {
+shared_ptr<ArtifactId> AclCppOpGenerator::genTransposeACLtoMIR(const string &name,
+ const Shape &input_shape,
+ const shared_ptr<ArtifactId> &input)
+{
Shape transposed_shape = transposeShape<0, 2, 3, 1>(input_shape);
shared_ptr<ArtifactId> transposed_id = genTensor(name, transposed_shape, false);
const bool allocate_at_inference = false;
return transposed_id;
}
-void AclCppOpGenerator::visit(ops::PoolOp& op) {
+void AclCppOpGenerator::visit(ops::PoolOp &op)
+{
assert(op.getNumInputs() == 1);
- const auto* ir_input = op.getInput(0)->getProducer();
- const auto* ir_output = op.getOutput(0);
+ const auto *ir_input = op.getInput(0)->getProducer();
+ const auto *ir_output = op.getOutput(0);
- const char* pooling_type = nullptr;
+ const char *pooling_type = nullptr;
- switch (op.getPoolingType()) {
+ switch (op.getPoolingType())
+ {
case ops::PoolOp::PoolingType::MAX:
pooling_type = "arm_compute::PoolingType::MAX";
break;
const string layer_name = output_tensor_name + "_pooling_layer";
- shared_ptr<ArtifactVariable> pad_stride_info_var =
- genPadStrideInfo(op, layer_name, _constrBlock);
+ shared_ptr<ArtifactVariable> pad_stride_info_var = genPadStrideInfo(op, layer_name, _constrBlock);
shared_ptr<ArtifactId> pad_stride_info = pad_stride_info_var->use();
shared_ptr<ArtifactVariable> kernel_window_var =
_constrBlock->var("arm_compute::Size2D", layer_name + "_kernel_window", {},
{AF::lit(to_string(op.getWindowShape().dim(1))),
- AF::lit(to_string(op.getWindowShape().dim(0)))});
+ AF::lit(to_string(op.getWindowShape().dim(0)))});
shared_ptr<ArtifactId> kernel_window = kernel_window_var->use();
// Create pooling info: pooling type, kernel info, strides, etc
shared_ptr<ArtifactVariable> pooling_info_var = _constrBlock->var(
- "arm_compute::PoolingLayerInfo", layer_name + "_pooling_info", {},
- {AF::lit(pooling_type), kernel_window, pad_stride_info,
- AF::lit(op.getBorderType() == ops::PoolOp::BorderType::EMPTY ? "true" : "false")});
+ "arm_compute::PoolingLayerInfo", layer_name + "_pooling_info", {},
+ {AF::lit(pooling_type), kernel_window, pad_stride_info,
+ AF::lit(op.getBorderType() == ops::PoolOp::BorderType::EMPTY ? "true" : "false")});
shared_ptr<ArtifactId> pooling_info = pooling_info_var->use();
// Generate auxiliary tensor to hold transposed output of pool in NCHW format
genTensor(layer_name + "_out_transpose", transposed_output_shape);
// Actual layer creation
- shared_ptr<ArtifactId> layer = genLayer("arm_compute::CLPoolingLayer", layer_name,
- {AF::ref(transposed_input), AF::ref(transposed_output), pooling_info});
+ shared_ptr<ArtifactId> layer =
+ genLayer("arm_compute::CLPoolingLayer", layer_name,
+ {AF::ref(transposed_input), AF::ref(transposed_output), pooling_info});
genTensorAllocation(_infBlock, transposed_output);
genLayerExecution(layer);
genTensorDeallocation(_infBlock, transposed_output);
}
-void AclCppOpGenerator::visit(ops::FullyConnectedOp& op) {
+void AclCppOpGenerator::visit(ops::FullyConnectedOp &op)
+{
assert(op.getNumInputs() == 2);
- const auto* ir_input = op.getInput(0)->getProducer();
- const auto* ir_weights = op.getInput(1)->getProducer();
- const auto* ir_output = op.getOutput(0);
+ const auto *ir_input = op.getInput(0)->getProducer();
+ const auto *ir_weights = op.getInput(1)->getProducer();
+ const auto *ir_output = op.getOutput(0);
- auto ir_weights_op = dynamic_cast<const mir::ops::ConstantOp*>(ir_weights->getNode());
+ auto ir_weights_op = dynamic_cast<const mir::ops::ConstantOp *>(ir_weights->getNode());
if (ir_weights_op == nullptr)
throw AclCppException("Unsupported operation type");
const TensorVariant ir_weights_tensor = transposeTensor<1, 0>(ir_weights_op->getValue());
- const Shape& ir_weights_shape = ir_weights_tensor.getShape();
+ const Shape &ir_weights_shape = ir_weights_tensor.getShape();
// Get the input node tensor id in the DOM.
auto in = AF::id(tensorName(ir_input));
genLayerExecution(layer);
}
-void AclCppOpGenerator::visit(ops::GemmOp& /*op*/) {
+void AclCppOpGenerator::visit(ops::GemmOp & /*op*/)
+{
throw AclCppException("Unimplemented operation: GemmOp");
}
-void AclCppOpGenerator::visit(ops::CappedReluOp& op) {
+void AclCppOpGenerator::visit(ops::CappedReluOp &op)
+{
genActivation(op, "LU_BOUNDED_RELU", op.getCap());
}
-void AclCppOpGenerator::visit(ops::InputOp& op) {
+void AclCppOpGenerator::visit(ops::InputOp &op)
+{
shared_ptr<ArtifactId> tensor;
tensor = genTensor(op.getOutput(0));
addToPersistentTensors(tensor);
}
// FIXME: temporary solution
-static bool shouldSerializeConstant(const ops::ConstantOp& op) {
- // Operations from 'self_serializing_ops_to_inputs' serializing tensors with appropriate index themselves,
+static bool shouldSerializeConstant(const ops::ConstantOp &op)
+{
+ // Operations from 'self_serializing_ops_to_inputs' serializing tensors with appropriate index
+ // themselves,
// so we don't serialize them here, also we don't serialize tensors from dangling ConstantOp
static std::map<Operation::Type, std::size_t> self_serializing_ops_to_inputs{
- {Operation::Type::conv2D, 1},
- {Operation::Type::fullyConnected, 1}};
+ {Operation::Type::conv2D, 1}, {Operation::Type::fullyConnected, 1}};
- for (const auto* consumer : op.getOutput(0)->getConsumers()) {
- auto self_serializing_op_it = self_serializing_ops_to_inputs.find(consumer->getNode()->getType());
+ for (const auto *consumer : op.getOutput(0)->getConsumers())
+ {
+ auto self_serializing_op_it =
+ self_serializing_ops_to_inputs.find(consumer->getNode()->getType());
// Serialize if next_node type not from 'self_serializing_ops_to_inputs'
if (self_serializing_op_it == self_serializing_ops_to_inputs.end())
return true;
return false;
}
-void AclCppOpGenerator::visit(ops::ConstantOp& op) {
- if (shouldSerializeConstant(op)) {
+void AclCppOpGenerator::visit(ops::ConstantOp &op)
+{
+ if (shouldSerializeConstant(op))
+ {
TensorVariant data = op.getValue();
shared_ptr<ArtifactId> out = genTensor(op.getOutput(0));
addToPersistentTensors(out);
}
}
-void AclCppOpGenerator::visit(ops::ReluOp& op) {
- genActivation(op, "RELU");
-}
+void AclCppOpGenerator::visit(ops::ReluOp &op) { genActivation(op, "RELU"); }
-void AclCppOpGenerator::visit(ops::ReshapeOp& op) {
+void AclCppOpGenerator::visit(ops::ReshapeOp &op)
+{
assert(op.getNumInputs() == 1);
- const auto* ir_input = op.getInput(0)->getProducer();
- const auto* ir_output = op.getOutput(0);
+ const auto *ir_input = op.getInput(0)->getProducer();
+ const auto *ir_output = op.getOutput(0);
// Get the id of the input tensor in the generated artifact.
auto in = AF::id(tensorName(ir_input));
// Create the output tensor in the DOM and return its id.
- const Shape& out_shape = ir_output->getShape();
+ const Shape &out_shape = ir_output->getShape();
// This check confirms that we can "safely" reshape data
// The only safe configuration of output shape is (1...1, N, 1 ... 1)
bool found_non_one = false;
- for (int32_t i = 0; i < out_shape.rank(); ++i) {
- if (out_shape.dim(i) != 1) {
+ for (int32_t i = 0; i < out_shape.rank(); ++i)
+ {
+ if (out_shape.dim(i) != 1)
+ {
if (found_non_one)
throw AclCppException("Unsupported result of reshape");
found_non_one = true;
genLayerExecution(layer);
}
-void AclCppOpGenerator::visit(mir::ops::SliceOp& /*op*/) {
+void AclCppOpGenerator::visit(mir::ops::SliceOp & /*op*/)
+{
throw AclCppException("Unimplemented operation: SliceOp");
}
-void AclCppOpGenerator::visit(ops::BatchNormOp& /*op*/) {
+void AclCppOpGenerator::visit(ops::BatchNormOp & /*op*/)
+{
// Not supported in our framework, but present in ACL API.
throw AclCppException("Not supported in inference yet.");
}
-void AclCppOpGenerator::visit(ops::DropoutOp& op) {
+void AclCppOpGenerator::visit(ops::DropoutOp &op)
+{
assert(op.getNumInputs() == 1);
- const auto* ir_input = op.getInput(0)->getProducer();
- const auto* ir_output = op.getOutput(0);
+ const auto *ir_input = op.getInput(0)->getProducer();
+ const auto *ir_output = op.getOutput(0);
// Just copy input tensor to the output one.
_constrBlock->var("arm_compute::CLTensor&", out->name(), {}, {in});
}
-void AclCppOpGenerator::visit(ops::TanhOp& op) {
- genActivation(op, "TANH");
-}
+void AclCppOpGenerator::visit(ops::TanhOp &op) { genActivation(op, "TANH"); }
-void AclCppOpGenerator::visit(ops::DeConv2DOp& op) {
+void AclCppOpGenerator::visit(ops::DeConv2DOp &op)
+{
genConvolution(op, "arm_compute::CLDeconvolutionLayer", "_deconvolution_layer");
}
-void AclCppOpGenerator::visit(ops::EluOp& /*op*/) {
+void AclCppOpGenerator::visit(ops::EluOp & /*op*/)
+{
throw AclCppException("EluOp not supported by the ACL library yet.");
}
-void AclCppOpGenerator::visit(ops::PadOp& op) {
+void AclCppOpGenerator::visit(ops::PadOp &op)
+{
assert(op.getNumInputs() == 1);
- const auto* ir_input = op.getInput(0)->getProducer();
- const auto* ir_output = op.getOutput(0);
+ const auto *ir_input = op.getInput(0)->getProducer();
+ const auto *ir_output = op.getOutput(0);
// Get the id of the input tensor.
auto input = AF::id(tensorName(ir_input));
auto prefix = out->name() + "_pad_layer";
auto pad_list_decl = _constrBlock->var("arm_compute::PaddingList", prefix + "_pads");
auto pad_list = pad_list_decl->use();
- for (int i = 0; i < op.getNumDim(); ++i) {
+ for (int i = 0; i < op.getNumDim(); ++i)
+ {
auto pad_var = _constrBlock->var("arm_compute::PaddingInfo", prefix + "_pad_" + to_string(i),
- {},
- {AF::lit(to_string(op.getPaddingForDim(i).first)),
- AF::lit(to_string(op.getPaddingForDim(i).second))});
+ {}, {AF::lit(to_string(op.getPaddingForDim(i).first)),
+ AF::lit(to_string(op.getPaddingForDim(i).second))});
auto pad = pad_var->use();
_constrBlock->call("push_back", {pad}, pad_list);
}
// Generate PadLayer
- auto layer = genLayer("arm_compute::CLPadLayer", prefix,
- {AF::ref(input), AF::ref(out), pad_list});
+ auto layer =
+ genLayer("arm_compute::CLPadLayer", prefix, {AF::ref(input), AF::ref(out), pad_list});
genLayerExecution(layer);
}
template <typename Op>
-void AclCppOpGenerator::genConvolution(Op& op, const string& acl_func_name, const string& suffix) {
- const auto* ir_input = op.getInput(0)->getProducer();
- const auto* ir_weights = op.getInput(1)->getProducer();
- const auto* ir_output = op.getOutput(0);
+void AclCppOpGenerator::genConvolution(Op &op, const string &acl_func_name, const string &suffix)
+{
+ const auto *ir_input = op.getInput(0)->getProducer();
+ const auto *ir_weights = op.getInput(1)->getProducer();
+ const auto *ir_output = op.getOutput(0);
- auto ir_weights_op = dynamic_cast<const ops::ConstantOp*>(ir_weights->getNode());
+ auto ir_weights_op = dynamic_cast<const ops::ConstantOp *>(ir_weights->getNode());
if (ir_weights_op == nullptr)
throw AclCppException("Unsupported operation type");
auto ir_weights_tensor = ir_weights_op->getValue();
- if (op.getType() == Operation::Type::conv2D) {
+ if (op.getType() == Operation::Type::conv2D)
+ {
// [Co, Hk, Wk, Ci] -> [Co, Ci, Hk, Wk].
ir_weights_tensor = transposeTensor<0, 3, 1, 2>(ir_weights_tensor);
- } else {
+ }
+ else
+ {
ir_weights_tensor = transposeTensor<3, 2, 0, 1>(ir_weights_tensor);
}
- const Shape& ir_weights_shape = ir_weights_tensor.getShape();
+ const Shape &ir_weights_shape = ir_weights_tensor.getShape();
// get output tensor name that is used as base for other names
const string output_tensor_name = tensorName(ir_output);
// The parameter for the conv_layer.config(&in, &weights, nullptr, &out, pad_stride_info)
// function call.
- list<shared_ptr<ArtifactExpr>> config_params{AF::ref(transposed_input),
- AF::ref(weights), AF::lit("nullptr"),
- AF::ref(transposed_output), pad_stride_info};
+ list<shared_ptr<ArtifactExpr>> config_params{AF::ref(transposed_input), AF::ref(weights),
+ AF::lit("nullptr"), AF::ref(transposed_output),
+ pad_stride_info};
// Add to additional parameters for deconvolution.
- if (op.getType() == Operation::Type::deConv2D) {
+ if (op.getType() == Operation::Type::deConv2D)
+ {
config_params.push_back(AF::lit("0"));
config_params.push_back(AF::lit("0"));
}
genTensorDeallocation(_infBlock, transposed_output);
}
-void AclCppOpGenerator::genActivation(const Operation& op, const std::string& activation_name,
- float a, float b) {
+void AclCppOpGenerator::genActivation(const Operation &op, const std::string &activation_name,
+ float a, float b)
+{
assert(op.getNumInputs() == 1);
- const auto* ir_input = op.getInput(0)->getProducer();
- const auto* ir_output = op.getOutput(0);
+ const auto *ir_input = op.getInput(0)->getProducer();
+ const auto *ir_output = op.getOutput(0);
// Get the id of the input tensor.
auto in = AF::id(tensorName(ir_input));
// constructor. This instance profide information about the concrete activation function,
// like: ReLU, Tanh etc and two optional parameter (alpha and betha) needed by some activations.
auto activation_info_var = _constrBlock->var(
- "arm_compute::ActivationLayerInfo", prefix + "_activation_info", {},
- {AF::lit("arm_compute::ActivationLayerInfo::ActivationFunction::" + activation_name),
- AF::lit(to_string(a)), AF::lit(to_string(b))});
+ "arm_compute::ActivationLayerInfo", prefix + "_activation_info", {},
+ {AF::lit("arm_compute::ActivationLayerInfo::ActivationFunction::" + activation_name),
+ AF::lit(to_string(a)), AF::lit(to_string(b))});
auto activation_info = activation_info_var->use();
// Create an instance of the CLActivationLayer class as a member of the artifact class.
genLayerExecution(layer);
}
-shared_ptr<ArtifactId> AclCppOpGenerator::genAddition(const string& prefix, size_t index,
- const Shape& ir_shape,
- const std::shared_ptr<ArtifactId>& in1,
- const std::shared_ptr<ArtifactId>& in2,
- std::shared_ptr<ArtifactId> out) {
+shared_ptr<ArtifactId> AclCppOpGenerator::genAddition(const string &prefix, size_t index,
+ const Shape &ir_shape,
+ const std::shared_ptr<ArtifactId> &in1,
+ const std::shared_ptr<ArtifactId> &in2,
+ std::shared_ptr<ArtifactId> out)
+{
string operation_name = prefix + "_" + to_string(index);
// Create the output tensor in the DOM or reuse the out, if it is not nullptr - that is for the
// last element in the handled sequence.
return out;
}
-shared_ptr<ArtifactId> AclCppOpGenerator::genMultiplication(const string& prefix, size_t index,
- const Shape& ir_shape,
- const shared_ptr<ArtifactId>& in1,
- const shared_ptr<ArtifactId>& in2,
- shared_ptr<ArtifactId> out) {
+shared_ptr<ArtifactId> AclCppOpGenerator::genMultiplication(const string &prefix, size_t index,
+ const Shape &ir_shape,
+ const shared_ptr<ArtifactId> &in1,
+ const shared_ptr<ArtifactId> &in2,
+ shared_ptr<ArtifactId> out)
+{
string operation_name = prefix + "_" + to_string(index);
// Create the output tensor in the DOM or reuse the out, if it is not nullptr - that is for the
// Create an instance of the CLArithmeticDivision class as a member of the artifact class.
auto arithmetic_div_layer_var1 = _artifactClass->var(false, "arm_compute::CLArithmeticDivision",
- operation_name + "_arithmetic_div_layer_1");
+ operation_name + "_arithmetic_div_layer_1");
auto arithmetic_div_layer1 = arithmetic_div_layer_var1->use();
// Generate the call: arithmetic_div_layer1.configure(&unit, &in2, &tmp);
return out;
}
-string AclCppOpGenerator::tensorName(const Operation::Output* ir_tensor) const {
+string AclCppOpGenerator::tensorName(const Operation::Output *ir_tensor) const
+{
string tensor_name;
// TODO Use the tensor name instead of the operation name.
- const auto& op_name = ir_tensor->getNode()->getName();
+ const auto &op_name = ir_tensor->getNode()->getName();
- if (!op_name.empty()) {
+ if (!op_name.empty())
+ {
tensor_name = "_" + op_name;
- replace_if(tensor_name.begin(),
- tensor_name.end(),
- [](char c) { return std::isalnum(c) == 0; }, '_');
- } else {
+ replace_if(tensor_name.begin(), tensor_name.end(), [](char c) { return std::isalnum(c) == 0; },
+ '_');
+ }
+ else
+ {
tensor_name = "tensor_" + to_string(ir_tensor->getNode()->getId());
}
template <typename T>
std::shared_ptr<ArtifactId>
-AclCppOpGenerator::genVectorInitializedVar(ArtifactBlock* block, const string& type,
- const string& name, const vector <T>& init) {
+AclCppOpGenerator::genVectorInitializedVar(ArtifactBlock *block, const string &type,
+ const string &name, const vector<T> &init)
+{
list<shared_ptr<ArtifactExpr>> dims;
- for (const auto& v : init)
+ for (const auto &v : init)
dims.push_back(AF::lit(to_string(v)));
auto shape_var = block->var(type, name, {}, dims);
return shape_id;
}
-shared_ptr<ArtifactId> AclCppOpGenerator::genTensor(const string& name,
- const Shape& ir_shape,
- bool gen_accessor) {
+shared_ptr<ArtifactId> AclCppOpGenerator::genTensor(const string &name, const Shape &ir_shape,
+ bool gen_accessor)
+{
auto id = AF::id(name);
- if (_tensorNames.insert(name).second) {
+ if (_tensorNames.insert(name).second)
+ {
_artifactClass->var(false, "arm_compute::CLTensor", name);
vector<int32_t> shape_vectorized;
for (int i = 0; i < ir_shape.rank(); ++i)
shape_vectorized.push_back(ir_shape.dim(-i - 1));
- const char* type_name = "arm_compute::TensorShape";
+ const char *type_name = "arm_compute::TensorShape";
shared_ptr<ArtifactId> shape =
genVectorInitializedVar(_constrBlock, type_name, name + "_shape", shape_vectorized);
_constrBlock->call("initializeTensor", {id, shape});
- if (gen_accessor) {
+ if (gen_accessor)
+ {
auto f = _artifactClass->func(true, "arm_compute::CLTensor&", "get" + name);
auto b = f->getBlock();
b->ret(id);
return id;
}
-shared_ptr<ArtifactId> AclCppOpGenerator::genTensor(const Operation::Output* ir_tensor) {
+shared_ptr<ArtifactId> AclCppOpGenerator::genTensor(const Operation::Output *ir_tensor)
+{
return genTensor(tensorName(ir_tensor), ir_tensor->getShape(),
!ir_tensor->getNode()->getName().empty());
}
-void AclCppOpGenerator::genNamed(Graph* graph) {
- const auto& inputs = graph->getInputs();
- if (inputs.size() == 1) {
- const auto* input_op = inputs[0];
+void AclCppOpGenerator::genNamed(Graph *graph)
+{
+ const auto &inputs = graph->getInputs();
+ if (inputs.size() == 1)
+ {
+ const auto *input_op = inputs[0];
auto f = _artifactClass->func(true, "arm_compute::CLTensor&", "getInput");
auto b = f->getBlock();
auto id = AF::id(tensorName(input_op->getOutput(0)));
b->ret(id);
}
- const auto& outputs = graph->getOutputs();
- if (outputs.size() == 1) {
- const auto* output_op = outputs[0];
+ const auto &outputs = graph->getOutputs();
+ if (outputs.size() == 1)
+ {
+ const auto *output_op = outputs[0];
auto f = _artifactClass->func(true, "arm_compute::CLTensor&", "getOutput");
auto b = f->getBlock();
auto id = AF::id(tensorName(output_op->getInput(0)->getProducer()));
}
}
-void AclCppOpGenerator::serializeTensor(const shared_ptr<ArtifactId>& tensor_id,
- const TensorVariant& ir_tensor) {
+void AclCppOpGenerator::serializeTensor(const shared_ptr<ArtifactId> &tensor_id,
+ const TensorVariant &ir_tensor)
+{
serializeIRTensor(ir_tensor);
_serializations.push_back(tensor_id);
}
-void AclCppOpGenerator::serializeIRTensor(const TensorVariant& tensor) {
- const Shape& shape = tensor.getShape();
+void AclCppOpGenerator::serializeIRTensor(const TensorVariant &tensor)
+{
+ const Shape &shape = tensor.getShape();
Index coords;
coords.resize(shape.rank());
Index dimensions;
dimensions.resize(shape.rank());
- for (int i = 0; i < shape.rank(); ++i) {
+ for (int i = 0; i < shape.rank(); ++i)
+ {
coords.at(i) = 0;
dimensions.at(i) = shape.dim(i);
}
_parOut.write(tensor.atOffset(0), data_size);
}
-void AclCppOpGenerator::genDeserializations() {
- for (auto& tensor : _serializations)
+void AclCppOpGenerator::genDeserializations()
+{
+ for (auto &tensor : _serializations)
_constrBlock->call("deserializeTensor", {_parIn, tensor});
}
-void AclCppOpGenerator::genFillings() {
+void AclCppOpGenerator::genFillings()
+{
for (auto f : _fillings)
_constrBlock->call("fillTensor", {f.first, AF::lit(f.second)});
}
-void AclCppOpGenerator::fillTensor(const shared_ptr<ArtifactId>& tensor_id, const string& val) {
+void AclCppOpGenerator::fillTensor(const shared_ptr<ArtifactId> &tensor_id, const string &val)
+{
_fillings.emplace_back(make_pair(tensor_id, val));
}
-void AclCppOpGenerator::visit(ops::SqueezeOp& /*op*/) {
+void AclCppOpGenerator::visit(ops::SqueezeOp & /*op*/)
+{
throw AclCppException("Unimplemented operation: Squeeze");
}
-void AclCppOpGenerator::visit(ops::SqrtOp& /*op*/) {
+void AclCppOpGenerator::visit(ops::SqrtOp & /*op*/)
+{
throw AclCppException("Unimplemented operation: Sqrt");
}
-void AclCppOpGenerator::addToPersistentTensors(const std::shared_ptr<ArtifactId>& tensor_id) {
+void AclCppOpGenerator::addToPersistentTensors(const std::shared_ptr<ArtifactId> &tensor_id)
+{
_persistent_tensors.push_back(tensor_id);
}
shared_ptr<ArtifactFunctionCall>
-AclCppOpGenerator::genTensorAllocation(ArtifactBlock* block,
- const shared_ptr<ArtifactId>& tensor) {
+AclCppOpGenerator::genTensorAllocation(ArtifactBlock *block, const shared_ptr<ArtifactId> &tensor)
+{
return block->call("allocate", {}, AF::call("allocator", {}, tensor), ArtifactCallType::ref);
}
shared_ptr<ArtifactFunctionCall>
-AclCppOpGenerator::genTensorDeallocation(ArtifactBlock* block,
- const shared_ptr<ArtifactId>& tensor) {
+AclCppOpGenerator::genTensorDeallocation(ArtifactBlock *block, const shared_ptr<ArtifactId> &tensor)
+{
return block->call("free", {}, AF::call("allocator", {}, tensor), ArtifactCallType::ref);
}
-void AclCppOpGenerator::genPersistentTensorAllocations() {
- for (auto& tensor : _persistent_tensors)
+void AclCppOpGenerator::genPersistentTensorAllocations()
+{
+ for (auto &tensor : _persistent_tensors)
genTensorAllocation(_constrBlock, tensor);
}
shared_ptr<ArtifactId>
-AclCppOpGenerator::genLayer(const string& layer_type, const string& layer_name,
- const list<shared_ptr<ArtifactExpr>>& config_params) {
+AclCppOpGenerator::genLayer(const string &layer_type, const string &layer_name,
+ const list<shared_ptr<ArtifactExpr>> &config_params)
+{
auto layer_var = _artifactClass->var(false, layer_type, layer_name);
auto layer = layer_var->use();
_constrBlock->call("configure", config_params, layer);
return layer;
}
-void AclCppOpGenerator::genLayerExecution(const shared_ptr<ArtifactId>& layer_id) {
+void AclCppOpGenerator::genLayerExecution(const shared_ptr<ArtifactId> &layer_id)
+{
_infBlock->call("run", {}, layer_id);
}
-void AclCppOpGenerator::visit(mir::ops::ResizeOp& /*op*/) {
+void AclCppOpGenerator::visit(mir::ops::ResizeOp & /*op*/)
+{
throw AclCppException("Unimplemented operation: Resize");
}
-void AclCppOpGenerator::visit(mir::ops::ReduceOp& /*op*/) {
+void AclCppOpGenerator::visit(mir::ops::ReduceOp & /*op*/)
+{
throw AclCppException("Unimplemented operation: ReduceOp");
}
-void AclCppOpGenerator::genTranspose(const std::shared_ptr<nnc::ArtifactId>& input,
- const std::shared_ptr<nnc::ArtifactId>& output,
- const std::vector<size_t>& mir_perm,
- bool allocate_at_inference) {
+void AclCppOpGenerator::genTranspose(const std::shared_ptr<nnc::ArtifactId> &input,
+ const std::shared_ptr<nnc::ArtifactId> &output,
+ const std::vector<size_t> &mir_perm,
+ bool allocate_at_inference)
+{
// acl 18.8 opencl implementation supports only 3 types of permutation:
// in mir (0, 3, 1, 2), in acl(axes are in reverse order) (1, 2, 0)
// in mir (2, 3, 1, 0), in acl (3, 2, 0, 1)
// so here we try to transform mir transpose into one acl supports
- const string& out_name = output->name();
+ const string &out_name = output->name();
vector<size_t> acl_perm;
if (mir_perm == vector<size_t>{0, 3, 1, 2})
throw AclCppException("Unsupported transpose sequence in operation " + out_name);
// Create operation parameter containing permutation vector
- shared_ptr<ArtifactId> perm_vector =
- genVectorInitializedVar(_constrBlock, "arm_compute::PermutationVector",
- out_name + "_perm_param", acl_perm);
+ shared_ptr<ArtifactId> perm_vector = genVectorInitializedVar(
+ _constrBlock, "arm_compute::PermutationVector", out_name + "_perm_param", acl_perm);
// Instantiate the CLPermute object.
string layer_name = out_name + "_transpose_layer";
genLayerExecution(layer);
}
-void AclCppOpGenerator::visit(mir::ops::TransposeOp& op) {
+void AclCppOpGenerator::visit(mir::ops::TransposeOp &op)
+{
assert(op.getNumInputs() == 1);
- const auto* ir_input = op.getInput(0)->getProducer();
- const auto* ir_output = op.getOutput(0);
+ const auto *ir_input = op.getInput(0)->getProducer();
+ const auto *ir_output = op.getOutput(0);
// Get the input node tensor id in the DOM.
shared_ptr<ArtifactId> input = AF::id(tensorName(ir_input));
- const vector<size_t>& mir_axis_order = op.getAxisOrder();
+ const vector<size_t> &mir_axis_order = op.getAxisOrder();
// Create the output tensor in the DOM.
if (ir_output->getShape().rank() != 4)
genTranspose(input, output, mir_axis_order, false);
}
-void AclCppOpGenerator::visit(mir::ops::GatherOp& /*op*/) {
+void AclCppOpGenerator::visit(mir::ops::GatherOp & /*op*/)
+{
throw AclCppException("Unimplemented operation: GatherOp");
}
-void AclCppOpGenerator::visit(ops::SigmoidOp& op) {
- genActivation(op, "LOGISTIC");
-}
+void AclCppOpGenerator::visit(ops::SigmoidOp &op) { genActivation(op, "LOGISTIC"); }
-void AclCppOpGenerator::visit(mir::ops::LeakyReluOp& op) {
+void AclCppOpGenerator::visit(mir::ops::LeakyReluOp &op)
+{
genActivation(op, "LEAKY_RELU", op.getAlpha());
}
-void AclCppOpGenerator::visit(mir::ops::OutputOp& /*op*/) {
+void AclCppOpGenerator::visit(mir::ops::OutputOp & /*op*/)
+{
// No-op.
}
#include <set>
-namespace nnc {
+namespace nnc
+{
/**
* @brief Implements the visitor for the model IR which generates the DOM description
* translated to C++ source/header files by the ACL soft backend code generators.
*/
-class AclCppOpGenerator : public mir::IVisitor {
+class AclCppOpGenerator : public mir::IVisitor
+{
public:
- AclCppOpGenerator(const std::string& name, std::ostream& par_out);
+ AclCppOpGenerator(const std::string &name, std::ostream &par_out);
/**
* @brief The main interface function to the class. Convers the model IR to the DOM.
* @param g - pointer the model IR graph.
* @return - reference to the top-level DOM entity.
*/
- const ArtifactModule& generate(mir::Graph* g);
+ const ArtifactModule &generate(mir::Graph *g);
/**
* @brief Implementations of the IVisitor visitors.
* @param op
*/
- void visit(mir::ops::AddOp& op) override;
- void visit(mir::ops::BatchNormOp& op) override;
- void visit(mir::ops::CappedReluOp& op) override;
- void visit(mir::ops::ConcatOp& op) override;
- void visit(mir::ops::ConstantOp& op) override;
- void visit(mir::ops::Conv2DOp& op) override;
- void visit(mir::ops::DeConv2DOp& op) override;
- void visit(mir::ops::DepthwiseConv2DOp& op) override;
- void visit(mir::ops::DivOp& op) override;
- void visit(mir::ops::DropoutOp& op) override;
- void visit(mir::ops::EluOp& op) override;
- void visit(mir::ops::FullyConnectedOp& op) override;
- void visit(mir::ops::GatherOp& op) override;
- void visit(mir::ops::GemmOp& op) override;
- void visit(mir::ops::InputOp& op) override;
- void visit(mir::ops::LeakyReluOp& op) override;
- void visit(mir::ops::MaxOp& op) override;
- void visit(mir::ops::MulOp& op) override;
- void visit(mir::ops::OutputOp& op) override;
- void visit(mir::ops::PadOp& op) override;
- void visit(mir::ops::PoolOp& op) override;
- void visit(mir::ops::ReduceOp& op) override;
- void visit(mir::ops::ReluOp& op) override;
- void visit(mir::ops::ReshapeOp& op) override;
- void visit(mir::ops::ResizeOp& op) override;
- void visit(mir::ops::SigmoidOp& op) override;
- void visit(mir::ops::SliceOp& op) override;
- void visit(mir::ops::SoftmaxOp& op) override;
- void visit(mir::ops::SqrtOp& op) override;
- void visit(mir::ops::SqueezeOp& op) override;
- void visit(mir::ops::SubOp& op) override;
- void visit(mir::ops::TanhOp& op) override;
- void visit(mir::ops::TransposeOp& op) override;
+ void visit(mir::ops::AddOp &op) override;
+ void visit(mir::ops::BatchNormOp &op) override;
+ void visit(mir::ops::CappedReluOp &op) override;
+ void visit(mir::ops::ConcatOp &op) override;
+ void visit(mir::ops::ConstantOp &op) override;
+ void visit(mir::ops::Conv2DOp &op) override;
+ void visit(mir::ops::DeConv2DOp &op) override;
+ void visit(mir::ops::DepthwiseConv2DOp &op) override;
+ void visit(mir::ops::DivOp &op) override;
+ void visit(mir::ops::DropoutOp &op) override;
+ void visit(mir::ops::EluOp &op) override;
+ void visit(mir::ops::FullyConnectedOp &op) override;
+ void visit(mir::ops::GatherOp &op) override;
+ void visit(mir::ops::GemmOp &op) override;
+ void visit(mir::ops::InputOp &op) override;
+ void visit(mir::ops::LeakyReluOp &op) override;
+ void visit(mir::ops::MaxOp &op) override;
+ void visit(mir::ops::MulOp &op) override;
+ void visit(mir::ops::OutputOp &op) override;
+ void visit(mir::ops::PadOp &op) override;
+ void visit(mir::ops::PoolOp &op) override;
+ void visit(mir::ops::ReduceOp &op) override;
+ void visit(mir::ops::ReluOp &op) override;
+ void visit(mir::ops::ReshapeOp &op) override;
+ void visit(mir::ops::ResizeOp &op) override;
+ void visit(mir::ops::SigmoidOp &op) override;
+ void visit(mir::ops::SliceOp &op) override;
+ void visit(mir::ops::SoftmaxOp &op) override;
+ void visit(mir::ops::SqrtOp &op) override;
+ void visit(mir::ops::SqueezeOp &op) override;
+ void visit(mir::ops::SubOp &op) override;
+ void visit(mir::ops::TanhOp &op) override;
+ void visit(mir::ops::TransposeOp &op) override;
private:
using AF = ArtifactFactory;
* @param input id of input tensor
* @return Id of result tensor
*/
- std::shared_ptr<ArtifactId> genTransposeMIRtoACL(const std::string& name,
- const mir::Shape& input_shape,
- const std::shared_ptr<ArtifactId>& input);
+ std::shared_ptr<ArtifactId> genTransposeMIRtoACL(const std::string &name,
+ const mir::Shape &input_shape,
+ const std::shared_ptr<ArtifactId> &input);
/**
* @brief generate transpose NCHW -> NHWC
* @param input id of input tensor
* @return Id of result tensor
*/
- std::shared_ptr<ArtifactId> genTransposeACLtoMIR(const std::string& name,
- const mir::Shape& input_shape,
- const std::shared_ptr<ArtifactId>& input);
+ std::shared_ptr<ArtifactId> genTransposeACLtoMIR(const std::string &name,
+ const mir::Shape &input_shape,
+ const std::shared_ptr<ArtifactId> &input);
/**
* @brief Generate DOM for PadStrideInfo object
* @return generated variable
*/
template <typename Op>
- std::shared_ptr<ArtifactVariable>
- genPadStrideInfo(const Op& op, const std::string& prefix, ArtifactBlock* block);
+ std::shared_ptr<ArtifactVariable> genPadStrideInfo(const Op &op, const std::string &prefix,
+ ArtifactBlock *block);
/**
* @brief The common part of the convolution and the depthwise convolution.
*/
template <typename Op>
- void genConvolution(Op& op, const std::string& acl_func_name, const std::string& suffix);
+ void genConvolution(Op &op, const std::string &acl_func_name, const std::string &suffix);
/**
* @brief Generates different types of activation functions: ReLU, Tanh etc.
* LINEAR, TANH.
* @param b - betha parameter used by some activation functions: LINEAR, LU_BOUNDED_RELU, TANH.
*/
- void
- genActivation(const mir::Operation& op, const std::string& activation_name, float a = 0,
- float b = 0);
+ void genActivation(const mir::Operation &op, const std::string &activation_name, float a = 0,
+ float b = 0);
/**
* @brief Used to generate a binary addition operation in handling of the elementwise.
* to the left of and including the in2 term, or the operation out if in2 was
* the last term in the sequence.
*/
- std::shared_ptr<ArtifactId> genAddition(const std::string& prefix, size_t index,
- const mir::Shape& ir_shape,
- const std::shared_ptr<ArtifactId>& in1,
- const std::shared_ptr<ArtifactId>& in2,
+ std::shared_ptr<ArtifactId> genAddition(const std::string &prefix, size_t index,
+ const mir::Shape &ir_shape,
+ const std::shared_ptr<ArtifactId> &in1,
+ const std::shared_ptr<ArtifactId> &in2,
std::shared_ptr<ArtifactId> out = nullptr);
/**
* elements to the left of and including the in2 term, or the operation out if
* in2 was the last term in the sequence.
*/
- std::shared_ptr<ArtifactId> genMultiplication(const std::string& prefix, size_t index,
- const mir::Shape& ir_shape,
- const std::shared_ptr<ArtifactId>& in1,
- const std::shared_ptr<ArtifactId>& in2,
+ std::shared_ptr<ArtifactId> genMultiplication(const std::string &prefix, size_t index,
+ const mir::Shape &ir_shape,
+ const std::shared_ptr<ArtifactId> &in1,
+ const std::shared_ptr<ArtifactId> &in2,
std::shared_ptr<ArtifactId> out = nullptr);
/**
* @brief Generates a unique name for the tensor.
*/
- std::string tensorName(const mir::Operation::Output* ir_tensor) const;
+ std::string tensorName(const mir::Operation::Output *ir_tensor) const;
/**
* @brief Generates variables tensor shape in DOM.
* @return - a DOM identifier for the created shape.
*/
template <typename T>
- std::shared_ptr<ArtifactId> genVectorInitializedVar(ArtifactBlock* block,
- const std::string& type,
- const std::string& name,
- const std::vector<T>& init);
+ std::shared_ptr<ArtifactId> genVectorInitializedVar(ArtifactBlock *block, const std::string &type,
+ const std::string &name,
+ const std::vector<T> &init);
/**
* @brief Generates a DOM tensor.
* in the artifact class.
* @return - a DOM identifier for the created tensor.
*/
- std::shared_ptr<ArtifactId> genTensor(const std::string& name, const mir::Shape& ir_shape,
+ std::shared_ptr<ArtifactId> genTensor(const std::string &name, const mir::Shape &ir_shape,
bool gen_accessor = false);
/**
* @param ir_tensor - the ModelIR tensor.
* @return - a DOM identifier for the created tensor.
*/
- std::shared_ptr<ArtifactId> genTensor(const mir::Operation::Output* ir_tensor);
+ std::shared_ptr<ArtifactId> genTensor(const mir::Operation::Output *ir_tensor);
/**
- * @brief generate transposing operation, @p mir_perm contains dimensions in MIR order (batch has index 0)
+ * @brief generate transposing operation, @p mir_perm contains dimensions in MIR order (batch has
+ * index 0)
* @param input id of input tensor
* @param output id out output tensor
* @param mir_perm new order of dimensions
*/
- void genTranspose(const std::shared_ptr<nnc::ArtifactId>& input,
- const std::shared_ptr<nnc::ArtifactId>& output,
- const std::vector<size_t>& mir_perm,
- bool allocate_at_inference);
+ void genTranspose(const std::shared_ptr<nnc::ArtifactId> &input,
+ const std::shared_ptr<nnc::ArtifactId> &output,
+ const std::vector<size_t> &mir_perm, bool allocate_at_inference);
/**
* @brief Generates accessors for the input/output tensors.
* @param graph - the ModelIR graph.
*/
- void genNamed(mir::Graph* graph);
+ void genNamed(mir::Graph *graph);
/**
* @brief Schedule a tensor serialization.
* @param tensor_id - an artifact ID of the tensor.
* @param ir_tensor - the IR source of the tensor.
*/
- void serializeTensor(const std::shared_ptr<ArtifactId>& tensor_id, const mir::TensorVariant& ir_tensor);
+ void serializeTensor(const std::shared_ptr<ArtifactId> &tensor_id,
+ const mir::TensorVariant &ir_tensor);
/**
* @brief Serialize an IR tensor in a file.
* @param tensor - tensor to serialize.
*/
- void serializeIRTensor(const mir::TensorVariant& tensor);
+ void serializeIRTensor(const mir::TensorVariant &tensor);
/**
* @brief Generate the deserialization calls in right places in the artifact.
* @param tensor_id - ID of the tensor.
* @param val - its value.
*/
- void fillTensor(const std::shared_ptr<ArtifactId>& tensor_id, const std::string& val);
+ void fillTensor(const std::shared_ptr<ArtifactId> &tensor_id, const std::string &val);
/**
* @brief Schedule the tensor allocation in the artifact constructor.
* @param tensor_id - ID of the scheduled tensor.
*/
- void addToPersistentTensors(const std::shared_ptr<ArtifactId>& tensor_id);
+ void addToPersistentTensors(const std::shared_ptr<ArtifactId> &tensor_id);
/**
* @brief Generate allocation of tensor
* @param tensor Id of tensor to allocate
*/
std::shared_ptr<ArtifactFunctionCall>
- genTensorAllocation(ArtifactBlock* block, const std::shared_ptr<ArtifactId>& tensor);
+ genTensorAllocation(ArtifactBlock *block, const std::shared_ptr<ArtifactId> &tensor);
/**
* @brief Generate deallocation of tensor
* @param tensor Id of tensor to deallocate
*/
std::shared_ptr<ArtifactFunctionCall>
- genTensorDeallocation(ArtifactBlock* block, const std::shared_ptr<ArtifactId>& tensor);
+ genTensorDeallocation(ArtifactBlock *block, const std::shared_ptr<ArtifactId> &tensor);
/**
* @brief Generate all the scheduled tensor allocations.
* @param config_params - input/output tensor names and the other configuration information.
* @return - generated tensor ID.
*/
- std::shared_ptr<ArtifactId> genLayer(const std::string& layer_type, const std::string& layer_name,
- const std::list<std::shared_ptr<ArtifactExpr>>& config_params);
+ std::shared_ptr<ArtifactId>
+ genLayer(const std::string &layer_type, const std::string &layer_name,
+ const std::list<std::shared_ptr<ArtifactExpr>> &config_params);
/**
* @brief Generate the layer run() call.
* @param layer_id - layer ID.
*/
- void genLayerExecution(const std::shared_ptr<ArtifactId>& layer_id);
+ void genLayerExecution(const std::shared_ptr<ArtifactId> &layer_id);
/**
* @brief All named tensors names.
/**
* @brief The stream for tensors serialization.
*/
- std::ostream& _parOut;
+ std::ostream &_parOut;
/**
* @brief The whole artifact module in the DOM.
/**
* @brief The constuctor block of DOM instructions.
*/
- ArtifactBlock* _constrBlock;
+ ArtifactBlock *_constrBlock;
/**
* @brief The inference function block of DOM instruction.
*/
- ArtifactBlock* _infBlock;
+ ArtifactBlock *_infBlock;
/**
* @brief The variable describing the input stream for tensors deserialization.
std::list<std::shared_ptr<ArtifactId>> _persistent_tensors;
/**
- * @brief Tensors which are serialized from the Model IR and need to be deserialized in the artifact.
+ * @brief Tensors which are serialized from the Model IR and need to be deserialized in the
+ * artifact.
*/
std::list<std::shared_ptr<ArtifactId>> _serializations;
using namespace std;
-namespace nnc {
+namespace nnc
+{
-ArtifactGeneratorCppCode::ArtifactGeneratorCppCode(ostream& out) : _out(out) {
-}
+ArtifactGeneratorCppCode::ArtifactGeneratorCppCode(ostream &out) : _out(out) {}
-void ArtifactGeneratorCppCode::visit(const ArtifactLiteral* node) {
- _out << node->getValue();
-}
+void ArtifactGeneratorCppCode::visit(const ArtifactLiteral *node) { _out << node->getValue(); }
-void ArtifactGeneratorCppCode::visit(const ArtifactId* node) {
- _out << node->name();
-}
+void ArtifactGeneratorCppCode::visit(const ArtifactId *node) { _out << node->name(); }
-void ArtifactGeneratorCppCode::visit(const ArtifactRef* node) {
+void ArtifactGeneratorCppCode::visit(const ArtifactRef *node)
+{
_out << "&";
node->obj()->accept(this);
}
-void ArtifactGeneratorCppCode::visit(const ArtifactDeref* node) {
+void ArtifactGeneratorCppCode::visit(const ArtifactDeref *node)
+{
_out << "*";
node->obj()->accept(this);
}
-void ArtifactGeneratorCppCode::visit(const ArtifactVariable* node) {
+void ArtifactGeneratorCppCode::visit(const ArtifactVariable *node)
+{
_out << node->typeName() << " " << node->name();
- for (const auto& d : node->getDimensions()) {
+ for (const auto &d : node->getDimensions())
+ {
_out << "[";
d->accept(this);
_out << "]";
}
- if (!node->getInitializers().empty()) {
+ if (!node->getInitializers().empty())
+ {
_out << "(";
bool add_comma = false;
- for (const auto& i : node->getInitializers()) {
+ for (const auto &i : node->getInitializers())
+ {
if (add_comma)
_out << ", ";
}
}
-void ArtifactGeneratorCppCode::visit(const ArtifactFunctionCall* node) {
- static const char* call_type_str[] = {".", "->", "::"};
+void ArtifactGeneratorCppCode::visit(const ArtifactFunctionCall *node)
+{
+ static const char *call_type_str[] = {".", "->", "::"};
- if (node->on()) {
+ if (node->on())
+ {
node->on()->accept(this);
_out << call_type_str[static_cast<int>(node->callType())];
}
_out << "(";
bool add_comma = false;
- for (const auto& par : node->paramList()) {
+ for (const auto &par : node->paramList())
+ {
if (add_comma)
_out << ", ";
_out << ")";
}
-void ArtifactGeneratorCppCode::visit(const ArtifactUnaryExpr* node) {
+void ArtifactGeneratorCppCode::visit(const ArtifactUnaryExpr *node)
+{
// The trailing space is intended in new and delete!
- static const char* un_op_str[] = {"++", "--", "new ", "delete ", "++", "--"};
+ static const char *un_op_str[] = {"++", "--", "new ", "delete ", "++", "--"};
- if (node->getOp() < ArtifactUnOp::postIncr) {
+ if (node->getOp() < ArtifactUnOp::postIncr)
+ {
_out << un_op_str[static_cast<int>(node->getOp())];
node->getExpr()->accept(this);
- } else {
+ }
+ else
+ {
node->getExpr()->accept(this);
_out << un_op_str[static_cast<int>(node->getOp())];
}
}
-void ArtifactGeneratorCppCode::visit(const ArtifactBinaryExpr* node) {
- static const char* bin_op_str[] = {"==", "!=", "<", "<=", ">", ">=", "=", "+", "-", "*", "/",
- "+=", "-=", "*=", "/="};
+void ArtifactGeneratorCppCode::visit(const ArtifactBinaryExpr *node)
+{
+ static const char *bin_op_str[] = {"==", "!=", "<", "<=", ">", ">=", "=", "+",
+ "-", "*", "/", "+=", "-=", "*=", "/="};
node->getLeft()->accept(this);
_out << " " << bin_op_str[static_cast<int>(node->getOp())] << " ";
node->getRight()->accept(this);
}
-void ArtifactGeneratorCppCode::visit(const ArtifactIndex* node) {
+void ArtifactGeneratorCppCode::visit(const ArtifactIndex *node)
+{
node->getExpr()->accept(this);
_out << "[";
node->getInd()->accept(this);
_out << "]";
}
-void ArtifactGeneratorCppCode::visit(const ArtifactRet* node) {
+void ArtifactGeneratorCppCode::visit(const ArtifactRet *node)
+{
_out << "return ";
node->expr()->accept(this);
}
-void ArtifactGeneratorCppCode::visit(const ArtifactBreak* /*node*/) {
- _out << "break";
-}
+void ArtifactGeneratorCppCode::visit(const ArtifactBreak * /*node*/) { _out << "break"; }
-void ArtifactGeneratorCppCode::visit(const ArtifactCont* /*node*/) {
- _out << "continue";
-}
+void ArtifactGeneratorCppCode::visit(const ArtifactCont * /*node*/) { _out << "continue"; }
-void ArtifactGeneratorCppCode::visit(const ArtifactBlock* node) {
+void ArtifactGeneratorCppCode::visit(const ArtifactBlock *node)
+{
_out << " {" << endl;
++_ind;
- for (const auto& st : node->getStatements()) {
+ for (const auto &st : node->getStatements())
+ {
_out << _ind;
st->accept(this);
_out << _ind << "}" << endl;
}
-void ArtifactGeneratorCppCode::visit(const ArtifactForLoop* node) {
+void ArtifactGeneratorCppCode::visit(const ArtifactForLoop *node)
+{
_out << "for(";
if (node->getInit())
node->getBlock()->accept(this);
}
-void ArtifactGeneratorCppCode::visit(const ArtifactIf* node) {
+void ArtifactGeneratorCppCode::visit(const ArtifactIf *node)
+{
_out << "if(";
node->getCond()->accept(this);
_out << ")";
node->getBlock()->accept(this);
- if (!node->getElseBlock()->getStatements().empty()) {
+ if (!node->getElseBlock()->getStatements().empty())
+ {
_out << _ind << "else";
node->getElseBlock()->accept(this);
}
}
-void ArtifactGeneratorCppCode::visit(const ArtifactFunction* /*node*/) {
+void ArtifactGeneratorCppCode::visit(const ArtifactFunction * /*node*/)
+{
// TODO implement this function
}
-void ArtifactGeneratorCppCode::visit(const ArtifactClass* node) {
+void ArtifactGeneratorCppCode::visit(const ArtifactClass *node)
+{
// Generate a public default constructor here.
_out << node->name() << "::" << node->name() << "()";
- if (!node->privateVariables().empty()) {
+ if (!node->privateVariables().empty())
+ {
_out << " : ";
bool add_delim = false;
- for (const auto& v : node->privateVariables()) {
+ for (const auto &v : node->privateVariables())
+ {
if (add_delim)
_out << ",\n";
}
}
- //TODO add constructors of public variables
+ // TODO add constructors of public variables
node->getConstrBlock()->accept(this);
_out << endl;
// Then generate the other stuff.
- for (const auto& e : node->publicFunctions())
+ for (const auto &e : node->publicFunctions())
e->accept(this);
- for (const auto& e : node->privateFunctions())
+ for (const auto &e : node->privateFunctions())
e->accept(this);
}
-void ArtifactGeneratorCppCode::visit(const ArtifactClassVariable* node) {
+void ArtifactGeneratorCppCode::visit(const ArtifactClassVariable *node)
+{
_out << node->name() << "(";
bool add_comma = false;
- for (const auto& i : node->getInitializers()) {
+ for (const auto &i : node->getInitializers())
+ {
if (add_comma)
_out << ", ";
_out << ")";
}
-void ArtifactGeneratorCppCode::visit(const ArtifactClassFunction* node) {
+void ArtifactGeneratorCppCode::visit(const ArtifactClassFunction *node)
+{
_out << node->getRetTypeName();
if (!node->getRetTypeName().empty())
_out << node->owner()->name() << "::" << node->name() << "(";
bool add_comma = false;
- for (const auto& p : node->getParameters()) {
+ for (const auto &p : node->getParameters())
+ {
if (add_comma)
_out << ", ";
_out << endl;
}
-void ArtifactGeneratorCppCode::visit(const ArtifactModule* node) {
+void ArtifactGeneratorCppCode::visit(const ArtifactModule *node)
+{
_out << "#include \"" << node->name() << ".h\"" << endl << endl;
- for (const auto& i : node->sourceSysIncludes())
+ for (const auto &i : node->sourceSysIncludes())
_out << "#include <" << i << ">" << endl;
if (!node->sourceSysIncludes().empty())
_out << endl;
- for (const auto& i : node->sourceIncludes())
+ for (const auto &i : node->sourceIncludes())
_out << "#include \"" << i << "\"" << endl;
if (!node->sourceIncludes().empty())
_out.write(AclArtifactUtilities, sizeof(AclArtifactUtilities));
_out << endl;
- for (const auto& e : node->entities())
+ for (const auto &e : node->entities())
e->accept(this);
}
/**
* @brief The ACL C++ artifact source code producer.
*/
-class ArtifactGeneratorCppCode : public IArtifactGenerator {
+class ArtifactGeneratorCppCode : public IArtifactGenerator
+{
public:
- explicit ArtifactGeneratorCppCode(std::ostream& out);
-
- void visit(const ArtifactLiteral* node) override;
- void visit(const ArtifactId* node) override;
- void visit(const ArtifactRef* node) override;
- void visit(const ArtifactDeref* node) override;
- void visit(const ArtifactVariable* node) override;
- void visit(const ArtifactFunctionCall* node) override;
- void visit(const ArtifactUnaryExpr* node) override;
- void visit(const ArtifactBinaryExpr* node) override;
- void visit(const ArtifactIndex* node) override;
- void visit(const ArtifactRet* node) override;
- void visit(const ArtifactBreak* node) override;
- void visit(const ArtifactCont* node) override;
- void visit(const ArtifactBlock* node) override;
- void visit(const ArtifactForLoop* node) override;
- void visit(const ArtifactIf* node) override;
- void visit(const ArtifactFunction* node) override;
- void visit(const ArtifactClass* node) override;
- void visit(const ArtifactClassVariable* node) override;
- void visit(const ArtifactClassFunction* node) override;
- void visit(const ArtifactModule* node) override;
+ explicit ArtifactGeneratorCppCode(std::ostream &out);
+
+ void visit(const ArtifactLiteral *node) override;
+ void visit(const ArtifactId *node) override;
+ void visit(const ArtifactRef *node) override;
+ void visit(const ArtifactDeref *node) override;
+ void visit(const ArtifactVariable *node) override;
+ void visit(const ArtifactFunctionCall *node) override;
+ void visit(const ArtifactUnaryExpr *node) override;
+ void visit(const ArtifactBinaryExpr *node) override;
+ void visit(const ArtifactIndex *node) override;
+ void visit(const ArtifactRet *node) override;
+ void visit(const ArtifactBreak *node) override;
+ void visit(const ArtifactCont *node) override;
+ void visit(const ArtifactBlock *node) override;
+ void visit(const ArtifactForLoop *node) override;
+ void visit(const ArtifactIf *node) override;
+ void visit(const ArtifactFunction *node) override;
+ void visit(const ArtifactClass *node) override;
+ void visit(const ArtifactClassVariable *node) override;
+ void visit(const ArtifactClassFunction *node) override;
+ void visit(const ArtifactModule *node) override;
private:
- std::ostream& _out;
- ArtifactIndent _ind;
+ std::ostream &_out;
+ ArtifactIndent _ind;
};
} // namespace nnc
using namespace std;
-namespace nnc {
+namespace nnc
+{
-ArtifactGeneratorCppDecl::ArtifactGeneratorCppDecl(ostream& out) : _out(out) {
-}
+ArtifactGeneratorCppDecl::ArtifactGeneratorCppDecl(ostream &out) : _out(out) {}
-void ArtifactGeneratorCppDecl::visit(const ArtifactLiteral* node) {
- _out << node->getValue();
-}
+void ArtifactGeneratorCppDecl::visit(const ArtifactLiteral *node) { _out << node->getValue(); }
-void ArtifactGeneratorCppDecl::visit(const ArtifactId* node) {
- _out << node->name();
-}
+void ArtifactGeneratorCppDecl::visit(const ArtifactId *node) { _out << node->name(); }
-void ArtifactGeneratorCppDecl::visit(const ArtifactRef* node) {
+void ArtifactGeneratorCppDecl::visit(const ArtifactRef *node)
+{
_out << "&";
node->obj()->accept(this);
}
-void ArtifactGeneratorCppDecl::visit(const ArtifactDeref* node) {
+void ArtifactGeneratorCppDecl::visit(const ArtifactDeref *node)
+{
_out << "*";
node->obj()->accept(this);
}
-void ArtifactGeneratorCppDecl::visit(const ArtifactVariable* node) {
+void ArtifactGeneratorCppDecl::visit(const ArtifactVariable *node)
+{
_out << node->typeName() << " " << node->name();
}
-void ArtifactGeneratorCppDecl::visit(const ArtifactFunctionCall* /*node*/) {}
+void ArtifactGeneratorCppDecl::visit(const ArtifactFunctionCall * /*node*/) {}
-void ArtifactGeneratorCppDecl::visit(const ArtifactUnaryExpr* /*node*/) {}
+void ArtifactGeneratorCppDecl::visit(const ArtifactUnaryExpr * /*node*/) {}
-void ArtifactGeneratorCppDecl::visit(const ArtifactBinaryExpr* /*node*/) {}
+void ArtifactGeneratorCppDecl::visit(const ArtifactBinaryExpr * /*node*/) {}
-void ArtifactGeneratorCppDecl::visit(const ArtifactIndex* /*node*/) {}
+void ArtifactGeneratorCppDecl::visit(const ArtifactIndex * /*node*/) {}
-void ArtifactGeneratorCppDecl::visit(const ArtifactRet* /*node*/) {}
+void ArtifactGeneratorCppDecl::visit(const ArtifactRet * /*node*/) {}
-void ArtifactGeneratorCppDecl::visit(const ArtifactBreak* /*node*/) {}
+void ArtifactGeneratorCppDecl::visit(const ArtifactBreak * /*node*/) {}
-void ArtifactGeneratorCppDecl::visit(const ArtifactCont* /*node*/) {}
+void ArtifactGeneratorCppDecl::visit(const ArtifactCont * /*node*/) {}
-void ArtifactGeneratorCppDecl::visit(const ArtifactBlock* /*node*/) {}
+void ArtifactGeneratorCppDecl::visit(const ArtifactBlock * /*node*/) {}
-void ArtifactGeneratorCppDecl::visit(const ArtifactForLoop* /*node*/) {}
+void ArtifactGeneratorCppDecl::visit(const ArtifactForLoop * /*node*/) {}
-void ArtifactGeneratorCppDecl::visit(const ArtifactIf* /*node*/) {}
+void ArtifactGeneratorCppDecl::visit(const ArtifactIf * /*node*/) {}
-void ArtifactGeneratorCppDecl::visit(const ArtifactFunction* node) {
+void ArtifactGeneratorCppDecl::visit(const ArtifactFunction *node)
+{
_out << node->getRetTypeName() << " " << node->name() << "(";
bool add_comma = false;
- for (const auto& par : node->getParameters()) {
+ for (const auto &par : node->getParameters())
+ {
if (add_comma)
_out << ", ";
_out << ");";
}
-void ArtifactGeneratorCppDecl::visit(const ArtifactClass* node) {
+void ArtifactGeneratorCppDecl::visit(const ArtifactClass *node)
+{
_out << "class " << node->name() << " {" << endl;
_out << "public:" << endl;
++_ind;
// Then generate the other stuff.
- for (const auto& e : node->publicFunctions()) {
+ for (const auto &e : node->publicFunctions())
+ {
_out << _ind;
e->accept(this);
}
_out << endl << "private:" << endl;
- for (const auto& e : node->privateFunctions()) {
+ for (const auto &e : node->privateFunctions())
+ {
_out << _ind;
e->accept(this);
}
// TODO add public variables
- for (const auto& e : node->privateVariables()) {
+ for (const auto &e : node->privateVariables())
+ {
_out << _ind;
e->accept(this);
}
_out << "};" << endl;
}
-void ArtifactGeneratorCppDecl::visit(const ArtifactClassVariable* node) {
+void ArtifactGeneratorCppDecl::visit(const ArtifactClassVariable *node)
+{
_out << node->typeName() << " " << node->name() << ";" << endl;
}
-void ArtifactGeneratorCppDecl::visit(const ArtifactClassFunction* node) {
+void ArtifactGeneratorCppDecl::visit(const ArtifactClassFunction *node)
+{
_out << node->getRetTypeName();
if (!node->getRetTypeName().empty())
_out << node->name() << "(";
bool add_comma = false;
- for (const auto& p : node->getParameters()) {
+ for (const auto &p : node->getParameters())
+ {
if (add_comma)
_out << ", ";
_out << ");" << endl;
}
-void ArtifactGeneratorCppDecl::visit(const ArtifactModule* node) {
- for (const auto& i : node->headerSysIncludes())
+void ArtifactGeneratorCppDecl::visit(const ArtifactModule *node)
+{
+ for (const auto &i : node->headerSysIncludes())
_out << "#include <" << i << ">" << endl;
if (!node->headerSysIncludes().empty())
_out << endl;
- for (const auto& i : node->headerIncludes())
+ for (const auto &i : node->headerIncludes())
_out << "#include \"" << i << "\"" << endl;
if (!node->headerIncludes().empty())
_out << endl;
- for (const auto& e : node->entities())
+ for (const auto &e : node->entities())
e->accept(this);
}
/**
* @brief The ACL C++ artifact header file producer.
*/
-class ArtifactGeneratorCppDecl : public IArtifactGenerator {
+class ArtifactGeneratorCppDecl : public IArtifactGenerator
+{
public:
- explicit ArtifactGeneratorCppDecl(std::ostream& out);
-
- void visit(const ArtifactLiteral* node) override;
- void visit(const ArtifactId* node) override;
- void visit(const ArtifactRef* node) override;
- void visit(const ArtifactDeref* node) override;
- void visit(const ArtifactVariable* node) override;
- void visit(const ArtifactFunctionCall* node) override;
- void visit(const ArtifactUnaryExpr* node) override;
- void visit(const ArtifactBinaryExpr* node) override;
- void visit(const ArtifactIndex* node) override;
- void visit(const ArtifactRet* node) override;
- void visit(const ArtifactBreak* node) override;
- void visit(const ArtifactCont* node) override;
- void visit(const ArtifactBlock* node) override;
- void visit(const ArtifactForLoop* node) override;
- void visit(const ArtifactIf* node) override;
- void visit(const ArtifactFunction* node) override;
- void visit(const ArtifactClass* node) override;
- void visit(const ArtifactClassVariable* node) override;
- void visit(const ArtifactClassFunction* node) override;
- void visit(const ArtifactModule* node) override;
+ explicit ArtifactGeneratorCppDecl(std::ostream &out);
+
+ void visit(const ArtifactLiteral *node) override;
+ void visit(const ArtifactId *node) override;
+ void visit(const ArtifactRef *node) override;
+ void visit(const ArtifactDeref *node) override;
+ void visit(const ArtifactVariable *node) override;
+ void visit(const ArtifactFunctionCall *node) override;
+ void visit(const ArtifactUnaryExpr *node) override;
+ void visit(const ArtifactBinaryExpr *node) override;
+ void visit(const ArtifactIndex *node) override;
+ void visit(const ArtifactRet *node) override;
+ void visit(const ArtifactBreak *node) override;
+ void visit(const ArtifactCont *node) override;
+ void visit(const ArtifactBlock *node) override;
+ void visit(const ArtifactForLoop *node) override;
+ void visit(const ArtifactIf *node) override;
+ void visit(const ArtifactFunction *node) override;
+ void visit(const ArtifactClass *node) override;
+ void visit(const ArtifactClassVariable *node) override;
+ void visit(const ArtifactClassFunction *node) override;
+ void visit(const ArtifactModule *node) override;
private:
- std::ostream& _out;
+ std::ostream &_out;
ArtifactIndent _ind;
};
#include <string>
#include <ostream>
-namespace nnc {
+namespace nnc
+{
/**
* @brief Used by code and declaration generators to indent generated text.
*/
-class ArtifactIndent {
+class ArtifactIndent
+{
public:
ArtifactIndent() : _level(0), _step(2) {}
- ArtifactIndent& operator++() {
+ ArtifactIndent &operator++()
+ {
_level += _step;
return *this;
}
- ArtifactIndent& operator--() {
+ ArtifactIndent &operator--()
+ {
_level -= _step;
return *this;
}
int _step;
};
-inline std::ostream& operator<<(std::ostream& out, const ArtifactIndent& ind) {
+inline std::ostream &operator<<(std::ostream &out, const ArtifactIndent &ind)
+{
if (ind.level() > 0)
out << std::string(ind.level(), ' ');
#include "ArtifactModel.h"
-namespace nnc {
+namespace nnc
+{
using namespace std;
// ArtifactFunctionCall implementation
ArtifactFunctionCall::ArtifactFunctionCall(string func_name,
list<shared_ptr<ArtifactExpr>> param_list,
- shared_ptr<ArtifactExpr> on,
- ArtifactCallType call_type) :
- _funcName(std::move(func_name)), _callType(call_type),
- _on(std::move(on)), _paramList(std::move(param_list)) {
+ shared_ptr<ArtifactExpr> on, ArtifactCallType call_type)
+ : _funcName(std::move(func_name)), _callType(call_type), _on(std::move(on)),
+ _paramList(std::move(param_list))
+{
}
// ArtifactBlock implementation.
-shared_ptr<ArtifactVariable> ArtifactBlock::var(
- const string& type_name,
- const string& var_name, const list<shared_ptr<ArtifactExpr>>& dimensions,
- const list<std::shared_ptr<ArtifactExpr>>& initializers) {
+shared_ptr<ArtifactVariable>
+ArtifactBlock::var(const string &type_name, const string &var_name,
+ const list<shared_ptr<ArtifactExpr>> &dimensions,
+ const list<std::shared_ptr<ArtifactExpr>> &initializers)
+{
auto var = make_shared<ArtifactVariable>(type_name, var_name, dimensions, initializers);
_statements.push_back(var);
return var;
}
-shared_ptr<ArtifactFunctionCall> ArtifactBlock::call(
- const string& func_name,
- const list<shared_ptr<ArtifactExpr>>& param_list,
- shared_ptr<ArtifactExpr> call_on, ArtifactCallType call_type) {
- auto func_call = make_shared<ArtifactFunctionCall>(func_name, param_list,
- call_on, call_type);
+shared_ptr<ArtifactFunctionCall>
+ArtifactBlock::call(const string &func_name, const list<shared_ptr<ArtifactExpr>> ¶m_list,
+ shared_ptr<ArtifactExpr> call_on, ArtifactCallType call_type)
+{
+ auto func_call = make_shared<ArtifactFunctionCall>(func_name, param_list, call_on, call_type);
_statements.push_back(func_call);
return func_call;
}
-shared_ptr<ArtifactRet> ArtifactBlock::ret(shared_ptr<ArtifactExpr> expr) {
+shared_ptr<ArtifactRet> ArtifactBlock::ret(shared_ptr<ArtifactExpr> expr)
+{
auto ret = make_shared<ArtifactRet>(expr);
_statements.push_back(ret);
return ret;
}
-shared_ptr<ArtifactBreak> ArtifactBlock::brk() {
+shared_ptr<ArtifactBreak> ArtifactBlock::brk()
+{
auto brk = make_shared<ArtifactBreak>();
_statements.push_back(brk);
return brk;
}
-shared_ptr<ArtifactCont> ArtifactBlock::cont() {
+shared_ptr<ArtifactCont> ArtifactBlock::cont()
+{
auto cont = make_shared<ArtifactCont>();
_statements.push_back(cont);
return cont;
}
-shared_ptr<ArtifactForLoop> ArtifactBlock::forLoop(
- shared_ptr<ArtifactVariable> init,
- shared_ptr<ArtifactExpr> cond, shared_ptr<ArtifactExpr> iter) {
+shared_ptr<ArtifactForLoop> ArtifactBlock::forLoop(shared_ptr<ArtifactVariable> init,
+ shared_ptr<ArtifactExpr> cond,
+ shared_ptr<ArtifactExpr> iter)
+{
auto loop = make_shared<ArtifactForLoop>(init, cond, iter);
_statements.push_back(loop);
return loop;
}
-shared_ptr<ArtifactIf> ArtifactBlock::ifCond(shared_ptr<ArtifactExpr> cond) {
+shared_ptr<ArtifactIf> ArtifactBlock::ifCond(shared_ptr<ArtifactExpr> cond)
+{
auto ifb = make_shared<ArtifactIf>(cond);
_statements.push_back(ifb);
return ifb;
}
-shared_ptr<ArtifactUnaryExpr> ArtifactBlock::un(ArtifactUnOp op,
- shared_ptr<ArtifactExpr> expr) {
+shared_ptr<ArtifactUnaryExpr> ArtifactBlock::un(ArtifactUnOp op, shared_ptr<ArtifactExpr> expr)
+{
auto un = make_shared<ArtifactUnaryExpr>(op, expr);
_statements.push_back(un);
return un;
}
-shared_ptr<ArtifactBinaryExpr> ArtifactBlock::bin(
- ArtifactBinOp op,
- shared_ptr<ArtifactExpr> left, shared_ptr<ArtifactExpr> right) {
+shared_ptr<ArtifactBinaryExpr> ArtifactBlock::bin(ArtifactBinOp op, shared_ptr<ArtifactExpr> left,
+ shared_ptr<ArtifactExpr> right)
+{
auto bin = make_shared<ArtifactBinaryExpr>(op, left, right);
_statements.push_back(bin);
return bin;
}
-shared_ptr<ArtifactUnaryExpr> ArtifactBlock::heapNew(shared_ptr<ArtifactExpr> expr) {
+shared_ptr<ArtifactUnaryExpr> ArtifactBlock::heapNew(shared_ptr<ArtifactExpr> expr)
+{
auto heap_new = make_shared<ArtifactUnaryExpr>(ArtifactUnOp::heapNew, expr);
_statements.push_back(heap_new);
return heap_new;
}
-shared_ptr<ArtifactUnaryExpr> ArtifactBlock::heapFree(shared_ptr<ArtifactExpr> expr) {
+shared_ptr<ArtifactUnaryExpr> ArtifactBlock::heapFree(shared_ptr<ArtifactExpr> expr)
+{
auto heap_del = make_shared<ArtifactUnaryExpr>(ArtifactUnOp::heapFree, expr);
_statements.push_back(heap_del);
return heap_del;
#include "IArtifactGenerator.h"
-namespace nnc {
+namespace nnc
+{
/**
* @todo FIXME: remove the identical accept() function implementations!
* @brief Indicates how object on which call is made is treated.
* In C++ syntax syntax: '.', '->', '::'
*/
-enum class ArtifactCallType {
- obj, // '.'
- ref, // '->'
- scope // '::'
+enum class ArtifactCallType
+{
+ obj, // '.'
+ ref, // '->'
+ scope // '::'
};
/**
* @brief The base class of the whole artifact entities hierarchy.
*/
-class ArtifactEntity {
+class ArtifactEntity
+{
public:
virtual ~ArtifactEntity() = default;
* @brief This is the core function of each artifact entity and
* is implemented by all concrete classes in the hierarchy.
*/
- virtual void accept(IArtifactGenerator* g) const = 0;
+ virtual void accept(IArtifactGenerator *g) const = 0;
protected:
ArtifactEntity() = default;
* Returns the identifier name.
* @return the identifier name.
*/
- const std::string& name() const { return _name; }
+ const std::string &name() const { return _name; }
private:
- std::string _name;
+ std::string _name;
};
/**
* @brief Basic class for all expressions: identifiers, function calls, references etc.
*/
-class ArtifactExpr : public ArtifactEntity {
+class ArtifactExpr : public ArtifactEntity
+{
};
/**
* @brief Represents literals which should go to the artifact source code as is.
*/
-class ArtifactLiteral : public ArtifactExpr {
+class ArtifactLiteral : public ArtifactExpr
+{
public:
explicit ArtifactLiteral(std::string value) : _value(std::move(value)) {}
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
- }
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
/**
* Returns the literal value.
* @return the literal value.
*/
- const std::string& getValue() const { return _value; }
+ const std::string &getValue() const { return _value; }
private:
std::string _value;
/**
* @brief Type of objects which can be used to reference named entities by their names.
*/
-class ArtifactId : public ArtifactExpr {
+class ArtifactId : public ArtifactExpr
+{
public:
explicit ArtifactId(std::string id) : _id(std::move(id)) {}
- explicit ArtifactId(const ArtifactNamed* named) : _id(named->name()) {}
+ explicit ArtifactId(const ArtifactNamed *named) : _id(named->name()) {}
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
- }
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
- const std::string& name() const { return _id; }
+ const std::string &name() const { return _id; }
private:
std::string _id;
/**
* @brief Represents an entity with semantics like C/C++ address of (&) operator.
*/
-class ArtifactRef : public ArtifactExpr {
+class ArtifactRef : public ArtifactExpr
+{
public:
explicit ArtifactRef(std::shared_ptr<ArtifactExpr> ref) : _ref(std::move(ref)) {}
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
- }
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
std::shared_ptr<ArtifactExpr> obj() const { return _ref; }
/**
* @brief Represents an entity with semantics of C/C++ dereference (*) operator.
*/
-class ArtifactDeref : public ArtifactExpr {
+class ArtifactDeref : public ArtifactExpr
+{
public:
explicit ArtifactDeref(std::shared_ptr<ArtifactExpr> ref) : _ref(std::move(ref)) {}
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
- }
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
std::shared_ptr<ArtifactExpr> obj() const { return _ref; }
/**
* @brief Represents a function call.
*/
-class ArtifactFunctionCall : public ArtifactExpr {
+class ArtifactFunctionCall : public ArtifactExpr
+{
public:
- ArtifactFunctionCall(std::string func_name,
- std::list<std::shared_ptr<ArtifactExpr>> param_list,
+ ArtifactFunctionCall(std::string func_name, std::list<std::shared_ptr<ArtifactExpr>> param_list,
std::shared_ptr<ArtifactExpr> on = nullptr,
ArtifactCallType call_type = ArtifactCallType::obj);
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
- }
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
- const std::string& funcName() const { return _funcName; }
- const std::list<std::shared_ptr<ArtifactExpr>>& paramList() const { return _paramList; }
+ const std::string &funcName() const { return _funcName; }
+ const std::list<std::shared_ptr<ArtifactExpr>> ¶mList() const { return _paramList; }
std::shared_ptr<ArtifactExpr> on() const { return _on; }
ArtifactCallType callType() const { return _callType; }
/**
* @brief Used for the ArtifactUnaryExpr.
*/
-enum class ArtifactUnOp {
+enum class ArtifactUnOp
+{
preIncr,
preDecr,
heapNew,
postDecr
};
-class ArtifactUnaryExpr : public ArtifactExpr {
+class ArtifactUnaryExpr : public ArtifactExpr
+{
public:
- ArtifactUnaryExpr(ArtifactUnOp op, std::shared_ptr<ArtifactExpr> expr) :
- _op(op), _expr(std::move(expr)) {}
-
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
+ ArtifactUnaryExpr(ArtifactUnOp op, std::shared_ptr<ArtifactExpr> expr)
+ : _op(op), _expr(std::move(expr))
+ {
}
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
+
ArtifactUnOp getOp() const { return _op; }
std::shared_ptr<ArtifactExpr> getExpr() const { return _expr; }
/**
* @brief Used for the ArtifactBinaryExpr.
*/
-enum class ArtifactBinOp {
+enum class ArtifactBinOp
+{
eq,
notEq,
less,
/**
* @brief Represents different types of binary expressions.
*/
-class ArtifactBinaryExpr : public ArtifactExpr {
+class ArtifactBinaryExpr : public ArtifactExpr
+{
public:
ArtifactBinaryExpr(ArtifactBinOp op, std::shared_ptr<ArtifactExpr> left,
- std::shared_ptr<ArtifactExpr> right) :
- _op(op), _left(std::move(left)), _right(std::move(right)) {}
-
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
+ std::shared_ptr<ArtifactExpr> right)
+ : _op(op), _left(std::move(left)), _right(std::move(right))
+ {
}
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
+
ArtifactBinOp getOp() const { return _op; }
std::shared_ptr<ArtifactExpr> getLeft() const { return _left; }
std::shared_ptr<ArtifactExpr> getRight() const { return _right; }
/**
* @brief Array index access
*/
-class ArtifactIndex : public ArtifactExpr {
+class ArtifactIndex : public ArtifactExpr
+{
public:
ArtifactIndex(std::shared_ptr<ArtifactExpr> expr, std::shared_ptr<ArtifactExpr> ind)
- : _expr(std::move(expr)), _ind(std::move(ind)) {}
-
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
+ : _expr(std::move(expr)), _ind(std::move(ind))
+ {
}
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
+
std::shared_ptr<ArtifactExpr> getExpr() const { return _expr; }
std::shared_ptr<ArtifactExpr> getInd() const { return _ind; }
/**
* @brief Just represents return from function statement.
*/
- class ArtifactRet : public ArtifactEntity {
- public:
- explicit ArtifactRet(std::shared_ptr<ArtifactExpr> expr) : _expr(std::move(expr)) {}
+class ArtifactRet : public ArtifactEntity
+{
+public:
+ explicit ArtifactRet(std::shared_ptr<ArtifactExpr> expr) : _expr(std::move(expr)) {}
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
- }
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
- std::shared_ptr<ArtifactExpr> expr() const { return _expr; }
+ std::shared_ptr<ArtifactExpr> expr() const { return _expr; }
- private:
- std::shared_ptr<ArtifactExpr> _expr;
- };
+private:
+ std::shared_ptr<ArtifactExpr> _expr;
+};
/**
* @brief Just represents the break statement.
*/
-class ArtifactBreak : public ArtifactEntity {
+class ArtifactBreak : public ArtifactEntity
+{
public:
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
- }
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
};
/**
* @brief Just represents the continue statement.
*/
-class ArtifactCont : public ArtifactEntity {
+class ArtifactCont : public ArtifactEntity
+{
public:
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
- }
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
};
/**
* @brief Represents a variable.
*/
-class ArtifactVariable : public ArtifactNamed {
+class ArtifactVariable : public ArtifactNamed
+{
public:
ArtifactVariable(std::string type_name, std::string var_name,
std::list<std::shared_ptr<ArtifactExpr>> dimensions = {},
std::list<std::shared_ptr<ArtifactExpr>> initializers = {})
- : _typeName(std::move(type_name)), _dimensions(std::move(dimensions)),
- _initializers(std::move(initializers)), ArtifactNamed(std::move(var_name)) {}
-
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
+ : _typeName(std::move(type_name)), _dimensions(std::move(dimensions)),
+ _initializers(std::move(initializers)), ArtifactNamed(std::move(var_name))
+ {
}
- const std::string& typeName() const { return _typeName; }
- const std::list<std::shared_ptr<ArtifactExpr>>& getDimensions() const { return _dimensions; };
- const std::list<std::shared_ptr<ArtifactExpr>>& getInitializers() const { return _initializers; }
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
+
+ const std::string &typeName() const { return _typeName; }
+ const std::list<std::shared_ptr<ArtifactExpr>> &getDimensions() const { return _dimensions; };
+ const std::list<std::shared_ptr<ArtifactExpr>> &getInitializers() const { return _initializers; }
std::shared_ptr<ArtifactId> use() { return std::make_shared<ArtifactId>(this); }
private:
std::string _typeName;
- std::list<std::shared_ptr<ArtifactExpr>> _dimensions;// If not empty, this is an array
+ std::list<std::shared_ptr<ArtifactExpr>> _dimensions; // If not empty, this is an array
std::list<std::shared_ptr<ArtifactExpr>> _initializers;
};
/**
* @brief Represents a block of instructions.
*/
-class ArtifactBlock : public ArtifactEntity {
+class ArtifactBlock : public ArtifactEntity
+{
public:
bool isBlock() const override { return true; }
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
- }
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
- void addStatement(const std::shared_ptr<ArtifactEntity>& statement) {
+ void addStatement(const std::shared_ptr<ArtifactEntity> &statement)
+ {
_statements.push_back(statement);
}
- const std::list<std::shared_ptr<ArtifactEntity>>& getStatements() const {
- return _statements;
- }
+ const std::list<std::shared_ptr<ArtifactEntity>> &getStatements() const { return _statements; }
/**
* @brief Creates a new variable and place it to the block.
* @param initializers - optional arguments of the object constructor.
* @return - the newly created variable.
*/
- std::shared_ptr<ArtifactVariable> var(
- const std::string& type_name, const std::string& var_name,
- const std::list<std::shared_ptr<ArtifactExpr>>& dimensions = {},
- const std::list<std::shared_ptr<ArtifactExpr>>& initializers = {});
+ std::shared_ptr<ArtifactVariable>
+ var(const std::string &type_name, const std::string &var_name,
+ const std::list<std::shared_ptr<ArtifactExpr>> &dimensions = {},
+ const std::list<std::shared_ptr<ArtifactExpr>> &initializers = {});
/**
* @brief Creates a function call.
* @param func_name - the function name.
* @param call_type - (for member functions only) call through: '.', '->', or '::'.
* @return
*/
- std::shared_ptr<ArtifactFunctionCall> call(
- const std::string& func_name,
- const std::list<std::shared_ptr<ArtifactExpr>>& param_list,
- std::shared_ptr<ArtifactExpr> call_on = nullptr,
- ArtifactCallType call_type = ArtifactCallType::obj);
+ std::shared_ptr<ArtifactFunctionCall>
+ call(const std::string &func_name, const std::list<std::shared_ptr<ArtifactExpr>> ¶m_list,
+ std::shared_ptr<ArtifactExpr> call_on = nullptr,
+ ArtifactCallType call_type = ArtifactCallType::obj);
/**
* @brief Creates a return from function statement.
* @param expr - value to return in generated code.
/**
* @brief Represents for loops.
*/
-class ArtifactForLoop : public ArtifactEntity {
+class ArtifactForLoop : public ArtifactEntity
+{
public:
explicit ArtifactForLoop(std::shared_ptr<ArtifactVariable> init = nullptr,
std::shared_ptr<ArtifactExpr> cond = nullptr,
std::shared_ptr<ArtifactExpr> iter = nullptr)
- : _init(std::move(init)), _cond(std::move(cond)), _iter(std::move(iter)) {}
+ : _init(std::move(init)), _cond(std::move(cond)), _iter(std::move(iter))
+ {
+ }
bool isBlock() const override { return true; }
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
- }
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
std::shared_ptr<ArtifactVariable> getInit() const { return _init; }
std::shared_ptr<ArtifactExpr> getCond() const { return _cond; }
std::shared_ptr<ArtifactExpr> getIter() const { return _iter; }
- const ArtifactBlock* getBlock() const { return &_body; }
- ArtifactBlock* getBlock() { return &_body; }
+ const ArtifactBlock *getBlock() const { return &_body; }
+ ArtifactBlock *getBlock() { return &_body; }
private:
std::shared_ptr<ArtifactVariable> _init;
/**
* @brief Represents if block.
*/
-class ArtifactIf : public ArtifactEntity {
+class ArtifactIf : public ArtifactEntity
+{
public:
explicit ArtifactIf(std::shared_ptr<ArtifactExpr> cond) : _cond(std::move(cond)) {}
bool isBlock() const override { return true; }
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
- }
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
std::shared_ptr<ArtifactExpr> getCond() const { return _cond; }
- const ArtifactBlock* getBlock() const { return &_body; }
- ArtifactBlock* getBlock() { return &_body; }
- const ArtifactBlock* getElseBlock() const { return &_elseBody; }
- ArtifactBlock* getElseBlock() { return &_elseBody; }
+ const ArtifactBlock *getBlock() const { return &_body; }
+ ArtifactBlock *getBlock() { return &_body; }
+ const ArtifactBlock *getElseBlock() const { return &_elseBody; }
+ ArtifactBlock *getElseBlock() { return &_elseBody; }
private:
std::shared_ptr<ArtifactExpr> _cond;
/**
* @brief Represents a function.
*/
-class ArtifactFunction : public ArtifactNamed {
+class ArtifactFunction : public ArtifactNamed
+{
public:
/**
* @brief Constructs a function object.
* @param func_name - the function name.
* @param params - the parameter list.
*/
- ArtifactFunction(std::string ret_type_name, const std::string& func_name,
- std::list<std::shared_ptr<ArtifactVariable>> params = {}) :
- ArtifactNamed(func_name), _params(std::move(params)),
- _retTypeName(std::move(ret_type_name)) {}
-
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
+ ArtifactFunction(std::string ret_type_name, const std::string &func_name,
+ std::list<std::shared_ptr<ArtifactVariable>> params = {})
+ : ArtifactNamed(func_name), _params(std::move(params)), _retTypeName(std::move(ret_type_name))
+ {
}
- const std::list<std::shared_ptr<ArtifactVariable>>& getParameters() const { return _params; }
- const std::string& getRetTypeName() const { return _retTypeName; }
- const ArtifactBlock* getBlock() const { return &_body; }
- ArtifactBlock* getBlock() { return &_body; }
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
+
+ const std::list<std::shared_ptr<ArtifactVariable>> &getParameters() const { return _params; }
+ const std::string &getRetTypeName() const { return _retTypeName; }
+ const ArtifactBlock *getBlock() const { return &_body; }
+ ArtifactBlock *getBlock() { return &_body; }
private:
std::list<std::shared_ptr<ArtifactVariable>> _params;
/**
* @brief Basic class for both class member variables and memmber functions.
*/
-class ArtifactClassMember {
+class ArtifactClassMember
+{
public:
- explicit ArtifactClassMember(const ArtifactClass* owner) : _owner(owner) {}
+ explicit ArtifactClassMember(const ArtifactClass *owner) : _owner(owner) {}
- const ArtifactClass* owner() const { return _owner; }
+ const ArtifactClass *owner() const { return _owner; }
protected:
- const ArtifactClass* _owner;
+ const ArtifactClass *_owner;
};
/**
* @brief A class member variables.
*/
-class ArtifactClassVariable : public ArtifactClassMember, public ArtifactVariable {
+class ArtifactClassVariable : public ArtifactClassMember, public ArtifactVariable
+{
public:
- ArtifactClassVariable(const ArtifactClass* owner, const std::string& type_name,
- const std::string& var_name,
- const std::list<std::shared_ptr<ArtifactExpr>>& dimensions = {},
- const std::list<std::shared_ptr<ArtifactExpr>>& initializers = {})
- : ArtifactClassMember(owner), ArtifactVariable(type_name, var_name, dimensions, initializers) {}
-
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
+ ArtifactClassVariable(const ArtifactClass *owner, const std::string &type_name,
+ const std::string &var_name,
+ const std::list<std::shared_ptr<ArtifactExpr>> &dimensions = {},
+ const std::list<std::shared_ptr<ArtifactExpr>> &initializers = {})
+ : ArtifactClassMember(owner), ArtifactVariable(type_name, var_name, dimensions, initializers)
+ {
}
+
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
};
/**
* @brief A class for member functions.
*/
-class ArtifactClassFunction : public ArtifactClassMember, public ArtifactFunction {
+class ArtifactClassFunction : public ArtifactClassMember, public ArtifactFunction
+{
public:
- ArtifactClassFunction(const ArtifactClass* owner, const std::string& ret_type_name,
- const std::string& func_name,
- const std::list<std::shared_ptr<ArtifactVariable>>& params = {})
- : ArtifactClassMember(owner), ArtifactFunction(ret_type_name, func_name, params) {}
-
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
+ ArtifactClassFunction(const ArtifactClass *owner, const std::string &ret_type_name,
+ const std::string &func_name,
+ const std::list<std::shared_ptr<ArtifactVariable>> ¶ms = {})
+ : ArtifactClassMember(owner), ArtifactFunction(ret_type_name, func_name, params)
+ {
}
+
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
};
/**
* @brief Represents a class.
*/
-class ArtifactClass : public ArtifactNamed {
+class ArtifactClass : public ArtifactNamed
+{
public:
- explicit ArtifactClass(const std::string& class_name) : ArtifactNamed(class_name) {}
+ explicit ArtifactClass(const std::string &class_name) : ArtifactNamed(class_name) {}
- void accept(IArtifactGenerator* g) const override {
- g->visit(this);
- }
+ void accept(IArtifactGenerator *g) const override { g->visit(this); }
/**
* @brief Creates a class member variable.
* @param constructors
* @return
*/
- std::shared_ptr<ArtifactClassVariable> var(
- bool is_public, const std::string& type_name,
- const std::string& var_name,
- const std::list<std::shared_ptr<ArtifactExpr>>& dimensions = {},
- const std::list<std::shared_ptr<ArtifactExpr>>& initializers = {}) {
- if (is_public) {
+ std::shared_ptr<ArtifactClassVariable>
+ var(bool is_public, const std::string &type_name, const std::string &var_name,
+ const std::list<std::shared_ptr<ArtifactExpr>> &dimensions = {},
+ const std::list<std::shared_ptr<ArtifactExpr>> &initializers = {})
+ {
+ if (is_public)
+ {
auto var = std::make_shared<ArtifactClassVariable>(this, type_name, var_name, dimensions,
initializers);
_publicVariables.push_back(var);
return var;
- } else {
+ }
+ else
+ {
auto var = std::make_shared<ArtifactClassVariable>(this, type_name, var_name, dimensions,
initializers);
_privateVariables.push_back(var);
* @param params
* @return
*/
- std::shared_ptr<ArtifactClassFunction> func(
- bool is_public,
- const std::string& ret_type_name, const std::string& func_name,
- const std::list<std::shared_ptr<ArtifactVariable>>& params = {}) {
- if (is_public) {
+ std::shared_ptr<ArtifactClassFunction>
+ func(bool is_public, const std::string &ret_type_name, const std::string &func_name,
+ const std::list<std::shared_ptr<ArtifactVariable>> ¶ms = {})
+ {
+ if (is_public)
+ {
auto func = std::make_shared<ArtifactClassFunction>(this, ret_type_name, func_name, params);
_publicFunctions.push_back(func);
return func;
- } else {
+ }
+ else
+ {
auto func = std::make_shared<ArtifactClassFunction>(this, ret_type_name, func_name, params);
_privateFunctions.push_back(func);
return func;
}
}
- const std::list<std::shared_ptr<ArtifactClassVariable>>& publicVariables() const {
+ const std::list<std::shared_ptr<ArtifactClassVariable>> &publicVariables() const
+ {
return _publicVariables;
}
- const std::list<std::shared_ptr<ArtifactClassVariable>>& privateVariables() const {
+ const std::list<std::shared_ptr<ArtifactClassVariable>> &privateVariables() const
+ {
return _privateVariables;
}
- const std::list<std::shared_ptr<ArtifactClassFunction>>& publicFunctions() const {
+ const std::list<std::shared_ptr<ArtifactClassFunction>> &publicFunctions() const
+ {
return _publicFunctions;
}
- const std::list<std::shared_ptr<ArtifactClassFunction>>& privateFunctions() const {
+ const std::list<std::shared_ptr<ArtifactClassFunction>> &privateFunctions() const
+ {
return _privateFunctions;
}
- ArtifactBlock* getConstrBlock() {
- return &_constrBlock;
- }
+ ArtifactBlock *getConstrBlock() { return &_constrBlock; }
- const ArtifactBlock* getConstrBlock() const {
- return &_constrBlock;
- }
+ const ArtifactBlock *getConstrBlock() const { return &_constrBlock; }
private:
- std::list<std::shared_ptr<ArtifactClassVariable>> _publicVariables;
- std::list<std::shared_ptr<ArtifactClassVariable>> _privateVariables;
- std::list<std::shared_ptr<ArtifactClassFunction>> _publicFunctions;
- std::list<std::shared_ptr<ArtifactClassFunction>> _privateFunctions;
- ArtifactBlock _constrBlock;
+ std::list<std::shared_ptr<ArtifactClassVariable>> _publicVariables;
+ std::list<std::shared_ptr<ArtifactClassVariable>> _privateVariables;
+ std::list<std::shared_ptr<ArtifactClassFunction>> _publicFunctions;
+ std::list<std::shared_ptr<ArtifactClassFunction>> _privateFunctions;
+ ArtifactBlock _constrBlock;
};
/**
* @brief Class representing a module in the ACL C++ soft backend.
*/
-class ArtifactModule {
+class ArtifactModule
+{
public:
explicit ArtifactModule(std::string name) : _name(std::move(name)) {}
- void accept(IArtifactGenerator* g) const {
- g->visit(this);
- }
+ void accept(IArtifactGenerator *g) const { g->visit(this); }
- std::shared_ptr<ArtifactClass> createClass(const std::string& name) {
+ std::shared_ptr<ArtifactClass> createClass(const std::string &name)
+ {
auto a_class = std::make_shared<ArtifactClass>(name);
_entities.emplace_back(a_class);
return a_class;
}
- void addHeaderInclude(const std::string& name) { _headerIncludes.push_back(name); }
- void addSourceInclude(const std::string& name) { _sourceIncludes.push_back(name); }
- void addHeaderSysInclude(const std::string& name) { _headerSysIncludes.push_back(name); }
- void addSourceSysInclude(const std::string& name) { _sourceSysIncludes.push_back(name); }
+ void addHeaderInclude(const std::string &name) { _headerIncludes.push_back(name); }
+ void addSourceInclude(const std::string &name) { _sourceIncludes.push_back(name); }
+ void addHeaderSysInclude(const std::string &name) { _headerSysIncludes.push_back(name); }
+ void addSourceSysInclude(const std::string &name) { _sourceSysIncludes.push_back(name); }
- const std::string& name() const { return _name; }
+ const std::string &name() const { return _name; }
const std::list<std::shared_ptr<ArtifactEntity>> entities() const { return _entities; }
- const std::list<std::string>& headerIncludes() const { return _headerIncludes; }
- const std::list<std::string>& sourceIncludes() const { return _sourceIncludes; }
- const std::list<std::string>& headerSysIncludes() const { return _headerSysIncludes; }
- const std::list<std::string>& sourceSysIncludes() const { return _sourceSysIncludes; }
+ const std::list<std::string> &headerIncludes() const { return _headerIncludes; }
+ const std::list<std::string> &sourceIncludes() const { return _sourceIncludes; }
+ const std::list<std::string> &headerSysIncludes() const { return _headerSysIncludes; }
+ const std::list<std::string> &sourceSysIncludes() const { return _sourceSysIncludes; }
private:
std::string _name;
/**
* @brief Factory for some kinds of frequently used artifact DOM objects.
*/
-class ArtifactFactory {
+class ArtifactFactory
+{
public:
- static std::shared_ptr<ArtifactId> id(const std::string& name) {
+ static std::shared_ptr<ArtifactId> id(const std::string &name)
+ {
return std::make_shared<ArtifactId>(name);
}
- static std::shared_ptr<ArtifactLiteral> lit(const std::string& name) {
+ static std::shared_ptr<ArtifactLiteral> lit(const std::string &name)
+ {
return std::make_shared<ArtifactLiteral>(name);
}
* @param constructors - optional arguments of the object constructor, if instantiating a class.
* @return - the newly created variable.
*/
- static std::shared_ptr<ArtifactVariable> var(
- const std::string& type_name,
- const std::string& var_name, const std::list<std::shared_ptr<ArtifactExpr>>& dimensions = {},
- const std::list<std::shared_ptr<ArtifactExpr>>& initializers = {}) {
+ static std::shared_ptr<ArtifactVariable>
+ var(const std::string &type_name, const std::string &var_name,
+ const std::list<std::shared_ptr<ArtifactExpr>> &dimensions = {},
+ const std::list<std::shared_ptr<ArtifactExpr>> &initializers = {})
+ {
return std::make_shared<ArtifactVariable>(type_name, var_name, dimensions, initializers);
}
* @param ref
* @return
*/
- static std::shared_ptr<ArtifactRef> ref(std::shared_ptr<ArtifactExpr> ref) {
+ static std::shared_ptr<ArtifactRef> ref(std::shared_ptr<ArtifactExpr> ref)
+ {
return std::make_shared<ArtifactRef>(ref);
}
* @param ref
* @return
*/
- static std::shared_ptr<ArtifactDeref> deref(std::shared_ptr<ArtifactExpr> ref) {
+ static std::shared_ptr<ArtifactDeref> deref(std::shared_ptr<ArtifactExpr> ref)
+ {
return std::make_shared<ArtifactDeref>(ref);
}
* @param call_type - (for member functions only) call through: '.', '->', or '::'.
* @return
*/
- static std::shared_ptr<ArtifactFunctionCall> call(
- const std::string& func_name,
- const std::list<std::shared_ptr<ArtifactExpr>>& param_list,
- std::shared_ptr<ArtifactExpr> on = nullptr,
- ArtifactCallType call_type = ArtifactCallType::obj) {
- return std::make_shared<ArtifactFunctionCall>(func_name, param_list, on, call_type);
+ static std::shared_ptr<ArtifactFunctionCall>
+ call(const std::string &func_name, const std::list<std::shared_ptr<ArtifactExpr>> ¶m_list,
+ std::shared_ptr<ArtifactExpr> on = nullptr,
+ ArtifactCallType call_type = ArtifactCallType::obj)
+ {
+ return std::make_shared<ArtifactFunctionCall>(func_name, param_list, on, call_type);
}
/**
* @param expr
* @return
*/
- static std::shared_ptr<ArtifactUnaryExpr> un(ArtifactUnOp op,
- std::shared_ptr<ArtifactExpr> expr) {
+ static std::shared_ptr<ArtifactUnaryExpr> un(ArtifactUnOp op, std::shared_ptr<ArtifactExpr> expr)
+ {
return std::make_shared<ArtifactUnaryExpr>(op, expr);
}
* @param right
* @return
*/
- static std::shared_ptr<ArtifactBinaryExpr> bin(
- ArtifactBinOp op,
- std::shared_ptr<ArtifactExpr> left, std::shared_ptr<ArtifactExpr> right) {
+ static std::shared_ptr<ArtifactBinaryExpr>
+ bin(ArtifactBinOp op, std::shared_ptr<ArtifactExpr> left, std::shared_ptr<ArtifactExpr> right)
+ {
return std::make_shared<ArtifactBinaryExpr>(op, left, right);
}
* @return
*/
static std::shared_ptr<ArtifactIndex> ind(std::shared_ptr<ArtifactExpr> expr,
- std::shared_ptr<ArtifactExpr> ind) {
+ std::shared_ptr<ArtifactExpr> ind)
+ {
return std::make_shared<ArtifactIndex>(expr, ind);
}
* @param expr
* @return
*/
- static std::shared_ptr<ArtifactUnaryExpr> heapNew(std::shared_ptr<ArtifactExpr> expr) {
+ static std::shared_ptr<ArtifactUnaryExpr> heapNew(std::shared_ptr<ArtifactExpr> expr)
+ {
return std::make_shared<ArtifactUnaryExpr>(ArtifactUnOp::heapNew, expr);
}
* @param expr
* @return
*/
- static std::shared_ptr<ArtifactUnaryExpr> heapFree(std::shared_ptr<ArtifactExpr> expr) {
+ static std::shared_ptr<ArtifactUnaryExpr> heapFree(std::shared_ptr<ArtifactExpr> expr)
+ {
return std::make_shared<ArtifactUnaryExpr>(ArtifactUnOp::heapFree, expr);
}
};
/**
* @brief The interface of the artifact source code producer.
*/
-class IArtifactGenerator {
+class IArtifactGenerator
+{
public:
virtual ~IArtifactGenerator() = default;
- virtual void visit(const ArtifactLiteral* node) = 0;
- virtual void visit(const ArtifactId* node) = 0;
- virtual void visit(const ArtifactRef* node) = 0;
- virtual void visit(const ArtifactDeref* node) = 0;
- virtual void visit(const ArtifactVariable* node) = 0;
- virtual void visit(const ArtifactFunctionCall* node) = 0;
- virtual void visit(const ArtifactUnaryExpr* node) = 0;
- virtual void visit(const ArtifactBinaryExpr* node) = 0;
- virtual void visit(const ArtifactIndex* node) = 0;
- virtual void visit(const ArtifactRet* node) = 0;
- virtual void visit(const ArtifactBreak* node) = 0;
- virtual void visit(const ArtifactCont* node) = 0;
- virtual void visit(const ArtifactBlock* node) = 0;
- virtual void visit(const ArtifactForLoop* node) = 0;
- virtual void visit(const ArtifactIf* node) = 0;
- virtual void visit(const ArtifactFunction* node) = 0;
- virtual void visit(const ArtifactClass* node) = 0;
- virtual void visit(const ArtifactClassVariable* node) = 0;
- virtual void visit(const ArtifactClassFunction* node) = 0;
- virtual void visit(const ArtifactModule* node) = 0;
+ virtual void visit(const ArtifactLiteral *node) = 0;
+ virtual void visit(const ArtifactId *node) = 0;
+ virtual void visit(const ArtifactRef *node) = 0;
+ virtual void visit(const ArtifactDeref *node) = 0;
+ virtual void visit(const ArtifactVariable *node) = 0;
+ virtual void visit(const ArtifactFunctionCall *node) = 0;
+ virtual void visit(const ArtifactUnaryExpr *node) = 0;
+ virtual void visit(const ArtifactBinaryExpr *node) = 0;
+ virtual void visit(const ArtifactIndex *node) = 0;
+ virtual void visit(const ArtifactRet *node) = 0;
+ virtual void visit(const ArtifactBreak *node) = 0;
+ virtual void visit(const ArtifactCont *node) = 0;
+ virtual void visit(const ArtifactBlock *node) = 0;
+ virtual void visit(const ArtifactForLoop *node) = 0;
+ virtual void visit(const ArtifactIf *node) = 0;
+ virtual void visit(const ArtifactFunction *node) = 0;
+ virtual void visit(const ArtifactClass *node) = 0;
+ virtual void visit(const ArtifactClassVariable *node) = 0;
+ virtual void visit(const ArtifactClassFunction *node) = 0;
+ virtual void visit(const ArtifactModule *node) = 0;
};
} // namespace nnc
#include "passes/common_frontend/NNImporter.h"
#ifdef NNC_FRONTEND_TFLITE_ENABLED
-# include "tflite_importer_pass.h"
+#include "tflite_importer_pass.h"
#endif // NNC_FRONTEND_TFLITE_ENABLED
#ifdef NNC_FRONTEND_CAFFE_ENABLED
-# include "caffe_importer_pass.h"
+#include "caffe_importer_pass.h"
#endif // NNC_FRONTEND_CAFFE_ENABLED
#ifdef NNC_FRONTEND_CAFFE2_ENABLED
-# include "caffe2_importer_pass.h"
+#include "caffe2_importer_pass.h"
#endif // NNC_FRONTEND_CAFFE2_ENABLED
#ifdef NNC_FRONTEND_ONNX_ENABLED
-# include "ONNXImporterPass.h"
+#include "ONNXImporterPass.h"
#endif // NNC_FRONTEND_ONNX_ENABLED
-namespace nnc {
+namespace nnc
+{
-std::unique_ptr<NNImporter> NNImporter::createNNImporter() {
+std::unique_ptr<NNImporter> NNImporter::createNNImporter()
+{
std::unique_ptr<NNImporter> importer(nullptr);
- if (cli::caffeFrontend) {
+ if (cli::caffeFrontend)
+ {
#ifdef NNC_FRONTEND_CAFFE_ENABLED
importer.reset(new CaffeImporterPass(cli::inputFile.getRawValue()));
#endif // NNC_FRONTEND_CAFFE_ENABLED
- } else if (cli::caffe2Frontend) {
+ }
+ else if (cli::caffe2Frontend)
+ {
#ifdef NNC_FRONTEND_CAFFE2_ENABLED
// FIXME: caffe2 input shapes are not provided by model and must be set from cli
// current 'inputShapes' could provide only one shape, while model could has several inputs
importer.reset(new Caffe2ImporterPass(cli::inputFile.getRawValue(), cli::initNet.getRawValue(),
- {cli::inputShapes.getRawValue()}));
+ {cli::inputShapes.getRawValue()}));
#endif // NNC_FRONTEND_CAFFE2_ENABLED
- } else if (cli::onnxFrontend) {
+ }
+ else if (cli::onnxFrontend)
+ {
#ifdef NNC_FRONTEND_ONNX_ENABLED
importer.reset(new ONNXImporterPass(cli::inputFile.getRawValue()));
#endif // NNC_FRONTEND_ONNX_ENABLED
- } else if (cli::tflFrontend) {
+ }
+ else if (cli::tflFrontend)
+ {
#ifdef NNC_FRONTEND_TFLITE_ENABLED
importer.reset(new TfliteImporterPass(cli::inputFile.getRawValue()));
#endif // NNC_FRONTEND_TFLITE_ENABLED
#include <fstream>
-
-namespace nnc {
+namespace nnc
+{
using namespace mir;
int DumperPass::_counter = 0;
-PassData DumperPass::run(PassData data) {
- auto g = static_cast<Graph*>(data);
+PassData DumperPass::run(PassData data)
+{
+ auto g = static_cast<Graph *>(data);
assert(g);
IrDotDumper dotDumper;
g->accept(&dotDumper);
std::ofstream f_out;
- f_out.open(std::to_string(_counter)+ "_"+ _file_name + ".dot");
+ f_out.open(std::to_string(_counter) + "_" + _file_name + ".dot");
dotDumper.writeDot(f_out);
f_out.close();
#include <iostream>
#include <vector>
-namespace nnc {
+namespace nnc
+{
using namespace mir;
std::vector<std::reference_wrapper<const TensorVariant>>
-NNInterpreter::getInputTensors(const Operation& op) {
+NNInterpreter::getInputTensors(const Operation &op)
+{
std::vector<std::reference_wrapper<const TensorVariant>> tensors;
- for (const auto& input : op.getInputs()) {
- const auto* producer = input.getProducer();
+ for (const auto &input : op.getInputs())
+ {
+ const auto *producer = input.getProducer();
tensors.emplace_back(_opResults.at(producer->getNode()).at(producer->getIndex()));
}
return tensors;
}
-void NNInterpreter::setOutputTensors(const Operation& op, std::vector<TensorVariant>&& outputs) {
+void NNInterpreter::setOutputTensors(const Operation &op, std::vector<TensorVariant> &&outputs)
+{
_opResults.emplace(&op, std::move(outputs));
}
-void NNInterpreter::setInput(const std::string &name, const TensorVariant& data) {
+void NNInterpreter::setInput(const std::string &name, const TensorVariant &data)
+{
_inputTensors.emplace(name, data);
}
-TensorVariant NNInterpreter::getResult(const Operation::Output* tensor) {
+TensorVariant NNInterpreter::getResult(const Operation::Output *tensor)
+{
return _opResults.at(tensor->getNode()).at(tensor->getIndex());
}
-void NNInterpreter::visit(ops::InputOp& op) {
+void NNInterpreter::visit(ops::InputOp &op)
+{
auto it = _inputTensors.find(op.getName());
if (it == _inputTensors.end())
throw std::runtime_error("Can't find data for node \"" + op.getName() +
setOutputTensors(op, {it->second});
}
-void NNInterpreter::visit(ops::ConstantOp& op) {
+void NNInterpreter::visit(ops::ConstantOp &op)
+{
assert(_inputTensors.find(op.getName()) == _inputTensors.end());
setOutputTensors(op, {op.getValue()});
}
-void NNInterpreter::visit(ops::ConcatOp& op) {
+void NNInterpreter::visit(ops::ConcatOp &op)
+{
auto inputs = getInputTensors(op);
auto outputs = Concat<float>(inputs, op.getOutputShape(0), op.getAxis())();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::Conv2DOp& op) {
+void NNInterpreter::visit(ops::Conv2DOp &op)
+{
auto inputs = getInputTensors(op);
auto outputs = Conv2D(inputs[0], inputs[1], op)();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::ReshapeOp& op) {
+void NNInterpreter::visit(ops::ReshapeOp &op)
+{
auto inputs = getInputTensors(op);
auto outputs = Reshape<float>(inputs[0], op.getOutputShape(0))();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::ReluOp& op) {
+void NNInterpreter::visit(ops::ReluOp &op)
+{
auto inputs = getInputTensors(op);
Tensor<float> input(inputs[0]);
auto outputs = Fill<float>(op.getOutputShape(0),
- [&input](const Index& id) { return std::max(input.at(id), 0.0f); })();
+ [&input](const Index &id) { return std::max(input.at(id), 0.0f); })();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::SigmoidOp& op) {
+void NNInterpreter::visit(ops::SigmoidOp &op)
+{
auto inputs = getInputTensors(op);
Tensor<float> input(inputs[0]);
- auto outputs = Fill<float>(op.getOutputShape(0), [&input](const Index& id) {
+ auto outputs = Fill<float>(op.getOutputShape(0), [&input](const Index &id) {
return 1.f / (1.f + std::exp(-input.at(id)));
})();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::SoftmaxOp& op) {
+void NNInterpreter::visit(ops::SoftmaxOp &op)
+{
auto inputs = getInputTensors(op);
auto outputs = Softmax<float>(inputs[0], op.getAxis())();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::PoolOp& op) {
+void NNInterpreter::visit(ops::PoolOp &op)
+{
auto inputs = getInputTensors(op);
auto outputs = Pool(inputs[0], op)();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::FullyConnectedOp& op) {
+void NNInterpreter::visit(ops::FullyConnectedOp &op)
+{
auto inputs = getInputTensors(op);
auto outputs = FullyConnected(inputs[0], inputs[1], op)();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::GemmOp& op) {
+void NNInterpreter::visit(ops::GemmOp &op)
+{
auto inputs = getInputTensors(op);
auto outputs = Gemm<float>(inputs[0], inputs[1], inputs[2], op)();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::CappedReluOp& op) {
+void NNInterpreter::visit(ops::CappedReluOp &op)
+{
auto inputs = getInputTensors(op);
Tensor<float> input(inputs[0]);
- auto outputs = Fill<float>(op.getOutputShape(0), [&input, &op](const Index& id) {
+ auto outputs = Fill<float>(op.getOutputShape(0), [&input, &op](const Index &id) {
return std::min(std::max(input.at(id), 0.0f), op.getCap());
})();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::DepthwiseConv2DOp& op) {
+void NNInterpreter::visit(ops::DepthwiseConv2DOp &op)
+{
auto inputs = getInputTensors(op);
auto outputs = DepthwiseConv2D(inputs[0], inputs[1], op)();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::BatchNormOp& op) {
+void NNInterpreter::visit(ops::BatchNormOp &op)
+{
auto inputs = getInputTensors(op);
auto outputs = BatchNorm<float>(inputs[0], op)();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::SliceOp& op) {
+void NNInterpreter::visit(ops::SliceOp &op)
+{
auto inputs = getInputTensors(op);
auto input = Tensor<float>(inputs[0]);
- auto outputs = Fill<float>(op.getOutputShape(0), [&input, &op](const Index& id) {
+ auto outputs = Fill<float>(op.getOutputShape(0), [&input, &op](const Index &id) {
Index idx = nnc::shift(id, op.getStarts());
return input.at(idx);
})();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::DropoutOp& op) {
+void NNInterpreter::visit(ops::DropoutOp &op)
+{
auto inputs = getInputTensors(op);
TensorVariant input(inputs[0]);
// TODO implement this
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::TanhOp& op) {
+void NNInterpreter::visit(ops::TanhOp &op)
+{
auto inputs = getInputTensors(op);
Tensor<float> input(inputs[0]);
- auto outputs = Fill<float>(op.getOutputShape(0), [&input](const Index& id) {
- return std::tanh(input.at(id));
- })();
+ auto outputs = Fill<float>(op.getOutputShape(0),
+ [&input](const Index &id) { return std::tanh(input.at(id)); })();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::DeConv2DOp& op) {
+void NNInterpreter::visit(ops::DeConv2DOp &op)
+{
auto inputs = getInputTensors(op);
auto outputs = DeConv2D(inputs[0], inputs[1], op)();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::EluOp& op) {
+void NNInterpreter::visit(ops::EluOp &op)
+{
auto inputs = getInputTensors(op);
Tensor<float> input(inputs[0]);
- auto outputs = Fill<float>(op.getOutputShape(0), [&input, &op](const Index& id) {
+ auto outputs = Fill<float>(op.getOutputShape(0), [&input, &op](const Index &id) {
if (input.at(id) >= 0)
return input.at(id);
else
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::SqueezeOp& op) {
+void NNInterpreter::visit(ops::SqueezeOp &op)
+{
auto inputs = getInputTensors(op);
// Squeeze is just a special case of reshape.
auto outputs = Reshape<float>(inputs[0], op.getOutputShape(0))();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::PadOp& op) {
+void NNInterpreter::visit(ops::PadOp &op)
+{
auto inputs = getInputTensors(op);
auto outputs = Pad(inputs[0], op)();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::SqrtOp& op) {
+void NNInterpreter::visit(ops::SqrtOp &op)
+{
auto inputs = getInputTensors(op);
Tensor<float> input(inputs[0]);
- auto outputs = Fill<float>(op.getOutputShape(0), [&input](const Index id) {
- return sqrt(input.at(id));
- })();
+ auto outputs =
+ Fill<float>(op.getOutputShape(0), [&input](const Index id) { return sqrt(input.at(id)); })();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::ResizeOp& op) {
+void NNInterpreter::visit(ops::ResizeOp &op)
+{
auto inputs = getInputTensors(op);
Tensor<float> input(inputs[0]);
assert(op.getMode() == ops::ResizeOp::ResizeMethod::nearestNeighbor);
auto scales = op.getScales();
- auto outputs = Fill<float>(op.getOutputShape(0), [&scales, &input](const Index& id) {
+ auto outputs = Fill<float>(op.getOutputShape(0), [&scales, &input](const Index &id) {
Index in_idx;
in_idx.resize(4);
- for (int i = 0; i < input.getShape().rank(); i++) {
- in_idx.at(i) = static_cast<int> (floorf(id.at(i) / scales[i]));
+ for (int i = 0; i < input.getShape().rank(); i++)
+ {
+ in_idx.at(i) = static_cast<int>(floorf(id.at(i) / scales[i]));
}
return input.at(in_idx);
})();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::ReduceOp& op) {
+void NNInterpreter::visit(ops::ReduceOp &op)
+{
auto inputs = getInputTensors(op);
auto outputs = Reduce<float>(inputs[0], op)();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::TransposeOp& op) {
+void NNInterpreter::visit(ops::TransposeOp &op)
+{
auto inputs = getInputTensors(op);
auto outputs = Transpose(inputs[0], op)();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::GatherOp& op) {
+void NNInterpreter::visit(ops::GatherOp &op)
+{
auto inputs = getInputTensors(op);
auto outputs = Gather(inputs[0], inputs[1], op)();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::LeakyReluOp& op) {
+void NNInterpreter::visit(ops::LeakyReluOp &op)
+{
auto inputs = getInputTensors(op);
float alpha = op.getAlpha();
Tensor<float> input(inputs[0]);
- auto outputs = Fill<float>(op.getOutputShape(0), [&input, alpha](const Index& id) {
+ auto outputs = Fill<float>(op.getOutputShape(0), [&input, alpha](const Index &id) {
float val = input.at(id);
return val > 0.0f ? val : val * alpha;
})();
setOutputTensors(op, std::move(outputs));
}
-void NNInterpreter::visit(ops::OutputOp& /*op*/) {
+void NNInterpreter::visit(ops::OutputOp & /*op*/)
+{
// No-op.
}
#ifdef NNC_HDF5_SUPPORTED
#include <H5Cpp.h>
-#endif // NNC_HDF5_SUPPORTED
+#endif // NNC_HDF5_SUPPORTED
#include "mir/Shape.h"
#include "mir/ShapeRange.h"
#include "mir/Tensor.h"
-
-namespace nnc {
+namespace nnc
+{
using namespace mir;
* @param tensor_name - name, by wich tensor will be saved
* @param destination - path to file, in which tensor will be saved
*/
-static void writeTensorToHDF5File(const TensorVariant& tensor,
- std::string tensor_name,
- const std::string& destination) {
+static void writeTensorToHDF5File(const TensorVariant &tensor, std::string tensor_name,
+ const std::string &destination)
+{
// Prepare shape, rank, dims, numElems
- auto& shape = tensor.getShape();
+ auto &shape = tensor.getShape();
const int32_t rank = shape.rank();
hsize_t dims[rank];
- for (int32_t axis = 0; axis < rank; ++axis) {
+ for (int32_t axis = 0; axis < rank; ++axis)
+ {
dims[axis] = static_cast<hsize_t>(shape.dim(axis));
}
ShapeRange out_range(shape);
Tensor<float> tensor_accessor(tensor);
- for (auto& out_idx : out_range)
+ for (auto &out_idx : out_range)
values.push_back(tensor_accessor.at(out_idx));
// Backslashes are not allowed in tensor names
dataset.write(values.data(), H5::PredType::NATIVE_FLOAT);
}
-#endif // NNC_HDF5_SUPPORTED
+#endif // NNC_HDF5_SUPPORTED
-static TensorVariant readTensorFromFile(const std::string& filename, DataType data_type,
- const Shape& shape) {
+static TensorVariant readTensorFromFile(const std::string &filename, DataType data_type,
+ const Shape &shape)
+{
assert(data_type == DataType::FLOAT32);
std::size_t input_data_size = shape.numElements() * sizeof(float);
if (static_cast<std::size_t>(file_size) != input_data_size)
throw PassException("File \"" + filename + "\" has incorrect size: " +
- std::to_string(file_size) +
- "(expected: " + std::to_string(input_data_size) + ").");
+ std::to_string(file_size) + "(expected: " +
+ std::to_string(input_data_size) + ").");
std::unique_ptr<char[]> data(new char[input_data_size]);
stream.read(data.get(), input_data_size);
return TensorVariant(data_type, shape, data.get());
}
-PassData InterpreterPass::run(PassData data) {
- auto g = static_cast<Graph*>(data);
+PassData InterpreterPass::run(PassData data)
+{
+ auto g = static_cast<Graph *>(data);
assert(g);
NNInterpreter interpreter;
- for (const auto* input_op : g->getInputs()) {
+ for (const auto *input_op : g->getInputs())
+ {
std::string tensor_name = input_op->getName();
std::replace(tensor_name.begin(), tensor_name.end(), '/', '_');
std::string filename = cli::interInputDataDir + "/" + tensor_name + ".dat";
g->accept(&interpreter);
- for (const auto* output_op : g->getOutputs()) {
- const auto& tensor = interpreter.getResult(output_op->getInput(0)->getProducer());
+ for (const auto *output_op : g->getOutputs())
+ {
+ const auto &tensor = interpreter.getResult(output_op->getInput(0)->getProducer());
#ifdef NNC_HDF5_SUPPORTED
writeTensorToHDF5File(tensor, output_op->getName(), cli::artifactDir);
#else
- std::cout << "Result <" << output_op->getName()
- << "> wasn't saved, due to lack of HDF5" << std::endl;
-#endif // NNC_HDF5_SUPPORTED
+ std::cout << "Result <" << output_op->getName() << "> wasn't saved, due to lack of HDF5"
+ << std::endl;
+#endif // NNC_HDF5_SUPPORTED
}
return nullptr;
* @note Simply copies input to output
* @tparam T type of data in input tensor
*/
-template<typename T>
-class BatchNorm : public OperationImpl<T>
+template <typename T> class BatchNorm : public OperationImpl<T>
{
public:
/**
* @param in input data
* @param op batch normalization operation description
*/
- explicit BatchNorm(const mir::TensorVariant& input, const mir::ops::BatchNormOp& op) : _input(input), _op(op) {}
+ explicit BatchNorm(const mir::TensorVariant &input, const mir::ops::BatchNormOp &op)
+ : _input(input), _op(op)
+ {
+ }
/**
* @brief computes operation aplication result
*/
std::vector<mir::TensorVariant> operator()() override
{
- //For now BatchNorm just copies input to output
- return Fill<T>(_input.getShape(), [this](const mir::Index& idx) {
- return _input.at(idx);
- })();
+ // For now BatchNorm just copies input to output
+ return Fill<T>(_input.getShape(), [this](const mir::Index &idx) { return _input.at(idx); })();
}
private:
const mir::Tensor<float> _input;
- const mir::ops::BatchNormOp& _op;
+ const mir::ops::BatchNormOp &_op;
};
} // namespace nnc
#include "Fill.h"
-namespace nnc {
+namespace nnc
+{
-template <typename T>
-class Concat : public Fill<T> {
+template <typename T> class Concat : public Fill<T>
+{
public:
- Concat(const std::vector<std::reference_wrapper<const mir::TensorVariant>>& inputs,
- const mir::Shape& outputShape,
- int32_t axis)
- : Fill<T>(outputShape, getSingleFunction(inputs, axis)) {}
+ Concat(const std::vector<std::reference_wrapper<const mir::TensorVariant>> &inputs,
+ const mir::Shape &outputShape, int32_t axis)
+ : Fill<T>(outputShape, getSingleFunction(inputs, axis))
+ {
+ }
private:
- const std::function<T(const mir::Index&)>
- getSingleFunction(const std::vector<std::reference_wrapper<const mir::TensorVariant>>& inputs,
- int32_t axis) {
+ const std::function<T(const mir::Index &)>
+ getSingleFunction(const std::vector<std::reference_wrapper<const mir::TensorVariant>> &inputs,
+ int32_t axis)
+ {
std::vector<mir::Tensor<T>> inputAccessors;
inputAccessors.reserve(inputs.size());
- for (auto& in : inputs)
+ for (auto &in : inputs)
inputAccessors.emplace_back(in);
- return std::function<T(const mir::Index&)>([inputAccessors, axis](const mir::Index& id) -> T {
+ return std::function<T(const mir::Index &)>([inputAccessors, axis](const mir::Index &id) -> T {
unsigned int mi = 0;
int32_t along_axis = id.at(axis);
- while (along_axis >= inputAccessors.at(mi).getShape().dim(axis)) {
+ while (along_axis >= inputAccessors.at(mi).getShape().dim(axis))
+ {
along_axis -= inputAccessors[mi].getShape().dim(axis);
mi++;
}
#include "mir/ShapeRange.h"
#include "mir/TensorUtil.h"
-namespace nnc {
+namespace nnc
+{
using namespace mir;
// Assuming input is in NHWC format with batch omitted( [in_height, in_width, in_channels] )
// Kernel is in [filter_height, filter_width, in_channels, out_channels]
// Refer to https://www.tensorflow.org/api_docs/python/tf/nn/conv2d for info
-std::vector<TensorVariant> Conv2D::operator()() {
- const Shape& in_shape = _input.getShape();
- const Shape& kernel_shape = _kernel.getShape();
- const Shape& out_shape = _op.getOutputShape(0);
- const Shape& strides = _op.getStrides();
- const std::vector<int32_t>& pads = _op.getPaddingBefore();
+std::vector<TensorVariant> Conv2D::operator()()
+{
+ const Shape &in_shape = _input.getShape();
+ const Shape &kernel_shape = _kernel.getShape();
+ const Shape &out_shape = _op.getOutputShape(0);
+ const Shape &strides = _op.getStrides();
+ const std::vector<int32_t> &pads = _op.getPaddingBefore();
assert(in_shape.rank() == 4);
assert(kernel_shape.rank() == 4);
Index in_index;
in_index.resize(4);
- for (const auto& out_index : out_range) {
+ for (const auto &out_index : out_range)
+ {
auto out_region = res_accessor.getRegion(out_index);
assert(out_region.size() == num_kernels);
- for (const auto& kernel_index : kernel_range) {
+ for (const auto &kernel_index : kernel_range)
+ {
in_index.at(0) = out_index.at(0);
for (int i = 0; i < 2; ++i)
in_index.at(1 + i) = out_index.at(1 + i) * strides.dim(i) + kernel_index.at(i) - pads[i];
in_index.at(3) = kernel_index.at(2);
- if (in_range.contains(in_index)) {
+ if (in_range.contains(in_index))
+ {
auto kernel_region = kernel.getRegion(kernel_index);
assert(kernel_region.size() == num_kernels);
float in_val = _input.at(in_index);
- for (int32_t kernel_i = 0; kernel_i < num_kernels; ++kernel_i) {
+ for (int32_t kernel_i = 0; kernel_i < num_kernels; ++kernel_i)
+ {
out_region.base()[kernel_i] += in_val * kernel_region.base()[kernel_i];
}
}
return {res};
}
-Conv2D::Conv2D(const TensorVariant& input,
- const TensorVariant& kernel,
- const ops::Conv2DOp& op)
- : _input(input), _kernel(transposeTensor<1, 2, 3, 0>(kernel)), _op(op) {
+Conv2D::Conv2D(const TensorVariant &input, const TensorVariant &kernel, const ops::Conv2DOp &op)
+ : _input(input), _kernel(transposeTensor<1, 2, 3, 0>(kernel)), _op(op)
+{
}
} // namespace nnc
#include "mir/ops/Conv2DOp.h"
#include "mir/Tensor.h"
-namespace nnc {
+namespace nnc
+{
-class Conv2D : public OperationImpl<float> {
+class Conv2D : public OperationImpl<float>
+{
public:
- Conv2D(const mir::TensorVariant& input,
- const mir::TensorVariant& kernel,
- const mir::ops::Conv2DOp& op);
+ Conv2D(const mir::TensorVariant &input, const mir::TensorVariant &kernel,
+ const mir::ops::Conv2DOp &op);
std::vector<mir::TensorVariant> operator()() override;
private:
const mir::Tensor<float> _input;
mir::TensorVariant _kernel;
- const mir::ops::Conv2DOp& _op;
+ const mir::ops::Conv2DOp &_op;
};
} // namespace nnc
#endif //_NNC_CORE_BACKEND_INTERPRETER_CONV2D_IMPL
-
#include "common.h"
#include <iostream>
-namespace nnc {
+namespace nnc
+{
using namespace mir;
using namespace mir::ops;
-std::vector<mir::TensorVariant> nnc::DeConv2D::operator()() {
- const auto& strides = _op.getStrides();
+std::vector<mir::TensorVariant> nnc::DeConv2D::operator()()
+{
+ const auto &strides = _op.getStrides();
Shape out_shape = _op.getOutputShape(0);
auto res = allocate_tensor(out_shape);
Tensor<float> res_accesor(res);
Shape in_shape = _input.getShape();
ShapeRange in_range(in_shape);
- auto tr_kernel = transposeTensor<0,1,3,2>(_kernel);
+ auto tr_kernel = transposeTensor<0, 1, 3, 2>(_kernel);
Tensor<float> kernel(tr_kernel);
Shape k_shape = kernel.getShape();
Index kernel_idx;
kernel_idx.resize(k_shape.rank());
- for (auto& out_idx : out_range) {
+ for (auto &out_idx : out_range)
+ {
auto out_region = res_accesor.getRegion(out_idx);
assert(out_region.size() == num_kernels);
- for (auto& kernel_idx_r : kernel_range) {
+ for (auto &kernel_idx_r : kernel_range)
+ {
// rotate kernel 180 deg around last axis
// by index transform
- for (int32_t d = 0; d < 2; ++d) {
+ for (int32_t d = 0; d < 2; ++d)
+ {
kernel_idx.at(d) = kernel.getShape().dim(d) - kernel_idx_r.at(d) - 1;
}
kernel_idx.at(2) = kernel_idx_r.at(2);
// flag that keeps info on whether the current input element is from input
// or is from dilation by stride
bool is_from_input = true;
- for (int32_t d = 1; d < input_idx.rank() - 1; ++d) {
+ for (int32_t d = 1; d < input_idx.rank() - 1; ++d)
+ {
const auto num = (out_idx.at(d) + pads.at(d - 1) - kernel_idx.at(d - 1));
- auto stride = strides.dim(d - 1 );
+ auto stride = strides.dim(d - 1);
const auto div_res = num / stride;
- const auto rem = num - div_res*stride;
+ const auto rem = num - div_res * stride;
is_from_input = is_from_input && rem == 0;
- if (rem != 0) break;
+ if (rem != 0)
+ break;
input_idx.at(d) = div_res;
}
- if (is_from_input) {
+ if (is_from_input)
+ {
// batch is same as output's
input_idx.at(0) = out_idx.at(0);
// channel index - same as kernel's
input_idx.at(3) = kernel_idx.at(2);
- if (in_range.contains(input_idx)) {
+ if (in_range.contains(input_idx))
+ {
auto kernel_region = kernel.getRegion(kernel_idx);
assert(kernel_region.size() == num_kernels);
auto in = _input.at(input_idx);
- for (int32_t kernel_index = 0; kernel_index < num_kernels; kernel_index++) {
+ for (int32_t kernel_index = 0; kernel_index < num_kernels; kernel_index++)
+ {
out_region.base()[kernel_index] += in * kernel_region.base()[kernel_index];
}
}
return {res};
}
-DeConv2D::DeConv2D(const TensorVariant& input, const TensorVariant& kernel, const DeConv2DOp& op)
- : _input(input), _kernel(kernel), _op(op) {
+DeConv2D::DeConv2D(const TensorVariant &input, const TensorVariant &kernel, const DeConv2DOp &op)
+ : _input(input), _kernel(kernel), _op(op)
+{
// Input shape: [N, Hi, Wi, Ci]
// Kernel shape: [Hk, Wk, Co, Ci]
assert(_op.getInputShape(0).rank() == 4);
- const auto& input_shape = _input.getShape();
- const auto& kernel_shape = _kernel.getShape();
+ const auto &input_shape = _input.getShape();
+ const auto &kernel_shape = _kernel.getShape();
assert(input_shape.rank() == 4);
assert(kernel_shape.rank() == 4);
assert(kernel_shape.dim(3) == input_shape.dim(3));
#include "mir/ops/Deconv2DOp.h"
#include "mir/Tensor.h"
-namespace nnc {
+namespace nnc
+{
/**
* @brief Transposed convolution (or Deconvolution)
* hence all the indexing can be deducted by expressing the input index
* of Conv in terms of it's output index.
*/
-class DeConv2D : public OperationImpl<float> {
+class DeConv2D : public OperationImpl<float>
+{
public:
- DeConv2D(const mir::TensorVariant& input,
- const mir::TensorVariant& kernel,
- const mir::ops::DeConv2DOp& op);
+ DeConv2D(const mir::TensorVariant &input, const mir::TensorVariant &kernel,
+ const mir::ops::DeConv2DOp &op);
std::vector<mir::TensorVariant> operator()() override;
private:
const mir::Tensor<float> _input;
const mir::TensorVariant _kernel;
- const mir::ops::DeConv2DOp& _op;
+ const mir::ops::DeConv2DOp &_op;
};
} // namespace nnc
-
#endif //_NNC_CORE_BACKEND_INTERPRETER_DECONV2D_IMPL_
#include "DepthwiseConv2D.h"
#include "mir/ShapeRange.h"
-namespace nnc {
+namespace nnc
+{
using namespace mir;
-std::vector<TensorVariant> DepthwiseConv2D::operator()() {
- const Shape& in_shape = _op.getInputShape(0);
- const Shape& kernel_shape = _op.getInputShape(1);
- const Shape& out_shape = _op.getOutputShape(0);
- const Shape& strides = _op.getStrides();
- const std::vector<int32_t>& pads = _op.getPaddingBefore();
+std::vector<TensorVariant> DepthwiseConv2D::operator()()
+{
+ const Shape &in_shape = _op.getInputShape(0);
+ const Shape &kernel_shape = _op.getInputShape(1);
+ const Shape &out_shape = _op.getOutputShape(0);
+ const Shape &strides = _op.getStrides();
+ const std::vector<int32_t> &pads = _op.getPaddingBefore();
assert(in_shape.rank() == 4);
assert(kernel_shape.rank() == 4);
Index in_index;
in_index.resize(4);
- for (const auto& out_index : out_range) {
+ for (const auto &out_index : out_range)
+ {
Index out_index_k = out_index;
- for (const auto& kernel_index : kernel_range) {
+ for (const auto &kernel_index : kernel_range)
+ {
in_index.at(0) = out_index.at(0);
for (int i = 0; i < 2; ++i)
in_index.at(1 + i) = out_index.at(1 + i) * strides.dim(i) + kernel_index.at(i) - pads[i];
in_index.at(3) = kernel_index.at(2);
- if (in_range.contains(in_index)) {
+ if (in_range.contains(in_index))
+ {
out_index_k.at(3) = kernel_index.at(2) * channel_multiplier + kernel_index.at(3);
res_accessor.at(out_index_k) += _input.at(in_index) * _kernel.at(kernel_index);
}
return {res};
}
-DepthwiseConv2D::DepthwiseConv2D(const TensorVariant& input,
- const TensorVariant& kernel,
- const ops::DepthwiseConv2DOp& op)
- : _input(input), _kernel(kernel), _op(op) {
+DepthwiseConv2D::DepthwiseConv2D(const TensorVariant &input, const TensorVariant &kernel,
+ const ops::DepthwiseConv2DOp &op)
+ : _input(input), _kernel(kernel), _op(op)
+{
}
} // namespace nnc
#include "mir/ops/DepthwiseConv2DOp.h"
#include "mir/Tensor.h"
-namespace nnc {
+namespace nnc
+{
-class DepthwiseConv2D : public OperationImpl<float> {
+class DepthwiseConv2D : public OperationImpl<float>
+{
public:
- DepthwiseConv2D(const mir::TensorVariant& input,
- const mir::TensorVariant& kernel,
- const mir::ops::DepthwiseConv2DOp& op);
+ DepthwiseConv2D(const mir::TensorVariant &input, const mir::TensorVariant &kernel,
+ const mir::ops::DepthwiseConv2DOp &op);
std::vector<mir::TensorVariant> operator()() override;
private:
const mir::Tensor<float> _input;
const mir::Tensor<float> _kernel;
- const mir::ops::DepthwiseConv2DOp& _op;
+ const mir::ops::DepthwiseConv2DOp &_op;
};
} // namespace nnc
* @note Simply copies input to output
* @tparam T type of data in input tensor
*/
-template<typename T>
-class Dropout : public OperationImpl<float> {
+template <typename T> class Dropout : public OperationImpl<float>
+{
public:
/**
* @param in input data
* @param op dropout operation description
*/
- explicit Dropout(const mir::TensorVariant& in, const mir::ops::DropoutOp& op) : _input(in), _op(op) {}
+ explicit Dropout(const mir::TensorVariant &in, const mir::ops::DropoutOp &op)
+ : _input(in), _op(op)
+ {
+ }
/**
* @brief computes operation aplication result
private:
const mir::Tensor<float> _input;
- const mir::ops::DropoutOp& _op;
+ const mir::ops::DropoutOp &_op;
};
-template<typename T>
-std::vector<mir::TensorVariant> Dropout<T>::operator()()
+template <typename T> std::vector<mir::TensorVariant> Dropout<T>::operator()()
{
- //For now dropout just copies input to output
- return Fill<T>(_input.getShape(), [this](const mir::Index& idx) {
- return _input.at(idx);
- })();
+ // For now dropout just copies input to output
+ return Fill<T>(_input.getShape(), [this](const mir::Index &idx) { return _input.at(idx); })();
}
} // namespace nnc
#include "mir/Tensor.h"
#include <functional>
-namespace nnc {
+namespace nnc
+{
-template <typename T>
-class Fill : public OperationImpl<T> {
+template <typename T> class Fill : public OperationImpl<T>
+{
public:
- Fill(const mir::Shape& shape, std::function<T(const mir::Index&)> f) :
- _shape(shape), _fval(std::move(f)) {}
+ Fill(const mir::Shape &shape, std::function<T(const mir::Index &)> f)
+ : _shape(shape), _fval(std::move(f))
+ {
+ }
- std::vector<mir::TensorVariant> operator()() override {
+ std::vector<mir::TensorVariant> operator()() override
+ {
auto res = OperationImpl<T>::allocate_tensor(_shape);
mir::Tensor<T> res_accessor(res);
- for (const auto& index : mir::ShapeRange(_shape)) {
+ for (const auto &index : mir::ShapeRange(_shape))
+ {
res_accessor.at(index) = _fval(index);
}
private:
const mir::Shape _shape;
- const std::function<T(const mir::Index&)> _fval;
+ const std::function<T(const mir::Index &)> _fval;
};
} // namespace nnc
#include "FullyConnected.h"
-namespace nnc {
+namespace nnc
+{
-FullyConnected::FullyConnected(const mir::TensorVariant& input,
- const mir::TensorVariant& weights,
- const mir::ops::FullyConnectedOp& _op)
- : _op(_op), _input(input), _weights(weights) {}
+FullyConnected::FullyConnected(const mir::TensorVariant &input, const mir::TensorVariant &weights,
+ const mir::ops::FullyConnectedOp &_op)
+ : _op(_op), _input(input), _weights(weights)
+{
+}
-std::vector<mir::TensorVariant> FullyConnected::operator()() {
+std::vector<mir::TensorVariant> FullyConnected::operator()()
+{
mir::TensorVariant res = OperationImpl<float>::allocate_tensor(_op.getOutputShape(0));
mir::Tensor<float> accessor(res);
- const mir::Shape& in_shape = _input.getShape();
+ const mir::Shape &in_shape = _input.getShape();
int32_t in_rank = in_shape.rank();
- const mir::Shape& w_shape = _weights.getShape();
+ const mir::Shape &w_shape = _weights.getShape();
int32_t w_rank = w_shape.rank();
assert(in_shape.dim(in_rank - 1) == w_shape.dim(w_rank - 2));
int32_t len = w_shape.dim(w_rank - 2);
- for (auto& out_index : out_range) {
+ for (auto &out_index : out_range)
+ {
mir::Index t_index = out_index;
- float& output_element = accessor.at(out_index);
+ float &output_element = accessor.at(out_index);
int32_t col = t_index.at(w_rank - 1);
int32_t row = t_index.at(w_rank - 2);
- for (int32_t i = 0; i < len; ++i) {
+ for (int32_t i = 0; i < len; ++i)
+ {
t_index.at(w_rank - 1) = i;
float in = _input.at(t_index);
t_index.at(w_rank - 1) = col;
return {res};
}
-} // namespace nnc
+} // namespace nnc
#include "mir/Tensor.h"
#include "mir/ShapeRange.h"
-namespace nnc {
+namespace nnc
+{
-class FullyConnected : public OperationImpl<float> {
+class FullyConnected : public OperationImpl<float>
+{
public:
- FullyConnected(const mir::TensorVariant& input,
- const mir::TensorVariant& weights,
- const mir::ops::FullyConnectedOp& _op);
+ FullyConnected(const mir::TensorVariant &input, const mir::TensorVariant &weights,
+ const mir::ops::FullyConnectedOp &_op);
std::vector<mir::TensorVariant> operator()() override;
private:
- const mir::ops::FullyConnectedOp& _op;
+ const mir::ops::FullyConnectedOp &_op;
const mir::Tensor<float> _input;
const mir::Tensor<float> _weights;
};
#include "Gather.h"
-namespace nnc {
+namespace nnc
+{
using namespace mir;
-Gather::Gather(const TensorVariant& data,
- const TensorVariant& indices,
- const ops::GatherOp& op)
- : _data(data), _indices(indices), _op(op) {}
+Gather::Gather(const TensorVariant &data, const TensorVariant &indices, const ops::GatherOp &op)
+ : _data(data), _indices(indices), _op(op)
+{
+}
-std::vector<TensorVariant> Gather::operator()() {
- const auto& data_shape = _data.getShape();
- const auto& indices_shape = _indices.getShape();
+std::vector<TensorVariant> Gather::operator()()
+{
+ const auto &data_shape = _data.getShape();
+ const auto &indices_shape = _indices.getShape();
auto res = allocate_tensor(_op.getOutputShape(0));
Tensor<float> data(_data);
Tensor<float> indices(_indices);
for (int32_t i = axis + 1; i < data_shape.rank(); ++i)
inner_size *= data_shape.dim(i);
- for (int32_t outer = 0; outer < outer_size; ++outer) {
- for (int32_t i = 0; i < num_indices; ++i) {
+ for (int32_t outer = 0; outer < outer_size; ++outer)
+ {
+ for (int32_t i = 0; i < num_indices; ++i)
+ {
auto index = static_cast<int32_t>(indices.atOffset(i));
assert(index >= 0 && index < axis_size);
- for (int32_t inner = 0; inner < inner_size; inner++) {
+ for (int32_t inner = 0; inner < inner_size; inner++)
+ {
output.atOffset((outer * num_indices + i) * inner_size + inner) =
data.atOffset((outer * axis_size + index) * inner_size + inner);
}
#include "mir/ops/GatherOp.h"
#include "mir/Tensor.h"
-namespace nnc {
+namespace nnc
+{
-class Gather : public OperationImpl<float> {
+class Gather : public OperationImpl<float>
+{
public:
- Gather(const mir::TensorVariant& data,
- const mir::TensorVariant& indices,
- const mir::ops::GatherOp& op);
+ Gather(const mir::TensorVariant &data, const mir::TensorVariant &indices,
+ const mir::ops::GatherOp &op);
std::vector<mir::TensorVariant> operator()() override;
private:
const mir::Tensor<float> _data;
const mir::Tensor<float> _indices;
- const mir::ops::GatherOp& _op;
+ const mir::ops::GatherOp &_op;
};
-} // namespace nnc
+} // namespace nnc
#endif //_NNC_CORE_BACKEND_INTERPRETER_GATHER_
#include "mir/TensorVariant.h"
#include "mir/ShapeRange.h"
-namespace nnc {
-template<typename T>
-class Gemm : public OperationImpl<T> {
+namespace nnc
+{
+template <typename T> class Gemm : public OperationImpl<T>
+{
public:
- Gemm(const mir::TensorVariant& a, const mir::TensorVariant& b,
- const mir::TensorVariant& c, mir::ops::GemmOp& op) :
- _op(op), _tensor_a(a), _tensor_b(b), _tensor_c(c) {}
+ Gemm(const mir::TensorVariant &a, const mir::TensorVariant &b, const mir::TensorVariant &c,
+ mir::ops::GemmOp &op)
+ : _op(op), _tensor_a(a), _tensor_b(b), _tensor_c(c)
+ {
+ }
- std::vector<mir::TensorVariant> operator()() override {
+ std::vector<mir::TensorVariant> operator()() override
+ {
mir::TensorVariant res = OperationImpl<T>::allocate_tensor(_op.getOutputShape(0));
mir::Tensor<T> accessor(res);
mir::ShapeRange out_range(res.getShape());
auto b_shape = _tensor_b.getShape();
int32_t b_rank = b_shape.rank();
- auto& in_shape = _tensor_a.getShape();
+ auto &in_shape = _tensor_a.getShape();
int32_t in_rank = in_shape.rank();
assert(in_shape.dim(in_rank - 1) == b_shape.dim(b_rank - 2));
(void)in_rank;
auto len = b_shape.dim(b_rank - 2);
int32_t row;
int32_t col;
- for (auto &out_idx : out_range) {
+ for (auto &out_idx : out_range)
+ {
mir::Index t_idx = out_idx;
- T& output_element = accessor.at(out_idx);
+ T &output_element = accessor.at(out_idx);
col = t_idx.at(-1);
row = t_idx.at(-2);
- for (int32_t i = 0; i < len; ++i) {
+ for (int32_t i = 0; i < len; ++i)
+ {
t_idx.at(-1) = i;
- T& in = _tensor_a.at(t_idx);
+ T &in = _tensor_a.at(t_idx);
t_idx.at(-1) = col;
t_idx.at(-2) = i;
- T& w = _tensor_b.at(t_idx);
+ T &w = _tensor_b.at(t_idx);
t_idx.at(-2) = row;
output_element += w * in;
}
// We'd like to broadcast Tensor C to the output shape
assert(_op.getOutputShape(0).rank() == 2);
assert((_op.getOutputShape(0).rank() == _op.getInputShape(2).rank()) ||
- ((_op.getInputShape(2).rank() == 1) &&
- (_op.getOutputShape(0).dim(0) == 1)));
+ ((_op.getInputShape(2).rank() == 1) && (_op.getOutputShape(0).dim(0) == 1)));
- auto t = mir::TensorVariant (_tensor_c, _op.getOutputShape(0));
+ auto t = mir::TensorVariant(_tensor_c, _op.getOutputShape(0));
mir::Tensor<T> tensor_c(t);
- for (auto idx : mir::ShapeRange(_op.getOutputShape(0))) {
+ for (auto idx : mir::ShapeRange(_op.getOutputShape(0)))
+ {
accessor.at(idx) += tensor_c.at(idx);
}
return {res};
}
private:
- mir::ops::GemmOp& _op;
+ mir::ops::GemmOp &_op;
mir::Tensor<T> _tensor_a;
mir::Tensor<T> _tensor_b;
mir::TensorVariant _tensor_c;
#include "mir/Shape.h"
#include <vector>
-namespace nnc {
+namespace nnc
+{
-template<typename T>
-class OperationImpl {
+template <typename T> class OperationImpl
+{
public:
virtual std::vector<mir::TensorVariant> operator()() = 0;
protected:
- mir::TensorVariant allocate_tensor(const mir::Shape& shape) {
+ mir::TensorVariant allocate_tensor(const mir::Shape &shape)
+ {
// Use hardcoded DataType for now, since theres no support for operations on types other than
// floats
std::vector<float> zeros(static_cast<std::size_t>(shape.numElements()), 0.0f);
#include "Pad.h"
-namespace nnc {
+namespace nnc
+{
using namespace mir;
-std::vector<TensorVariant> Pad::operator()() {
+std::vector<TensorVariant> Pad::operator()()
+{
auto result = allocate_tensor(_op.getOutputShape(0));
Tensor<float> result_accessor(result);
temp_index.resize(rank);
bool index_on_padding(false);
- for (const Index& ind : out_range) {
+ for (const Index &ind : out_range)
+ {
index_on_padding = false;
- for (int32_t i = 0; i < rank; i++) {
+ for (int32_t i = 0; i < rank; i++)
+ {
// index on input values
if (ind.at(i) >= _op.getPaddingForDim(i).first &&
- ind.at(i) < out_shape.dim(i) - _op.getPaddingForDim(i).second) {
+ ind.at(i) < out_shape.dim(i) - _op.getPaddingForDim(i).second)
+ {
temp_index.at(i) = ind.at(i) - _op.getPaddingForDim(i).first;
- } else { // not in input
+ }
+ else
+ { // not in input
index_on_padding = true;
break;
}
}
- if (index_on_padding) {
+ if (index_on_padding)
+ {
result_accessor.at(ind) = _op.getScalar().get<float>();
- } else {
+ }
+ else
+ {
result_accessor.at(ind) = _input.at(temp_index);
}
}
#include "mir/ops/PadOp.h"
#include "mir/Tensor.h"
-namespace nnc {
+namespace nnc
+{
/**
* @brief Implements PadOp for interpreter backend
*
* you specify. For each dimension of input add values
* before and after of contents.
*/
-class Pad : public OperationImpl<float> {
+class Pad : public OperationImpl<float>
+{
public:
/**
* @param input The Input tensor
* @param op The Pad operation object
*/
- Pad(const mir::TensorVariant& input, const mir::ops::PadOp& op)
- : _input(input), _op(op) {
+ Pad(const mir::TensorVariant &input, const mir::ops::PadOp &op) : _input(input), _op(op)
+ {
assert(_input.getShape().rank() == _op.getNumDim());
}
private:
const mir::Tensor<float> _input;
- const mir::ops::PadOp& _op;
+ const mir::ops::PadOp &_op;
};
} // namespace nnc
{
float out = initialValue;
size_t avgDenominator = 0;
- for (auto& kIdx : ShapeRange(window_shape))
+ for (auto &kIdx : ShapeRange(window_shape))
{
translate(inIdx, outIdx, kIdx, strides, pads);
float in = 0.0f;
- if(inRange.contains(inIdx)) {
+ if (inRange.contains(inIdx))
+ {
avgDenominator++;
in = _input.at(inIdx);
- } else {
- switch(_op.getBorderType()) {
- case PoolOp::BorderType::ZEROFILLED: {
- //Elements outside input range are zero
+ }
+ else
+ {
+ switch (_op.getBorderType())
+ {
+ case PoolOp::BorderType::ZEROFILLED:
+ {
+ // Elements outside input range are zero
avgDenominator++;
in = 0.0f;
break;
}
- case PoolOp::BorderType::EMPTY: {
- //Skip all elements outside input range
+ case PoolOp::BorderType::EMPTY:
+ {
+ // Skip all elements outside input range
continue;
}
- default: {
+ default:
+ {
assert(false && "Invalid border type for pooling");
}
}
}
out = poolingFunc(out, in);
-
}
if (_op.getPoolingType() == PoolOp::PoolingType::AVG)
{
{
switch (_op.getPoolingType())
{
- case PoolOp::PoolingType::MAX:
- return (val > prev) ? val : prev;
- case PoolOp::PoolingType::AVG:
- return prev + val;
- case PoolOp::PoolingType::MIN:
- return (val < prev) ? val : prev;
- default:
- assert(false && "Unsupported pooling type");
+ case PoolOp::PoolingType::MAX:
+ return (val > prev) ? val : prev;
+ case PoolOp::PoolingType::AVG:
+ return prev + val;
+ case PoolOp::PoolingType::MIN:
+ return (val < prev) ? val : prev;
+ default:
+ assert(false && "Unsupported pooling type");
}
// This should not happen
// Should throw, but it is too expensive
float poolingFunc(float prev, float val);
private:
- const mir::ops::PoolOp&_op;
+ const mir::ops::PoolOp &_op;
const mir::Tensor<float> _input;
};
#include "mir/Tensor.h"
#include "mir/ShapeRange.h"
-namespace nnc {
+namespace nnc
+{
-template<typename T>
-class Reduce : public OperationImpl<T> {
+template <typename T> class Reduce : public OperationImpl<T>
+{
public:
- Reduce(const mir::TensorVariant& input, const mir::ops::ReduceOp& op)
- : _input(input), _op(op) {}
+ Reduce(const mir::TensorVariant &input, const mir::ops::ReduceOp &op) : _input(input), _op(op) {}
- std::vector<mir::TensorVariant> operator()() override {
- const auto& input_shape = _op.getInputShape(0);
- const auto& output_shape = _op.getOutputShape(0);
- const auto& reduction_dims = _op.getReductionDims();
+ std::vector<mir::TensorVariant> operator()() override
+ {
+ const auto &input_shape = _op.getInputShape(0);
+ const auto &output_shape = _op.getOutputShape(0);
+ const auto &reduction_dims = _op.getReductionDims();
const bool keep_dims = _op.getKeepDims();
assert(_op.getFuncType() == mir::ops::ReduceOp::FuncType::mean);
// This mask contains `true` for axis that should be reduced. For example, if we want to reduce
// axes 1 and 3 with total number of axes of 4, the mask will be [false, true, false, true].
std::vector<bool> reduce_axis_mask(input_shape.rank(), false);
- for (auto axis : reduction_dims) {
+ for (auto axis : reduction_dims)
+ {
reduce_axis_mask[axis] = true;
}
mir::Index out_index;
out_index.resize(output_shape.rank());
- for (const mir::Index& in_index : mir::ShapeRange(input_shape)) {
+ for (const mir::Index &in_index : mir::ShapeRange(input_shape))
+ {
int32_t out_index_dim = 0;
- for (int32_t d = 0; d < input_shape.rank(); ++d) {
- if (keep_dims) {
+ for (int32_t d = 0; d < input_shape.rank(); ++d)
+ {
+ if (keep_dims)
+ {
out_index.at(out_index_dim++) = reduce_axis_mask[d] ? 0 : in_index.at(d);
- } else {
- if (!reduce_axis_mask[d]) {
+ }
+ else
+ {
+ if (!reduce_axis_mask[d])
+ {
out_index.at(out_index_dim++) = in_index.at(d);
}
}
const int32_t reduction_factor = input_shape.numElements() / output_shape.numElements();
- for (const auto& index : mir::ShapeRange(output_shape)) {
+ for (const auto &index : mir::ShapeRange(output_shape))
+ {
res_accessor.at(index) /= reduction_factor;
}
private:
const mir::Tensor<T> _input;
- const mir::ops::ReduceOp& _op;
+ const mir::ops::ReduceOp &_op;
};
} // namespace nnc
#include "OperationImpl.h"
#include "Fill.h"
-namespace nnc {
+namespace nnc
+{
-template <typename T>
-class Reshape : public OperationImpl<T> {
+template <typename T> class Reshape : public OperationImpl<T>
+{
public:
- Reshape(const mir::TensorVariant& input, const mir::Shape& output_shape)
- : _input(input),
- _output_shape(output_shape) {
+ Reshape(const mir::TensorVariant &input, const mir::Shape &output_shape)
+ : _input(input), _output_shape(output_shape)
+ {
assert(input.getShape().numElements() == _output_shape.numElements());
}
- std::vector<mir::TensorVariant> operator()() override {
+ std::vector<mir::TensorVariant> operator()() override
+ {
mir::ShapeRange inRange(_input.getShape());
auto inIter = inRange.begin();
auto out = OperationImpl<T>::allocate_tensor(_output_shape);
// Shapes element count compared in Reshape ctor
- return Fill<T>(_output_shape, [this, &inIter](const mir::Index&) -> T { return _input.at(*inIter++); })();
+ return Fill<T>(_output_shape,
+ [this, &inIter](const mir::Index &) -> T { return _input.at(*inIter++); })();
}
private:
mir::Tensor<T> _input;
- const mir::Shape& _output_shape;
+ const mir::Shape &_output_shape;
};
} // namespace nnc
#include "mir/Tensor.h"
#include <cmath>
-namespace nnc {
+namespace nnc
+{
-template<typename T>
-class Softmax : public OperationImpl<T> {
+template <typename T> class Softmax : public OperationImpl<T>
+{
public:
- Softmax(const mir::TensorVariant& input, int32_t axis)
- : _input(input), _axis(axis) {}
+ Softmax(const mir::TensorVariant &input, int32_t axis) : _input(input), _axis(axis) {}
- std::vector<mir::TensorVariant> operator()() override {
+ std::vector<mir::TensorVariant> operator()() override
+ {
mir::Shape expsum_shape = _input.getShape();
expsum_shape.dim(_axis) = 1;
mir::Tensor<T> expsum_accessor(expsum);
mir::Tensor<T> res_accessor(res);
- for (const auto& out_idx : mir::ShapeRange(expsum_shape)) {
+ for (const auto &out_idx : mir::ShapeRange(expsum_shape))
+ {
T element = T();
mir::Index in_idx = out_idx;
int32_t end = _input.getShape().dim(_axis);
- for (int32_t i = 0; i < end; ++i) {
+ for (int32_t i = 0; i < end; ++i)
+ {
in_idx.at(_axis) = i;
element += std::exp(input_accessor.at(in_idx));
}
expsum_accessor.at(out_idx) = element;
}
- for (const auto& out_idx : mir::ShapeRange(_input.getShape())) {
+ for (const auto &out_idx : mir::ShapeRange(_input.getShape()))
+ {
mir::Index expsum_idx = out_idx;
expsum_idx.at(_axis) = 0;
res_accessor.at(out_idx) =
#include "mir/Tensor.h"
#include "mir/ShapeRange.h"
-namespace nnc {
+namespace nnc
+{
using namespace mir;
-Transpose::Transpose(const mir::TensorVariant& input,
- const mir::ops::TransposeOp& op) : _op(op), _input(input) {}
+Transpose::Transpose(const mir::TensorVariant &input, const mir::ops::TransposeOp &op)
+ : _op(op), _input(input)
+{
+}
-std::vector<mir::TensorVariant> Transpose::operator()() {
+std::vector<mir::TensorVariant> Transpose::operator()()
+{
auto res = allocate_tensor(_op.getOutputShape(0));
Tensor<float> res_accessor(res);
- auto& input_shape = _op.getInputShape(0);
- auto& axis_order = _op.getAxisOrder();
+ auto &input_shape = _op.getInputShape(0);
+ auto &axis_order = _op.getAxisOrder();
std::size_t num_axes = axis_order.size();
ShapeRange in_range(input_shape);
Index out_index;
out_index.resize(input_shape.rank());
- for (auto& in_index : in_range) {
+ for (auto &in_index : in_range)
+ {
for (std::size_t i = 0; i < num_axes; ++i)
out_index.at(static_cast<int32_t>(i)) = in_index.at(static_cast<int32_t>(axis_order.at(i)));
res_accessor.at(out_index) = _input.at(in_index);
return {res};
}
-} // namespace nnc
+} // namespace nnc
#include "mir/ops/TransposeOp.h"
#include "mir/Tensor.h"
-namespace nnc {
+namespace nnc
+{
-class Transpose : public OperationImpl<float> {
+class Transpose : public OperationImpl<float>
+{
public:
std::vector<mir::TensorVariant> operator()() override;
- Transpose(const mir::TensorVariant& input, const mir::ops::TransposeOp& op);
+ Transpose(const mir::TensorVariant &input, const mir::ops::TransposeOp &op);
private:
- const mir::ops::TransposeOp& _op;
+ const mir::ops::TransposeOp &_op;
const mir::Tensor<float> _input;
};
-} // namespace nnc
+} // namespace nnc
#endif //_NNC_CORE_BACKEND_INTERPRETER_TRANSPOSE_
}
}
-Index shift(const Index& in_index, const Shape& shift_from) {
+Index shift(const Index &in_index, const Shape &shift_from)
+{
Index index = in_index;
assert(index.rank() == shift_from.rank());
- for (int32_t d = 0; d < in_index.rank(); ++d) {
+ for (int32_t d = 0; d < in_index.rank(); ++d)
+ {
index.at(d) = index.at(d) + shift_from.dim(d);
}
return index;
/// \param[in] kernelIndex current kernel element
/// \param[in] strides
/// \param[in] paddings
-void translate(mir::Index &translatedIndex, const mir::Index &sourceIndex, const mir::Index &kernelIndex,
- const mir::Shape &strides, const mir::Index &paddings);
+void translate(mir::Index &translatedIndex, const mir::Index &sourceIndex,
+ const mir::Index &kernelIndex, const mir::Shape &strides,
+ const mir::Index &paddings);
/**
* Shift in_index by `shift`
* @param[in] shift
* @return the
*/
-mir::Index shift(const mir::Index& in_index, const mir::Shape& shift_from);
+mir::Index shift(const mir::Index &in_index, const mir::Shape &shift_from);
} // namespace nnc
namespace mir_onnx
{
- class ONNXImporterImpl;
+class ONNXImporterImpl;
}
namespace nnc
#include "mir/GraphPatternMatcher.h"
#include <algorithm>
-namespace nnc {
+namespace nnc
+{
using namespace mir;
-std::vector<size_t> combineAxisOrders(const std::vector<std::size_t>& order1,
- const std::vector<std::size_t>& order2) {
+std::vector<size_t> combineAxisOrders(const std::vector<std::size_t> &order1,
+ const std::vector<std::size_t> &order2)
+{
assert(order1.size() == order2.size());
std::vector<size_t> res(order1.size());
- for (size_t i = 0; i < order1.size(); i++) {
+ for (size_t i = 0; i < order1.size(); i++)
+ {
res[order2[order1[i]]] = i;
}
return res;
}
-static bool isIdentityTranspose(const std::vector<size_t>& axis_order) {
- for (size_t i = 0; i < ( axis_order.size()); i++) {
- if (axis_order[i] != i) {
+static bool isIdentityTranspose(const std::vector<size_t> &axis_order)
+{
+ for (size_t i = 0; i < (axis_order.size()); i++)
+ {
+ if (axis_order[i] != i)
+ {
return false;
}
}
return true;
}
-nnc::PassData nnc::CombineTransposes::run(nnc::PassData data) {
- auto g = static_cast<Graph*>(data);
+nnc::PassData nnc::CombineTransposes::run(nnc::PassData data)
+{
+ auto g = static_cast<Graph *>(data);
assert(g);
GraphPatternMatcher matcher(g);
- auto is_tr = [](const Operation* op1) { return op1->getType() == Operation::Type::transpose; };
- std::vector<std::pair<Operation*, Operation*>> matches = matcher.matchEdge(is_tr, is_tr);
- std::unordered_set<Operation*> deleted_nodes;
- while (!matches.empty()) {
- for (std::pair<Operation*, Operation*> match : matches) {
- if (deleted_nodes.find(match.first) != deleted_nodes.end()) { break; };
- auto* top_transpose = dynamic_cast<mir::ops::TransposeOp*>(match.first);
- if (deleted_nodes.find(match.second) != deleted_nodes.end()) { break; };
- auto* bottom_transpose = dynamic_cast<mir::ops::TransposeOp*>(match.second);
- auto combined_axis_order = combineAxisOrders(top_transpose->getAxisOrder(),
- bottom_transpose->getAxisOrder());
+ auto is_tr = [](const Operation *op1) { return op1->getType() == Operation::Type::transpose; };
+ std::vector<std::pair<Operation *, Operation *>> matches = matcher.matchEdge(is_tr, is_tr);
+ std::unordered_set<Operation *> deleted_nodes;
+ while (!matches.empty())
+ {
+ for (std::pair<Operation *, Operation *> match : matches)
+ {
+ if (deleted_nodes.find(match.first) != deleted_nodes.end())
+ {
+ break;
+ };
+ auto *top_transpose = dynamic_cast<mir::ops::TransposeOp *>(match.first);
+ if (deleted_nodes.find(match.second) != deleted_nodes.end())
+ {
+ break;
+ };
+ auto *bottom_transpose = dynamic_cast<mir::ops::TransposeOp *>(match.second);
+ auto combined_axis_order =
+ combineAxisOrders(top_transpose->getAxisOrder(), bottom_transpose->getAxisOrder());
- if (!isIdentityTranspose(combined_axis_order)) {
- auto new_tr_op = g->create<mir::ops::TransposeOp>(
- top_transpose->getName() + "new",
- top_transpose->getInput(0)->getProducer(), combined_axis_order);
+ if (!isIdentityTranspose(combined_axis_order))
+ {
+ auto new_tr_op = g->create<mir::ops::TransposeOp>(top_transpose->getName() + "new",
+ top_transpose->getInput(0)->getProducer(),
+ combined_axis_order);
g->replaceNode(bottom_transpose, new_tr_op);
- } else {
+ }
+ else
+ {
// Connect top input to all outputs of bottom
- Operation* top = top_transpose->getInput(0)->getProducer()->getNode();
+ Operation *top = top_transpose->getInput(0)->getProducer()->getNode();
g->replaceNode(bottom_transpose, top);
}
deleted_nodes.emplace(bottom_transpose);
- if (top_transpose->getOutput(0)->getConsumers().empty()) {
+ if (top_transpose->getOutput(0)->getConsumers().empty())
+ {
g->removeNode(top_transpose);
deleted_nodes.emplace(top_transpose);
}
return g;
}
-} //namespace nnc
+} // namespace nnc
#include <algorithm>
-namespace nnc {
+namespace nnc
+{
-namespace {
+namespace
+{
using namespace mir;
using namespace std;
using namespace opt_util;
using OpType = Operation::Type;
-using Edge = pair<Operation*, Operation*>;
+using Edge = pair<Operation *, Operation *>;
/**
* This function used to get 'ConstantOp' with weights of 'AddOp', 'MulOp' or 'Conv2DOp'
* For each of these ops weights stored in second input node
*/
-ops::ConstantOp* getSecondInputAsConst(const Operation* op) {
- assert(op->getType() == OpType::add ||
- op->getType() == OpType::mul ||
+ops::ConstantOp *getSecondInputAsConst(const Operation *op)
+{
+ assert(op->getType() == OpType::add || op->getType() == OpType::mul ||
op->getType() == OpType::conv2D);
- return dynamic_cast<ops::ConstantOp*>(op->getInput(1)->getProducer()->getNode());
+ return dynamic_cast<ops::ConstantOp *>(op->getInput(1)->getProducer()->getNode());
}
// This function finds successive operations of given types, with ConstantOp as second input
-vector<Edge> findSuccessiveOpsWithConstWeights(Graph* g, OpType first_op_type,
- OpType second_op_type) {
+vector<Edge> findSuccessiveOpsWithConstWeights(Graph *g, OpType first_op_type,
+ OpType second_op_type)
+{
vector<Edge> matches;
- unordered_set<Operation*> matched_nodes;
- for (auto* first_op: g->getNodes()) {
- if (first_op->getType() == first_op_type && getSecondInputAsConst(first_op)) {
- for (auto& out : first_op->getOutputs()) {
- for (auto* consumer : out.getConsumers()) {
- Operation* second_op = consumer->getNode();
- if (second_op->getType() == second_op_type && getSecondInputAsConst(second_op)) {
- /**
- * Don't match already matched nodes, so for op1->op2->op3 this function
- * will return {{f1, f2}} and not {{f1, f2}, {f2, f3}}
- */
+ unordered_set<Operation *> matched_nodes;
+ for (auto *first_op : g->getNodes())
+ {
+ if (first_op->getType() == first_op_type && getSecondInputAsConst(first_op))
+ {
+ for (auto &out : first_op->getOutputs())
+ {
+ for (auto *consumer : out.getConsumers())
+ {
+ Operation *second_op = consumer->getNode();
+ if (second_op->getType() == second_op_type && getSecondInputAsConst(second_op))
+ {
+ /**
+ * Don't match already matched nodes, so for op1->op2->op3 this function
+ * will return {{f1, f2}} and not {{f1, f2}, {f2, f3}}
+ */
if (matched_nodes.find(first_op) == matched_nodes.end() &&
- matched_nodes.find(second_op) == matched_nodes.end()) {
+ matched_nodes.find(second_op) == matched_nodes.end())
+ {
matched_nodes.emplace(first_op);
matched_nodes.emplace(second_op);
matches.emplace_back(first_op, second_op);
* This function merges two ConstantOp into new one, by elementwise multiplication or addition
* If first ConstantOp rank > 1, second one broadcasting to first by axis=0
*/
-Operation* mergeConstantOps(Graph* g, const ops::ConstantOp* const1_op,
- const ops::ConstantOp* const2_op, OpType merge_type) {
- const auto& const1_val = const1_op->getValue();
- const auto& const2_val = const2_op->getValue();
+Operation *mergeConstantOps(Graph *g, const ops::ConstantOp *const1_op,
+ const ops::ConstantOp *const2_op, OpType merge_type)
+{
+ const auto &const1_val = const1_op->getValue();
+ const auto &const2_val = const2_op->getValue();
assert(const1_val.getShape().rank() >= const2_val.getShape().rank());
assert(const2_val.getShape().rank() == 1);
assert(const1_val.getShape().dim(0) == const2_val.getShape().dim(0));
Tensor<float> const2_accessor(const2_val);
Tensor<float> new_const_accessor(new_const_val);
ShapeRange const1_range(const1_val.getShape());
- for (auto& idx : const1_range) {
+ for (auto &idx : const1_range)
+ {
float operand1 = const1_accessor.at(idx);
/**
* Broadcast second ConstantOp to first one:
* idx of second constant always has rank 1 and equals to first dimension of first constant idx
*/
float operand2 = const2_accessor.at(Index{idx.at(0)});
- switch (merge_type) {
+ switch (merge_type)
+ {
case OpType::mul:
new_const_accessor.at(idx) = operand1 * operand2;
break;
* \\ // |
* [Mul] |
*/
-bool fuseSuccessiveOps(Graph* g) {
+bool fuseSuccessiveOps(Graph *g)
+{
// Find all successive ops
vector<Edge> successive_ops;
auto mul_mul_vec = findSuccessiveOpsWithConstWeights(g, OpType::mul, OpType::mul);
auto conv_mul_vec = findSuccessiveOpsWithConstWeights(g, OpType::conv2D, OpType::mul);
successive_ops.insert(successive_ops.end(), conv_mul_vec.begin(), conv_mul_vec.end());
- for (auto& edge : successive_ops) {
+ for (auto &edge : successive_ops)
+ {
auto const1_op = getSecondInputAsConst(edge.first);
auto const2_op = getSecondInputAsConst(edge.second);
assert(const1_op && const2_op);
* [Mul] | [Add]
* |
*/
-bool sinkAddThroughMul(Graph* g) {
+bool sinkAddThroughMul(Graph *g)
+{
auto add_mul_edges = findSuccessiveOpsWithConstWeights(g, OpType::add, OpType::mul);
- for (auto& edge : add_mul_edges) {
+ for (auto &edge : add_mul_edges)
+ {
auto old_add_op = edge.first;
auto old_mul_op = edge.second;
auto old_add_const_op = getSecondInputAsConst(old_add_op);
// Create new operations
auto old_add_input = old_add_op->getInput(0)->getProducer();
- auto new_mul_op = g->copyOpWithInputs(old_mul_op, {old_add_input, ols_mul_const_op->getOutput(0)});
- auto new_add_const_op = mergeConstantOps(g, old_add_const_op, ols_mul_const_op,
- OpType::mul);
- auto new_add_op = g->copyOpWithInputs(
- old_add_op, {new_mul_op->getOutput(0), new_add_const_op->getOutput(0)});
+ auto new_mul_op =
+ g->copyOpWithInputs(old_mul_op, {old_add_input, ols_mul_const_op->getOutput(0)});
+ auto new_add_const_op = mergeConstantOps(g, old_add_const_op, ols_mul_const_op, OpType::mul);
+ auto new_add_op =
+ g->copyOpWithInputs(old_add_op, {new_mul_op->getOutput(0), new_add_const_op->getOutput(0)});
// Replace old mul with new add and remove old nodes
g->replaceNode(old_mul_op, new_add_op);
return !add_mul_edges.empty();
}
-} // unnamed namespace
+} // unnamed namespace
-nnc::PassData nnc::FuseArithmeticOps::run(nnc::PassData data) {
- auto g = static_cast<Graph*>(data);
+nnc::PassData nnc::FuseArithmeticOps::run(nnc::PassData data)
+{
+ auto g = static_cast<Graph *>(data);
bool graph_changed = true;
- while (graph_changed) {
+ while (graph_changed)
+ {
graph_changed = false;
graph_changed |= fuseSuccessiveOps(g);
graph_changed |= sinkAddThroughMul(g);
return g;
}
-} // namespace nnc
+} // namespace nnc
*/
#include "passes/optimizations/OptimizationUtils.h"
-namespace nnc {
-namespace opt_util {
+namespace nnc
+{
+namespace opt_util
+{
-void swapAdjacent(mir::Graph* g, mir::Operation* top, mir::Operation* bottom) {
- assert(
- top->getNumInputs() == bottom->getNumInputs() && top->getNumInputs() == 1 &&
- top->getNumInputs() == top->getNumOutputs() &&
- top->getNumInputs() == bottom->getNumOutputs() && "incompatible ops");
- auto& ins = top->getInputs();
- std::vector<mir::Operation::Output*> prods;
+void swapAdjacent(mir::Graph *g, mir::Operation *top, mir::Operation *bottom)
+{
+ assert(top->getNumInputs() == bottom->getNumInputs() && top->getNumInputs() == 1 &&
+ top->getNumInputs() == top->getNumOutputs() &&
+ top->getNumInputs() == bottom->getNumOutputs() && "incompatible ops");
+ auto &ins = top->getInputs();
+ std::vector<mir::Operation::Output *> prods;
prods.reserve(top->getNumInputs());
- for (auto& in: ins) {
+ for (auto &in : ins)
+ {
prods.emplace_back(in.getProducer());
}
- mir::Operation* new_bottom = g->copyOpWithInputs(bottom, prods);
+ mir::Operation *new_bottom = g->copyOpWithInputs(bottom, prods);
prods.clear();
prods.reserve(new_bottom->getNumOutputs());
- for (mir::Operation::Output& out: new_bottom->getOutputs()) {
+ for (mir::Operation::Output &out : new_bottom->getOutputs())
+ {
prods.emplace_back(&out);
}
- mir::Operation* new_top = g->copyOpWithInputs(top, prods);
+ mir::Operation *new_top = g->copyOpWithInputs(top, prods);
g->replaceNode(bottom, new_top);
g->replaceNode(top, new_bottom);
}
// TODO: this function and it's usages should be removed, after DCE optimization will be implemented
-void removeNodeIfUnused(mir::Graph* g, mir::Operation* op) {
+void removeNodeIfUnused(mir::Graph *g, mir::Operation *op)
+{
if (op->getOutput(0)->getConsumers().empty())
g->removeNode(op);
}
using namespace mir;
-nnc::PassData nnc::RemoveDeadEnds::run(PassData data) {
- auto g = static_cast<Graph*>(data);
+nnc::PassData nnc::RemoveDeadEnds::run(PassData data)
+{
+ auto g = static_cast<Graph *>(data);
assert(g);
- for (auto op: g->getNodes()) {
- if (op->getOutput(0)->getConsumers().empty() && op->getType() == mir::Operation::Type::constant) {
+ for (auto op : g->getNodes())
+ {
+ if (op->getOutput(0)->getConsumers().empty() && op->getType() == mir::Operation::Type::constant)
+ {
g->removeNode(op);
}
}
#include <string>
#include <algorithm>
-namespace nnc {
+namespace nnc
+{
using namespace mir;
using namespace opt_util;
-PassData SinkRelu::run(PassData data) {
- auto g = static_cast<Graph*>(data);
+PassData SinkRelu::run(PassData data)
+{
+ auto g = static_cast<Graph *>(data);
assert(g);
GraphPatternMatcher matcher(g);
- auto is_relu = [](const Operation* op) { return op->getType() == Operation::Type::ReLU; };
- auto is_concat = [](const Operation* op) { return op->getType() == Operation::Type::concat; };
- auto is_max_pool = [](const Operation* op) {
- auto* p_op = dynamic_cast<const ops::PoolOp*>(op);
- if (!p_op) return false;
+ auto is_relu = [](const Operation *op) { return op->getType() == Operation::Type::ReLU; };
+ auto is_concat = [](const Operation *op) { return op->getType() == Operation::Type::concat; };
+ auto is_max_pool = [](const Operation *op) {
+ auto *p_op = dynamic_cast<const ops::PoolOp *>(op);
+ if (!p_op)
+ return false;
return p_op->getPoolingType() == ops::PoolOp::PoolingType::MAX;
};
- std::vector<std::pair<Operation*, Operation*>> matches;
+ std::vector<std::pair<Operation *, Operation *>> matches;
// sink ReLU through MaxPool
matches = matcher.matchEdge(is_relu, is_max_pool);
- for (auto pair: matches) {
+ for (auto pair : matches)
+ {
swapAdjacent(g, pair.first, pair.second);
}
// sink ReLU through Concat
auto matches_v = matcher.matchUpBush(is_relu, is_concat);
- for (const auto& pair : matches_v) {
+ for (const auto &pair : matches_v)
+ {
auto relus = pair.first;
- auto* concat = dynamic_cast<ops::ConcatOp*>(pair.second);
- std::vector<Operation::Output*> pre_relu;
+ auto *concat = dynamic_cast<ops::ConcatOp *>(pair.second);
+ std::vector<Operation::Output *> pre_relu;
pre_relu.reserve(relus.size());
- for (auto* r : relus) {
+ for (auto *r : relus)
+ {
pre_relu.emplace_back(r->getInput(0)->getProducer());
}
// create replacement nodes
- auto new_concat = g->create<ops::ConcatOp>(
- concat->getName() + "_before_relu", pre_relu, concat->getAxis());
- auto new_relu = g->create<ops::ReluOp>(
- relus[0]->getName() + "_after_concat", new_concat->getOutput(0));
+ auto new_concat =
+ g->create<ops::ConcatOp>(concat->getName() + "_before_relu", pre_relu, concat->getAxis());
+ auto new_relu =
+ g->create<ops::ReluOp>(relus[0]->getName() + "_after_concat", new_concat->getOutput(0));
// concat is deleted here
g->replaceNode(concat, new_relu);
- for (auto r: relus) {
+ for (auto r : relus)
+ {
removeNodeIfUnused(g, r);
}
}
#include <string>
#include <algorithm>
-namespace nnc {
+namespace nnc
+{
using namespace mir;
using namespace opt_util;
-PassData SinkTranspose::run(PassData data) {
- auto g = static_cast<Graph*>(data);
+PassData SinkTranspose::run(PassData data)
+{
+ auto g = static_cast<Graph *>(data);
assert(g); // NOLINT
GraphPatternMatcher matcher(g);
- auto is_tr = [](const Operation* op1) { return op1->getType() == Operation::Type::transpose; };
- auto is_relu = [](const Operation* op2) { return op2->getType() == Operation::Type::ReLU; };
- auto is_concat = [](const Operation* op2) { return op2->getType() == Operation::Type::concat; };
- std::vector<std::pair<Operation*, Operation*>> matches;
+ auto is_tr = [](const Operation *op1) { return op1->getType() == Operation::Type::transpose; };
+ auto is_relu = [](const Operation *op2) { return op2->getType() == Operation::Type::ReLU; };
+ auto is_concat = [](const Operation *op2) { return op2->getType() == Operation::Type::concat; };
+ std::vector<std::pair<Operation *, Operation *>> matches;
// sink transpose below ReLU
matches = matcher.matchEdge(is_tr, is_relu);
- for (auto pair : matches) {
+ for (auto pair : matches)
+ {
swapAdjacent(g, pair.first, pair.second);
}
// sink transpose through Concat
auto v_matches = matcher.matchUpBush(is_tr, is_concat);
- for (const auto& pair : v_matches) {
- std::vector<Operation*> trs = pair.first;
- auto* concat = dynamic_cast<ops::ConcatOp*>(pair.second);
- auto axis_order = dynamic_cast<ops::TransposeOp* >(trs[0])->getAxisOrder();
- if (std::all_of( trs.begin(), trs.end(), [&axis_order](Operation* tr) {
- return dynamic_cast<ops::TransposeOp*>(tr)->getAxisOrder() == axis_order;
- })) {
- std::vector<Operation::Output*> prev_trans;
+ for (const auto &pair : v_matches)
+ {
+ std::vector<Operation *> trs = pair.first;
+ auto *concat = dynamic_cast<ops::ConcatOp *>(pair.second);
+ auto axis_order = dynamic_cast<ops::TransposeOp *>(trs[0])->getAxisOrder();
+ if (std::all_of(trs.begin(), trs.end(), [&axis_order](Operation *tr) {
+ return dynamic_cast<ops::TransposeOp *>(tr)->getAxisOrder() == axis_order;
+ }))
+ {
+ std::vector<Operation::Output *> prev_trans;
prev_trans.reserve(trs.size());
- for (auto transpose : trs) {
+ for (auto transpose : trs)
+ {
prev_trans.emplace_back(transpose->getInput(0)->getProducer());
}
- auto new_concat = g->create<ops::ConcatOp>(
- concat->getName() + "_transposed", prev_trans, axis_order[concat->getAxis()]);
+ auto new_concat = g->create<ops::ConcatOp>(concat->getName() + "_transposed", prev_trans,
+ axis_order[concat->getAxis()]);
auto new_transpose = g->create<ops::TransposeOp>(trs[0]->getName() + "_after_concat",
- new_concat->getOutput(0),
- axis_order);
+ new_concat->getOutput(0), axis_order);
// removes old concat
g->replaceNode(concat, new_transpose);
- for (auto tr: trs) {
+ for (auto tr : trs)
+ {
removeNodeIfUnused(g, tr);
}
}
using namespace std;
-namespace nnc {
+namespace nnc
+{
-namespace {
+namespace
+{
/**
* @brief Creates pointer to some output stream to encapsulate resource management into deleter
* @return Pointer output stream
* @throws PluginException if did not succeed
*/
-unique_ptr<ofstream> getStream(const string& path) {
+unique_ptr<ofstream> getStream(const string &path)
+{
unique_ptr<ofstream> ofs(new ofstream(path));
if (ofs->fail())
throw PassException("Can not open code output file: " + path);
* @param path Path to desired directory
* @throws PluginException in did not succeed
*/
-void createDir(const string& path) {
- int res = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); // NOLINT(hicpp-signed-bitwise)
+void createDir(const string &path)
+{
+ int res =
+ mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); // NOLINT(hicpp-signed-bitwise)
if (res != 0 && errno != EEXIST)
throw PassException("Failed to create output directory");
}
} // unnamed namespace
-BaseCodeGenerator::BaseCodeGenerator() {
+BaseCodeGenerator::BaseCodeGenerator()
+{
string base_path = cli::artifactDir + "/" + cli::artifactName;
_headerPath = base_path + ".h";
_codePath = base_path + ".cpp";
_paramsPath = base_path + ".params";
}
-void BaseCodeGenerator::materializeModelParams(ostream& out, const Serializer& s) {
+void BaseCodeGenerator::materializeModelParams(ostream &out, const Serializer &s)
+{
using namespace params;
// First form a dump header
out.write(header, HEADER_LEN);
if (out.fail())
throw PassException("Failed to write model parameters header");
- auto& params = s.getBuffer();
+ auto ¶ms = s.getBuffer();
out.write(params.data(), params.size());
if (out.fail())
throw PassException("Failed to write model Parameters");
}
-PassData BaseCodeGenerator::run(PassData data) {
- auto g = static_cast<mir::Graph*>(data);
+PassData BaseCodeGenerator::run(PassData data)
+{
+ auto g = static_cast<mir::Graph *>(data);
assert(g);
// visit and analyze graph
using namespace std;
-namespace nnc {
+namespace nnc
+{
-void CCodeGenerator::formatTensorNames(const ModelAnalyzer& /*ma*/) {
+void CCodeGenerator::formatTensorNames(const ModelAnalyzer & /*ma*/)
+{
// TODO format tensor names according to c backend requirements
}
-void CCodeGenerator::materializeHeader(ostream& /*out*/, const ModelAnalyzer& /*ma*/) {
+void CCodeGenerator::materializeHeader(ostream & /*out*/, const ModelAnalyzer & /*ma*/)
+{
// TODO emit C header to out stream
}
-void CCodeGenerator::materializeCode(ostream& /*out*/, const ModelAnalyzer& /*ma*/,
- const Serializer& /*s*/) {
+void CCodeGenerator::materializeCode(ostream & /*out*/, const ModelAnalyzer & /*ma*/,
+ const Serializer & /*s*/)
+{
// TODO emit C code to out stream
}
-Pass& CCodeGenerator::getInstance() {
+Pass &CCodeGenerator::getInstance()
+{
static CCodeGenerator instance;
return instance;
}
#include "cpp_gather.generated.h"
#include "cpp_gemm.generated.h"
-namespace nnc {
+namespace nnc
+{
using namespace sir;
* @brief Renames tensors with respect to C++ naming conventions
* @param ma Intermediate artifact information
*/
-void CPPCodeGenerator::formatTensorNames(const ModelAnalyzer& ma) {
+void CPPCodeGenerator::formatTensorNames(const ModelAnalyzer &ma)
+{
int tmp_tensors = 0;
- for (const TensorDescriptor& td: ma.getTensors()) {
+ for (const TensorDescriptor &td : ma.getTensors())
+ {
string formatted_name;
- if (td.name.empty()) {
+ if (td.name.empty())
+ {
assert(td.type == TensorType::temporary);
formatted_name = "Tensor_" + to_string(tmp_tensors++);
- } else {
+ }
+ else
+ {
if (td.type != TensorType::temporary)
formatted_name.append("_");
formatted_name.append(td.name);
- for (char& c: formatted_name) {
+ for (char &c : formatted_name)
+ {
if (!isalnum(c))
c = '_';
}
* network constructor, setters to feed data to network, getters to get results,
* and doInference method that performs actual inference.
*/
-void CPPCodeGenerator::materializeHeader(ostream& out, const ModelAnalyzer& ma) {
+void CPPCodeGenerator::materializeHeader(ostream &out, const ModelAnalyzer &ma)
+{
string class_name = ma.getModelName() + "Model";
out.write(cpp_header_types, sizeof(cpp_header_types));
out << "class " << class_name << "\n"
- "{\n"
- "public:\n"
- " " << class_name << "(const std::string& parametersPath);\n"
- " ~" << class_name << "();\n";
+ "{\n"
+ "public:\n"
+ " "
+ << class_name << "(const std::string& parametersPath);\n"
+ " ~"
+ << class_name << "();\n";
// generate input setters
if (ma.getInputs().size() == 1)
out << " bool setInput(const Tensor& inputs);\n";
- for (const size_t inId: ma.getInputs()) {
- const string& tName = _formattedTensors[inId];
+ for (const size_t inId : ma.getInputs())
+ {
+ const string &tName = _formattedTensors[inId];
out << " bool set" << tName << "(const Tensor& t);\n";
}
// generate output getters
- if (ma.getOutputs().size() == 1) {
+ if (ma.getOutputs().size() == 1)
+ {
out << " std::shared_ptr<Tensor> getOutput();\n";
}
- for (const size_t out_id: ma.getPersistentTensors()) {
- const string& tensor_name = _formattedTensors[out_id];
+ for (const size_t out_id : ma.getPersistentTensors())
+ {
+ const string &tensor_name = _formattedTensors[out_id];
out << " std::shared_ptr<Tensor> get" << tensor_name << "();\n";
}
out << " void doInference();\n\n"
"private:\n"
- " " << class_name << "() = delete;\n"
- " " << class_name << "(const " << class_name << "& orig) = delete;\n"
- " " << class_name << "& operator=(const " << class_name << "& orig) = delete;\n";
+ " "
+ << class_name << "() = delete;\n"
+ " "
+ << class_name << "(const " << class_name << "& orig) = delete;\n"
+ " "
+ << class_name << "& operator=(const " << class_name << "& orig) = delete;\n";
// generate input/output tensors
- for (const size_t in_tensor_id: ma.getInputs()) {
- const string& tName = _formattedTensors[in_tensor_id];
+ for (const size_t in_tensor_id : ma.getInputs())
+ {
+ const string &tName = _formattedTensors[in_tensor_id];
out << " Tensor " << tName << ";\n";
}
- for (const size_t out_tensor_id: ma.getPersistentTensors()) {
- const string& tName = _formattedTensors[out_tensor_id];
+ for (const size_t out_tensor_id : ma.getPersistentTensors())
+ {
+ const string &tName = _formattedTensors[out_tensor_id];
out << " std::shared_ptr<Tensor> " << tName << ";\n";
}
// pointer to NN parameters
* @param out Stream to write program text
* @param args arguments to print
*/
-static void printOperationArgs(ostream& out, const vector<string>& args) {
+static void printOperationArgs(ostream &out, const vector<string> &args)
+{
bool insert_comma = false;
- for (const string& arg: args) {
+ for (const string &arg : args)
+ {
if (insert_comma)
out << ", ";
insert_comma = true;
}
}
-void CPPCodeGenerator::gatherOperationArguments(const ModelAnalyzer& ma,
- const vector<size_t>& arg_ids,
- vector<string>& args) {
+void CPPCodeGenerator::gatherOperationArguments(const ModelAnalyzer &ma,
+ const vector<size_t> &arg_ids, vector<string> &args)
+{
- for (size_t id: arg_ids) {
- const string& tensor_name = _formattedTensors[id];
+ for (size_t id : arg_ids)
+ {
+ const string &tensor_name = _formattedTensors[id];
if (ma.getTensors()[id].type == TensorDescriptor::Type::persistent)
args.push_back("*" + tensor_name);
else
}
}
-void CPPCodeGenerator::printSetter(ostream& out,
- const string& class_name,
- const string& setter_name,
- const TensorDescriptor& td) {
+void CPPCodeGenerator::printSetter(ostream &out, const string &class_name,
+ const string &setter_name, const TensorDescriptor &td)
+{
- const string& var_name = _formattedTensors[td.id];
+ const string &var_name = _formattedTensors[td.id];
out << "bool " << class_name << "::set" << setter_name << "(const Tensor& t)\n"
- "{\n";
+ "{\n";
// need to insert input correctness check
const mir::Shape expected = td.shape;
int rank = expected.rank();
- if (rank != 0) {
- out << " " << "if (t.getShape().getDims() != " << td.shape.rank() << ") return false;\n";
+ if (rank != 0)
+ {
+ out << " "
+ << "if (t.getShape().getDims() != " << td.shape.rank() << ") return false;\n";
for (int i = 0; i < rank; ++i)
- out << " " << "if (t.getShape()[" << i << "] != " << expected.dim(i) << ") return false;\n";
+ out << " "
+ << "if (t.getShape()[" << i << "] != " << expected.dim(i) << ") return false;\n";
}
out << " " << var_name << " = t;\n"
- " return true;\n"
- "}\n\n";
+ " return true;\n"
+ "}\n\n";
}
-void CPPCodeGenerator::printGetter(ostream& out,
- const string& class_name,
- const string& getter_name,
- const TensorDescriptor& td) {
+void CPPCodeGenerator::printGetter(ostream &out, const string &class_name,
+ const string &getter_name, const TensorDescriptor &td)
+{
- const string& var_name = _formattedTensors[td.id];
- out << "shared_ptr<Tensor> " << class_name <<"::get" << getter_name << "()\n"
- "{\n"
- " return " << var_name << ";\n"
- "}\n\n";
+ const string &var_name = _formattedTensors[td.id];
+ out << "shared_ptr<Tensor> " << class_name << "::get" << getter_name << "()\n"
+ "{\n"
+ " return "
+ << var_name << ";\n"
+ "}\n\n";
}
-void CPPCodeGenerator::materializeCall(ostream& out, const ModelAnalyzer& ma,
- const sir::CallFunction* call) {
+void CPPCodeGenerator::materializeCall(ostream &out, const ModelAnalyzer &ma,
+ const sir::CallFunction *call)
+{
assert(call != nullptr);
if (call->mirOp->getType() == mir::Operation::Type::input)
return;
// materialize call
out << " " << call->funcName << "(";
- const auto& prev_nodes = call->mirOp->getInputs();
- const auto& out_tensors = call->outputs;
+ const auto &prev_nodes = call->mirOp->getInputs();
+ const auto &out_tensors = call->outputs;
vector<string> args;
args.reserve(prev_nodes.size() + out_tensors.size() + 1);
// gather output arguments
out << ");\n";
}
-void CPPCodeGenerator::materializeTranspose(ostream& out, const ModelAnalyzer& ma,
- const sir::TransposeTensor* transpose) {
+void CPPCodeGenerator::materializeTranspose(ostream &out, const ModelAnalyzer &ma,
+ const sir::TransposeTensor *transpose)
+{
assert(transpose != nullptr);
(void)out;
(void)ma;
assert(false && "not implemented");
}
-void CPPCodeGenerator::materializeConstructor(ostream& out, const ModelAnalyzer& ma,
- const sir::CreateTmp* constructor) {
+void CPPCodeGenerator::materializeConstructor(ostream &out, const ModelAnalyzer &ma,
+ const sir::CreateTmp *constructor)
+{
assert(constructor != nullptr);
- const TensorDescriptor& td = ma.getTensors()[constructor->tensorId];
+ const TensorDescriptor &td = ma.getTensors()[constructor->tensorId];
assert(td.type == sir::TensorDescriptor::Type::temporary);
(void)td;
- const string& t_name = _formattedTensors[constructor->tensorId];
+ const string &t_name = _formattedTensors[constructor->tensorId];
out << " Tensor " << t_name << ";\n";
}
-void CPPCodeGenerator::materializeDestructor(ostream& out, const ModelAnalyzer& ma,
- const sir::DestroyTmp* destructor) {
+void CPPCodeGenerator::materializeDestructor(ostream &out, const ModelAnalyzer &ma,
+ const sir::DestroyTmp *destructor)
+{
assert(destructor != nullptr);
- const TensorDescriptor& td = ma.getTensors()[destructor->tensorId];
+ const TensorDescriptor &td = ma.getTensors()[destructor->tensorId];
assert(td.type == sir::TensorDescriptor::Type::temporary);
(void)td;
- const string& t_name = _formattedTensors[destructor->tensorId];
+ const string &t_name = _formattedTensors[destructor->tensorId];
out << " " << t_name << ".clean();\n";
}
-
-void CPPCodeGenerator::materializeInferenceSequence(ostream& out, const ModelAnalyzer& ma) {
+void CPPCodeGenerator::materializeInferenceSequence(ostream &out, const ModelAnalyzer &ma)
+{
// Allocate temporary(im2col) tensor
- out << " Tensor " << _formattedTensors[ma.getTempTID()] <<
- "(Shape{" << ma.getMaxTemporarySize() << "});\n";
-
- for (const unique_ptr<Action>& action: ma.getInferenceSequence()) {
- Action* ptr = action.get();
- switch (action->type) {
+ out << " Tensor " << _formattedTensors[ma.getTempTID()] << "(Shape{" << ma.getMaxTemporarySize()
+ << "});\n";
+
+ for (const unique_ptr<Action> &action : ma.getInferenceSequence())
+ {
+ Action *ptr = action.get();
+ switch (action->type)
+ {
case Action::Type::callFunction:
- materializeCall(out, ma, dynamic_cast<const sir::CallFunction*>(ptr));
+ materializeCall(out, ma, dynamic_cast<const sir::CallFunction *>(ptr));
break;
case Action::Type::transposeTensor:
- materializeTranspose(out, ma, dynamic_cast<const sir::TransposeTensor*>(ptr));
+ materializeTranspose(out, ma, dynamic_cast<const sir::TransposeTensor *>(ptr));
break;
case Action::Type::createTmp:
- materializeConstructor(out, ma, dynamic_cast<const sir::CreateTmp*>(ptr));
+ materializeConstructor(out, ma, dynamic_cast<const sir::CreateTmp *>(ptr));
break;
case Action::Type::destroyTmp:
- materializeDestructor(out, ma, dynamic_cast<const sir::DestroyTmp*>(ptr));
+ materializeDestructor(out, ma, dynamic_cast<const sir::DestroyTmp *>(ptr));
break;
default:
assert(false && "unexpected action type");
}
/**
- * Function writes to output stream needed code snippets, and implementations of artifact class functions.
+ * Function writes to output stream needed code snippets, and implementations of artifact class
+ * functions.
*/
-void CPPCodeGenerator::materializeCode(ostream& out, const ModelAnalyzer& ma, const Serializer& s) {
+void CPPCodeGenerator::materializeCode(ostream &out, const ModelAnalyzer &ma, const Serializer &s)
+{
string class_name = ma.getModelName() + "Model";
out << "#include \"" << cli::artifactName << ".h\"\n";
out.write(cpp_leaky_relu, sizeof(cpp_leaky_relu));
// gen NN constructor
- out << class_name << "::" << class_name << "(const string& parametersPath)\n"
+ out << class_name << "::" << class_name
+ << "(const string& parametersPath)\n"
"{\n"
" readParameters(_parameters, _paramSize, parametersPath, "
<< s.getFormatVersion() << ", " << s.getModelHash() << ");\n"
- "}\n\n";
+ "}\n\n";
// gen NN destructor
out << class_name << "::~" << class_name << "()\n"
- "{\n"
- " releaseParameters(_parameters, _paramSize);\n"
- "}\n\n";
+ "{\n"
+ " releaseParameters(_parameters, _paramSize);\n"
+ "}\n\n";
// generate input setters
// generate main setter if network has only one
- const auto& inputs = ma.getInputs();
- const auto& tensors = ma.getTensors();
- if (inputs.size() == 1) {
- const TensorDescriptor& td = tensors[inputs[0]];
+ const auto &inputs = ma.getInputs();
+ const auto &tensors = ma.getTensors();
+ if (inputs.size() == 1)
+ {
+ const TensorDescriptor &td = tensors[inputs[0]];
printSetter(out, class_name, "Input", td);
}
// generate setters by names
- for (size_t input_tensor_id: inputs) {
- const string& input_tensor_name = _formattedTensors[input_tensor_id];
- const TensorDescriptor& td = tensors[input_tensor_id];
+ for (size_t input_tensor_id : inputs)
+ {
+ const string &input_tensor_name = _formattedTensors[input_tensor_id];
+ const TensorDescriptor &td = tensors[input_tensor_id];
printSetter(out, class_name, input_tensor_name, td);
}
// gen output getters
// generate main getter if network has only one
- const auto& outputs = ma.getOutputs();
- if (outputs.size() == 1) {
- const TensorDescriptor& td = tensors[outputs[0]];
+ const auto &outputs = ma.getOutputs();
+ if (outputs.size() == 1)
+ {
+ const TensorDescriptor &td = tensors[outputs[0]];
printGetter(out, class_name, "Output", td);
}
- for (size_t output_tensor_id: ma.getPersistentTensors()) {
- const string& output_tensor_name = _formattedTensors[output_tensor_id];
- const TensorDescriptor& td = tensors[output_tensor_id];
+ for (size_t output_tensor_id : ma.getPersistentTensors())
+ {
+ const string &output_tensor_name = _formattedTensors[output_tensor_id];
+ const TensorDescriptor &td = tensors[output_tensor_id];
printGetter(out, class_name, output_tensor_name, td);
}
out << "void " << class_name << "::doInference()\n"
- "{\n";
- for (size_t output_tensor_id: ma.getPersistentTensors()) {
- const string& output_tensor_name = _formattedTensors[output_tensor_id];
+ "{\n";
+ for (size_t output_tensor_id : ma.getPersistentTensors())
+ {
+ const string &output_tensor_name = _formattedTensors[output_tensor_id];
out << " " << output_tensor_name << ".reset(new Tensor());\n";
}
using namespace std;
-namespace nnc {
+namespace nnc
+{
using namespace mir;
using namespace sir;
-void ModelAnalyzer::appendOperationToInference(
- Operation* op, const string& function_name, std::vector<size_t> aux_args) {
+void ModelAnalyzer::appendOperationToInference(Operation *op, const string &function_name,
+ std::vector<size_t> aux_args)
+{
vector<size_t> node_output_tensors;
- const string& op_name = op->getName();
+ const string &op_name = op->getName();
// process operation outputs
size_t node_output_tensor_id = INVALID_TENSOR_ID;
- if (op->getType() == Operation::Type::input) {
+ if (op->getType() == Operation::Type::input)
+ {
// register input tensor
node_output_tensor_id = declareInputTensor(op_name, op->getOutputShape(0));
- } else if (op->getType() == Operation::Type::constant) {
+ }
+ else if (op->getType() == Operation::Type::constant)
+ {
// register constant tensor
// it's data is deserialized to described tensor by O(1) at runtime
node_output_tensor_id = declareTemporaryTensor();
- } else if (op->getType() == Operation::Type::output) {
+ }
+ else if (op->getType() == Operation::Type::output)
+ {
// process output op
node_output_tensor_id = declarePersistentTensor(op_name);
- } else if (!op_name.empty()) {
+ }
+ else if (!op_name.empty())
+ {
// process a named operation
node_output_tensor_id = declarePersistentTensor(op_name);
- } else {
+ }
+ else
+ {
// process ordinary unnamed operation
node_output_tensor_id = declareTemporaryTensor();
}
// process operation inputs
vector<size_t> node_input_tensors;
- for (const auto& input: op->getInputs()) {
+ for (const auto &input : op->getInputs())
+ {
size_t idx = input.getProducer()->getIndex();
- const Operation* prev_op = input.getProducer()->getNode();
+ const Operation *prev_op = input.getProducer()->getNode();
assert(_opToDescr.find(prev_op) != _opToDescr.end());
- auto call = dynamic_cast<const CallFunction*>(_opToDescr[prev_op]);
+ auto call = dynamic_cast<const CallFunction *>(_opToDescr[prev_op]);
assert(call);
- const size_t& in_tensor_id = call->outputs[idx];
+ const size_t &in_tensor_id = call->outputs[idx];
node_input_tensors.push_back(in_tensor_id);
}
std::copy(aux_args.begin(), aux_args.end(), std::back_inserter(node_input_tensors));
- unique_ptr<Action> operation_call(new CallFunction(op, function_name,
- std::move(node_input_tensors),
- std::move(node_output_tensors)));
+ unique_ptr<Action> operation_call(new CallFunction(
+ op, function_name, std::move(node_input_tensors), std::move(node_output_tensors)));
_inferenceSequence.push_back(std::move(operation_call));
_opToDescr[op] = _inferenceSequence.back().get();
}
-void ModelAnalyzer::updateMaxTemporarySize(const size_t size) {
+void ModelAnalyzer::updateMaxTemporarySize(const size_t size)
+{
_max_temp_size = std::max(_max_temp_size, size);
}
-size_t ModelAnalyzer::declareInputTensor(const std::string& name, const mir::Shape& shape) {
+size_t ModelAnalyzer::declareInputTensor(const std::string &name, const mir::Shape &shape)
+{
assert(!name.empty() && "Input tensor must have name");
size_t id = _allocatedTensors++;
_tensors.push_back({id, TensorDescriptor::Type::input, name, shape});
return id;
}
-size_t ModelAnalyzer::declarePersistentTensor(const std::string& name) {
+size_t ModelAnalyzer::declarePersistentTensor(const std::string &name)
+{
size_t id = _allocatedTensors++;
auto type = TensorDescriptor::Type::persistent;
- if (name.empty()) {
+ if (name.empty())
+ {
// special case for unnamed output tensors
_tensors.push_back({id, type, "unnamed_output" + to_string(id), {}});
- } else {
+ }
+ else
+ {
_tensors.push_back({id, type, name, {}});
}
_persistent_tensors.push_back(id);
return id;
}
-size_t ModelAnalyzer::declareTemporaryTensor() {
+size_t ModelAnalyzer::declareTemporaryTensor()
+{
size_t id = _allocatedTensors++;
_tensors.push_back({id, TensorDescriptor::Type::temporary, "", {}});
return id;
}
-void ModelAnalyzer::gatherDefUseInfo(const vector<unique_ptr<Action>>& post_order,
- map<size_t, size_t>& first_def,
- map<size_t, size_t>& last_use) {
+void ModelAnalyzer::gatherDefUseInfo(const vector<unique_ptr<Action>> &post_order,
+ map<size_t, size_t> &first_def, map<size_t, size_t> &last_use)
+{
- for (size_t pos = 0; pos < post_order.size(); ++pos) {
- const unique_ptr<Action>& action = post_order[pos];
- const CallFunction* call = dynamic_cast<CallFunction*>(action.get());
+ for (size_t pos = 0; pos < post_order.size(); ++pos)
+ {
+ const unique_ptr<Action> &action = post_order[pos];
+ const CallFunction *call = dynamic_cast<CallFunction *>(action.get());
assert(call);
// update def info
- for (size_t output_tensor_id : call->outputs) {
- const TensorDescriptor& td = _tensors[output_tensor_id];
+ for (size_t output_tensor_id : call->outputs)
+ {
+ const TensorDescriptor &td = _tensors[output_tensor_id];
if (td.type != TensorDescriptor::Type::temporary)
continue;
}
// update usage info
- for (size_t input_tensor_id : call->inputs) {
- const TensorDescriptor& td = _tensors[input_tensor_id];
+ for (size_t input_tensor_id : call->inputs)
+ {
+ const TensorDescriptor &td = _tensors[input_tensor_id];
if (td.type != TensorDescriptor::Type::temporary)
continue;
}
}
-void ModelAnalyzer::constructInferenceSequence(const vector<Operation*>& post_order) {
+void ModelAnalyzer::constructInferenceSequence(const vector<Operation *> &post_order)
+{
// Run inference sequence construction over constructed list of operations
- for (auto it = post_order.rbegin(); it != post_order.rend(); ++it) {
- Operation* node = *it;
+ for (auto it = post_order.rbegin(); it != post_order.rend(); ++it)
+ {
+ Operation *node = *it;
node->accept(this);
}
old_inference_seq.swap(_inferenceSequence);
_inferenceSequence.reserve(old_inference_seq.size());
-
- for (size_t pos = 0; pos < old_inference_seq.size(); ++pos) {
- unique_ptr<Action>& action = old_inference_seq[pos];
- const CallFunction* call = dynamic_cast<CallFunction*>(action.get());
+ for (size_t pos = 0; pos < old_inference_seq.size(); ++pos)
+ {
+ unique_ptr<Action> &action = old_inference_seq[pos];
+ const CallFunction *call = dynamic_cast<CallFunction *>(action.get());
assert(call);
// construct required temporary tensors
- for (size_t output_tensor_id : call->outputs) {
- const TensorDescriptor& td = _tensors[output_tensor_id];
+ for (size_t output_tensor_id : call->outputs)
+ {
+ const TensorDescriptor &td = _tensors[output_tensor_id];
assert(td.id == output_tensor_id);
if (td.type != TensorDescriptor::Type::temporary)
continue;
- if (first_def[output_tensor_id] == pos) {
+ if (first_def[output_tensor_id] == pos)
+ {
unique_ptr<Action> tmp_constructor(new CreateTmp(output_tensor_id));
_inferenceSequence.push_back(std::move(tmp_constructor));
}
_inferenceSequence.push_back(std::move(action));
// destroy unused temporary tensors
- for (size_t input_tensor_id : call->inputs) {
- const TensorDescriptor& td = _tensors[input_tensor_id];
+ for (size_t input_tensor_id : call->inputs)
+ {
+ const TensorDescriptor &td = _tensors[input_tensor_id];
assert(td.id == input_tensor_id);
if (td.type != TensorDescriptor::Type::temporary)
continue;
- if (last_use[input_tensor_id] == pos) {
+ if (last_use[input_tensor_id] == pos)
+ {
unique_ptr<Action> tmp_destructor(new DestroyTmp(input_tensor_id));
_inferenceSequence.push_back(std::move(tmp_destructor));
}
}
}
-void ModelAnalyzer::collectOutputs(const mir::Graph* g) {
- for (ops::OutputOp* out_op: g->getOutputs()) {
- auto op_call = dynamic_cast<const CallFunction*>(_opToDescr[out_op]);
+void ModelAnalyzer::collectOutputs(const mir::Graph *g)
+{
+ for (ops::OutputOp *out_op : g->getOutputs())
+ {
+ auto op_call = dynamic_cast<const CallFunction *>(_opToDescr[out_op]);
assert(op_call);
_outputs.insert(_outputs.end(), op_call->outputs.begin(), op_call->outputs.end());
}
}
-void ModelAnalyzer::analyze(const mir::Graph* g) {
+void ModelAnalyzer::analyze(const mir::Graph *g)
+{
// Current path through graph
- stack<pair<Operation*, size_t>> s;
+ stack<pair<Operation *, size_t>> s;
// Nodes in Reverse Post Order stored by DFS
- vector<Operation*> post_order;
+ vector<Operation *> post_order;
// Set contains pointer to node if it is visited by DFS
- set<Operation*> visited;
+ set<Operation *> visited;
- vector<Operation*> init_ops;
- for (Operation* op : g->getNodes()) {
- if (op->getNumInputs() == 0) {
+ vector<Operation *> init_ops;
+ for (Operation *op : g->getNodes())
+ {
+ if (op->getNumInputs() == 0)
+ {
init_ops.emplace_back(op);
}
}
_temp_tensor_id = declareTemporaryTensor();
// Walk all network inputs
- for (Operation* in : init_ops) {
- if (!visited.count(in)) {
+ for (Operation *in : init_ops)
+ {
+ if (!visited.count(in))
+ {
visited.insert(in);
s.push({in, 0});
}
// main DFS loop
- while (!s.empty()) {
+ while (!s.empty())
+ {
// top stores current node and current outgoing edge from it
- auto& top = s.top();
- Operation* node = top.first;
+ auto &top = s.top();
+ Operation *node = top.first;
auto edge = top.second++;
// FIXME Refactor me.
- std::vector<Operation*> next_nodes;
- for (const auto& out : node->getOutputs()) {
- const auto& consumers = out.getConsumers();
+ std::vector<Operation *> next_nodes;
+ for (const auto &out : node->getOutputs())
+ {
+ const auto &consumers = out.getConsumers();
std::transform(consumers.begin(), consumers.end(), std::back_inserter(next_nodes),
- [](Operation::Input* input) { return input->getNode(); });
+ [](Operation::Input *input) { return input->getNode(); });
}
- if (edge == next_nodes.size()) {
+ if (edge == next_nodes.size())
+ {
// this node is fully analyzed, push it into RPO and pop from stack
post_order.push_back(node);
s.pop();
- } else {
+ }
+ else
+ {
// Search current outgoing edge
- Operation* successor = next_nodes[edge];
- if (!visited.count(successor)) {
+ Operation *successor = next_nodes[edge];
+ if (!visited.count(successor))
+ {
visited.insert(successor);
s.push({next_nodes[edge], 0});
}
collectOutputs(g);
}
-void ModelAnalyzer::visit(ops::ConcatOp& op) {
- appendOperationToInference(&op, "concat");
-}
+void ModelAnalyzer::visit(ops::ConcatOp &op) { appendOperationToInference(&op, "concat"); }
-void ModelAnalyzer::visit(ops::Conv2DOp& op) {
- const auto& kernel_shape = op.getInputShape(1);
- const auto& out_shape = op.getOutputShape(0);
- const int32_t tmp_size = kernel_shape.dim(1) * kernel_shape.dim(2) * kernel_shape.dim(3)
- * out_shape.dim(0) * out_shape.dim(1) * out_shape.dim(2);
+void ModelAnalyzer::visit(ops::Conv2DOp &op)
+{
+ const auto &kernel_shape = op.getInputShape(1);
+ const auto &out_shape = op.getOutputShape(0);
+ const int32_t tmp_size = kernel_shape.dim(1) * kernel_shape.dim(2) * kernel_shape.dim(3) *
+ out_shape.dim(0) * out_shape.dim(1) * out_shape.dim(2);
updateMaxTemporarySize(static_cast<size_t>(tmp_size));
appendOperationToInference(&op, "conv2d", {_temp_tensor_id});
}
-void ModelAnalyzer::visit(ops::DepthwiseConv2DOp& op) {
+void ModelAnalyzer::visit(ops::DepthwiseConv2DOp &op)
+{
appendOperationToInference(&op, "depthwiseConv2d");
}
-void ModelAnalyzer::visit(ops::SoftmaxOp& op) {
- appendOperationToInference(&op, "softmax");
-}
+void ModelAnalyzer::visit(ops::SoftmaxOp &op) { appendOperationToInference(&op, "softmax"); }
/**
* Model Ir does not separate different types of pool operations, but for code generation
* it is easier to implement different types of pooling by different functions
*/
-void ModelAnalyzer::visit(ops::PoolOp& op) {
- const char* func_name = nullptr;
- switch (op.getPoolingType()) {
+void ModelAnalyzer::visit(ops::PoolOp &op)
+{
+ const char *func_name = nullptr;
+ switch (op.getPoolingType())
+ {
case ops::PoolOp::PoolingType::MAX:
func_name = "maxPool";
break;
appendOperationToInference(&op, func_name);
}
-void ModelAnalyzer::visit(ops::FullyConnectedOp& op) {
+void ModelAnalyzer::visit(ops::FullyConnectedOp &op)
+{
appendOperationToInference(&op, "fullConnect");
}
-void ModelAnalyzer::visit(ops::GemmOp& op) {
- appendOperationToInference(&op, "gemmOp");
-}
+void ModelAnalyzer::visit(ops::GemmOp &op) { appendOperationToInference(&op, "gemmOp"); }
-void ModelAnalyzer::visit(ops::CappedReluOp& op) {
- appendOperationToInference(&op, "cappedRelu");
-}
+void ModelAnalyzer::visit(ops::CappedReluOp &op) { appendOperationToInference(&op, "cappedRelu"); }
-void ModelAnalyzer::visit(ops::InputOp& op) {
+void ModelAnalyzer::visit(ops::InputOp &op)
+{
assert(op.getNumInputs() == 0);
appendOperationToInference(&op, "in");
}
-void ModelAnalyzer::visit(ops::ConstantOp& op) {
+void ModelAnalyzer::visit(ops::ConstantOp &op)
+{
assert(op.getNumInputs() == 0);
// FIXME This is to work around deserializeTensors not being able to deserialize tensors of type
// other than float32.
- const auto* output = op.getOutput(0);
+ const auto *output = op.getOutput(0);
if (output->getConsumers().empty())
return;
appendOperationToInference(&op, "constant");
}
-void ModelAnalyzer::visit(ops::ReluOp& op) {
- appendOperationToInference(&op, "relu");
-}
+void ModelAnalyzer::visit(ops::ReluOp &op) { appendOperationToInference(&op, "relu"); }
-void ModelAnalyzer::visit(ops::ReshapeOp& op) {
- appendOperationToInference(&op, "reshape");
-}
+void ModelAnalyzer::visit(ops::ReshapeOp &op) { appendOperationToInference(&op, "reshape"); }
-void ModelAnalyzer::visit(mir::ops::ResizeOp& op) {
- switch (op.getMode()) {
+void ModelAnalyzer::visit(mir::ops::ResizeOp &op)
+{
+ switch (op.getMode())
+ {
case mir::ops::ResizeOp::ResizeMethod::nearestNeighbor:
appendOperationToInference(&op, "resize");
break;
}
}
-void ModelAnalyzer::visit(ops::DropoutOp& op) {
- appendOperationToInference(&op, "dropout");
-}
+void ModelAnalyzer::visit(ops::DropoutOp &op) { appendOperationToInference(&op, "dropout"); }
-void ModelAnalyzer::visit(mir::ops::SliceOp& op) {
- appendOperationToInference(&op, "slice");
-}
+void ModelAnalyzer::visit(mir::ops::SliceOp &op) { appendOperationToInference(&op, "slice"); }
-void ModelAnalyzer::visit(ops::BatchNormOp& op) {
- appendOperationToInference(&op, "batchNorm");
-}
+void ModelAnalyzer::visit(ops::BatchNormOp &op) { appendOperationToInference(&op, "batchNorm"); }
-void ModelAnalyzer::visit(mir::ops::TanhOp& op) {
+void ModelAnalyzer::visit(mir::ops::TanhOp &op)
+{
appendOperationToInference(&op, "tanhActivation");
}
-void ModelAnalyzer::visit(mir::ops::EluOp& op) {
- appendOperationToInference(&op, "elu");
-}
+void ModelAnalyzer::visit(mir::ops::EluOp &op) { appendOperationToInference(&op, "elu"); }
-void ModelAnalyzer::visit(mir::ops::DeConv2DOp& op) {
- const auto& kernel_shape = op.getInputShape(1);
- const auto& out_shape = op.getOutputShape(0);
+void ModelAnalyzer::visit(mir::ops::DeConv2DOp &op)
+{
+ const auto &kernel_shape = op.getInputShape(1);
+ const auto &out_shape = op.getOutputShape(0);
const int32_t tmp_size = kernel_shape.dim(0) * kernel_shape.dim(1) * kernel_shape.dim(3) *
out_shape.dim(0) * out_shape.dim(1) * out_shape.dim(2);
updateMaxTemporarySize(static_cast<size_t>(tmp_size));
appendOperationToInference(&op, "convTransposed2d", {_temp_tensor_id});
}
-void ModelAnalyzer::visit(ops::SqueezeOp& op) {
- appendOperationToInference(&op, "reshape");
-}
+void ModelAnalyzer::visit(ops::SqueezeOp &op) { appendOperationToInference(&op, "reshape"); }
-void ModelAnalyzer::visit(ops::SqrtOp& op) {
- appendOperationToInference(&op, "sqrtFN");
-}
+void ModelAnalyzer::visit(ops::SqrtOp &op) { appendOperationToInference(&op, "sqrtFN"); }
-void ModelAnalyzer::visit(mir::ops::PadOp& op) {
- appendOperationToInference(&op, "pad");
-}
+void ModelAnalyzer::visit(mir::ops::PadOp &op) { appendOperationToInference(&op, "pad"); }
-void ModelAnalyzer::visit(mir::ops::ReduceOp& op) {
- switch (op.getFuncType()) {
+void ModelAnalyzer::visit(mir::ops::ReduceOp &op)
+{
+ switch (op.getFuncType())
+ {
case mir::ops::ReduceOp::FuncType::mean:
appendOperationToInference(&op, "reduceMean");
break;
}
}
-void ModelAnalyzer::visit(mir::ops::TransposeOp& op) {
+void ModelAnalyzer::visit(mir::ops::TransposeOp &op)
+{
appendOperationToInference(&op, "transpose");
}
-void ModelAnalyzer::visit(mir::ops::GatherOp& op) {
- appendOperationToInference(&op, "gather");
-}
+void ModelAnalyzer::visit(mir::ops::GatherOp &op) { appendOperationToInference(&op, "gather"); }
-void ModelAnalyzer::visit(mir::ops::SigmoidOp& op) {
- appendOperationToInference(&op, "sigmoid");
-}
+void ModelAnalyzer::visit(mir::ops::SigmoidOp &op) { appendOperationToInference(&op, "sigmoid"); }
-void ModelAnalyzer::visit(mir::ops::LeakyReluOp& op) {
+void ModelAnalyzer::visit(mir::ops::LeakyReluOp &op)
+{
appendOperationToInference(&op, "leakyRelu");
}
-void ModelAnalyzer::visit(mir::ops::OutputOp& op) {
- appendOperationToInference(&op, "out");
-}
+void ModelAnalyzer::visit(mir::ops::OutputOp &op) { appendOperationToInference(&op, "out"); }
void ModelAnalyzer::visit(mir::ops::AddOp &op)
{
#include <cassert>
#include <iterator>
-namespace nnc {
+namespace nnc
+{
/**
* @brief Constructs inference sequence for given computational graph,
* gathers list of variables used in artifact.
*/
-class ModelAnalyzer: public mir::IVisitor {
+class ModelAnalyzer : public mir::IVisitor
+{
public:
-
/**
* @brief contructs inference sequence
* @param g pointer to graph to linearize
*/
- void analyze(const mir::Graph* g);
-
- void visit(mir::ops::AddOp& op) override;
- void visit(mir::ops::BatchNormOp& op) override;
- void visit(mir::ops::CappedReluOp& op) override;
- void visit(mir::ops::ConcatOp& op) override;
- void visit(mir::ops::ConstantOp& op) override;
- void visit(mir::ops::Conv2DOp& op) override;
- void visit(mir::ops::DeConv2DOp& op) override;
- void visit(mir::ops::DepthwiseConv2DOp& op) override;
- void visit(mir::ops::DivOp& op) override;
- void visit(mir::ops::DropoutOp& op) override;
- void visit(mir::ops::EluOp& op) override;
- void visit(mir::ops::FullyConnectedOp& op) override;
- void visit(mir::ops::GatherOp& op) override;
- void visit(mir::ops::GemmOp& op) override;
- void visit(mir::ops::InputOp& op) override;
- void visit(mir::ops::LeakyReluOp& op) override;
- void visit(mir::ops::MaxOp& op) override;
- void visit(mir::ops::MulOp& op) override;
- void visit(mir::ops::OutputOp& op) override;
- void visit(mir::ops::PadOp& op) override;
- void visit(mir::ops::PoolOp& op) override;
- void visit(mir::ops::ReduceOp& op) override;
- void visit(mir::ops::ReluOp& op) override;
- void visit(mir::ops::ReshapeOp& op) override;
- void visit(mir::ops::ResizeOp& op) override;
- void visit(mir::ops::SigmoidOp& op) override;
- void visit(mir::ops::SliceOp& op) override;
- void visit(mir::ops::SoftmaxOp& op) override;
- void visit(mir::ops::SqrtOp& op) override;
- void visit(mir::ops::SqueezeOp& op) override;
- void visit(mir::ops::SubOp& op) override;
- void visit(mir::ops::TanhOp& op) override;
- void visit(mir::ops::TransposeOp& op) override;
+ void analyze(const mir::Graph *g);
+
+ void visit(mir::ops::AddOp &op) override;
+ void visit(mir::ops::BatchNormOp &op) override;
+ void visit(mir::ops::CappedReluOp &op) override;
+ void visit(mir::ops::ConcatOp &op) override;
+ void visit(mir::ops::ConstantOp &op) override;
+ void visit(mir::ops::Conv2DOp &op) override;
+ void visit(mir::ops::DeConv2DOp &op) override;
+ void visit(mir::ops::DepthwiseConv2DOp &op) override;
+ void visit(mir::ops::DivOp &op) override;
+ void visit(mir::ops::DropoutOp &op) override;
+ void visit(mir::ops::EluOp &op) override;
+ void visit(mir::ops::FullyConnectedOp &op) override;
+ void visit(mir::ops::GatherOp &op) override;
+ void visit(mir::ops::GemmOp &op) override;
+ void visit(mir::ops::InputOp &op) override;
+ void visit(mir::ops::LeakyReluOp &op) override;
+ void visit(mir::ops::MaxOp &op) override;
+ void visit(mir::ops::MulOp &op) override;
+ void visit(mir::ops::OutputOp &op) override;
+ void visit(mir::ops::PadOp &op) override;
+ void visit(mir::ops::PoolOp &op) override;
+ void visit(mir::ops::ReduceOp &op) override;
+ void visit(mir::ops::ReluOp &op) override;
+ void visit(mir::ops::ReshapeOp &op) override;
+ void visit(mir::ops::ResizeOp &op) override;
+ void visit(mir::ops::SigmoidOp &op) override;
+ void visit(mir::ops::SliceOp &op) override;
+ void visit(mir::ops::SoftmaxOp &op) override;
+ void visit(mir::ops::SqrtOp &op) override;
+ void visit(mir::ops::SqueezeOp &op) override;
+ void visit(mir::ops::SubOp &op) override;
+ void visit(mir::ops::TanhOp &op) override;
+ void visit(mir::ops::TransposeOp &op) override;
/**
* @return vector of id's of network input tensors
*/
- const std::vector<size_t>& getInputs() const {
- return _inputs;
- }
+ const std::vector<size_t> &getInputs() const { return _inputs; }
/**
* @return vector of id's of tensors with unique names taken from Model IR
*/
- const std::vector<size_t>& getPersistentTensors() const {
- return _persistent_tensors;
- }
+ const std::vector<size_t> &getPersistentTensors() const { return _persistent_tensors; }
/**
* @return vector of id's of network output tensors
*/
- const std::vector<size_t>& getOutputs() const {
- return _outputs;
- }
+ const std::vector<size_t> &getOutputs() const { return _outputs; }
/**
* @return vector of all network tensors
*/
- const std::vector<sir::TensorDescriptor>& getTensors() const {
- return _tensors;
- }
+ const std::vector<sir::TensorDescriptor> &getTensors() const { return _tensors; }
/**
* @return Inference sequence
*/
- const std::vector<std::unique_ptr<sir::Action>>& getInferenceSequence() const {
+ const std::vector<std::unique_ptr<sir::Action>> &getInferenceSequence() const
+ {
return _inferenceSequence;
}
/**
* @return Inference sequence
*/
- std::vector<std::unique_ptr<sir::Action>>& getInferenceSequence() {
- return _inferenceSequence;
- }
+ std::vector<std::unique_ptr<sir::Action>> &getInferenceSequence() { return _inferenceSequence; }
/**
* @return Model name, taken from Model IR
*/
- const std::string& getModelName() const {
- return _modelName;
- }
+ const std::string &getModelName() const { return _modelName; }
- size_t getMaxTemporarySize() const {
- return _max_temp_size;
- }
+ size_t getMaxTemporarySize() const { return _max_temp_size; }
- size_t getTempTID() const {
- return _temp_tensor_id;
- }
+ size_t getTempTID() const { return _temp_tensor_id; }
private:
/**
* @param aux_args Auxilliary argument ids
*
* Inserts information about CG operation into inference sequence: name of operation,
- * creates tensors for operation outputs, binds operation inputs with tensors from previous operations
+ * creates tensors for operation outputs, binds operation inputs with tensors from previous
+ * operations
*/
- void appendOperationToInference(mir::Operation* op,
- const std::string& function_name,
+ void appendOperationToInference(mir::Operation *op, const std::string &function_name,
std::vector<size_t> aux_args = {});
/**
* @param shape expected shape of input
* @return Id of created tensor
*/
- size_t declareInputTensor(const std::string& name, const mir::Shape& shape);
+ size_t declareInputTensor(const std::string &name, const mir::Shape &shape);
/**
* @brief Declares persistent tensor in artifact
* @param name Name of variable, if empty - assigned automaticly
* @return Id of created tensor
*/
- size_t declarePersistentTensor(const std::string& name);
+ size_t declarePersistentTensor(const std::string &name);
/**
* @brief Declares temporary tensor in artifact
* @param first_def Maps tensor id to position in inf sequence where it was defined first time.
* @param last_use Maps tensor id to position in inf sequence where it was used last time.
*/
- void gatherDefUseInfo(const std::vector<std::unique_ptr<sir::Action>>& post_order,
- std::map<size_t, size_t>& first_def,
- std::map<size_t, size_t>& last_use);
-
+ void gatherDefUseInfo(const std::vector<std::unique_ptr<sir::Action>> &post_order,
+ std::map<size_t, size_t> &first_def, std::map<size_t, size_t> &last_use);
/**
* @brief constructs inference sequence from vector of mir::Operations, constructed
* @param post_order vector representing layout of operations in inference
*/
- void constructInferenceSequence(const std::vector<mir::Operation*>& post_order);
+ void constructInferenceSequence(const std::vector<mir::Operation *> &post_order);
/**
* @brief Fill list of outputs in ModelAnalyzer
* @param g Graph where to get list of outputs
*/
- void collectOutputs(const mir::Graph* g);
+ void collectOutputs(const mir::Graph *g);
std::string _modelName = "NN";
std::vector<std::unique_ptr<sir::Action>> _inferenceSequence;
size_t _max_temp_size = 0;
size_t _temp_tensor_id = 0;
std::vector<sir::TensorDescriptor> _tensors;
- std::map<const mir::Operation*, const sir::Action*> _opToDescr;
+ std::map<const mir::Operation *, const sir::Action *> _opToDescr;
};
} // namespace nnc
#define UNUSED(x) ((void)(x))
-namespace nnc {
+namespace nnc
+{
static_assert(std::numeric_limits<float>::is_iec559, "Unsupported float type");
namespace ops = mir::ops;
-namespace {
+namespace
+{
// Currently there are no operations with more then 4 dimensions in kernels/weights etc supported
const auto MAX_DIMS = 4;
const auto MAX_DIM_SIZE = numeric_limits<int32_t>::max();
const auto MAX_ENUM_VAL = numeric_limits<char>::max();
} // unnamed namespace
-void Serializer::packData(const void* data, size_t size) {
- auto p = static_cast<const char*>(data);
+void Serializer::packData(const void *data, size_t size)
+{
+ auto p = static_cast<const char *>(data);
size_t old_size = _buffer.size();
_buffer.resize(old_size + size);
copy(p, p + size, _buffer.data() + old_size);
}
-template <typename T>
-void Serializer::serializeT(const T& obj) {
- packData(&obj, sizeof(T));
-}
+template <typename T> void Serializer::serializeT(const T &obj) { packData(&obj, sizeof(T)); }
/**
* @brief Convert enum to it's underlying type
* @param enum_value Value of enum
* @return Integer value that correspond to enumVal
*/
-template <typename E>
-typename underlying_type<E>::type etoi(E enum_value) {
+template <typename E> typename underlying_type<E>::type etoi(E enum_value)
+{
return static_cast<typename underlying_type<E>::type>(enum_value);
}
-void Serializer::serializeShape(const Shape& s) {
+void Serializer::serializeShape(const Shape &s)
+{
int32_t rank = s.rank();
assert(rank <= MAX_DIMS);
serializeT<int32_t>(s.rank());
- for (int32_t i = 0; i < rank; ++i) {
+ for (int32_t i = 0; i < rank; ++i)
+ {
int32_t dim = s.dim(i);
serializeT<int32_t>(dim);
}
}
-void Serializer::serializeTensor(const TensorVariant& t) {
+void Serializer::serializeTensor(const TensorVariant &t)
+{
// serialize type
assert(etoi(t.getDataType()) < MAX_ENUM_VAL);
serializeT<int32_t>(etoi(t.getDataType()));
assert(element_size <= MAX_DIMS);
serializeT<int32_t>(element_size);
// serialize shape
- const Shape& shape = t.getShape();
+ const Shape &shape = t.getShape();
serializeShape(shape);
// serialize actual data
size_t data_size = element_size * shape.numElements();
size_t old_serialized_data_size = _buffer.size();
_buffer.reserve(old_serialized_data_size + data_size);
- for (const Index& idx: ShapeRange(shape)) {
+ for (const Index &idx : ShapeRange(shape))
+ {
packData(t.at(idx), element_size);
}
}
-template <typename Op>
-void Serializer::serializePads(const Op& op, int32_t number_of_pads) {
+template <typename Op> void Serializer::serializePads(const Op &op, int32_t number_of_pads)
+{
assert(number_of_pads <= MAX_DIMS);
serializeT<int32_t>(number_of_pads);
- for (int i = 0; i < static_cast<int>(number_of_pads); ++i) {
+ for (int i = 0; i < static_cast<int>(number_of_pads); ++i)
+ {
auto pad = op.getPaddingBefore().at(i);
assert(pad <= MAX_DIM_SIZE);
assert(pad >= 0);
}
}
-void Serializer::visit(ops::ConcatOp& op) {
+void Serializer::visit(ops::ConcatOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
// axis number should fit into one byte
assert(op.getAxis() <= MAX_DIMS);
serializeShape(op.getOutputShape(0));
}
-void Serializer::visit(ops::Conv2DOp& op) {
+void Serializer::visit(ops::Conv2DOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
// serialize strides
serializeShape(op.getStrides());
serializeShape(op.getOutputShape(0));
}
-void Serializer::visit(ops::DepthwiseConv2DOp& op) {
+void Serializer::visit(ops::DepthwiseConv2DOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
// serialize strides
serializeShape(op.getStrides());
serializeShape(op.getOutputShape(0));
}
-void Serializer::visit(ops::SoftmaxOp& op) {
+void Serializer::visit(ops::SoftmaxOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
// axis number should fit into one byte
assert(op.getAxis() <= MAX_DIMS);
serializeT<int32_t>(op.getAxis());
}
-void Serializer::visit(ops::PoolOp& op) {
+void Serializer::visit(ops::PoolOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
// serialize window shape
serializeShape(op.getWindowShape());
serializePads(op, number_of_pads);
// serialize border type
PoolBorderType border_type;
- switch (op.getBorderType()) {
+ switch (op.getBorderType())
+ {
case ops::PoolOp::BorderType::EMPTY:
border_type = PoolBorderType::EMPTY;
break;
serializeShape(op.getOutputShape(0));
}
-void Serializer::visit(ops::FullyConnectedOp& op) {
+void Serializer::visit(ops::FullyConnectedOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
serializeShape(op.getOutputShape(0));
}
-void Serializer::visit(ops::GemmOp& op) {
+void Serializer::visit(ops::GemmOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
serializeShape(op.getOutputShape(0));
}
-void Serializer::visit(ops::CappedReluOp& op) {
+void Serializer::visit(ops::CappedReluOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
serializeT<float>(op.getCap());
}
-void Serializer::visit(ops::InputOp& /*op*/) {
+void Serializer::visit(ops::InputOp & /*op*/)
+{
// no parameters to dump
}
-void Serializer::visit(ops::ConstantOp& op) {
+void Serializer::visit(ops::ConstantOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
serializeTensor(op.getValue());
}
-void Serializer::visit(ops::ReluOp& /*op*/) {
+void Serializer::visit(ops::ReluOp & /*op*/)
+{
_curOp->paramStartOffset = _buffer.size();
// no parameters to dump
}
-void Serializer::visit(ops::ReshapeOp& op) {
+void Serializer::visit(ops::ReshapeOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
serializeShape(op.getOutputShape(0));
}
-void Serializer::visit(ops::BatchNormOp& op) {
+void Serializer::visit(ops::BatchNormOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
serializeT<float>(op.getEps());
serializeT<float>(op.getMovingAvgFraction());
serializeT<int32_t>(op.getSpatial());
}
-void Serializer::visit(mir::ops::SliceOp& op) {
+void Serializer::visit(mir::ops::SliceOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
serializeShape(op.getStarts());
serializeShape(op.getSizes());
serializeShape(op.getOutputShape(0));
}
-void Serializer::visit(ops::DropoutOp& op) {
+void Serializer::visit(ops::DropoutOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
serializeT<float>(op.getRate());
}
-void Serializer::visit(mir::ops::TanhOp& /*op*/) {
+void Serializer::visit(mir::ops::TanhOp & /*op*/)
+{
_curOp->paramStartOffset = _buffer.size();
// no parameters to dump
}
-void Serializer::visit(mir::ops::EluOp& op) {
+void Serializer::visit(mir::ops::EluOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
serializeT<float>(op.getAlpha());
}
-void Serializer::visit(mir::ops::DeConv2DOp& op) {
+void Serializer::visit(mir::ops::DeConv2DOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
// serialize strides
serializeShape(op.getStrides());
serializeShape(op.getOutputShape(0));
}
-void Serializer::visit(ops::SqueezeOp& op) {
+void Serializer::visit(ops::SqueezeOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
serializeShape(op.getOutputShape(0));
}
-void Serializer::visit(mir::ops::PadOp& op) {
+void Serializer::visit(mir::ops::PadOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
// serialize paddings
// serialize num dimensions
serializeT<int32_t>(op.getNumDim());
- for (int i = 0; i < num_dims; i++) {
+ for (int i = 0; i < num_dims; i++)
+ {
std::pair<int32_t, int32_t> pair = op.getPaddingForDim(num_dims - 1 - i);
serializeT<int32_t>(pair.first);
serializeT<int32_t>(pair.second);
}
}
-void Serializer::visit(mir::ops::SqrtOp& /*op*/) {
+void Serializer::visit(mir::ops::SqrtOp & /*op*/)
+{
_curOp->paramStartOffset = _buffer.size();
// no parameters to dump
}
-void Serializer::visit(mir::ops::ResizeOp& op) {
+void Serializer::visit(mir::ops::ResizeOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
// Result shape is the same as Output shape
serializeShape(op.getOutputShape(0));
}
-void Serializer::visit(mir::ops::ReduceOp& op) {
+void Serializer::visit(mir::ops::ReduceOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
serializeShape(Shape(op.getReductionDims())); // reuse shape serialization
serializeT<int32_t>(op.getKeepDims());
serializeShape(op.getOutputShape(0));
}
-void Serializer::visit(mir::ops::TransposeOp& op) {
+void Serializer::visit(mir::ops::TransposeOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
// serializer parameters
- auto& axis_order = op.getAxisOrder();
+ auto &axis_order = op.getAxisOrder();
serializeT(static_cast<int32_t>(axis_order.size()));
- for (auto& axis : axis_order)
+ for (auto &axis : axis_order)
serializeT(static_cast<int32_t>(axis));
// serialize output shape
serializeShape(op.getOutputShape(0));
}
-void Serializer::visit(mir::ops::GatherOp& op) {
+void Serializer::visit(mir::ops::GatherOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
// serialize parameters
serializeT<int32_t>(op.getAxis());
serializeShape(op.getOutputShape(0));
}
-void Serializer::visit(mir::ops::SigmoidOp& /*op*/) {
- _curOp->paramStartOffset = _buffer.size();
-}
+void Serializer::visit(mir::ops::SigmoidOp & /*op*/) { _curOp->paramStartOffset = _buffer.size(); }
-void Serializer::visit(mir::ops::LeakyReluOp& op) {
+void Serializer::visit(mir::ops::LeakyReluOp &op)
+{
_curOp->paramStartOffset = _buffer.size();
serializeT<float>(op.getAlpha());
serializeShape(op.getOutputShape(0));
}
-void Serializer::serialize(vector<unique_ptr<sir::Action>>& inference_sequence) {
- for (unique_ptr<sir::Action>& action: inference_sequence) {
+void Serializer::serialize(vector<unique_ptr<sir::Action>> &inference_sequence)
+{
+ for (unique_ptr<sir::Action> &action : inference_sequence)
+ {
if (action->type != sir::Action::Type::callFunction)
continue;
- _curOp = dynamic_cast<sir::CallFunction*>(action.get());
+ _curOp = dynamic_cast<sir::CallFunction *>(action.get());
_curOp->mirOp->accept(this);
}
}
-void Serializer::visit(mir::ops::OutputOp& /*op*/) {
+void Serializer::visit(mir::ops::OutputOp & /*op*/)
+{
// no parameters to dump
}
#include <vector>
#include <cstdint>
-namespace nnc {
+namespace nnc
+{
/**
* @brief Serializer of network parameters for soft backend
* To gather this vector use `getBuffer` method.
* Objects of this class are one-off and not designed to serialize more than one IR
*/
-class Serializer : public mir::IVisitor {
+class Serializer : public mir::IVisitor
+{
public:
- void visit(mir::ops::AddOp& op) override;
- void visit(mir::ops::BatchNormOp& op) override;
- void visit(mir::ops::CappedReluOp& op) override;
- void visit(mir::ops::ConcatOp& op) override;
- void visit(mir::ops::ConstantOp& op) override;
- void visit(mir::ops::Conv2DOp& op) override;
- void visit(mir::ops::DeConv2DOp& op) override;
- void visit(mir::ops::DepthwiseConv2DOp& op) override;
- void visit(mir::ops::DivOp& op) override;
- void visit(mir::ops::DropoutOp& op) override;
- void visit(mir::ops::EluOp& op) override;
- void visit(mir::ops::FullyConnectedOp& op) override;
- void visit(mir::ops::GatherOp& op) override;
- void visit(mir::ops::GemmOp& op) override;
- void visit(mir::ops::InputOp& op) override;
- void visit(mir::ops::LeakyReluOp& op) override;
- void visit(mir::ops::MaxOp& op) override;
- void visit(mir::ops::MulOp& op) override;
- void visit(mir::ops::OutputOp& op) override;
- void visit(mir::ops::PadOp& op) override;
- void visit(mir::ops::PoolOp& op) override;
- void visit(mir::ops::ReduceOp& op) override;
- void visit(mir::ops::ReluOp& op) override;
- void visit(mir::ops::ReshapeOp& op) override;
- void visit(mir::ops::ResizeOp& op) override;
- void visit(mir::ops::SigmoidOp& op) override;
- void visit(mir::ops::SliceOp& op) override;
- void visit(mir::ops::SoftmaxOp& op) override;
- void visit(mir::ops::SqrtOp& op) override;
- void visit(mir::ops::SqueezeOp& op) override;
- void visit(mir::ops::SubOp& op) override;
- void visit(mir::ops::TanhOp& op) override;
- void visit(mir::ops::TransposeOp& op) override;
+ void visit(mir::ops::AddOp &op) override;
+ void visit(mir::ops::BatchNormOp &op) override;
+ void visit(mir::ops::CappedReluOp &op) override;
+ void visit(mir::ops::ConcatOp &op) override;
+ void visit(mir::ops::ConstantOp &op) override;
+ void visit(mir::ops::Conv2DOp &op) override;
+ void visit(mir::ops::DeConv2DOp &op) override;
+ void visit(mir::ops::DepthwiseConv2DOp &op) override;
+ void visit(mir::ops::DivOp &op) override;
+ void visit(mir::ops::DropoutOp &op) override;
+ void visit(mir::ops::EluOp &op) override;
+ void visit(mir::ops::FullyConnectedOp &op) override;
+ void visit(mir::ops::GatherOp &op) override;
+ void visit(mir::ops::GemmOp &op) override;
+ void visit(mir::ops::InputOp &op) override;
+ void visit(mir::ops::LeakyReluOp &op) override;
+ void visit(mir::ops::MaxOp &op) override;
+ void visit(mir::ops::MulOp &op) override;
+ void visit(mir::ops::OutputOp &op) override;
+ void visit(mir::ops::PadOp &op) override;
+ void visit(mir::ops::PoolOp &op) override;
+ void visit(mir::ops::ReduceOp &op) override;
+ void visit(mir::ops::ReluOp &op) override;
+ void visit(mir::ops::ReshapeOp &op) override;
+ void visit(mir::ops::ResizeOp &op) override;
+ void visit(mir::ops::SigmoidOp &op) override;
+ void visit(mir::ops::SliceOp &op) override;
+ void visit(mir::ops::SoftmaxOp &op) override;
+ void visit(mir::ops::SqrtOp &op) override;
+ void visit(mir::ops::SqueezeOp &op) override;
+ void visit(mir::ops::SubOp &op) override;
+ void visit(mir::ops::TanhOp &op) override;
+ void visit(mir::ops::TransposeOp &op) override;
- void serialize(std::vector<std::unique_ptr<sir::Action>>& inference_sequence);
+ void serialize(std::vector<std::unique_ptr<sir::Action>> &inference_sequence);
- const std::vector<char>& getBuffer() const {
- return _buffer;
- }
+ const std::vector<char> &getBuffer() const { return _buffer; }
- uint32_t getFormatVersion() const {
- return _formatVersion;
- }
+ uint32_t getFormatVersion() const { return _formatVersion; }
- uint32_t getModelHash() const {
- return _modelHash;
- }
+ uint32_t getModelHash() const { return _modelHash; }
private:
/**
* @param data Buffer containing data to serialize
* @param size Size of data to serialize
*/
- void packData(const void* data, size_t size);
+ void packData(const void *data, size_t size);
/**
* @brief Serialize trivially copyable objects
* @tparam T Type of object to serialize
* @param obj Reference to object to serialize
*/
- template <typename T>
- void serializeT(const T& obj);
+ template <typename T> void serializeT(const T &obj);
/**
* @brief Serialize Tensor shape object
* @param s shape to serialize
*/
- void serializeShape(const mir::Shape& s);
+ void serializeShape(const mir::Shape &s);
/**
* @brief Function serializes type of given tensor base data,
* it's shape and raw data in 'c' format(i.e. layout of multidimensional C array)
* @param t Tensor to serialize
*/
- void serializeTensor(const mir::TensorVariant& t);
+ void serializeTensor(const mir::TensorVariant &t);
/**
* @brief Serialize pads for operations like Conv2D
* @tparam Op Operation type
* @param op Reference to operation where pads are stored
* @param padsRank Number of pads to serialize
*/
- template <class Op>
- void serializePads(const Op& op, int32_t number_of_pads);
+ template <class Op> void serializePads(const Op &op, int32_t number_of_pads);
- sir::CallFunction* _curOp = nullptr;
+ sir::CallFunction *_curOp = nullptr;
const uint32_t _formatVersion = 1;
uint32_t _modelHash = 0;
std::vector<char> _buffer;
} // namespace nnc
#endif //_NNC_SOFT_BACKEND_SERIALIZER_H_
-
#include <limits>
#include <list>
-namespace nnc {
+namespace nnc
+{
-namespace sir {
+namespace sir
+{
const size_t INVALID_TENSOR_ID = std::numeric_limits<size_t>::max();
* @brief Represents variable used in artifact.
* This variable can store inputs, outputs of network and temporary data.
*/
-struct TensorDescriptor {
+struct TensorDescriptor
+{
/**
* input tensors of this type supposed to be set outside of artifact
* persistent tensors store data after inference process is over, this include NN outputs
* temporary tensors are not accessible outside artifact in any way,
* they are created and destructed on demand
*/
- enum class Type {
+ enum class Type
+ {
input,
persistent,
temporary
/**
* @brief Action represents operation in inference sequence that is needed to
*/
-struct Action {
+struct Action
+{
/**
* Defines which type of action to perform
* destroyTmp responsible for deletion of temporary tensor
* transpose
*/
- enum class Type {
+ enum class Type
+ {
createTmp,
destroyTmp,
callFunction,
Type type;
};
-struct TransposeTensor : public Action {
+struct TransposeTensor : public Action
+{
- TransposeTensor(size_t input, size_t output, std::vector<int32_t>&& perm)
- : Action(Type::transposeTensor),
- perm(std::move(perm)),
- input(input),
- output(output) {
+ TransposeTensor(size_t input, size_t output, std::vector<int32_t> &&perm)
+ : Action(Type::transposeTensor), perm(std::move(perm)), input(input), output(output)
+ {
}
-
std::vector<int32_t> perm;
size_t input;
size_t output;
};
-struct CreateTmp : public Action {
+struct CreateTmp : public Action
+{
explicit CreateTmp(size_t tid) : Action(Type::createTmp), tensorId(tid) {}
size_t tensorId;
};
-struct DestroyTmp : public Action {
+struct DestroyTmp : public Action
+{
explicit DestroyTmp(size_t tid) : Action(Type::destroyTmp), tensorId(tid) {}
size_t tensorId;
};
-struct CallFunction : public Action {
+struct CallFunction : public Action
+{
- CallFunction(mir::Operation* op, std::string func_name,
- std::vector<size_t>&& inputs, std::vector<size_t>&& outputs)
- : Action(Type::callFunction),
- mirOp(op),
- funcName(std::move(func_name)),
- inputs(inputs),
- outputs(outputs),
- paramStartOffset(0) {}
+ CallFunction(mir::Operation *op, std::string func_name, std::vector<size_t> &&inputs,
+ std::vector<size_t> &&outputs)
+ : Action(Type::callFunction), mirOp(op), funcName(std::move(func_name)), inputs(inputs),
+ outputs(outputs), paramStartOffset(0)
+ {
+ }
CallFunction() : Action(Type::callFunction), mirOp(nullptr), paramStartOffset(0) {}
- mir::Operation* mirOp;
+ mir::Operation *mirOp;
std::string funcName;
// list of input tensors
std::vector<size_t> inputs;
#include <sys/types.h>
#include <unistd.h>
-namespace nnc {
-namespace cli {
-
-void checkInFile(const Option<std::string> &in_file) {
- if ( in_file.empty() )
+namespace nnc
+{
+namespace cli
+{
+
+void checkInFile(const Option<std::string> &in_file)
+{
+ if (in_file.empty())
throw BadOption("Input file name should not be empty");
auto f = fopen(in_file.c_str(), "rb");
fclose(f);
} // checkInFile
-void checkOutFile(const Option<std::string> &out_file) {
- if ( out_file.empty() )
+void checkOutFile(const Option<std::string> &out_file)
+{
+ if (out_file.empty())
throw BadOption("Output file name should not be empty");
/// @todo: if file already exists need to check accessibility
} // checkOutFile
-void checkInDir(const Option<std::string>& dir) {
+void checkInDir(const Option<std::string> &dir)
+{
auto stream = opendir(dir.c_str());
if (stream == nullptr)
closedir(stream);
} // checkInDir
-void checkOutDir(const Option<std::string> &dir) {
+void checkOutDir(const Option<std::string> &dir)
+{
auto stream = opendir(dir.c_str());
- if (stream == nullptr) {
+ if (stream == nullptr)
+ {
// Do not consider the missing directory an error.
if (errno == ENOENT)
return;
namespace cli
{
-constexpr const char* const IOption::_groupNames[];
+constexpr const char *const IOption::_groupNames[];
static std::vector<std::string> splitByComma(const char *str)
{
const char *cur_str = str;
std::vector<std::string> ret;
- if ( std::string(str).empty() )
+ if (std::string(str).empty())
return ret;
- for ( size_t i = 0, cnt = 0; str[i] != '\0'; i++ )
+ for (size_t i = 0, cnt = 0; str[i] != '\0'; i++)
{
- if ( str[i] == ',' )
+ if (str[i] == ',')
{
std::string name(cur_str, cnt);
name.erase(remove_if(name.begin(), name.end(), isspace), name.end());
} // splitByComma
-std::vector<std::string> optname(const char *names)
-{
- return splitByComma(names);
-}
+std::vector<std::string> optname(const char *names) { return splitByComma(names); }
-std::vector<std::string> optvalues(const char *vals)
-{
- return splitByComma(vals);
-}
+std::vector<std::string> optvalues(const char *vals) { return splitByComma(vals); }
std::vector<char> separators(const char *seps)
{
std::vector<char> ret;
int i;
- if ( std::string(seps).empty() )
+ if (std::string(seps).empty())
return ret;
- for ( i = 0; isspace(seps[i]); i++ ) ;
+ for (i = 0; isspace(seps[i]); i++)
+ ;
- if ( seps[i] )
+ if (seps[i])
{
ret.push_back(seps[i]);
i++;
}
- for ( ; seps[i] != '\0'; i++ )
+ for (; seps[i] != '\0'; i++)
{
- if ( seps[i] == ',' )
+ if (seps[i] == ',')
{
- for ( i++; isspace(seps[i]); i++ ) ;
+ for (i++; isspace(seps[i]); i++)
+ ;
ret.push_back(seps[i]);
}
* @param options - vector of all options
* @return maximum name length of size among all options
*/
-static size_t calcMaxLenOfOptionsNames(std::vector<IOption*> options ) {
+static size_t calcMaxLenOfOptionsNames(std::vector<IOption *> options)
+{
size_t max_len = 0, len;
for (const auto opt : options)
- if ( !opt->isDisabled() ) {
+ if (!opt->isDisabled())
+ {
len = 0;
- for (const auto &n : opt->getNames()) len += n.length();
+ for (const auto &n : opt->getNames())
+ len += n.length();
max_len = (max_len < len) ? len : max_len;
}
* @param max_opt_name_len - maximum name length of size among all options
* @param leading_spaces - leading spaces that will be printed before option name
*/
-static void printOption(IOption* opt, size_t max_opt_name_len, size_t leading_spaces) {
+static void printOption(IOption *opt, size_t max_opt_name_len, size_t leading_spaces)
+{
const auto &option_descr = opt->getOverview();
const auto &names = opt->getNames();
// determine max length
size_t max_len = calcMaxLenOfOptionsNames(_options);
- for (const auto opt : _options) {
- if ( opt->isDisabled() )
+ for (const auto opt : _options)
+ {
+ if (opt->isDisabled())
// options that are disabled not have to be shown
continue;
}
// print grouped options
- for (const auto& group : _grouped_options) {
+ for (const auto &group : _grouped_options)
+ {
std::cerr << "Options from '" << group.second[0]->getGroupName() << "' group:" << std::endl;
- for (const auto opt : group.second) {
+ for (const auto opt : group.second)
+ {
printOption(opt, max_len, 4);
}
}
{
auto i = _options_name.emplace(n, opt);
- if ( !i.second )
+ if (!i.second)
{
std::cerr << "option name must be unique: `" << n << "'" << std::endl;
exit(EXIT_FAILURE);
_options.push_back(opt);
- if (opt->isGrouped()) {
+ if (opt->isGrouped())
+ {
auto it = _grouped_options.find(opt->getGroup());
if (it == _grouped_options.end())
- _grouped_options.emplace(opt->getGroup(), std::vector<IOption*>{opt});
+ _grouped_options.emplace(opt->getGroup(), std::vector<IOption *>{opt});
else
it->second.push_back(opt);
}
{
auto it = _options_name.find(optname);
- if ( it == _options_name.end() )
+ if (it == _options_name.end())
{
// optname can contain separators, try
// to strip these separators and repeat a search
size_t i = 0;
- for ( ; optname[i] != '\0' && optname[i] != '=' && optname[i] != ':'; i++ ) ;
+ for (; optname[i] != '\0' && optname[i] != '=' && optname[i] != ':'; i++)
+ ;
std::string strip_optname(optname, i);
it = _options_name.find(strip_optname);
- if ( it == _options_name.end() )
+ if (it == _options_name.end())
{
// couldn't find option
throw BadOption(optname, "");
{
IOption *opt = it->second;
- if ( opt->getSeparators().empty() )
+ if (opt->getSeparators().empty())
{
// couldn't find option
throw BadOption(optname, "");
}
}
- if ( it->second->isDisabled() )
+ if (it->second->isDisabled())
{
// if option is disabled we don't have to recognize it
throw BadOption(optname, "");
} // findOption
// check that option value is correct
-static void checkOptionValue(const IOption *opt, const std::string &opt_name, const std::string &val)
+static void checkOptionValue(const IOption *opt, const std::string &opt_name,
+ const std::string &val)
{
auto valid_vals = opt->getValidVals();
bool is_valid = valid_vals.empty();
- for ( const auto &v: valid_vals )
+ for (const auto &v : valid_vals)
{
- if ( v == val )
+ if (v == val)
{
// value is valid
is_valid = true;
}
}
- if ( !is_valid )
+ if (!is_valid)
{
throw BadOption(opt_name, val);
}
const char *val_pos = nullptr;
// search one of the separators
- for ( auto s : seps )
+ for (auto s : seps)
{
- for ( int i = 0; opt_name[i] != '\0'; i++ )
+ for (int i = 0; opt_name[i] != '\0'; i++)
{
- if ( s == opt_name[i] )
+ if (s == opt_name[i])
{
// separator is found, set val_pos to symbol after it
val_pos = &opt_name[i] + 1;
}
}
- if ( val_pos )
+ if (val_pos)
{
break;
}
// found then we assume that option value is the next element in argv,
// but if the next element starts with '-' we suppose that option value is empty
// because options start with '-'
- if ( !val_pos )
+ if (!val_pos)
{
- if ( _args_num == cur_argv + 1 )
+ if (_args_num == cur_argv + 1)
{
val_pos = "";
}
} // findOptionValue
-const char *CommandLine::findValueForMultOption(const IOption *opt,
- const std::string &opt_name,
+const char *CommandLine::findValueForMultOption(const IOption *opt, const std::string &opt_name,
const char **argv, int cur_argv)
{
const char *val_pos = nullptr;
- if ( cur_argv >= _args_num )
+ if (cur_argv >= _args_num)
{
return nullptr;
}
* @param options - all options
* @return true if option was found in options
*/
-static bool isOptionInOptions(IOption* opt, const std::set<std::string>& options) {
+static bool isOptionInOptions(IOption *opt, const std::set<std::string> &options)
+{
- for (const auto &name : opt->getNames()) {
- if (options.find(name) != options.end()) {
- return true;
- }
+ for (const auto &name : opt->getNames())
+ {
+ if (options.find(name) != options.end())
+ {
+ return true;
}
+ }
- return false;
+ return false;
} // isOptionInOptions
-static bool areOptionsIntersected(const std::vector<IOption*> grouped_options,
- const std::set<std::string>& all_options) {
- for (const auto& opt : grouped_options)
+static bool areOptionsIntersected(const std::vector<IOption *> grouped_options,
+ const std::set<std::string> &all_options)
+{
+ for (const auto &opt : grouped_options)
if (isOptionInOptions(opt, all_options))
return true;
void CommandLine::checkRegisteredOptions(const std::set<std::string> &cmd_args)
{
- for (const auto& opt : _options) {
+ for (const auto &opt : _options)
+ {
if (opt->isOptional() || isOptionInOptions(opt, cmd_args))
continue;
- if (opt->isGrouped()) {
+ if (opt->isGrouped())
+ {
auto it = _grouped_options.find(opt->getGroup());
assert(it != _grouped_options.end());
// option is not found then print error message
std::string options;
- for ( const auto &n : opt->getNames() )
+ for (const auto &n : opt->getNames())
{
options += (n + " ");
}
void CommandLine::checkOptions(const std::set<std::string> &cmd_args)
{
- for ( const auto &o : _options )
+ for (const auto &o : _options)
{
// search option from command line
- for ( const auto &n : o->getNames() )
+ for (const auto &n : o->getNames())
{
- if ( cmd_args.find(n) == cmd_args.end() )
+ if (cmd_args.find(n) == cmd_args.end())
{
// name isn't found
continue;
}
} // opt names
- } // options
+ } // options
} // checkOptions
_prog_name = argv[0];
_args_num = argc;
- if ( argc == 1 )
+ if (argc == 1)
{
// empty command line
usage();
}
// search help option and print help if this option is passed
- for ( int i = 1; i < argc; i++ )
+ for (int i = 1; i < argc; i++)
{
- if ( !strcmp(argv[i], "-h") || !strcmp(argv[i], "--help") )
+ if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
{
usage("", EXIT_SUCCESS);
}
}
- for ( int i = 1; i < argc; i += (argv[i+1] == arg_val) ? 2 : 1 )
+ for (int i = 1; i < argc; i += (argv[i + 1] == arg_val) ? 2 : 1)
{
- if ( argv[i][0] != '-' )
+ if (argv[i][0] != '-')
{
std::string err_msg(std::string("invalid command line argument: ") + argv[i]);
usage(err_msg);
{
opt = findOption(argv[i]);
}
- catch ( BadOption &e )
+ catch (BadOption &e)
{
std::string err_msg(std::string("invalid option: ") + e.getName());
usage(err_msg);
// figure out value for option
try
{
- if ( opt->canHaveSeveralVals() )
+ if (opt->canHaveSeveralVals())
{
int j = i + 1;
- for ( arg_val = findValueForMultOption(opt, argv[i], argv, j);
- arg_val;
- arg_val = findValueForMultOption(opt, argv[i], argv, j) )
+ for (arg_val = findValueForMultOption(opt, argv[i], argv, j); arg_val;
+ arg_val = findValueForMultOption(opt, argv[i], argv, j))
{
// set value for option
opt->setValue(arg_val);
opt->setValue(arg_val);
}
}
- catch ( BadOption &e )
+ catch (BadOption &e)
{
std::string optname = e.getName();
optname = optname.empty() ? argv[i] : optname;
cmd_args.insert(opt->getNames()[0]);
}
- if ( check_nonoptional )
+ if (check_nonoptional)
{
// check that all registered options are present in command line
checkRegisteredOptions(cmd_args);
} // parseCommandLine
-
//
// specializations of setValue method for all supported option type
//
// string
-template <>
-void Option<std::string>::setValue(const std::string &val)
+template <> void Option<std::string>::setValue(const std::string &val)
{
- if ( !val.empty() )
+ if (!val.empty())
this->setRawValue(val);
}
// vector of strings
-template <>
-void Option<std::vector<std::string>>::setValue(const std::string &val)
+template <> void Option<std::vector<std::string>>::setValue(const std::string &val)
{
- if ( !val.empty() )
+ if (!val.empty())
this->push_back(val);
}
// vector of ints
-template <>
-void Option<std::vector<int>>::setValue(const std::string &val)
+template <> void Option<std::vector<int>>::setValue(const std::string &val)
{
if (!val.empty())
this->push_back(stoi(val));
}
// bool
-template <>
-void Option<bool>::setValue(const std::string &val)
+template <> void Option<bool>::setValue(const std::string &val)
{
this->setRawValue(this->convToBool(val));
}
// char
-template <>
-void Option<char>::setValue(const std::string &val)
+template <> void Option<char>::setValue(const std::string &val)
{
- if ( !val.empty() )
+ if (!val.empty())
this->setRawValue(this->convToChar(val));
}
// int8
-template <>
-void Option<int8_t>::setValue(const std::string &val)
+template <> void Option<int8_t>::setValue(const std::string &val)
{
- if ( !val.empty() )
+ if (!val.empty())
this->setRawValue(this->template convToNum<int64_t>(val));
}
// int16
-template <>
-void Option<int16_t>::setValue(const std::string &val)
+template <> void Option<int16_t>::setValue(const std::string &val)
{
- if ( !val.empty() )
+ if (!val.empty())
this->setRawValue(this->template convToNum<int64_t>(val));
}
// int32
-template <>
-void Option<int32_t>::setValue(const std::string &val)
+template <> void Option<int32_t>::setValue(const std::string &val)
{
- if ( !val.empty() )
+ if (!val.empty())
this->setRawValue(this->template convToNum<int64_t>(val));
}
// uint8
-template <>
-void Option<uint8_t>::setValue(const std::string &val)
+template <> void Option<uint8_t>::setValue(const std::string &val)
{
- if ( !val.empty() )
+ if (!val.empty())
this->setRawValue(this->template convToNum<uint64_t>(val));
}
// uint16
-template <>
-void Option<uint16_t>::setValue(const std::string &val)
+template <> void Option<uint16_t>::setValue(const std::string &val)
{
- if ( !val.empty() )
+ if (!val.empty())
this->setRawValue(this->template convToNum<uint64_t>(val));
}
// uint32
-template <>
-void Option<uint32_t>::setValue(const std::string &val)
+template <> void Option<uint32_t>::setValue(const std::string &val)
{
- if ( !val.empty() )
+ if (!val.empty())
this->setRawValue(this->template convToNum<uint64_t>(val));
}
static string netAddr(getenv("ODROID_NET_ADDR") ? getenv("ODROID_NET_ADDR") : "");
-static unique_ptr<char[]> readTensorDataFromHdf5File(const string& file_name, vector<int>& shape) {
- try {
+static unique_ptr<char[]> readTensorDataFromHdf5File(const string &file_name, vector<int> &shape)
+{
+ try
+ {
H5::H5File h5File(file_name, H5F_ACC_RDONLY);
auto tensor_name = h5File.getObjnameByIdx(0);
auto dataset = h5File.openDataSet(tensor_name);
int size = 1;
- for (int i = 0; i < rank; ++i) {
+ for (int i = 0; i < rank; ++i)
+ {
size *= dims[i];
shape.push_back(dims[i]);
}
auto result = unique_ptr<char[]>(new char[size * sizeof(float)]);
dataset.read(&result[0], H5::PredType::NATIVE_FLOAT);
return result;
- } catch (H5::FileIException&) {
+ }
+ catch (H5::FileIException &)
+ {
return nullptr;
}
}
// TODO: this function was copied from CPPOperations.cpp, move it to a shared place.
-bool areFloatsNear(float a, float b, int32_t ulp, float eps) {
+bool areFloatsNear(float a, float b, int32_t ulp, float eps)
+{
assert(ulp < (1 << 23) && "this algorithm is not applicable for such large diffs");
assert(eps >= 0 && "epsilon should be positive number");
if (fabs(a - b) <= eps)
return bi - ai <= ulp;
}
-static void compareHdf5Files(const string& file_name1, const string& file_name2) {
+static void compareHdf5Files(const string &file_name1, const string &file_name2)
+{
vector<int> shape1;
auto tensor1 = readTensorDataFromHdf5File(file_name1, shape1);
- float* tensorData1 = reinterpret_cast<float*>(&tensor1[0]);
+ float *tensorData1 = reinterpret_cast<float *>(&tensor1[0]);
ASSERT_NE(tensorData1, nullptr);
vector<int> shape2;
auto tensor2 = readTensorDataFromHdf5File(file_name2, shape2);
- float* tensorData2 = reinterpret_cast<float*>(&tensor2[0]);
+ float *tensorData2 = reinterpret_cast<float *>(&tensor2[0]);
ASSERT_NE(tensorData2, nullptr);
ASSERT_EQ(shape1.size(), shape2.size());
int size = 1;
- for (int i = 0; i < shape1.size(); ++i) {
+ for (int i = 0; i < shape1.size(); ++i)
+ {
ASSERT_EQ(shape1[i], shape2[i]);
size *= shape1[i];
}
- for (int i = 0; i < size; ++i) {
+ for (int i = 0; i < size; ++i)
+ {
ASSERT_TRUE(areFloatsNear(tensorData1[i], tensorData2[i], 32, 1e-6));
}
}
-static string genTmpDirName() {
+static string genTmpDirName()
+{
string result("/tmp/nnc_test_");
stringstream ss;
ss << this_thread::get_id();
return result;
}
-static bool runOnOdroid(const string& remote_cmd) {
+static bool runOnOdroid(const string &remote_cmd)
+{
string cmd = "ssh " + netAddr + " \"" + remote_cmd + "\"";
return system(cmd.c_str()) == 0;
}
-static bool copyToOdroid(const string& src, const string& dst) {
+static bool copyToOdroid(const string &src, const string &dst)
+{
string cmd("scp -q " + src + " " + netAddr + ":" + dst);
return system(cmd.c_str()) == 0;
}
-static bool copyFromOdroid(const string& src, const string& dst) {
+static bool copyFromOdroid(const string &src, const string &dst)
+{
string cmd("scp -q " + netAddr + ":" + src + " " + dst);
return system(cmd.c_str()) == 0;
}
-static void runAclSystemTest(const string& name) {
+static void runAclSystemTest(const string &name)
+{
// Ensure the Odroid device net address was set.
ASSERT_TRUE(!netAddr.empty());
ASSERT_TRUE(copyToOdroid(binDir + "/" + name + "/AclArtifact.par", dir_name));
// Copy the model input HDF5 file to the remote device.
- ASSERT_TRUE(copyToOdroid(binDir + "/" + name + "/in_" + name + "_caffe.hdf5",
- dir_name + "/in.hdf5"));
+ ASSERT_TRUE(
+ copyToOdroid(binDir + "/" + name + "/in_" + name + "_caffe.hdf5", dir_name + "/in.hdf5"));
// Switch to the artifact directory on the remote device and run the artifact.
ASSERT_TRUE(runOnOdroid("cd " + dir_name + "; ./nnc_test"));
compareHdf5Files(binDir + "/" + name + "/ref.hdf5", binDir + "/" + name + "/out.hdf5");
}
-TEST(acl_cpp_operations_test, convolution) {
- runAclSystemTest("convolution");
-}
+TEST(acl_cpp_operations_test, convolution) { runAclSystemTest("convolution"); }
-TEST(acl_cpp_operations_test, depthwise_convolution) {
- runAclSystemTest("depthwise_convolution");
-}
+TEST(acl_cpp_operations_test, depthwise_convolution) { runAclSystemTest("depthwise_convolution"); }
-TEST(acl_cpp_operations_test, convolution_with_bias) {
- runAclSystemTest("convolution_with_bias");
-}
+TEST(acl_cpp_operations_test, convolution_with_bias) { runAclSystemTest("convolution_with_bias"); }
-TEST(acl_cpp_operations_test, scale) {
- runAclSystemTest("scale");
-}
+TEST(acl_cpp_operations_test, scale) { runAclSystemTest("scale"); }
-TEST(acl_cpp_operations_test, relu) {
- runAclSystemTest("relu");
-}
+TEST(acl_cpp_operations_test, relu) { runAclSystemTest("relu"); }
-TEST(acl_cpp_operations_test, pooling_max) {
- runAclSystemTest("pooling_max");
-}
+TEST(acl_cpp_operations_test, pooling_max) { runAclSystemTest("pooling_max"); }
-TEST(acl_cpp_operations_test, pooling_avg) {
- runAclSystemTest("pooling_avg");
-}
+TEST(acl_cpp_operations_test, pooling_avg) { runAclSystemTest("pooling_avg"); }
-TEST(acl_cpp_operations_test, concatenate) {
- runAclSystemTest("concatenate");
-}
+TEST(acl_cpp_operations_test, concatenate) { runAclSystemTest("concatenate"); }
-TEST(acl_cpp_operations_test, reshape) {
- runAclSystemTest("reshape");
-}
+TEST(acl_cpp_operations_test, reshape) { runAclSystemTest("reshape"); }
-TEST(acl_cpp_operations_test, fully_connected) {
- runAclSystemTest("fully_connected");
-}
+TEST(acl_cpp_operations_test, fully_connected) { runAclSystemTest("fully_connected"); }
using namespace std;
using namespace arm_compute;
-static unique_ptr<char[]> getTensorData(CLTensor& tensor) {
+static unique_ptr<char[]> getTensorData(CLTensor &tensor)
+{
auto buf = unique_ptr<char[]>(new char[tensor.info()->total_size()]);
tensor.map();
Window window;
window.use_tensor_dimensions(tensor.info()->tensor_shape());
Iterator i(&tensor, window);
- char* ptr = &buf[0];
+ char *ptr = &buf[0];
- execute_window_loop(window, [&i, &ptr](const Coordinates&) {
- memcpy(ptr, i.ptr(), sizeof(float));
- ptr += sizeof(float);
- }, i);
+ execute_window_loop(window,
+ [&i, &ptr](const Coordinates &) {
+ memcpy(ptr, i.ptr(), sizeof(float));
+ ptr += sizeof(float);
+ },
+ i);
tensor.unmap();
return buf;
}
-static void readTensor(CLTensor& tensor, H5::DataSet& dataset) {
+static void readTensor(CLTensor &tensor, H5::DataSet &dataset)
+{
auto buf = unique_ptr<char[]>(new char[tensor.info()->total_size()]);
dataset.read(&buf[0], H5::PredType::NATIVE_FLOAT);
tensor.map();
Window window;
window.use_tensor_dimensions(tensor.info()->tensor_shape());
Iterator i(&tensor, window);
- char* ptr = &buf[0];
+ char *ptr = &buf[0];
- execute_window_loop(window, [&i, &ptr](const Coordinates&) {
- memcpy(i.ptr(), ptr, sizeof(float));
- ptr += sizeof(float);
- }, i);
+ execute_window_loop(window,
+ [&i, &ptr](const Coordinates &) {
+ memcpy(i.ptr(), ptr, sizeof(float));
+ ptr += sizeof(float);
+ },
+ i);
tensor.unmap();
}
-static bool readTensorFromHDF5File(CLTensor& tensor, const string& file_name) {
+static bool readTensorFromHDF5File(CLTensor &tensor, const string &file_name)
+{
// Read from the .hdf5 file
- try {
+ try
+ {
H5::H5File h5File(file_name, H5F_ACC_RDONLY);
auto tensor_name = h5File.getObjnameByIdx(0);
auto dataset = h5File.openDataSet(tensor_name);
shape[rank - i - 1] = dims[i];
readTensor(tensor, dataset);
- } catch (H5::FileIException&) {
+ }
+ catch (H5::FileIException &)
+ {
return false;
}
return true;
}
-static void writeTensorToHDF5File(CLTensor& tensor, const string& tensor_name,
- const string& file_name) {
- const TensorShape& orig_shape = tensor.info()->tensor_shape();
- const TensorShape& transposed_shape = orig_shape;
+static void writeTensorToHDF5File(CLTensor &tensor, const string &tensor_name,
+ const string &file_name)
+{
+ const TensorShape &orig_shape = tensor.info()->tensor_shape();
+ const TensorShape &transposed_shape = orig_shape;
int rank = transposed_shape.num_dimensions();
hsize_t dims[rank + 1];
dims[0] = 1;
dataset.write(&getTensorData(tensor)[0], H5::PredType::NATIVE_FLOAT);
}
-int main(int argc, char* argv[]) {
+int main(int argc, char *argv[])
+{
CLScheduler::get().default_init();
- if (!CLScheduler::get().is_initialised()) {
+ if (!CLScheduler::get().is_initialised())
+ {
cout << "Failed to initialise the ACL scheduler" << endl;
return 1;
}
AclArtifact artifact;
- CLTensor& artifact_in = artifact.getInput();
+ CLTensor &artifact_in = artifact.getInput();
readTensorFromHDF5File(artifact_in, "in.hdf5");
artifact.Inference();
- CLTensor& artifact_out = artifact.getOutput();
+ CLTensor &artifact_out = artifact.getOutput();
writeTensorToHDF5File(artifact_out, "out", "out.hdf5");
return 0;
using namespace nnc;
-int main(int argc, const char **argv) {
+int main(int argc, const char **argv)
+{
if (argc != 2)
return 1;
nnc::CaffeImporterPass importer{cli::inputFile};
- try {
+ try
+ {
importer.importModel();
}
- catch (...) {
+ catch (...)
+ {
std::cout << "Could not create IR for model \"" << cli::inputFile << "\"" << std::endl;
return 1;
}
using namespace nnc;
using namespace mir;
-
// Creates simple graph with input and output
-static void fillGraph(Graph& g) {
+static void fillGraph(Graph &g)
+{
Shape input_shape{1, 2, 3};
- Operation* input_op = g.create<ops::InputOp>("in", input_shape);
- Operation* relu_op = g.create<ops::ReluOp>("relu", input_op->getOutput(0));
- Operation* output_op = g.create<ops::OutputOp>("out", relu_op->getOutput(0));
+ Operation *input_op = g.create<ops::InputOp>("in", input_shape);
+ Operation *relu_op = g.create<ops::ReluOp>("relu", input_op->getOutput(0));
+ Operation *output_op = g.create<ops::OutputOp>("out", relu_op->getOutput(0));
}
-static void checkFileExists(const string& path) {
+static void checkFileExists(const string &path)
+{
ifstream f(path);
- if (!f.good()) {
+ if (!f.good())
+ {
cerr << "file " << path << " not created\n";
exit(1);
}
}
-static void createMain(const string& path, const string& header_path) {
+static void createMain(const string &path, const string &header_path)
+{
ofstream out(path);
- if (!out.good()) {
+ if (!out.good())
+ {
cerr << "Main file " << path << " not created\n";
exit(1);
}
out.write(test_main, sizeof(test_main));
}
-int main(int argc, const char* argv[]) {
+int main(int argc, const char *argv[])
+{
cli::CommandLine::getParser()->parseCommandLine(argc, argv, false);
std::string output_dir = cli::artifactDir;
std::string artifact_name = cli::artifactName;
// call compiler
int res = system(compiler_command.c_str());
- if (res == -1) {
+ if (res == -1)
+ {
cerr << "failed to call compiler\n";
return 2;
}
- if (res != 0) {
+ if (res != 0)
+ {
cerr << "compiler did not succeed with error code " << res << ": " << compiler_command << "\n";
return 3;
}
using AF = ArtifactFactory;
-TEST(acl_backend_dom_to_text, ArtifactLiteral) {
+TEST(acl_backend_dom_to_text, ArtifactLiteral)
+{
stringstream code_out;
stringstream decl_out;
ArtifactGeneratorCppCode code_gen(code_out);
ArtifactGeneratorCppDecl decl_gen(decl_out);
- const char* lit_data = "hello_world";
+ const char *lit_data = "hello_world";
shared_ptr<ArtifactLiteral> lit = AF::lit(lit_data);
lit->accept(&code_gen);
lit->accept(&decl_gen);
ASSERT_EQ(decl_out.str(), lit_data);
}
-TEST(acl_backend_dom_to_text, ArtifactId) {
+TEST(acl_backend_dom_to_text, ArtifactId)
+{
stringstream code_out;
stringstream decl_out;
ArtifactGeneratorCppCode code_gen(code_out);
ArtifactGeneratorCppDecl decl_gen(decl_out);
- const char* id_data = "some_id";
+ const char *id_data = "some_id";
shared_ptr<ArtifactId> id = AF::id(id_data);
id->accept(&code_gen);
id->accept(&decl_gen);
ASSERT_EQ(decl_out.str(), id_data);
}
-TEST(acl_backend_dom_to_text, ArtifactRef) {
+TEST(acl_backend_dom_to_text, ArtifactRef)
+{
stringstream code_out;
stringstream decl_out;
ArtifactGeneratorCppCode code_gen(code_out);
ArtifactGeneratorCppDecl decl_gen(decl_out);
- const char* id_data = "some_id";
+ const char *id_data = "some_id";
shared_ptr<ArtifactId> id = AF::id(id_data);
shared_ptr<ArtifactRef> ref = AF::ref(id);
ref->accept(&code_gen);
ASSERT_EQ(decl_out.str(), ref_data);
}
-TEST(acl_backend_dom_to_text, ArtifactDeref) {
+TEST(acl_backend_dom_to_text, ArtifactDeref)
+{
stringstream code_out;
stringstream decl_out;
ArtifactGeneratorCppCode code_gen(code_out);
ArtifactGeneratorCppDecl decl_gen(decl_out);
- const char* id_data = "some_id";
+ const char *id_data = "some_id";
shared_ptr<ArtifactId> id = AF::id(id_data);
shared_ptr<ArtifactDeref> deref = AF::deref(id);
deref->accept(&code_gen);
ASSERT_EQ(decl_out.str(), ref_data);
}
-static void checkCall(ArtifactCallType type,
- const char* call_name,
- const list<shared_ptr<ArtifactExpr>>& args,
- shared_ptr<ArtifactExpr> obj,
- const char* ref_data) {
+static void checkCall(ArtifactCallType type, const char *call_name,
+ const list<shared_ptr<ArtifactExpr>> &args, shared_ptr<ArtifactExpr> obj,
+ const char *ref_data)
+{
stringstream code_out;
ArtifactGeneratorCppCode code_gen(code_out);
shared_ptr<ArtifactFunctionCall> call = AF::call(call_name, args, obj, type);
ASSERT_EQ(code_out.str(), ref_data);
}
-TEST(acl_backend_dom_to_text, ArtifactFunctionCall) {
- const char* lit_data = "123";
- const char* id_data = "some_id";
+TEST(acl_backend_dom_to_text, ArtifactFunctionCall)
+{
+ const char *lit_data = "123";
+ const char *id_data = "some_id";
shared_ptr<ArtifactExpr> id = AF::id(id_data);
shared_ptr<ArtifactExpr> lit = AF::lit(lit_data);
const list<shared_ptr<ArtifactExpr>> args{id, lit};
-
shared_ptr<ArtifactId> obj = AF::id("obj");
- using TestCase = tuple<ArtifactCallType, shared_ptr<ArtifactExpr>, const char*>;
- TestCase test_cases[] = {
- TestCase{ArtifactCallType::scope, nullptr, "foo(some_id, 123)"},
- TestCase{ArtifactCallType::obj, obj, "obj.foo(some_id, 123)"},
- TestCase{ArtifactCallType::ref, obj, "obj->foo(some_id, 123)"},
- TestCase{ArtifactCallType::scope, obj, "obj::foo(some_id, 123)"}
- };
+ using TestCase = tuple<ArtifactCallType, shared_ptr<ArtifactExpr>, const char *>;
+ TestCase test_cases[] = {TestCase{ArtifactCallType::scope, nullptr, "foo(some_id, 123)"},
+ TestCase{ArtifactCallType::obj, obj, "obj.foo(some_id, 123)"},
+ TestCase{ArtifactCallType::ref, obj, "obj->foo(some_id, 123)"},
+ TestCase{ArtifactCallType::scope, obj, "obj::foo(some_id, 123)"}};
- for (const auto& test: test_cases) {
+ for (const auto &test : test_cases)
+ {
ArtifactCallType call_type = get<0>(test);
shared_ptr<ArtifactExpr> obj = get<1>(test);
- const char* ref_output = get<2>(test);
+ const char *ref_output = get<2>(test);
checkCall(call_type, "foo", args, obj, ref_output);
}
}
-static void checkUnaryExpression(ArtifactUnOp op,
- shared_ptr<ArtifactExpr> var,
- const char* ref_data) {
+static void checkUnaryExpression(ArtifactUnOp op, shared_ptr<ArtifactExpr> var,
+ const char *ref_data)
+{
stringstream code_out;
ArtifactGeneratorCppCode code_gen(code_out);
ASSERT_EQ(code_out.str(), ref_data);
}
-TEST(acl_backend_dom_to_text, ArtifactUnaryExpr) {
- const char* var_name = "id";
+TEST(acl_backend_dom_to_text, ArtifactUnaryExpr)
+{
+ const char *var_name = "id";
shared_ptr<ArtifactId> var = AF::id(var_name);
- pair<ArtifactUnOp, const char*> test_cases[] = {
- {ArtifactUnOp::preIncr, "++id"},
- {ArtifactUnOp::preDecr, "--id"},
- {ArtifactUnOp::heapNew, "new id"},
- {ArtifactUnOp::heapFree, "delete id"},
- {ArtifactUnOp::postIncr, "id++"},
- {ArtifactUnOp::postDecr, "id--"}
- };
-
- for (auto test: test_cases) {
+ pair<ArtifactUnOp, const char *> test_cases[] = {
+ {ArtifactUnOp::preIncr, "++id"}, {ArtifactUnOp::preDecr, "--id"},
+ {ArtifactUnOp::heapNew, "new id"}, {ArtifactUnOp::heapFree, "delete id"},
+ {ArtifactUnOp::postIncr, "id++"}, {ArtifactUnOp::postDecr, "id--"}};
+
+ for (auto test : test_cases)
+ {
auto op_type = test.first;
auto ref_output = test.second;
checkUnaryExpression(op_type, var, ref_output);
}
}
-static void checkBinaryExpression(ArtifactBinOp op,
- shared_ptr<ArtifactExpr> op1,
- shared_ptr<ArtifactExpr> op2,
- const char* ref_data) {
+static void checkBinaryExpression(ArtifactBinOp op, shared_ptr<ArtifactExpr> op1,
+ shared_ptr<ArtifactExpr> op2, const char *ref_data)
+{
stringstream code_out;
ArtifactGeneratorCppCode code_gen(code_out);
ASSERT_EQ(code_out.str(), ref_data);
}
-TEST(acl_backend_dom_to_text, ArtifactBinaryExpr) {
+TEST(acl_backend_dom_to_text, ArtifactBinaryExpr)
+{
stringstream code_out;
ArtifactGeneratorCppCode code_gen(code_out);
- const char* op1_name = "a";
- const char* op2_name = "b";
+ const char *op1_name = "a";
+ const char *op2_name = "b";
shared_ptr<ArtifactId> op1 = AF::id(op1_name);
shared_ptr<ArtifactId> op2 = AF::id(op2_name);
- pair<ArtifactBinOp, const char*> test_cases[] ={
- {ArtifactBinOp::eq, "a == b"},
- {ArtifactBinOp::notEq, "a != b"},
- {ArtifactBinOp::less, "a < b"},
- {ArtifactBinOp::lessOrEq, "a <= b"},
- {ArtifactBinOp::great, "a > b"},
- {ArtifactBinOp::greatOrEq, "a >= b"},
- {ArtifactBinOp::assign, "a = b"},
- {ArtifactBinOp::plus, "a + b"},
- {ArtifactBinOp::minus, "a - b"},
- {ArtifactBinOp::mult, "a * b"},
- {ArtifactBinOp::div, "a / b"},
- {ArtifactBinOp::plusAssign, "a += b"},
- {ArtifactBinOp::minusAssign, "a -= b"},
- {ArtifactBinOp::multAssign, "a *= b"},
- {ArtifactBinOp::divAssign, "a /= b"}
- };
-
- for (auto test: test_cases) {
+ pair<ArtifactBinOp, const char *> test_cases[] = {
+ {ArtifactBinOp::eq, "a == b"}, {ArtifactBinOp::notEq, "a != b"},
+ {ArtifactBinOp::less, "a < b"}, {ArtifactBinOp::lessOrEq, "a <= b"},
+ {ArtifactBinOp::great, "a > b"}, {ArtifactBinOp::greatOrEq, "a >= b"},
+ {ArtifactBinOp::assign, "a = b"}, {ArtifactBinOp::plus, "a + b"},
+ {ArtifactBinOp::minus, "a - b"}, {ArtifactBinOp::mult, "a * b"},
+ {ArtifactBinOp::div, "a / b"}, {ArtifactBinOp::plusAssign, "a += b"},
+ {ArtifactBinOp::minusAssign, "a -= b"}, {ArtifactBinOp::multAssign, "a *= b"},
+ {ArtifactBinOp::divAssign, "a /= b"}};
+
+ for (auto test : test_cases)
+ {
auto op_type = test.first;
auto ref_output = test.second;
checkBinaryExpression(op_type, op1, op2, ref_output);
}
}
-TEST(acl_backend_dom_to_text, ArtifactIndex) {
+TEST(acl_backend_dom_to_text, ArtifactIndex)
+{
stringstream code_out;
ArtifactGeneratorCppCode code_gen(code_out);
- const char* arr_name = "a";
- const char* idx_name = "b";
+ const char *arr_name = "a";
+ const char *idx_name = "b";
shared_ptr<ArtifactId> arr = AF::id(arr_name);
shared_ptr<ArtifactId> idx = AF::id(idx_name);
shared_ptr<ArtifactIndex> indexing = AF::ind(arr, idx);
ASSERT_EQ(code_out.str(), "a[b]");
}
-TEST(acl_backend_dom_to_text, ArtifactRet) {
+TEST(acl_backend_dom_to_text, ArtifactRet)
+{
stringstream code_out;
ArtifactGeneratorCppCode code_gen(code_out);
- const char* result_name = "a";
+ const char *result_name = "a";
shared_ptr<ArtifactId> result = AF::id(result_name);
ArtifactRet ret(result);
ret.accept(&code_gen);
ASSERT_EQ(code_out.str(), "return a");
}
-TEST(acl_backend_dom_to_text, ArtifactBreak) {
+TEST(acl_backend_dom_to_text, ArtifactBreak)
+{
stringstream code_out;
ArtifactGeneratorCppCode code_gen(code_out);
ArtifactBreak brk;
ASSERT_EQ(code_out.str(), "break");
}
-TEST(acl_backend_dom_to_text, ArtifactCont) {
+TEST(acl_backend_dom_to_text, ArtifactCont)
+{
stringstream code_out;
ArtifactGeneratorCppCode code_gen(code_out);
ArtifactCont cont;
ASSERT_EQ(code_out.str(), "continue");
}
-TEST(acl_backend_dom_to_text, ArtifactVariable) {
+TEST(acl_backend_dom_to_text, ArtifactVariable)
+{
stringstream code_out;
ArtifactGeneratorCppCode code_gen(code_out);
- const char* var_type = "int";
- const char* var_name = "data";
+ const char *var_type = "int";
+ const char *var_name = "data";
shared_ptr<ArtifactLiteral> dim1 = AF::lit("2");
shared_ptr<ArtifactLiteral> dim2 = AF::lit("3");
list<shared_ptr<ArtifactExpr>> dims{dim1, dim2};
ASSERT_EQ(code_out.str(), "int data[2][3](123)");
}
-TEST(acl_backend_dom_to_text, ArtifactBlock) {
+TEST(acl_backend_dom_to_text, ArtifactBlock)
+{
stringstream code_out;
ArtifactGeneratorCppCode code_gen(code_out);
- const char* var_name = "var";
- const char* lit_val = "123";
+ const char *var_name = "var";
+ const char *lit_val = "123";
shared_ptr<ArtifactExpr> id = AF::id(var_name);
shared_ptr<ArtifactExpr> lit = AF::lit(lit_val);
ASSERT_EQ(code_out.str(), " {\n foo(var, 123);\n}\n");
}
-TEST(acl_backend_dom_to_text, ArtifactForLoop) {
+TEST(acl_backend_dom_to_text, ArtifactForLoop)
+{
stringstream code_out;
ArtifactGeneratorCppCode code_gen(code_out);
- const char* var_name = "i";
- const char* var_type = "int";
+ const char *var_name = "i";
+ const char *var_type = "int";
shared_ptr<ArtifactVariable> iter = AF::var(var_type, var_name, {}, {AF::lit("0")});
- shared_ptr<ArtifactExpr> step = AF::bin(ArtifactBinOp::plusAssign, AF::id(var_name), AF::lit("1"));
- shared_ptr<ArtifactExpr> cond = AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123"));
+ shared_ptr<ArtifactExpr> step =
+ AF::bin(ArtifactBinOp::plusAssign, AF::id(var_name), AF::lit("1"));
+ shared_ptr<ArtifactExpr> cond =
+ AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123"));
- shared_ptr<ArtifactBinaryExpr> expr = AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world"));
+ shared_ptr<ArtifactBinaryExpr> expr =
+ AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world"));
ArtifactForLoop loop(iter, cond, step);
ASSERT_EQ(code_out.str(), "for(int i(0); i <= 123; i += 1) {\n hello += world;\n}\n");
}
-TEST(acl_backend_dom_to_text, ArtifactIf) {
+TEST(acl_backend_dom_to_text, ArtifactIf)
+{
stringstream code_out;
ArtifactGeneratorCppCode code_gen(code_out);
- const char* var_name = "i";
+ const char *var_name = "i";
- shared_ptr<ArtifactExpr> cond = AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123"));
+ shared_ptr<ArtifactExpr> cond =
+ AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123"));
- shared_ptr<ArtifactBinaryExpr> expr = AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world"));
+ shared_ptr<ArtifactBinaryExpr> expr =
+ AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world"));
ArtifactIf if_stmt(cond);
ASSERT_EQ(code_out.str(), "if(i <= 123) {\n hello += world;\n}\n");
}
-TEST(acl_backend_dom_to_text, ArtifactFunction) {
+TEST(acl_backend_dom_to_text, ArtifactFunction)
+{
stringstream code_out;
stringstream decl_out;
ArtifactGeneratorCppCode code_gen(code_out);
ArtifactGeneratorCppDecl decl_gen(decl_out);
- const char* ret_type = "int";
- const char* func_name = "foo";
+ const char *ret_type = "int";
+ const char *func_name = "foo";
shared_ptr<ArtifactVariable> arg1 = AF::var("int", "a");
shared_ptr<ArtifactVariable> arg2 = AF::var("bool", "b");
list<shared_ptr<ArtifactVariable>> args{arg1, arg2};
ASSERT_EQ(decl_out.str(), "int foo(int a, bool b);");
}
-TEST(acl_backend_dom_to_text, ArtifactClassVariable) {
+TEST(acl_backend_dom_to_text, ArtifactClassVariable)
+{
stringstream code_out;
stringstream decl_out;
ArtifactGeneratorCppCode code_gen(code_out);
ArtifactGeneratorCppDecl decl_gen(decl_out);
- const char* var_type = "int";
- const char* var_name = "data";
+ const char *var_type = "int";
+ const char *var_name = "data";
ArtifactClass cls("Class");
ASSERT_EQ(decl_out.str(), "int data;\n");
}
-TEST(acl_backend_dom_to_text, ArtifactClassFunction) {
+TEST(acl_backend_dom_to_text, ArtifactClassFunction)
+{
stringstream code_out;
stringstream decl_out;
ArtifactGeneratorCppCode code_gen(code_out);
ArtifactGeneratorCppDecl decl_gen(decl_out);
- const char* ret_type = "int";
- const char* func_name = "foo";
+ const char *ret_type = "int";
+ const char *func_name = "foo";
shared_ptr<ArtifactVariable> arg1 = AF::var("int", "a");
shared_ptr<ArtifactVariable> arg2 = AF::var("bool", "b");
list<shared_ptr<ArtifactVariable>> args{arg1, arg2};
ASSERT_EQ(decl_out.str(), "int foo(int a, bool b);\n");
}
-static shared_ptr<ArtifactClassVariable> createClsVariable(ArtifactClass& cls,
- const char* var_name,
- bool is_public) {
- const char* var_type = "int";
+static shared_ptr<ArtifactClassVariable> createClsVariable(ArtifactClass &cls, const char *var_name,
+ bool is_public)
+{
+ const char *var_type = "int";
shared_ptr<ArtifactLiteral> dim1 = AF::lit("2");
shared_ptr<ArtifactLiteral> dim2 = AF::lit("3");
list<shared_ptr<ArtifactExpr>> dims{dim1, dim2};
return var_decl;
}
-static shared_ptr<ArtifactClassFunction> createClsFunction(ArtifactClass& cls,
- const char* func_name,
- bool is_public) {
- const char* var_type = "int";
- const char* func_type = "void";
+static shared_ptr<ArtifactClassFunction> createClsFunction(ArtifactClass &cls,
+ const char *func_name, bool is_public)
+{
+ const char *var_type = "int";
+ const char *func_type = "void";
shared_ptr<ArtifactVariable> var1 = AF::var(var_type, "a");
shared_ptr<ArtifactVariable> var2 = AF::var(var_type, "b");
list<shared_ptr<ArtifactVariable>> args{var1, var2};
return func_decl;
}
-TEST(acl_backend_dom_to_text, ArtifactClass) {
+TEST(acl_backend_dom_to_text, ArtifactClass)
+{
stringstream code_out;
stringstream decl_out;
ArtifactGeneratorCppCode code_gen(code_out);
" int invisible;\n};\n");
}
-TEST(acl_backend_dom_to_text, ArtifactModule) {
+TEST(acl_backend_dom_to_text, ArtifactModule)
+{
stringstream code_out;
stringstream decl_out;
ArtifactGeneratorCppCode code_gen(code_out);
// test cpp file generation
// We use snippet code to encode some common functions
// This snippet is wrapped in prefix and postfix code
- const char* code_prefix = "#include \"module.h\"\n\n#include <list>\n\n#include \"bar.h\"\n\n";
- const char* code_suffix = "\nClass::Class() {\n}\n\n";
+ const char *code_prefix = "#include \"module.h\"\n\n#include <list>\n\n#include \"bar.h\"\n\n";
+ const char *code_suffix = "\nClass::Class() {\n}\n\n";
string ref_data = string(code_prefix) +
- string(AclArtifactUtilities, sizeof(AclArtifactUtilities)) + code_suffix;
+ string(AclArtifactUtilities, sizeof(AclArtifactUtilities)) + code_suffix;
m.accept(&code_gen);
ASSERT_EQ(code_out.str(), ref_data);
// test header code generation
- const char* ref_decl_data = "#include <vector>\n\n#include \"foo.h\"\n\nclass Class {\npublic:\n Class();\n\nprivate:\n};\n";
+ const char *ref_decl_data = "#include <vector>\n\n#include \"foo.h\"\n\nclass Class {\npublic:\n "
+ " Class();\n\nprivate:\n};\n";
m.accept(&decl_gen);
ASSERT_EQ(decl_out.str(), ref_decl_data);
using namespace nnc;
using namespace mir;
-namespace {
+namespace
+{
-using OpConstructor = function<Operation*(Graph& g, vector<Operation::Output*>& inputs)>;
+using OpConstructor = function<Operation *(Graph &g, vector<Operation::Output *> &inputs)>;
-const char* artifactName = "nnmodel";
+const char *artifactName = "nnmodel";
/**
- * @brief Creates graph with one operation generated by opGen function and returns this operation node
+ * @brief Creates graph with one operation generated by opGen function and returns this operation
+ * node
* @param g reference to graph which should be filled with operations
* @param op_constr functor which creates main operations of graph
* @param input_shapes vector of network input shapes
* */
-void fillGraph(Graph& g, const OpConstructor& op_constr, const vector<Shape>& input_shapes) {
+void fillGraph(Graph &g, const OpConstructor &op_constr, const vector<Shape> &input_shapes)
+{
// Create graph inputs.
- vector<mir::Operation::Output*> inputs;
- for (std::size_t i = 0; i < input_shapes.size(); ++i) {
+ vector<mir::Operation::Output *> inputs;
+ for (std::size_t i = 0; i < input_shapes.size(); ++i)
+ {
auto input_op = g.create<ops::InputOp>("x" + to_string(i), input_shapes[i]);
inputs.push_back(input_op->getOutput(0));
}
// Create the operation.
- Operation* op = op_constr(g, inputs);
+ Operation *op = op_constr(g, inputs);
// Create graph outputs.
for (std::size_t i = 0; i < op->getNumOutputs(); ++i)
* @param message Message to print in case of check failure
*/
void checkHeadersSetsEqual(const list<string> &artifact_headers,
- const set<string>& expected_headers,
- const char* message) {
+ const set<string> &expected_headers, const char *message)
+{
set<string> artifact_set(artifact_headers.begin(), artifact_headers.end());
ASSERT_EQ(artifact_set, expected_headers) << message;
}
* @brief Check that artifact DOM has all needed includes
* @param m Root module of DOM
*/
-void checkDomIncludes(const ArtifactModule& m) {
+void checkDomIncludes(const ArtifactModule &m)
+{
// check system includes, like '#include <vector>'
checkHeadersSetsEqual(m.headerSysIncludes(), {"fstream"}, "header includes diverged");
checkHeadersSetsEqual(m.sourceIncludes(), {}, "source includes diverged");
// check ordinary includes, like '#include "artifact_data.h"'
- checkHeadersSetsEqual(m.headerIncludes(), {"arm_compute/core/Types.h",
- "arm_compute/runtime/BlobLifetimeManager.h",
- "arm_compute/runtime/CL/CLBufferAllocator.h",
- "arm_compute/runtime/CL/CLFunctions.h",
- "arm_compute/runtime/CL/CLScheduler.h",
- "arm_compute/runtime/MemoryManagerOnDemand.h",
- "arm_compute/runtime/PoolManager.h"},
- "system header includes diverged");
+ checkHeadersSetsEqual(
+ m.headerIncludes(),
+ {"arm_compute/core/Types.h", "arm_compute/runtime/BlobLifetimeManager.h",
+ "arm_compute/runtime/CL/CLBufferAllocator.h", "arm_compute/runtime/CL/CLFunctions.h",
+ "arm_compute/runtime/CL/CLScheduler.h", "arm_compute/runtime/MemoryManagerOnDemand.h",
+ "arm_compute/runtime/PoolManager.h"},
+ "system header includes diverged");
checkHeadersSetsEqual(m.sourceSysIncludes(), {}, "system source includes diverged");
}
* @param c Main artifact class
* @param tensors List of values accessible via getters
*/
-void checkDomArtifactGetters(const ArtifactClass& c, const vector<string>& tensors) {
+void checkDomArtifactGetters(const ArtifactClass &c, const vector<string> &tensors)
+{
// TODO
}
* @param c Main artifact class
* @param tensors List of NN layers
*/
-void checkDomArtifactConstructor(const ArtifactClass& c, const vector<string>& tensors) {
+void checkDomArtifactConstructor(const ArtifactClass &c, const vector<string> &tensors)
+{
// TODO
}
* @param f Inference function description
* @param layers List of layers in inference
*/
-void checkDomInference(const ArtifactFunction& f, const vector<string>& layers) {
+void checkDomInference(const ArtifactFunction &f, const vector<string> &layers)
+{
// TODO
}
* @param layers Names of NN layers in inference sequence
* @param tensors Names of tensors in artifact
*/
-void checkArtifactClass(const ArtifactClass& c,
- const vector<string>& layers,
- const vector<string>& tensors) {
+void checkArtifactClass(const ArtifactClass &c, const vector<string> &layers,
+ const vector<string> &tensors)
+{
checkDomArtifactGetters(c, tensors);
checkDomArtifactConstructor(c, tensors);
- const ArtifactFunction* inf_func = nullptr;
- for (const shared_ptr<ArtifactClassFunction>& method: c.publicFunctions()) {
- if (method->name() == "Inference") {
+ const ArtifactFunction *inf_func = nullptr;
+ for (const shared_ptr<ArtifactClassFunction> &method : c.publicFunctions())
+ {
+ if (method->name() == "Inference")
+ {
inf_func = method.get();
break;
}
* @param layers Names of NN layers in inference sequence
* @param tensors Names of tensors in artifact
*/
-void checkDomStructure(const ArtifactModule& m,
- const vector<string>& layers,
- const vector<string>& tensors) {
+void checkDomStructure(const ArtifactModule &m, const vector<string> &layers,
+ const vector<string> &tensors)
+{
ASSERT_EQ(m.name(), artifactName);
checkDomIncludes(m);
ASSERT_EQ(m.entities().size(), 1);
- ArtifactClass* cls = dynamic_cast<ArtifactClass*>(m.entities().front().get());
+ ArtifactClass *cls = dynamic_cast<ArtifactClass *>(m.entities().front().get());
ASSERT_NE(cls, nullptr);
checkArtifactClass(*cls, layers, tensors);
}
* @param shape Desired shape of TV
* @return TensorVariant with specified shape
*/
-TensorVariant createTensorVariant(const Shape& shape) {
+TensorVariant createTensorVariant(const Shape &shape)
+{
auto num_elems = shape.numElements();
unique_ptr<float[]> data(new float[num_elems]);
- float* data_ptr = data.get();
+ float *data_ptr = data.get();
for (int32_t i = 0; i < num_elems; ++i)
data_ptr[i] = i;
return TensorVariant(DataType::FLOAT32, shape, data_ptr);
}
-
}
// Actual tests
-TEST(acl_backend_mir_to_dom, constant) {
+TEST(acl_backend_mir_to_dom, constant)
+{
Shape shape{3, 4};
TensorVariant constant_data = createTensorVariant(shape);
Graph g;
- OpConstructor op_generator = [&constant_data](Graph& g,
- const vector<Operation::Output*>& inputs) {
+ OpConstructor op_generator = [&constant_data](Graph &g,
+ const vector<Operation::Output *> &inputs) {
return g.create<mir::ops::ConstantOp>("data", constant_data);
};
stringstream params_out;
AclCppOpGenerator dom_gen(artifactName, params_out);
- const ArtifactModule& m = dom_gen.generate(&g);
+ const ArtifactModule &m = dom_gen.generate(&g);
checkDomStructure(m, {}, {});
}
-TEST(acl_backend_mir_to_dom, concat) {
+TEST(acl_backend_mir_to_dom, concat)
+{
Graph g;
- OpConstructor op_generator = [](Graph& g, const vector<Operation::Output*>& inputs) {
- return g.create<mir::ops::ConcatOp>("concat", inputs, 3);
+ OpConstructor op_generator = [](Graph &g, const vector<Operation::Output *> &inputs) {
+ return g.create<mir::ops::ConcatOp>("concat", inputs, 3);
};
vector<Shape> input_shapes{{2, 3, 5, 1}, {2, 3, 5, 3}};
stringstream params_out;
AclCppOpGenerator dom_gen(artifactName, params_out);
- const ArtifactModule& m = dom_gen.generate(&g);
+ const ArtifactModule &m = dom_gen.generate(&g);
checkDomStructure(m, {}, {});
ArtifactGeneratorCppCode code_gen(code_out);
}
-TEST(acl_backend_mir_to_dom, DISABLED_add) {
+TEST(acl_backend_mir_to_dom, DISABLED_add)
+{
// TODO
}
-TEST(acl_backend_mir_to_dom, DISABLED_mul) {
+TEST(acl_backend_mir_to_dom, DISABLED_mul)
+{
// TODO
}
-TEST(acl_backend_mir_to_dom, DISABLED_max) {
+TEST(acl_backend_mir_to_dom, DISABLED_max)
+{
// TODO
}
-TEST(acl_backend_mir_to_dom, DISABLED_conv_transposed2d) {
+TEST(acl_backend_mir_to_dom, DISABLED_conv_transposed2d)
+{
// TODO
}
-TEST(acl_backend_mir_to_dom, conv2d) {
+TEST(acl_backend_mir_to_dom, conv2d)
+{
const int32_t channels = 3;
mir::Shape kernel_shape{1, 3, 3, channels}; // output Channels, Height, Width, input Channels
mir::Shape strides{1, 1};
Graph g;
OpConstructor op_generator =
- [kernel_tensor, strides](mir::Graph& g,
- const std::vector<mir::Operation::Output*>& inputs) {
+ [kernel_tensor, strides](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
std::vector<int32_t> padding{0, 0};
auto kernel = g.create<mir::ops::ConstantOp>("", kernel_tensor)->getOutput(0);
return g.create<mir::ops::Conv2DOp>("conv2d", inputs[0], kernel, strides, padding, padding);
stringstream params_out;
AclCppOpGenerator dom_gen(artifactName, params_out);
- const ArtifactModule& m = dom_gen.generate(&g);
+ const ArtifactModule &m = dom_gen.generate(&g);
checkDomStructure(m, {}, {});
}
-TEST(acl_backend_mir_to_dom, depthwise_conv) {
+TEST(acl_backend_mir_to_dom, depthwise_conv)
+{
const int32_t channels = 3;
mir::Shape kernel_shape{3, 3, channels, 1}; // Height, Width, Channels, Channel multiplier
mir::Shape strides{1, 1};
Graph g;
OpConstructor op_generator =
- [kernel_tensor, strides](mir::Graph& g,
- const std::vector<mir::Operation::Output*>& inputs) {
+ [kernel_tensor, strides](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
std::vector<int32_t> padding{0, 0};
auto kernel = g.create<mir::ops::ConstantOp>("", kernel_tensor)->getOutput(0);
- return g.create<mir::ops::DepthwiseConv2DOp>("depthwiseConv2d", inputs[0], kernel,
- strides, padding, padding);
+ return g.create<mir::ops::DepthwiseConv2DOp>("depthwiseConv2d", inputs[0], kernel, strides,
+ padding, padding);
};
vector<Shape> input_shapes{{1, 10, 10, channels}};
stringstream params_out;
AclCppOpGenerator dom_gen(artifactName, params_out);
- const ArtifactModule& m = dom_gen.generate(&g);
+ const ArtifactModule &m = dom_gen.generate(&g);
checkDomStructure(m, {}, {});
ArtifactGeneratorCppCode code_gen(code_out);
}
-TEST(acl_backend_mir_to_dom, fully_connected) {
+TEST(acl_backend_mir_to_dom, fully_connected)
+{
const int32_t in_size = 13;
const int32_t out_size = 7;
Shape input_shape_data{1, in_size};
TensorVariant weights_tensor = createTensorVariant(weights_shape);
Graph g;
- OpConstructor opGenerator = [weights_tensor](Graph& g, const vector<Operation::Output*>& inputs) {
+ OpConstructor opGenerator = [weights_tensor](Graph &g,
+ const vector<Operation::Output *> &inputs) {
auto weights = g.create<mir::ops::ConstantOp>("", weights_tensor)->getOutput(0);
return g.create<mir::ops::FullyConnectedOp>("fc", inputs[0], weights);
};
stringstream params_out;
AclCppOpGenerator dom_gen(artifactName, params_out);
- const ArtifactModule& m = dom_gen.generate(&g);
+ const ArtifactModule &m = dom_gen.generate(&g);
checkDomStructure(m, {}, {});
ArtifactGeneratorCppCode code_gen(code_out);
}
-TEST(acl_backend_mir_to_dom, maxpool) {
+TEST(acl_backend_mir_to_dom, maxpool)
+{
mir::Shape window_shape{3, 3}; // Height, Width
mir::Shape strides{1, 1};
Graph g;
- OpConstructor op_generator = [window_shape, strides](
- mir::Graph& g, const std::vector<mir::Operation::Output*>& inputs) {
- std::vector<int32_t> padding{0, 0};
- return g.create<mir::ops::PoolOp>("maxPool", inputs[0], ops::PoolOp::PoolingType::MAX,
- window_shape, strides, padding, padding,
- mir::ops::PoolOp::BorderType::EMPTY);
- };
+ OpConstructor op_generator =
+ [window_shape, strides](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
+ std::vector<int32_t> padding{0, 0};
+ return g.create<mir::ops::PoolOp>("maxPool", inputs[0], ops::PoolOp::PoolingType::MAX,
+ window_shape, strides, padding, padding,
+ mir::ops::PoolOp::BorderType::EMPTY);
+ };
vector<Shape> input_shapes{{1, 10, 10, 3}};
stringstream params_out;
AclCppOpGenerator dom_gen(artifactName, params_out);
- const ArtifactModule& m = dom_gen.generate(&g);
+ const ArtifactModule &m = dom_gen.generate(&g);
checkDomStructure(m, {}, {});
ArtifactGeneratorCppCode code_gen(code_out);
}
-TEST(acl_backend_mir_to_dom, DISABLED_avgpool) {
+TEST(acl_backend_mir_to_dom, DISABLED_avgpool)
+{
// TODO
}
* @brief Function to test simple activation operations
* @param op_generator functor that generates target operator
*/
-static void testActivationOp(const OpConstructor& op_generator) {
+static void testActivationOp(const OpConstructor &op_generator)
+{
Graph g;
vector<Shape> input_shapes{{1, 10, 10, 3}};
stringstream params_out;
AclCppOpGenerator dom_gen(artifactName, params_out);
- const ArtifactModule& m = dom_gen.generate(&g);
+ const ArtifactModule &m = dom_gen.generate(&g);
checkDomStructure(m, {}, {});
ArtifactGeneratorCppCode code_gen(code_out);
}
-TEST(acl_backend_mir_to_dom, relu) {
- OpConstructor op_generator = [](Graph& g, const std::vector<Operation::Output*>& inputs) {
- return g.create<mir::ops::ReluOp>("relu", inputs[0]);
+TEST(acl_backend_mir_to_dom, relu)
+{
+ OpConstructor op_generator = [](Graph &g, const std::vector<Operation::Output *> &inputs) {
+ return g.create<mir::ops::ReluOp>("relu", inputs[0]);
};
testActivationOp(op_generator);
}
-TEST(acl_backend_mir_to_dom, capped_relu) {
+TEST(acl_backend_mir_to_dom, capped_relu)
+{
float cap = 6;
- OpConstructor op_generator = [cap](Graph& g, const std::vector<Operation::Output*>& inputs) {
- return g.create<mir::ops::CappedReluOp>("capped_relu", inputs[0], cap);
+ OpConstructor op_generator = [cap](Graph &g, const std::vector<Operation::Output *> &inputs) {
+ return g.create<mir::ops::CappedReluOp>("capped_relu", inputs[0], cap);
};
testActivationOp(op_generator);
}
-TEST(acl_backend_mir_to_dom, sigmoid) {
- OpConstructor op_generator = [](Graph& g, const std::vector<Operation::Output*>& inputs) {
- return g.create<mir::ops::SigmoidOp>("sigmoid", inputs[0]);
+TEST(acl_backend_mir_to_dom, sigmoid)
+{
+ OpConstructor op_generator = [](Graph &g, const std::vector<Operation::Output *> &inputs) {
+ return g.create<mir::ops::SigmoidOp>("sigmoid", inputs[0]);
};
testActivationOp(op_generator);
}
-TEST(acl_backend_mir_to_dom, DISABLED_elu) {
+TEST(acl_backend_mir_to_dom, DISABLED_elu)
+{
// TODO
}
-TEST(acl_backend_mir_to_dom, tanh) {
- OpConstructor op_generator = [](Graph& g, const std::vector<Operation::Output*>& inputs) {
- return g.create<mir::ops::TanhOp>("tanh", inputs[0]);
+TEST(acl_backend_mir_to_dom, tanh)
+{
+ OpConstructor op_generator = [](Graph &g, const std::vector<Operation::Output *> &inputs) {
+ return g.create<mir::ops::TanhOp>("tanh", inputs[0]);
};
testActivationOp(op_generator);
}
-TEST(acl_backend_mir_to_dom, DISABLED_reduce_mean) {
+TEST(acl_backend_mir_to_dom, DISABLED_reduce_mean)
+{
// TODO
}
-TEST(acl_backend_mir_to_dom, softmax) {
+TEST(acl_backend_mir_to_dom, softmax)
+{
Graph g;
- OpConstructor op_generator = [](Graph& g, const vector<Operation::Output*>& inputs) {
- return g.create<mir::ops::SoftmaxOp>("softmax", inputs[0], 3);
+ OpConstructor op_generator = [](Graph &g, const vector<Operation::Output *> &inputs) {
+ return g.create<mir::ops::SoftmaxOp>("softmax", inputs[0], 3);
};
vector<Shape> input_shapes{{1, 1, 1, 3}};
stringstream params_out;
AclCppOpGenerator dom_gen(artifactName, params_out);
- const ArtifactModule& m = dom_gen.generate(&g);
+ const ArtifactModule &m = dom_gen.generate(&g);
checkDomStructure(m, {}, {});
ArtifactGeneratorCppCode code_gen(code_out);
}
-TEST(acl_backend_mir_to_dom, reshape) {
+TEST(acl_backend_mir_to_dom, reshape)
+{
Graph g;
const int32_t h = 10;
Shape input_shape{1, h, w, c};
Shape output_shape{1, h * w * c};
- OpConstructor op_generator = [output_shape](Graph& g, const vector<Operation::Output*>& inputs) {
+ OpConstructor op_generator = [output_shape](Graph &g, const vector<Operation::Output *> &inputs) {
return g.create<mir::ops::ReshapeOp>("reshape", inputs[0], output_shape);
};
stringstream params_out;
AclCppOpGenerator dom_gen(artifactName, params_out);
- const ArtifactModule& m = dom_gen.generate(&g);
+ const ArtifactModule &m = dom_gen.generate(&g);
checkDomStructure(m, {}, {});
ArtifactGeneratorCppCode code_gen(code_out);
}
-TEST(acl_backend_mir_to_dom, DISABLED_pad) {
+TEST(acl_backend_mir_to_dom, DISABLED_pad)
+{
// TODO
}
-TEST(acl_backend_mir_to_dom, transpose) {
+TEST(acl_backend_mir_to_dom, transpose)
+{
const int32_t channels = 2;
TensorVariant w = createTensorVariant({channels});
vector<size_t> perm{0, 3, 1, 2};
Graph g;
- OpConstructor op_generator = [&perm](Graph& g, const vector<Operation::Output*>& inputs) {
- return g.create<mir::ops::TransposeOp>("transpose", inputs[0], perm);
+ OpConstructor op_generator = [&perm](Graph &g, const vector<Operation::Output *> &inputs) {
+ return g.create<mir::ops::TransposeOp>("transpose", inputs[0], perm);
};
vector<Shape> input_shapes{{1, 10, 10, channels}};
stringstream params_out;
AclCppOpGenerator dom_gen(artifactName, params_out);
- const ArtifactModule& m = dom_gen.generate(&g);
+ const ArtifactModule &m = dom_gen.generate(&g);
checkDomStructure(m, {}, {});
}
resDir = sys.argv[1]
m = model_helper.ModelHelper(name='unsupported_net')
-m.net.GivenTensorFill([], 'input_data', values=(1.,), shape=(1,))
+m.net.GivenTensorFill([], 'input_data', values=(1., ), shape=(1, ))
m.net.Sin(['input_data'], 'result')
save_net(os.path.join(resDir, 'init_net.pb'), os.path.join(resDir, 'predict_net.pb'), m)
" * Sin: unknown layer";
// When adding support for new layers, change the model, not the test
-TEST(CAFFE_IMPORT_UNSUPPORTED, ImportAModelWithUnsupportedLayers) {
+TEST(CAFFE_IMPORT_UNSUPPORTED, ImportAModelWithUnsupportedLayers)
+{
std::string predict_net = std::string(TEST_DIR) + "/predict_net.pb";
std::string init_net = std::string(TEST_DIR) + "/init_net.pb";
nnc::Caffe2ImporterPass importer{predict_net, init_net, {{1}}};
- try {
+ try
+ {
importer.importModel();
}
- catch (nnc::PassException &e) {
+ catch (nnc::PassException &e)
+ {
ASSERT_EQ(std::string(ErrorMsg), e.what());
importer.cleanup();
return;
#include <string>
#include <iostream>
-
const char *ErrorMsg = "NNC can't load model. Detected problems:\n"
" * DummyData: unsupported layer\n"
" * LSTM: parameter 'expose_hidden' has unsupported value: 1\n"
" * UnexcitingLayerType: unknown layer";
// When adding support for new layers, change the model, not the test
-TEST(CAFFE_IMPORT_UNSUPPORTED, ImportAModelWithUnsupportedLayers) {
+TEST(CAFFE_IMPORT_UNSUPPORTED, ImportAModelWithUnsupportedLayers)
+{
std::string filename = std::string(TEST_DIR) + "unsupported.caffemodel";
nnc::CaffeImporterPass importer{filename};
- try {
+ try
+ {
importer.importModel();
}
- catch (nnc::PassException &e) {
+ catch (nnc::PassException &e)
+ {
ASSERT_EQ(std::string(ErrorMsg), e.what());
importer.cleanup();
return;
using namespace nnc;
using namespace mir;
-namespace {
+namespace
+{
-TEST(OptPass, eliminateTransposesLinear) {
+TEST(OptPass, eliminateTransposesLinear)
+{
mir::Graph g;
/* Create graph:
* [input]
* ||
* [relu]
*/
- Operation* input = g.create<ops::InputOp>("input", Shape{1, 2, 3});
- Operation* tr1 = g.create<ops::TransposeOp>("tr", input->getOutput(0), vector<size_t>{1, 0, 2});
- Operation* tr15 = g.create<ops::TransposeOp>("tr", tr1->getOutput(0), vector<size_t>{1, 0, 2});
- Operation* tr2 = g.create<ops::TransposeOp>("tr", tr15->getOutput(0), vector<size_t>{1, 0, 2});
- Operation* relu = g.create<ops::ReluOp>("relu", tr2->getOutput(0));
+ Operation *input = g.create<ops::InputOp>("input", Shape{1, 2, 3});
+ Operation *tr1 = g.create<ops::TransposeOp>("tr", input->getOutput(0), vector<size_t>{1, 0, 2});
+ Operation *tr15 = g.create<ops::TransposeOp>("tr", tr1->getOutput(0), vector<size_t>{1, 0, 2});
+ Operation *tr2 = g.create<ops::TransposeOp>("tr", tr15->getOutput(0), vector<size_t>{1, 0, 2});
+ Operation *relu = g.create<ops::ReluOp>("relu", tr2->getOutput(0));
// Check that layout is desired
std::stringstream ss;
ASSERT_EQ("i_input.t_tr.r_relu.", ss.str());
}
-TEST(OptPass, combineTransposesLinear) {
+TEST(OptPass, combineTransposesLinear)
+{
mir::Graph g;
/* Create graph:
* [input]
* ||
* [relu]
*/
- Operation* input = g.create<ops::InputOp>("input", Shape{1, 2, 3});
- Operation* tr1 = g.create<ops::TransposeOp>("tr1", input->getOutput(0),
- vector<size_t>{1, 0, 2});
- Operation* tr2 = g.create<ops::TransposeOp>("tr2", tr1->getOutput(0), vector<size_t>{0, 2, 1});
- Operation* relu = g.create<ops::ReluOp>("relu", tr2->getOutput(0));
+ Operation *input = g.create<ops::InputOp>("input", Shape{1, 2, 3});
+ Operation *tr1 = g.create<ops::TransposeOp>("tr1", input->getOutput(0), vector<size_t>{1, 0, 2});
+ Operation *tr2 = g.create<ops::TransposeOp>("tr2", tr1->getOutput(0), vector<size_t>{0, 2, 1});
+ Operation *relu = g.create<ops::ReluOp>("relu", tr2->getOutput(0));
std::stringstream ss;
DumpVisitor d(ss);
// Assert transposes are combined
ASSERT_EQ("i_input.t_tr1new.r_relu.", ss.str());
- auto ax_ord_actual = dynamic_cast<ops::TransposeOp*>(
- ( *( g.getInputs()[0]->getOutput(0)->getConsumers().begin()))->getNode())->getAxisOrder();
+ auto ax_ord_actual = dynamic_cast<ops::TransposeOp *>(
+ (*(g.getInputs()[0]->getOutput(0)->getConsumers().begin()))->getNode())
+ ->getAxisOrder();
auto ax_ord_true = vector<size_t>{1, 2, 0};
ASSERT_TRUE(ax_ord_actual == ax_ord_true);
}
-TEST(OptPass, combineTransposesBush) {
+TEST(OptPass, combineTransposesBush)
+{
mir::Graph g;
/* Create graph:
* [input]
* \\ //
* [Add]
*/
- Operation* input = g.create<ops::InputOp>("input", Shape{1, 2, 3, 2});
- Operation* tr1 = g.create<ops::TransposeOp>("tr1", input->getOutput(0),
- vector<size_t>{1, 0, 2, 3});
- Operation* tr2 = g.create<ops::TransposeOp>("tr2", tr1->getOutput(0),
- vector<size_t>{1, 0, 2, 3});
- Operation* tr3 = g.create<ops::TransposeOp>("tr3", tr1->getOutput(0),
- vector<size_t>{1, 0, 2, 3});
+ Operation *input = g.create<ops::InputOp>("input", Shape{1, 2, 3, 2});
+ Operation *tr1 =
+ g.create<ops::TransposeOp>("tr1", input->getOutput(0), vector<size_t>{1, 0, 2, 3});
+ Operation *tr2 = g.create<ops::TransposeOp>("tr2", tr1->getOutput(0), vector<size_t>{1, 0, 2, 3});
+ Operation *tr3 = g.create<ops::TransposeOp>("tr3", tr1->getOutput(0), vector<size_t>{1, 0, 2, 3});
Operation *elw = g.create<ops::AddOp>("elewiseAdd", tr2->getOutput(0), tr3->getOutput(0));
std::stringstream ss;
DumpVisitor d(ss);
ASSERT_EQ(elw->getInput(1)->getProducer()->getNode()->getName(), "input");
}
-TEST(OptPass, combineTransposesOpOrder) {
+TEST(OptPass, combineTransposesOpOrder)
+{
mir::Graph g;
/* Create graph:
* [input] [input2]
* \\ //
* [Add]
*/
- Operation* in1 = g.create<ops::InputOp>("inp1", Shape{1, 2, 3});
- Operation* in2 = g.create<ops::InputOp>("inp2", Shape{1, 2, 3});
- Operation* tr0 = g.create<ops::TransposeOp>("tr0", in1->getOutput(0), vector<size_t>{1, 0, 2});
- Operation* tr1 = g.create<ops::TransposeOp>("tr1", in2->getOutput(0), vector<size_t>{2, 1, 0});
- Operation* tr2 = g.create<ops::TransposeOp>("tr2", tr0->getOutput(0), vector<size_t>{1, 0, 2});
- Operation* tr3 = g.create<ops::TransposeOp>("tr3", tr1->getOutput(0), vector<size_t>{2, 1, 0});
+ Operation *in1 = g.create<ops::InputOp>("inp1", Shape{1, 2, 3});
+ Operation *in2 = g.create<ops::InputOp>("inp2", Shape{1, 2, 3});
+ Operation *tr0 = g.create<ops::TransposeOp>("tr0", in1->getOutput(0), vector<size_t>{1, 0, 2});
+ Operation *tr1 = g.create<ops::TransposeOp>("tr1", in2->getOutput(0), vector<size_t>{2, 1, 0});
+ Operation *tr2 = g.create<ops::TransposeOp>("tr2", tr0->getOutput(0), vector<size_t>{1, 0, 2});
+ Operation *tr3 = g.create<ops::TransposeOp>("tr3", tr1->getOutput(0), vector<size_t>{2, 1, 0});
Operation *elw = g.create<ops::AddOp>("elewiseAdd", tr2->getOutput(0), tr3->getOutput(0));
g.create<ops::OutputOp>("out", elw->getOutput(0));
int n1 = elw->getInput(0)->getNode()->getInput(0)->getNode()->getInput(0)->getNode()->getId();
CombineTransposes pass;
pass.run(&g);
ASSERT_EQ(g.getOutputs()[0]->getInput(0)->getProducer()->getNode()->getName(), "elewiseAdd");
- //Order is preserved
+ // Order is preserved
ASSERT_EQ(n1, elw->getInput(0)->getNode()->getId());
ASSERT_EQ(n2, elw->getInput(1)->getNode()->getId());
}
using namespace nnc;
using namespace mir;
-namespace {
+namespace
+{
-TEST(OptPass, fuseConvBiasScaleScaleBias) {
+TEST(OptPass, fuseConvBiasScaleScaleBias)
+{
mir::Graph g;
// Create graph: 'input->conv->bias->scale->scale->bias'
auto conv_const = g.create<ops::ConstantOp>("", TensorVariant(DataType::FLOAT32, {10, 3, 3, 3}));
std::vector<int32_t> padding{0, 0};
auto conv = g.create<ops::Conv2DOp>("conv", input->getOutput(0), conv_const->getOutput(0),
- Shape{1, 1}, padding, padding);
+ Shape{1, 1}, padding, padding);
auto bias1_const = g.create<ops::ConstantOp>("", TensorVariant(DataType::FLOAT32, {10}));
auto bias1 = g.create<ops::AddOp>("bias1", conv->getOutput(0), bias1_const->getOutput(0));
auto scale1_const = g.create<ops::ConstantOp>("", TensorVariant(DataType::FLOAT32, {10}));
"const_.const_.i_input.conv_conv.b_bias1." == ss.str());
}
-} // unnamed namespace
+} // unnamed namespace
* limitations under the License.
*/
-
#include "passes/optimizations/RemoveDeadEnds.h"
#include "mir/ops/ReluOp.h"
#include "mir/ops/ConstantOp.h"
#include <gtest/gtest.h>
-namespace {
+namespace
+{
using namespace std;
using namespace nnc;
using namespace mir;
-TEST(OptPass, removeDeadEndConstants) {
+TEST(OptPass, removeDeadEndConstants)
+{
mir::Graph g;
/* Create graph: (with useless constants)
* [input]
* ||
* [relu]
*/
- Operation* C0 = g.create<ops::ConstantOp>("C0", TensorVariant(DataType::FLOAT32, {2, 2}));
- Operation* input = g.create<ops::InputOp>("input", Shape{1, 2, 3});
- Operation* C1 = g.create<ops::ConstantOp>("C1", TensorVariant(DataType::FLOAT32, {2, 2}));
- Operation* C2 = g.create<ops::ConstantOp>("C2", TensorVariant(DataType::FLOAT32, {2, 2}));
- Operation* relu = g.create<ops::ReluOp>("relu", input->getOutput(0));
+ Operation *C0 = g.create<ops::ConstantOp>("C0", TensorVariant(DataType::FLOAT32, {2, 2}));
+ Operation *input = g.create<ops::InputOp>("input", Shape{1, 2, 3});
+ Operation *C1 = g.create<ops::ConstantOp>("C1", TensorVariant(DataType::FLOAT32, {2, 2}));
+ Operation *C2 = g.create<ops::ConstantOp>("C2", TensorVariant(DataType::FLOAT32, {2, 2}));
+ Operation *relu = g.create<ops::ReluOp>("relu", input->getOutput(0));
std::stringstream ss;
RemoveDeadEnds pass;
using namespace nnc;
using namespace mir;
-namespace {
-Operation* getPrev(Operation* op) {
+namespace
+{
+Operation *getPrev(Operation *op)
+{
assert(op->getNumInputs() == 1);
return op->getInput(0)->getProducer()->getNode();
}
-Operation* getNext(Operation* op) {
- assert(op->getNumOutputs() == 1 && ( op->getOutput(0)->getConsumers().size() == 1 ));
- return ( *op->getOutput(0)->getConsumers().begin())->getNode();
+Operation *getNext(Operation *op)
+{
+ assert(op->getNumOutputs() == 1 && (op->getOutput(0)->getConsumers().size() == 1));
+ return (*op->getOutput(0)->getConsumers().begin())->getNode();
}
/* This tests swapping relu and transpose */
-TEST(OptPass, sinkTrReLU) {
+TEST(OptPass, sinkTrReLU)
+{
mir::Graph g;
/*
* Create graph:
* ||
* [tanh]
*/
- Operation* input = g.create<ops::InputOp>("input", Shape{1, 2, 3});
- Operation* tr1 = g.create<ops::TransposeOp>("tr1", input->getOutput(0),
- vector<size_t>{1, 0, 2});
- Operation* relu = g.create<ops::ReluOp>("relu", tr1->getOutput(0));
- Operation* tanh = g.create<ops::TanhOp>("tanh", relu->getOutput(0));
- Operation* out = g.create<ops::OutputOp>("out", tanh->getOutput(0));
- (void) out;
-
-// Check that layout is desired
+ Operation *input = g.create<ops::InputOp>("input", Shape{1, 2, 3});
+ Operation *tr1 = g.create<ops::TransposeOp>("tr1", input->getOutput(0), vector<size_t>{1, 0, 2});
+ Operation *relu = g.create<ops::ReluOp>("relu", tr1->getOutput(0));
+ Operation *tanh = g.create<ops::TanhOp>("tanh", relu->getOutput(0));
+ Operation *out = g.create<ops::OutputOp>("out", tanh->getOutput(0));
+ (void)out;
+
+ // Check that layout is desired
SinkTranspose pass;
pass.run(&g);
}
/* This tests swapping concat and transpose */
-TEST(OptPass, sinkTrConcat) {
+TEST(OptPass, sinkTrConcat)
+{
mir::Graph g;
/*
* Create graph:
* ||
* [TanH]
*/
- Operation* in1 = g.create<ops::InputOp>("inp1", Shape{1, 1, 2, 3});
- Operation* in2 = g.create<ops::InputOp>("inp2", Shape{1, 1, 2, 3});
- Operation* tr1 = g.create<ops::TransposeOp>("tr1", in1->getOutput(0),
- vector<size_t>{0, 3, 1, 2});
- Operation* tr2 = g.create<ops::TransposeOp>("tr2", in2->getOutput(0),
- vector<size_t>{0, 3, 1, 2});
- Operation* conc = g.create<ops::ConcatOp>("concat", vector<Operation::Output*>{
- tr1->getOutput(0), tr2->getOutput(0)}, 1);
- Operation* tanh = g.create<ops::TanhOp>("tanh", conc->getOutput(0));
- Operation* out = g.create<ops::OutputOp>("out", tanh->getOutput(0));
- (void) out;
+ Operation *in1 = g.create<ops::InputOp>("inp1", Shape{1, 1, 2, 3});
+ Operation *in2 = g.create<ops::InputOp>("inp2", Shape{1, 1, 2, 3});
+ Operation *tr1 = g.create<ops::TransposeOp>("tr1", in1->getOutput(0), vector<size_t>{0, 3, 1, 2});
+ Operation *tr2 = g.create<ops::TransposeOp>("tr2", in2->getOutput(0), vector<size_t>{0, 3, 1, 2});
+ Operation *conc = g.create<ops::ConcatOp>(
+ "concat", vector<Operation::Output *>{tr1->getOutput(0), tr2->getOutput(0)}, 1);
+ Operation *tanh = g.create<ops::TanhOp>("tanh", conc->getOutput(0));
+ Operation *out = g.create<ops::OutputOp>("out", tanh->getOutput(0));
+ (void)out;
// Check that layout is as desired
SinkTranspose pass;
pass.run(&g);
- ASSERT_EQ(getPrev(getPrev(g.getOutputs()[0]))->getType(),
- Operation::Type::transpose);
- ASSERT_TRUE(static_cast<ops::TransposeOp*>(getPrev(tanh))->getAxisOrder() ==
+ ASSERT_EQ(getPrev(getPrev(g.getOutputs()[0]))->getType(), Operation::Type::transpose);
+ ASSERT_TRUE(static_cast<ops::TransposeOp *>(getPrev(tanh))->getAxisOrder() ==
vector<size_t>({0, 3, 1, 2}));
/* Expected Result:
* TanH(Transpose(Concat(inp1,inp2)))
}
/* This tests swapping concat and transpose */
-TEST(OptPass, sinkReluConcat) {
+TEST(OptPass, sinkReluConcat)
+{
mir::Graph g;
/*
* Create graph:
* ||
* [TanH]
*/
- Operation* in1 = g.create<ops::InputOp>("inp1", Shape{1, 1, 2, 3});
- Operation* in2 = g.create<ops::InputOp>("inp2", Shape{1, 1, 2, 3});
- Operation* relu1 = g.create<ops::ReluOp>("relu1", in1->getOutput(0));
- Operation* relu2 = g.create<ops::ReluOp>("relu2", in2->getOutput(0));
- Operation* conc = g.create<ops::ConcatOp>("concat", vector<Operation::Output*>{
- relu1->getOutput(0), relu2->getOutput(0)}, 1);
- Operation* tanh = g.create<ops::TanhOp>("tanh", conc->getOutput(0));
- Operation* out = g.create<ops::OutputOp>("out", tanh->getOutput(0));
- (void) out;
+ Operation *in1 = g.create<ops::InputOp>("inp1", Shape{1, 1, 2, 3});
+ Operation *in2 = g.create<ops::InputOp>("inp2", Shape{1, 1, 2, 3});
+ Operation *relu1 = g.create<ops::ReluOp>("relu1", in1->getOutput(0));
+ Operation *relu2 = g.create<ops::ReluOp>("relu2", in2->getOutput(0));
+ Operation *conc = g.create<ops::ConcatOp>(
+ "concat", vector<Operation::Output *>{relu1->getOutput(0), relu2->getOutput(0)}, 1);
+ Operation *tanh = g.create<ops::TanhOp>("tanh", conc->getOutput(0));
+ Operation *out = g.create<ops::OutputOp>("out", tanh->getOutput(0));
+ (void)out;
// Check that layout is as desired
SinkRelu pass;
}
/* This tests swapping relu and max_pool */
-TEST(OptPass, sinkPoolReLU) {
+TEST(OptPass, sinkPoolReLU)
+{
mir::Graph g;
/*
* Create graph:
* ||
* [tanh]
*/
- Operation* input = g.create<ops::InputOp>("input", Shape{1, 4, 4, 3});
- Operation* relu = g.create<ops::ReluOp>("relu", input->getOutput(0));
- Operation* mp = g.create<ops::PoolOp>("pool", relu->getOutput(0),
- ops::PoolOp::PoolingType::MAX, Shape{2, 2}, Shape{2, 2},
- vector<int32_t>{0, 0}, vector<int32_t>{0, 0},
- ops::PoolOp::BorderType::EMPTY);
- Operation* tanh = g.create<ops::TanhOp>("tanh", mp->getOutput(0));
- Operation* out = g.create<ops::OutputOp>("out", tanh->getOutput(0));
- (void) out;
+ Operation *input = g.create<ops::InputOp>("input", Shape{1, 4, 4, 3});
+ Operation *relu = g.create<ops::ReluOp>("relu", input->getOutput(0));
+ Operation *mp = g.create<ops::PoolOp>("pool", relu->getOutput(0), ops::PoolOp::PoolingType::MAX,
+ Shape{2, 2}, Shape{2, 2}, vector<int32_t>{0, 0},
+ vector<int32_t>{0, 0}, ops::PoolOp::BorderType::EMPTY);
+ Operation *tanh = g.create<ops::TanhOp>("tanh", mp->getOutput(0));
+ Operation *out = g.create<ops::OutputOp>("out", tanh->getOutput(0));
+ (void)out;
SinkRelu pass;
pass.run(&g);
ASSERT_EQ(getNext(g.getInputs()[0])->getName(), "pool");
ASSERT_EQ(getPrev(g.getOutputs()[0])->getName(), "tanh");
ASSERT_EQ("i_input.p_pool.r_relu.th_tanh.", ss.str());
-
}
} // unnamed namespace
#include "mir/ops/Conv2DOp.h"
#include "mir/Visitor.h"
-namespace nnc {
+namespace nnc
+{
-class DumpVisitor : public mir::Visitor {
+class DumpVisitor : public mir::Visitor
+{
public:
- explicit DumpVisitor(std::ostream& s) : _s(s) {}
+ explicit DumpVisitor(std::ostream &s) : _s(s) {}
- void visit(mir::ops::InputOp& op) override { _s << "i_" << op.getName() << "."; };
+ void visit(mir::ops::InputOp &op) override { _s << "i_" << op.getName() << "."; };
- void visit(mir::ops::TanhOp& op) override { _s << "th_" << op.getName() << "."; }
+ void visit(mir::ops::TanhOp &op) override { _s << "th_" << op.getName() << "."; }
- void visit(mir::ops::MulOp& op) override { _s << "s_" << op.getName() << "."; }
+ void visit(mir::ops::MulOp &op) override { _s << "s_" << op.getName() << "."; }
- void visit(mir::ops::AddOp& op) override { _s << "b_" << op.getName() << "."; }
+ void visit(mir::ops::AddOp &op) override { _s << "b_" << op.getName() << "."; }
- void visit(mir::ops::ReluOp& op) override { _s << "r_" << op.getName() << "."; }
+ void visit(mir::ops::ReluOp &op) override { _s << "r_" << op.getName() << "."; }
- void visit(mir::ops::PoolOp& op) override { _s << "p_" << op.getName() << "."; }
+ void visit(mir::ops::PoolOp &op) override { _s << "p_" << op.getName() << "."; }
- void visit(mir::ops::TransposeOp& op) override { _s << "t_" << op.getName() << "."; }
+ void visit(mir::ops::TransposeOp &op) override { _s << "t_" << op.getName() << "."; }
- void visit(mir::ops::Conv2DOp& op) override { _s << "conv_" << op.getName() << "."; }
+ void visit(mir::ops::Conv2DOp &op) override { _s << "conv_" << op.getName() << "."; }
- void visit(mir::ops::ConstantOp& op) override { _s << "const_" << op.getName() << "."; }
+ void visit(mir::ops::ConstantOp &op) override { _s << "const_" << op.getName() << "."; }
- std::ostream& _s;
+ std::ostream &_s;
};
} // namespace nnc
-#endif //NNCC_UTIL_H
+#endif // NNCC_UTIL_H
using namespace nnc;
-namespace {
+namespace
+{
std::string ErrorMsg = "error constructor";
void passErr1() { throw PassException(ErrorMsg); }
-void passErr2() {
- try {
+void passErr2()
+{
+ try
+ {
passErr1();
- } catch (const PassException &e) {
+ }
+ catch (const PassException &e)
+ {
throw;
}
}
-TEST(CONTRIB_PASS, PassException) {
- try {
+TEST(CONTRIB_PASS, PassException)
+{
+ try
+ {
passErr2();
- } catch (const PassException &e) {
+ }
+ catch (const PassException &e)
+ {
ASSERT_TRUE(ErrorMsg == e.what());
return;
}
using namespace nnc;
-
class DummyPass1 : public Pass
{
public:
{
auto graph = static_cast<mir::Graph *>(data);
- if ( !graph )
+ if (!graph)
{
throw PassException();
}
{
auto tv = static_cast<mir::TensorVariant *>(data);
- if ( !tv )
+ if (!tv)
{
throw PassException();
}
#include "gtest/gtest.h"
-template <class List>
-static inline void checkListShapeEq(List list, Shape shape, index_t volume) {
+template <class List> static inline void checkListShapeEq(List list, Shape shape, index_t volume)
+{
ASSERT_EQ(static_cast<size_t>(shape.getDims()), list.size());
index_t idx = 0;
- for (auto el: list) {
+ for (auto el : list)
+ {
ASSERT_EQ(shape[idx], el);
idx++;
}
ASSERT_EQ(shape.getNumElems(), volume);
}
-TEST(SOFT_BACKEND, shape_and_index) {
- auto list = {2,3,4};
+TEST(SOFT_BACKEND, shape_and_index)
+{
+ auto list = {2, 3, 4};
index_t volume = std::accumulate(list.begin(), list.end(), 1, std::multiplies<index_t>());
Shape s1(list);
checkListShapeEq(list, s1, volume);
- // This check must be performed only if assertions are enabled
+// This check must be performed only if assertions are enabled
#ifndef NDEBUG
ASSERT_DEATH(s1[list.size()], "");
#endif
Shape s2(s1);
checkListShapeEq(list, s2, volume);
- Shape s3 {1};
+ Shape s3{1};
ASSERT_EQ(s3.getNumElems(), 1);
ASSERT_EQ(s3.getDims(), 1);
s3 = s1;
s3.setDims(4);
s3[3] = 2;
- ASSERT_EQ(s3.getNumElems(), volume*2);
+ ASSERT_EQ(s3.getNumElems(), volume * 2);
s3.setDims(3);
ASSERT_EQ(s3.getNumElems(), volume);
}
-TEST(SOFT_BACKEND, tensor) {
+TEST(SOFT_BACKEND, tensor)
+{
// test reshape
Tensor t1;
ASSERT_EQ(t1.getShape().getNumElems(), 1);
// test at functions
float expected_sum = 0;
for (index_t i = 0; i < tensor1_height; ++i)
- for (index_t j = 0; j < tensor1_width; ++j) {
+ for (index_t j = 0; j < tensor1_width; ++j)
+ {
index_t elem = (i + 1) * (j + 1);
expected_sum += elem;
t1.at({i, j}) = elem;
}
float sum = 0;
for (index_t i = 0; i < tensor1_height; ++i)
- for (index_t j = 0; j < tensor1_width; ++j) {
+ for (index_t j = 0; j < tensor1_width; ++j)
+ {
sum += t1.at({i, j});
}
ASSERT_EQ(sum, expected_sum);
const index_t tensor3_width = 3;
std::vector<float> data({1.0, 2.0, 4.0});
data.resize(tensor3_depth * tensor3_height * tensor3_width);
- float* data_ptr = data.data();
+ float *data_ptr = data.data();
Tensor t3(Shape({tensor3_depth, tensor3_height, tensor3_width}), data_ptr);
ASSERT_EQ(t3.getShape().getNumElems(), tensor3_depth * tensor3_height * tensor3_width);
sum = 0;
for (index_t k = 0; k < tensor3_depth; ++k)
for (index_t i = 0; i < tensor3_height; ++i)
- for (index_t j = 0; j < tensor3_width; ++j) {
+ for (index_t j = 0; j < tensor3_width; ++j)
+ {
sum += t3.at({k, i, j});
}
ASSERT_EQ(sum, std::accumulate(data_ptr, data_ptr + t3.getShape().getNumElems(), 0.0f));
t4 = t3;
for (index_t k = 0; k < tensor3_depth; ++k)
for (index_t i = 0; i < tensor3_height; ++i)
- for (index_t j = 0; j < tensor3_height; ++j) {
+ for (index_t j = 0; j < tensor3_height; ++j)
+ {
ASSERT_EQ(t3.at({k, i, j}), t4.at({k, i, j}));
}
}
NNC data types are: mir::TensorVariant, tensor::Shape, mir::Tensor<float>
*/
-namespace {
+namespace
+{
/**
- * @brief Creates graph with one operation generated by opGen function and returns this operation node
+ * @brief Creates graph with one operation generated by opGen function and returns this operation
+ * node
*/
-mir::Operation*
-fillGraph(mir::Graph& g,
- const function<mir::Operation*(mir::Graph& g,
- vector<mir::Operation::Output*>& inputs)>& op_gen,
- const vector<unique_ptr<mir::TensorVariant>>& input_ntensors) {
+mir::Operation *
+fillGraph(mir::Graph &g,
+ const function<mir::Operation *(mir::Graph &g, vector<mir::Operation::Output *> &inputs)>
+ &op_gen,
+ const vector<unique_ptr<mir::TensorVariant>> &input_ntensors)
+{
// Create graph inputs.
- std::vector<mir::Operation::Output*> inputs;
- for (std::size_t i = 0; i < input_ntensors.size(); ++i) {
+ std::vector<mir::Operation::Output *> inputs;
+ for (std::size_t i = 0; i < input_ntensors.size(); ++i)
+ {
auto input_op =
g.create<mir::ops::InputOp>("x" + std::to_string(i), input_ntensors[i]->getShape());
inputs.push_back(input_op->getOutput(0));
}
// Create the operation.
- mir::Operation* op = op_gen(g, inputs);
+ mir::Operation *op = op_gen(g, inputs);
// Create graph outputs.
assert(op->getNumOutputs() == 1);
/**
* @brief Fills NNC Shape object with data from src container
*/
-void fillNShape(mir::Shape &nshape, const vector<int> &raw_shape_data) {
+void fillNShape(mir::Shape &nshape, const vector<int> &raw_shape_data)
+{
int shape_rank = raw_shape_data.size();
nshape.resize(shape_rank);
for (int i = 0; i < shape_rank; ++i)
/**
* @brief Converts NNC Shape to artifact Shape
*/
-void copyAShapeFromNShape(Shape &ashape, const mir::Shape &src) {
+void copyAShapeFromNShape(Shape &ashape, const mir::Shape &src)
+{
int shape_rank = src.rank();
ashape.setDims(shape_rank);
for (int i = 0; i < shape_rank; ++i)
/**
* @brief Fills NNC and artifact Shape objects with data from rawShapeData
*/
-void fillShapes(mir::Shape &nshape, Shape &ashape, const vector<int> &raw_shape_data) {
+void fillShapes(mir::Shape &nshape, Shape &ashape, const vector<int> &raw_shape_data)
+{
fillNShape(nshape, raw_shape_data);
copyAShapeFromNShape(ashape, nshape);
}
/**
* @brief Fills NNC tensor with some determined data
*/
-void fillNTensor(mir::TensorVariant &dst, float start) {
+void fillNTensor(mir::TensorVariant &dst, float start)
+{
float t = start;
mir::Tensor<float> wrapper(dst);
- for (const mir::Index& idx: mir::ShapeRange(dst.getShape())) {
+ for (const mir::Index &idx : mir::ShapeRange(dst.getShape()))
+ {
wrapper.at(idx) = sin(t) * 2.0f;
t += 1.0f;
}
/**
* @brief Converts NNC mir::TensorVariant to artifact Tensor object
*/
-void copyATensorFromNTensor(Tensor &dst, mir::TensorVariant &src) {
+void copyATensorFromNTensor(Tensor &dst, mir::TensorVariant &src)
+{
mir::Tensor<float> wrapper(src);
Index art_idx;
int rank = src.getShape().rank();
art_idx.setDims(rank);
- for (mir::Index idx: mir::ShapeRange(src.getShape())) {
+ for (mir::Index idx : mir::ShapeRange(src.getShape()))
+ {
for (int i = 0; i < rank; ++i)
art_idx[i] = idx.at(i);
dst.at(art_idx) = wrapper.at(idx);
/**
* @brief Fills NNC and artifact tensor objects with some determined data
*/
-void fillTensors(unique_ptr<mir::TensorVariant> &ntensor,
- Tensor &atensor,
- const vector<int> &shape,
- float start) {
+void fillTensors(unique_ptr<mir::TensorVariant> &ntensor, Tensor &atensor, const vector<int> &shape,
+ float start)
+{
Shape ashape;
mir::Shape nshape;
fillShapes(nshape, ashape, shape);
/**
* @brief Run interpreter to get reference output data
*/
-mir::TensorVariant
-getReferenceTensor(mir::Graph& g,
- const vector<unique_ptr<mir::TensorVariant>>& input_ntensors) {
+mir::TensorVariant getReferenceTensor(mir::Graph &g,
+ const vector<unique_ptr<mir::TensorVariant>> &input_ntensors)
+{
NNInterpreter interpreter;
for (int i = 0; i < static_cast<int>(input_ntensors.size()); ++i)
interpreter.setInput("x" + to_string(i), *input_ntensors[i]);
g.accept(&interpreter);
- const auto* output_op = g.getOutputs()[0];
+ const auto *output_op = g.getOutputs()[0];
return interpreter.getResult(output_op->getInput(0)->getProducer());
};
/**
- * @brief Run selected operation, used to make code in tests more compact and fit getReferenceTensor format
+ * @brief Run selected operation, used to make code in tests more compact and fit getReferenceTensor
+ * format
*/
-template <typename Operation, typename ...Args>
-Tensor run(Operation op, const Args &...args) {
+template <typename Operation, typename... Args> Tensor run(Operation op, const Args &... args)
+{
Tensor output;
op(output, args...);
return output;
* @param b Second number to compare
* @param ulp Max tolerated number of units in the last place
* @param eps Max tolerated absolute difference
- * @return true if diff of two numbers is less than 'eps' or ULP between arguments is less than 'ulp'
+ * @return true if diff of two numbers is less than 'eps' or ULP between arguments is less than
+ * 'ulp'
*/
-bool areFloatsNear(float a, float b, int32_t ulp, float eps) {
+bool areFloatsNear(float a, float b, int32_t ulp, float eps)
+{
assert(ulp < (1 << 23) && "this algorithm is not applicable for such large diffs");
assert(eps >= 0 && "epsilon should be positive number");
if (fabs(a - b) <= eps)
* @param ref_nnc_tensor Reference tensor that interpreter produced
* @param test_art_tensor Tensor that artifact operation computed
*/
-void compareResults(const mir::TensorVariant &ref_nnc_tensor, const Tensor &test_art_tensor) {
+void compareResults(const mir::TensorVariant &ref_nnc_tensor, const Tensor &test_art_tensor)
+{
assert(ref_nnc_tensor.getElementSize() == 4L &&
ref_nnc_tensor.getDataType() == mir::DataType::FLOAT32);
// check that reference and test tensor contents are equal
Index artifact_idx;
artifact_idx.setDims(rank);
- for (mir::Index nnc_idx: mir::ShapeRange(nnc_shape)) {
+ for (mir::Index nnc_idx : mir::ShapeRange(nnc_shape))
+ {
for (int i = 0; i < rank; ++i)
artifact_idx[i] = nnc_idx.at(i);
// Input and output data lies in range of [-10, 10],
float ref_data = mir::Tensor<float>(ref_nnc_tensor).at(nnc_idx);
float test_data = test_art_tensor.at(artifact_idx);
ASSERT_TRUE(areFloatsNear(ref_data, test_data, 32, 1e-5))
- << "Tensor element " << nnc_idx << " diverged, reference: "
- << ref_data << " test result: " << test_data;
+ << "Tensor element " << nnc_idx << " diverged, reference: " << ref_data
+ << " test result: " << test_data;
}
}
/**
- * @brief This function creates test graph, runs interpeter, specifies artifact operation and compares results
+ * @brief This function creates test graph, runs interpeter, specifies artifact operation and
+ * compares results
*/
-template <typename TestFunc, typename ...Args>
+template <typename TestFunc, typename... Args>
void createAndRunTestGraph(
- function<mir::Operation*(mir::Graph&,
- const std::vector<mir::Operation::Output*>& inputs)> op_generator,
- TestFunc artifactOperation,
- const vector<unique_ptr<mir::TensorVariant>>& input_ntensors,
- Args& ...input_atensors) {
+ function<mir::Operation *(mir::Graph &, const std::vector<mir::Operation::Output *> &inputs)>
+ op_generator,
+ TestFunc artifactOperation, const vector<unique_ptr<mir::TensorVariant>> &input_ntensors,
+ Args &... input_atensors)
+{
mir::Graph g;
mir::Operation *actual_operation = fillGraph(g, op_generator, input_ntensors);
inference_sequence.push_back(std::move(op_call));
Serializer serializer;
serializer.serialize(inference_sequence);
- assert(static_cast<sir::CallFunction*>(inference_sequence.front().get())->paramStartOffset == 0);
+ assert(static_cast<sir::CallFunction *>(inference_sequence.front().get())->paramStartOffset == 0);
mir::TensorVariant reference_output = getReferenceTensor(g, input_ntensors);
compareResults(reference_output, test_output);
}
-
}
-TEST(cpp_operations_test, capped_relu) {
+TEST(cpp_operations_test, capped_relu)
+{
// test prerequisites
// cap has this value to cut input numbers(they are in range [-1, 1])
float cap = 0.5f;
Tensor input_atensor;
vector<unique_ptr<mir::TensorVariant>> input_ntensors(1);
fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f);
- auto op_generator = [cap](mir::Graph& g, const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [cap](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::CappedReluOp>("y", inputs[0], cap);
};
createAndRunTestGraph(op_generator, cappedRelu, input_ntensors, input_atensor);
}
-TEST(cpp_operations_test, concat) {
+TEST(cpp_operations_test, concat)
+{
for (int num_dims = 1; num_dims <= 4; ++num_dims)
for (int axis = 0; axis < num_dims; ++axis)
{
vector<unique_ptr<mir::TensorVariant>> input_ntensors(2);
fillTensors(input_ntensors[0], input_atensors[0], shape_data1, 1.0f);
fillTensors(input_ntensors[1], input_atensors[1], shape_data2, 2.0f);
- auto op_generator = [axis](mir::Graph& g,
- const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [axis](mir::Graph &g,
+ const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::ConcatOp>("y", inputs, axis);
};
- createAndRunTestGraph(op_generator,
- concat<Tensor, Tensor>,
- input_ntensors,
- input_atensors[0],
+ createAndRunTestGraph(op_generator, concat<Tensor, Tensor>, input_ntensors, input_atensors[0],
input_atensors[1]);
}
}
}
}
-TEST(cpp_operations_test, convTransposed2d) {
+TEST(cpp_operations_test, convTransposed2d)
+{
// Iterate over kernel width, kernel height,
// input channels(input_c), output channels(output_c),
// stride width, stride height
- // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal to 1
+ // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal
+ // to 1
using iT = int32_t;
Tensor temporary(Shape({1024 * 40}));
for (iT kernel_h = 2; kernel_h <= 4; ++kernel_h)
for (iT input_c = 1; input_c <= 3; ++input_c)
for (iT output_c = 1; output_c <= 3; ++output_c)
for (iT stride_h = 1; stride_h <= 3; ++stride_h)
- for (iT stride_w = 1; stride_w <= 3; ++stride_w) {
- vector<int> input_shape_data{3, 9, 3, static_cast<int>(input_c)}; // NHWC
+ for (iT stride_w = 1; stride_w <= 3; ++stride_w)
+ {
+ vector<int> input_shape_data{3, 9, 3, static_cast<int>(input_c)}; // NHWC
vector<int> kernel_shape_data{kernel_h, kernel_w, output_c, input_c};
mir::Shape strides{stride_h, stride_w};
vector<unique_ptr<mir::TensorVariant>> input_ntensors(2);
fillTensors(input_ntensors[1], input_atensor1, kernel_shape_data, 1.0f);
auto pad_t = mir::ops::PaddingType::Same;
auto op_generator = [&strides, pad_t](
- mir::Graph& g, const std::vector<mir::Operation::Output*>& inputs) {
+ mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::DeConv2DOp>("y", inputs[0], inputs[1], strides, pad_t);
};
- createAndRunTestGraph(op_generator, convTransposed2d, input_ntensors,
- input_atensor0, input_atensor1, temporary);
+ createAndRunTestGraph(op_generator, convTransposed2d, input_ntensors, input_atensor0,
+ input_atensor1, temporary);
}
}
-TEST(cpp_operations_test, conv2d) {
+TEST(cpp_operations_test, conv2d)
+{
// Iterate over kernel width, kernel height,
// input channels(input_c), output channels(output_c),
// stride width, stride height
- // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal to 1
+ // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal
+ // to 1
using iT = int32_t;
Tensor temporary(Shape({1024 * 20}));
for (iT kernel_h = 1; kernel_h <= 3; ++kernel_h)
for (iT input_c = 1; input_c <= 3; ++input_c)
for (iT output_c = 1; output_c <= 3; ++output_c)
for (iT stride_h = 1; stride_h <= 3; ++stride_h)
- for (iT stride_w = 1; stride_w <= 3; ++stride_w) {
- vector<int> input_shape_data{3, 5, 7, static_cast<int>(input_c)}; // NHWC
+ for (iT stride_w = 1; stride_w <= 3; ++stride_w)
+ {
+ vector<int> input_shape_data{3, 5, 7, static_cast<int>(input_c)}; // NHWC
vector<int> kernel_shape_data{output_c, kernel_h, kernel_w, input_c}; // OHWI
mir::Shape strides{stride_h, stride_w};
vector<unique_ptr<mir::TensorVariant>> input_ntensors(2);
Tensor input_atensor1;
fillTensors(input_ntensors[0], input_atensor0, input_shape_data, 1.0f);
fillTensors(input_ntensors[1], input_atensor1, kernel_shape_data, 1.0f);
- auto op_generator = [&strides](mir::Graph& g,
- const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [&strides](mir::Graph &g,
+ const std::vector<mir::Operation::Output *> &inputs) {
std::vector<int32_t> padding{0, 0};
- return g.create<mir::ops::Conv2DOp>("y", inputs[0], inputs[1],
- strides, padding, padding);
+ return g.create<mir::ops::Conv2DOp>("y", inputs[0], inputs[1], strides, padding,
+ padding);
};
- createAndRunTestGraph(op_generator, conv2d, input_ntensors,
- input_atensor0, input_atensor1, temporary);
+ createAndRunTestGraph(op_generator, conv2d, input_ntensors, input_atensor0,
+ input_atensor1, temporary);
}
}
-TEST(cpp_operations_test, depthwise_conv) {
+TEST(cpp_operations_test, depthwise_conv)
+{
// Iterate over kernel width, kernel height,
// channels
// stride width, stride height
// layers multiplier
- // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal to 1
+ // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal
+ // to 1
using iT = int32_t;
for (iT kernel_h = 1; kernel_h <= 3; ++kernel_h)
for (iT kernel_w = 1; kernel_w <= 3; ++kernel_w)
for (iT channels = 1; channels <= 3; ++channels)
for (iT stride_w = 1; stride_w <= 3; ++stride_w)
for (iT stride_h = 1; stride_h <= 3; ++stride_h)
- for (iT multiplier = 1; multiplier <= 2; ++multiplier) {
- vector<int> input_shape_data{3, 7, 6, static_cast<int>(channels)}; // NHWC
+ for (iT multiplier = 1; multiplier <= 2; ++multiplier)
+ {
+ vector<int> input_shape_data{3, 7, 6, static_cast<int>(channels)}; // NHWC
vector<int> kernel_shape_data{kernel_h, kernel_w, channels, multiplier}; // HWCN
mir::Shape strides{stride_h, stride_w};
vector<unique_ptr<mir::TensorVariant>> input_ntensors(2);
Tensor input_atensor1;
fillTensors(input_ntensors[0], input_atensor0, input_shape_data, 1.0f);
fillTensors(input_ntensors[1], input_atensor1, kernel_shape_data, 1.0f);
- auto op_generator = [&strides](mir::Graph& g,
- const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [&strides](mir::Graph &g,
+ const std::vector<mir::Operation::Output *> &inputs) {
std::vector<int32_t> padding{0, 0};
- return g.create<mir::ops::DepthwiseConv2DOp>("y", inputs[0], inputs[1],
- strides, padding, padding);
+ return g.create<mir::ops::DepthwiseConv2DOp>("y", inputs[0], inputs[1], strides,
+ padding, padding);
};
- createAndRunTestGraph(op_generator, depthwiseConv2d, input_ntensors,
- input_atensor0, input_atensor1);
+ createAndRunTestGraph(op_generator, depthwiseConv2d, input_ntensors, input_atensor0,
+ input_atensor1);
}
}
-TEST(cpp_operations_test, fully_connected) {
+TEST(cpp_operations_test, fully_connected)
+{
vector<int> input_shape_data{3, 13};
vector<int> weights_shape_data{13, 7};
vector<unique_ptr<mir::TensorVariant>> input_ntensors(2);
Tensor input_atensor1;
fillTensors(input_ntensors[0], input_atensor0, input_shape_data, 1.0f);
fillTensors(input_ntensors[1], input_atensor1, weights_shape_data, 1.0f);
- auto op_generator = [](mir::Graph& g, const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::FullyConnectedOp>("y", inputs[0], inputs[1]);
};
createAndRunTestGraph(op_generator, fullConnect, input_ntensors, input_atensor0, input_atensor1);
}
-TEST(cpp_operations_test, resize_NN_test) {
- mir::Shape test_shapes[] = {
- {1, 8, 8, 1},
- {2, 10, 10, 1},
- {1, 11, 11, 2},
- {2, 8, 12, 2},
- {1, 48, 12, 1},
- {1, 48, 48, 1},
- {1, 48, 56, 1}
- };
- for (mir::Shape res_shape: test_shapes) {
+TEST(cpp_operations_test, resize_NN_test)
+{
+ mir::Shape test_shapes[] = {{1, 8, 8, 1}, {2, 10, 10, 1}, {1, 11, 11, 2}, {2, 8, 12, 2},
+ {1, 48, 12, 1}, {1, 48, 48, 1}, {1, 48, 56, 1}};
+ for (mir::Shape res_shape : test_shapes)
+ {
vector<int> input_shape_data{res_shape.dim(0), 4, 4, res_shape.dim(3)};
vector<unique_ptr<mir::TensorVariant>> input_ntensors(1);
Tensor input_atensor;
fillTensors(input_ntensors[0], input_atensor, input_shape_data, 1.0f);
- auto op_generator = [&res_shape](mir::Graph& g,
- const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [&res_shape](mir::Graph &g,
+ const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::ResizeOp>(
- "y", inputs[0],
- mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, res_shape);
+ "y", inputs[0], mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, res_shape);
};
createAndRunTestGraph(op_generator, resize, input_ntensors, input_atensor);
}
}
-TEST(cpp_operations_test, resize_NN_test_scales) {
+TEST(cpp_operations_test, resize_NN_test_scales)
+{
cout << "\n";
std::vector<float> test_scales[] = {
- {1, 2, 2, 1},
- {1, 2, 3, 1},
- {1, 3, 2, 1},
- {1, 2.5, 2, 1},
- {1, 3, 9, 1}
- };
- for (const std::vector<float>& scales: test_scales) {
+ {1, 2, 2, 1}, {1, 2, 3, 1}, {1, 3, 2, 1}, {1, 2.5, 2, 1}, {1, 3, 9, 1}};
+ for (const std::vector<float> &scales : test_scales)
+ {
vector<int> input_shape_data{1, 4, 4, 1};
vector<unique_ptr<mir::TensorVariant>> input_ntensors(1);
Tensor input_atensor;
fillTensors(input_ntensors[0], input_atensor, input_shape_data, 1.0f);
- auto op_generator = [&scales](mir::Graph& g,
- const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [&scales](mir::Graph &g,
+ const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::ResizeOp>(
- "y", inputs[0],
- mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, scales);
+ "y", inputs[0], mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, scales);
};
createAndRunTestGraph(op_generator, resize, input_ntensors, input_atensor);
}
}
template <irOps::PoolOp::PoolingType poolT>
-static mir::Operation* createPool(mir::Graph& g,
- const std::vector<mir::Operation::Output*>& inputs,
- mir::Shape& window_shape,
- mir::Shape& strides,
- irOps::PoolOp::BorderType border) {
+static mir::Operation *
+createPool(mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs,
+ mir::Shape &window_shape, mir::Shape &strides, irOps::PoolOp::BorderType border)
+{
std::vector<int32_t> padding{0, 0};
- return g.create<mir::ops::PoolOp>("pool", inputs[0], poolT, window_shape, strides,
- padding, padding, border);
+ return g.create<mir::ops::PoolOp>("pool", inputs[0], poolT, window_shape, strides, padding,
+ padding, border);
};
template <irOps::PoolOp::PoolingType poolT, typename Func>
-static void genericPoolTest(Func test_func, const vector<irOps::PoolOp::BorderType> borders) {
+static void genericPoolTest(Func test_func, const vector<irOps::PoolOp::BorderType> borders)
+{
// Iterate over window width, window height
// channels
// stride width, stride height
- // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal to 1
+ // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal
+ // to 1
using iT = int32_t;
for (iT windowH = 1; windowH <= 3; ++windowH)
for (iT windowW = 1; windowW <= 3; ++windowW)
for (iT channels = 1; channels <= 2; ++channels)
for (iT stride_h = 1; stride_h <= 3; ++stride_h)
- for (iT stride_w = 1; stride_w <= 3; ++stride_w) {
+ for (iT stride_w = 1; stride_w <= 3; ++stride_w)
+ {
vector<int> shape_data{3, 5, 7, static_cast<int>(channels)};
mir::Shape window_shape{windowH, windowW};
mir::Shape strides{stride_h, stride_w};
vector<unique_ptr<mir::TensorVariant>> input_ntensors(1);
fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f);
- for (auto border: borders) {
+ for (auto border : borders)
+ {
using namespace std::placeholders;
auto op_generator =
}
};
-TEST(cpp_operations_test, maxpool) {
- vector<irOps::PoolOp::BorderType> border_types = {
- irOps::PoolOp::BorderType::EMPTY
- };
+TEST(cpp_operations_test, maxpool)
+{
+ vector<irOps::PoolOp::BorderType> border_types = {irOps::PoolOp::BorderType::EMPTY};
genericPoolTest<mir::ops::PoolOp::PoolingType::MAX>(maxPool, border_types);
}
-TEST(cpp_operations_test, avgpool) {
- vector<irOps::PoolOp::BorderType> border_types = {
- irOps::PoolOp::BorderType::EMPTY,
- irOps::PoolOp::BorderType::ZEROFILLED
- };
+TEST(cpp_operations_test, avgpool)
+{
+ vector<irOps::PoolOp::BorderType> border_types = {irOps::PoolOp::BorderType::EMPTY,
+ irOps::PoolOp::BorderType::ZEROFILLED};
genericPoolTest<mir::ops::PoolOp::PoolingType::AVG>(avgPool, border_types);
}
-TEST(cpp_operations_test, relu) {
+TEST(cpp_operations_test, relu)
+{
// test prerequisites
vector<int> shape_data{2, 3, 4, 5};
Tensor input_atensor;
vector<unique_ptr<mir::TensorVariant>> input_ntensors(1);
fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f);
- auto op_generator = [](mir::Graph& g, const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::ReluOp>("y", inputs[0]);
};
createAndRunTestGraph(op_generator, relu, input_ntensors, input_atensor);
}
-TEST(cpp_operations_test, leaky_relu) {
+TEST(cpp_operations_test, leaky_relu)
+{
// test prerequisites
vector<int> shape_data{2, 3, 4, 5};
Tensor input_atensor;
vector<unique_ptr<mir::TensorVariant>> input_ntensors(1);
fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f);
- auto op_generator = [](mir::Graph& g, const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::LeakyReluOp>("y", inputs[0], 0.1);
};
createAndRunTestGraph(op_generator, leakyRelu, input_ntensors, input_atensor);
}
-TEST(cpp_operations_test, sigmoid) {
+TEST(cpp_operations_test, sigmoid)
+{
// test prerequisites
vector<int> shape_data{2, 3, 4, 5};
Tensor input_atensor;
vector<unique_ptr<mir::TensorVariant>> input_ntensors(1);
fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f);
- auto opGenerator = [](mir::Graph& g, const std::vector<mir::Operation::Output*>& inputs) {
+ auto opGenerator = [](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::SigmoidOp>("y", inputs[0]);
};
createAndRunTestGraph(opGenerator, sigmoid, input_ntensors, input_atensor);
}
-TEST(cpp_operations_test, elu) {
+TEST(cpp_operations_test, elu)
+{
// test prerequisites
vector<int> shape_data{2, 3, 4, 5};
Tensor input_atensor;
vector<unique_ptr<mir::TensorVariant>> input_ntensors(1);
fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f);
- auto op_generator = [](mir::Graph& g, const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::EluOp>("y", inputs[0], 1);
};
createAndRunTestGraph(op_generator, elu, input_ntensors, input_atensor);
}
-TEST(cpp_operations_test, tanh) {
+TEST(cpp_operations_test, tanh)
+{
// test prerequisites
vector<int> shape_data{2, 3, 4, 5};
Tensor input_atensor;
vector<unique_ptr<mir::TensorVariant>> input_ntensors(1);
fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f);
- auto op_generator = [](mir::Graph& g, const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::TanhOp>("y", inputs[0]);
};
createAndRunTestGraph(op_generator, tanhActivation, input_ntensors, input_atensor);
}
-TEST(cpp_operations_test, reduceMeanTst) {
+TEST(cpp_operations_test, reduceMeanTst)
+{
// test prerequisites
// different test cases
- std::vector<int> test_axis_list[] = {
- {2, 3},
- {1},
- {0},
- {2},
- {3},
- {0, 2},
- {1, 2, 3}
- };
- for (const vector<int>& axis_list: test_axis_list) {
- for (const bool keep_dims: {true, false}) {
+ std::vector<int> test_axis_list[] = {{2, 3}, {1}, {0}, {2}, {3}, {0, 2}, {1, 2, 3}};
+ for (const vector<int> &axis_list : test_axis_list)
+ {
+ for (const bool keep_dims : {true, false})
+ {
vector<int> input_shape_data{2, 3, 4, 5};
Tensor input_atensor;
vector<unique_ptr<mir::TensorVariant>> input_ntensors(1);
fillTensors(input_ntensors[0], input_atensor, input_shape_data, 1.0f);
auto op_generator = [&axis_list, keep_dims](
- mir::Graph& g, const std::vector<mir::Operation::Output*>& inputs) {
- auto op = g.create<mir::ops::ReduceOp>(
- "y", inputs[0], axis_list, keep_dims,
- mir::ops::ReduceOp::FuncType::mean);
+ mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
+ auto op = g.create<mir::ops::ReduceOp>("y", inputs[0], axis_list, keep_dims,
+ mir::ops::ReduceOp::FuncType::mean);
return op;
};
}
}
-TEST(cpp_operations_test, softmax) {
+TEST(cpp_operations_test, softmax)
+{
// iterate over number of dimensions in tensor
- for (int num_dims = 1; num_dims <= 4; ++num_dims) {
+ for (int num_dims = 1; num_dims <= 4; ++num_dims)
+ {
// test prerequisites
vector<int> shape_data{2, 3, 4, 5};
shape_data.resize(num_dims);
Tensor input_atensor;
vector<unique_ptr<mir::TensorVariant>> input_ntensors(1);
fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f);
- auto op_generator = [axis](mir::Graph& g, const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [axis](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::SoftmaxOp>("y", inputs[0], axis);
};
}
}
-TEST(cpp_operations_test, slice4d) {
+TEST(cpp_operations_test, slice4d)
+{
vector<int> shape_data{5, 30, 40, 12};
- vector<int> starts[] = {{0, 0, 0, 0},
- {1, 1, 1, 1},
- {1, 0, 1, 0},
- {0, 1, 1, 0}};
+ vector<int> starts[] = {{0, 0, 0, 0}, {1, 1, 1, 1}, {1, 0, 1, 0}, {0, 1, 1, 0}};
vector<int> sizes[] = {
- {-1, -1, -1, -1},
- {4, -1, 10, -1},
+ {-1, -1, -1, -1}, {4, -1, 10, -1},
};
- for (auto st : starts) {
- for (auto sz : sizes) {
+ for (auto st : starts)
+ {
+ for (auto sz : sizes)
+ {
Tensor input_atensor;
vector<unique_ptr<mir::TensorVariant>> input_n_tensor(1);
fillTensors(input_n_tensor[0], input_atensor, shape_data, 1.0f);
- auto op_gen = [st, sz](mir::Graph& g, const std::vector<mir::Operation::Output*>& inputs) {
- return g.create<mir::ops::SliceOp>("y", inputs[0], mir::Shape(st),
- mir::Shape(sz));
+ auto op_gen = [st, sz](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
+ return g.create<mir::ops::SliceOp>("y", inputs[0], mir::Shape(st), mir::Shape(sz));
};
createAndRunTestGraph(op_gen, slice, input_n_tensor, input_atensor);
}
}
}
-TEST(cpp_operations_test, reshape) {
+TEST(cpp_operations_test, reshape)
+{
// test prerequisites
vector<int> input_shape_data{2, 3, 4, 5};
vector<int> output_shape_data{1, 120};
Tensor input_atensor;
vector<unique_ptr<mir::TensorVariant>> input_ntensors(1);
fillTensors(input_ntensors[0], input_atensor, input_shape_data, 1.0f);
- auto op_generator = [&output_nshape](mir::Graph& g,
- const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [&output_nshape](mir::Graph &g,
+ const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::ReshapeOp>("y", inputs[0], output_nshape);
};
createAndRunTestGraph(op_generator, reshape, input_ntensors, input_atensor);
}
-TEST(cpp_operations_test, sqrtTest) {
+TEST(cpp_operations_test, sqrtTest)
+{
// test prerequisites
vector<int> shape_data{2, 3, 4, 5};
Tensor input_atensor;
vector<unique_ptr<mir::TensorVariant>> input_ntensor(1);
fillTensors(input_ntensor[0], input_atensor, shape_data, 1.0f);
- auto op_generator = [](mir::Graph& g, const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::SqrtOp>("y", inputs[0]);
};
createAndRunTestGraph(op_generator, sqrtFN, input_ntensor, input_atensor);
}
-TEST(cpp_operations_test, pad) {
+TEST(cpp_operations_test, pad)
+{
// test on matrix 2x3
- vector<int> input_shape{2,3};
+ vector<int> input_shape{2, 3};
Tensor input_atensor;
vector<unique_ptr<mir::TensorVariant>> input_ntensor(1);
float const_value = 0.0;
- mir::Scalar constant_value(reinterpret_cast<char*>(&const_value),
- mir::DataType::FLOAT32, sizeof(float));
+ mir::Scalar constant_value(reinterpret_cast<char *>(&const_value), mir::DataType::FLOAT32,
+ sizeof(float));
- auto op_generator = [num_dims, &paddings, &constant_value]
- (mir::Graph& g, const std::vector<mir::Operation::Output*>& inputs) {
+ auto op_generator = [num_dims, &paddings, &constant_value](
+ mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::PadOp>("y", inputs[0], num_dims, paddings, constant_value);
};
createAndRunTestGraph(op_generator, pad, input_ntensor, input_atensor);
}
-TEST(cpp_operations_test, transpose) {
+TEST(cpp_operations_test, transpose)
+{
// test transpose for 4 dims tensors
vector<int> input_shape_4d{2, 3, 4, 5};
Tensor input_atensor_4d;
vector<unique_ptr<mir::TensorVariant>> input_ntensor_4d(1);
fillTensors(input_ntensor_4d[0], input_atensor_4d, input_shape_4d, 1.0f);
- vector<size_t> test_cases_pack_4d[] = {
- {0, 1, 2, 3},
- {1, 0, 2, 3},
- {3, 2, 1, 0}
- };
- for (const auto& permute: test_cases_pack_4d) {
- auto op_generator = [&permute](mir::Graph& g,
- const std::vector<mir::Operation::Output*>& inputs) {
- return g.create<mir::ops::TransposeOp>("transpose", inputs[0], permute);
+ vector<size_t> test_cases_pack_4d[] = {{0, 1, 2, 3}, {1, 0, 2, 3}, {3, 2, 1, 0}};
+ for (const auto &permute : test_cases_pack_4d)
+ {
+ auto op_generator = [&permute](mir::Graph &g,
+ const std::vector<mir::Operation::Output *> &inputs) {
+ return g.create<mir::ops::TransposeOp>("transpose", inputs[0], permute);
};
createAndRunTestGraph(op_generator, transpose, input_ntensor_4d, input_atensor_4d);
}
Tensor input_atensor_3d;
vector<unique_ptr<mir::TensorVariant>> input_ntensor_3d(1);
fillTensors(input_ntensor_3d[0], input_atensor_3d, input_shape_3d, 1.0f);
- vector<size_t> test_cases_pack_3d[] = {
- {0, 1, 2},
- {1, 0, 2},
- {2, 1, 0}
- };
- for (const auto& permute: test_cases_pack_3d) {
- auto op_generator = [&permute](mir::Graph& g,
- const std::vector<mir::Operation::Output*>& inputs) {
- return g.create<mir::ops::TransposeOp>("transpose", inputs[0], permute);
+ vector<size_t> test_cases_pack_3d[] = {{0, 1, 2}, {1, 0, 2}, {2, 1, 0}};
+ for (const auto &permute : test_cases_pack_3d)
+ {
+ auto op_generator = [&permute](mir::Graph &g,
+ const std::vector<mir::Operation::Output *> &inputs) {
+ return g.create<mir::ops::TransposeOp>("transpose", inputs[0], permute);
};
createAndRunTestGraph(op_generator, transpose, input_ntensor_3d, input_atensor_3d);
}
-
-
}
using namespace nnc;
using namespace mir;
-static bool isFileExists(const string& path) {
+static bool isFileExists(const string &path)
+{
ifstream f(path);
return f.good();
}
-static void deleteFile(const string& path) {
+static void deleteFile(const string &path)
+{
int res = remove(path.c_str());
assert(!res && "failed to remove file");
(void)res;
}
-int removeRec(const char* fpath, const struct stat* /*sb*/,
- int /*typeflag*/, struct FTW* /*ftwbuf*/) {
+int removeRec(const char *fpath, const struct stat * /*sb*/, int /*typeflag*/,
+ struct FTW * /*ftwbuf*/)
+{
deleteFile(fpath);
return 0;
}
-static void deleteDir(const string& path) {
+static void deleteDir(const string &path)
+{
int res = nftw(path.c_str(), removeRec, 1, FTW_DEPTH | FTW_PHYS);
assert(!res && "failed to remove dir");
(void)res;
}
-static void checkOutputExists(const string& common_path) {
+static void checkOutputExists(const string &common_path)
+{
ASSERT_TRUE(isFileExists(common_path + ".h"));
ASSERT_TRUE(isFileExists(common_path + ".cpp"));
ASSERT_TRUE(isFileExists(common_path + ".params"));
}
-static void emptyFile(const string& path) {
- ofstream of(path);
-}
+static void emptyFile(const string &path) { ofstream of(path); }
-TEST(Generator, check_generator_call) {
- // assume here that c++ and c code generators behave identically in terms of parameters check
- // test only c++ generator
- #define TEST_DIR "output_dir"
- #define TEST_NAME "someName"
- #define BASE_NAME TEST_DIR "/" TEST_NAME
- const char* argv[] = {"soft_backend_test",
- "-d", TEST_DIR,
- "-o", TEST_NAME,
- nullptr};
+TEST(Generator, check_generator_call)
+{
+// assume here that c++ and c code generators behave identically in terms of parameters check
+// test only c++ generator
+#define TEST_DIR "output_dir"
+#define TEST_NAME "someName"
+#define BASE_NAME TEST_DIR "/" TEST_NAME
+ const char *argv[] = {"soft_backend_test", "-d", TEST_DIR, "-o", TEST_NAME, nullptr};
int argc = (sizeof(argv) / sizeof(argv[0])) - 1;
cli::CommandLine::getParser()->parseCommandLine(argc, argv, false);
mir::Graph g;
- Operation* input = g.create<ops::InputOp>("input", Shape{1, 2, 3, 4});
- Operation* output = g.create<ops::ReluOp>("output", input->getOutput(0));
+ Operation *input = g.create<ops::InputOp>("input", Shape{1, 2, 3, 4});
+ Operation *output = g.create<ops::ReluOp>("output", input->getOutput(0));
// test that generator creates output dir and files
if (isFileExists(TEST_DIR))
using namespace mir;
using namespace sir;
-static const CallFunction* getCall(const unique_ptr<Action>& ptr) {
- return dynamic_cast<const CallFunction*>(ptr.get());
+static const CallFunction *getCall(const unique_ptr<Action> &ptr)
+{
+ return dynamic_cast<const CallFunction *>(ptr.get());
}
/*
* This test designed to check basic layout properties of Model analyzer
*/
-TEST(ModelAnalyzer, linearization) {
+TEST(ModelAnalyzer, linearization)
+{
mir::Graph g;
/*
* Create graph:
* \ /
* [join]
*/
- Operation* input = g.create<ops::InputOp>("input", Shape{1, 2, 3});
- Operation* head1 = g.create<ops::ReluOp>("head1", input->getOutput(0));
- Operation* head2 = g.create<ops::ReluOp>("head2", input->getOutput(0));
- Operation* tail1 = g.create<ops::ReluOp>("tail1", head1->getOutput(0));
- Operation* tail2 = g.create<ops::ReluOp>("tail2", head2->getOutput(0));
- std::vector<mir::Operation::Output*> concat_inputs{tail1->getOutput(0), tail2->getOutput(0)};
- Operation* join = g.create<ops::ConcatOp>("join", concat_inputs, 0);
+ Operation *input = g.create<ops::InputOp>("input", Shape{1, 2, 3});
+ Operation *head1 = g.create<ops::ReluOp>("head1", input->getOutput(0));
+ Operation *head2 = g.create<ops::ReluOp>("head2", input->getOutput(0));
+ Operation *tail1 = g.create<ops::ReluOp>("tail1", head1->getOutput(0));
+ Operation *tail2 = g.create<ops::ReluOp>("tail2", head2->getOutput(0));
+ std::vector<mir::Operation::Output *> concat_inputs{tail1->getOutput(0), tail2->getOutput(0)};
+ Operation *join = g.create<ops::ConcatOp>("join", concat_inputs, 0);
// Check that layout is desired
ModelAnalyzer ma;
ma.analyze(&g);
- const auto& seq = ma.getInferenceSequence();
+ const auto &seq = ma.getInferenceSequence();
ASSERT_EQ(seq.size(), 6u);
auto it = seq.begin();
ASSERT_EQ(getCall(*(it++))->mirOp, input);
using namespace nnc::cli;
+void soption_checker1(const Option<std::string> &opt) { ASSERT_EQ(opt, "SOME_VALUE1,SOME_VALUE2"); }
-void soption_checker1(const Option<std::string> &opt)
-{
- ASSERT_EQ(opt, "SOME_VALUE1,SOME_VALUE2");
-}
-
-void soption_checker2(const Option<std::string> &opt)
-{
- ASSERT_EQ(opt, "AAA_VALUE");
-}
+void soption_checker2(const Option<std::string> &opt) { ASSERT_EQ(opt, "AAA_VALUE"); }
-void boption_checker(const Option<bool> &opt)
-{
- ASSERT_EQ(opt, false);
-}
+void boption_checker(const Option<bool> &opt) { ASSERT_EQ(opt, false); }
/**
* declare command line options for testing
overview("description of option with single name"));
// test option with several separators
Option<std::string> SSeveralSepOpt(optname("-several_separators"),
- overview("description of option with several separators"),
- "",
- optional(false),
- optvalues(""),
- soption_checker1,
+ overview("description of option with several separators"), "",
+ optional(false), optvalues(""), soption_checker1,
separators("=, :"));
// test option with one separator
Option<std::string> SOneSepOpt(optname("--one_separarot"),
- overview("description of option with one separator"),
- "",
- optional(false),
- optvalues(""),
- soption_checker2,
- separators("="));
+ overview("description of option with one separator"), "",
+ optional(false), optvalues(""), soption_checker2, separators("="));
// test option with defalut value
Option<std::string> SDefaultOpt(optname("-default_val_opt"),
overview("description of option with default value"),
"DEFAULT_VALUE");
// test optional option
Option<std::string> SOptionalOpt(optname("--optional_opt"),
- overview("description of optional option"),
- "",
- optional(true));
+ overview("description of optional option"), "", optional(true));
// test option with valid values
Option<std::string> SValidValsOpt(optname("-valid_opt"),
- overview("description of option with valid values"),
- "",
- optional(true),
- optvalues("value1, value2"));
+ overview("description of option with valid values"), "",
+ optional(true), optvalues("value1, value2"));
//
// declare integer options
//
// test option with negative value and valid values
Option<int32_t> NNegOpt(optname("-neg_val"),
- overview("description of integer option with negative value"),
- -1,
- optional(false),
- optvalues("-42, -33"));
+ overview("description of integer option with negative value"), -1,
+ optional(false), optvalues("-42, -33"));
// test option with default negative value
-Option<int32_t> NDefaultNegOpt(optname("-default_neg_val"),
- overview("description of integer option with default negative value"),
- -33);
+Option<int32_t>
+ NDefaultNegOpt(optname("-default_neg_val"),
+ overview("description of integer option with default negative value"), -33);
// test option with positive values
Option<uint32_t> NPosOpt(optname("-pos_val"),
- overview("description of integer option with positive value"),
- 1,
- optional(false),
- optvalues("42, 33"));
+ overview("description of integer option with positive value"), 1,
+ optional(false), optvalues("42, 33"));
//
// declare char options
//
-Option<char> CharOpt(optname("-char-opt"),
- overview("description of char option"),
- '\0',
- optional(false),
- optvalues("a, b"));
-
-Option<char> DashOpt(optname("-dash_opt"),
- overview("description of char option with dash value"),
- '\0',
- optional(false),
- optvalues("-"));
+Option<char> CharOpt(optname("-char-opt"), overview("description of char option"), '\0',
+ optional(false), optvalues("a, b"));
+
+Option<char> DashOpt(optname("-dash_opt"), overview("description of char option with dash value"),
+ '\0', optional(false), optvalues("-"));
//
// declare bool option
//
-Option<bool> BoolOpt(optname("-bool_opt"),
- overview("description of bool option"),
- true,
- optional(false),
- optvalues(""),
- boption_checker,
- separators("="));
-Option<bool> BoolOpt2(optname("-bool-opt2"),
- overview("description of bool option with value"));
+Option<bool> BoolOpt(optname("-bool_opt"), overview("description of bool option"), true,
+ optional(false), optvalues(""), boption_checker, separators("="));
+Option<bool> BoolOpt2(optname("-bool-opt2"), overview("description of bool option with value"));
//
// declare vector<string> option
overview("description of vector option"));
Option<std::vector<std::string>> VecStrOptWithVals(optname("--vec_opt_with_vals"),
overview("description of vector option"),
- std::vector<std::string>(),
- optional(false),
+ std::vector<std::string>(), optional(false),
optvalues("abc, 123, xxx"));
//
// declare options in group
//
// declare bool option
//
-Option<bool> GroupOpt1(optname("-group_opt1"),
- overview("description of group option"),
- true,
- optional(false),
- optvalues(""),
- nullptr,
- separators(""),
- showopt(true),
+Option<bool> GroupOpt1(optname("-group_opt1"), overview("description of group option"), true,
+ optional(false), optvalues(""), nullptr, separators(""), showopt(true),
IOption::Group::caffe2);
-Option<std::string> GroupOpt2(optname("-group_opt2"),
- overview("description of group option"),
- std::string(),
- optional(true),
- optvalues(""),
- nullptr,
- separators(""),
- showopt(true),
- IOption::Group::caffe2);
-Option<int32_t> GroupOpt3(optname("-group_opt3"),
- overview("description of group option"),
- 42,
- optional(true),
- optvalues(""),
- nullptr,
- separators(""),
- showopt(true),
+Option<std::string> GroupOpt2(optname("-group_opt2"), overview("description of group option"),
+ std::string(), optional(true), optvalues(""), nullptr, separators(""),
+ showopt(true), IOption::Group::caffe2);
+Option<int32_t> GroupOpt3(optname("-group_opt3"), overview("description of group option"), 42,
+ optional(true), optvalues(""), nullptr, separators(""), showopt(true),
IOption::Group::onnx);
// test options
TEST(SUPPORT_NNC, verify_cl_options)
{
// create command line
- const char *argv[] = {"CLTest", // program name
- // string options
- "-m", "multiopt_value", // second name for option with several names
- "--single", "single_value", // option with single name
- "-several_separators:SOME_VALUE1,SOME_VALUE2", // test option with several separators
- "--one_separarot=AAA_VALUE", // test option whit one separator
- "-default_val_opt", // test option with default value
- "--optional_opt", "/home/guest/tmp", // test optional option
- "-valid_opt", "value2", // test options with defined values
- // integer options
- "-neg_val", "-42", // test negative value for integer option
- "-default_neg_val", // test integer option with default value
- "-pos_val", "33", // test positive value for integer option
- // char options
- "-char-opt", "b",
- "-dash_opt", "-",
- // bool options
- "-bool_opt=false",
- "-bool-opt2",
- // vector of strings options
- "-vec_opt1", "1", "c", "222", "ABC", "857",
- "-vec_opt2",
- "--vec_opt_with_vals", "abc", "123", "xxx", "abc", "xxx",
- // grouped options
- "-group_opt1",
- "-group_opt2", "abc",
- "-group_opt3", "11",
- nullptr};
+ const char *argv[] = {
+ "CLTest", // program name
+ // string options
+ "-m", "multiopt_value", // second name for option with several names
+ "--single", "single_value", // option with single name
+ "-several_separators:SOME_VALUE1,SOME_VALUE2", // test option with several separators
+ "--one_separarot=AAA_VALUE", // test option whit one separator
+ "-default_val_opt", // test option with default value
+ "--optional_opt", "/home/guest/tmp", // test optional option
+ "-valid_opt", "value2", // test options with defined values
+ // integer options
+ "-neg_val", "-42", // test negative value for integer option
+ "-default_neg_val", // test integer option with default value
+ "-pos_val", "33", // test positive value for integer option
+ // char options
+ "-char-opt", "b", "-dash_opt", "-",
+ // bool options
+ "-bool_opt=false", "-bool-opt2",
+ // vector of strings options
+ "-vec_opt1", "1", "c", "222", "ABC", "857", "-vec_opt2", "--vec_opt_with_vals", "abc", "123",
+ "xxx", "abc", "xxx",
+ // grouped options
+ "-group_opt1", "-group_opt2", "abc", "-group_opt3", "11", nullptr};
int argc = (sizeof(argv) / sizeof(argv[0])) - 1;
// It must be failed if option is not passed and other options are in the same group
- argv[argc-5] = "-m"; // disable -group_opt1
+ argv[argc - 5] = "-m"; // disable -group_opt1
ASSERT_DEATH(CommandLine::getParser()->parseCommandLine(argc, argv), "");
- argv[argc-5] = "-group_opt1"; // enable -group_opt1
+ argv[argc - 5] = "-group_opt1"; // enable -group_opt1
- // test when mandatory grouped option is not passed. It must be OK if options being from the same group are missed
- argv[argc-4] = "-m"; // disable -group_opt2
- argv[argc-2] = "-m"; // disable -group_opt3
+ // test when mandatory grouped option is not passed. It must be OK if options being from the same
+ // group are missed
+ argv[argc - 4] = "-m"; // disable -group_opt2
+ argv[argc - 2] = "-m"; // disable -group_opt3
CommandLine::getParser()->parseCommandLine(argc, argv);
- argv[argc-4] = "-group_opt2"; // enable -group_opt2
- argv[argc-2] = "-group_opt3"; // enable -group_opt3
+ argv[argc - 4] = "-group_opt2"; // enable -group_opt2
+ argv[argc - 2] = "-group_opt3"; // enable -group_opt3
// parse command line
CommandLine::getParser()->parseCommandLine(argc, argv);
try:
import numpy as np
except ImportError:
- print("!! NumPy is not installed, tflite frontend test not generated", file=sys.stderr)
+ print(
+ "!! NumPy is not installed, tflite frontend test not generated", file=sys.stderr)
exit(1)
try:
import tensorflow as tf
if (LooseVersion(tf.VERSION) < LooseVersion("1.11.0")):
raise (Exception("Wrong Version"))
except:
- print("!! Tensorflow v 1.11 not installed, tflite frontend test not generated", file=sys.stderr)
+ print(
+ "!! Tensorflow v 1.11 not installed, tflite frontend test not generated",
+ file=sys.stderr)
exit(1)
resDir = sys.argv[1]
-if resDir[-1]!="/": resDir +="/"
+if resDir[-1] != "/": resDir += "/"
output_shape = [1, 28, 28, 1]
-strides = [1,1,1,1]
-W = tf.constant(np.ones([7, 7, 1, 1]).astype(np.float32), name = "ker_d")
+strides = [1, 1, 1, 1]
+W = tf.constant(np.ones([7, 7, 1, 1]).astype(np.float32), name="ker_d")
# Create the graph.
X = tf.placeholder(shape=[1, 28, 28, 1], name='input', dtype=tf.float32)
out0 = tf.identity(Y, name="out")
# Filter the input image.
with tf.Session() as sess:
- out = sess.run(out0, feed_dict = {"input:0": np.ones((1, 28, 28, 1)).astype(np.float32)})
+ out = sess.run(
+ out0, feed_dict={"input:0": np.ones((1, 28, 28, 1)).astype(np.float32)})
frozen_graphdef = tf.graph_util.convert_variables_to_constants(
sess, sess.graph_def, ["out"])
converter = tf.contrib.lite.TocoConverter.from_session(sess, [X], [out0])
tflite_model = converter.convert()
- open(resDir+"unsupported.tflite", "wb").write(tflite_model)
+ open(resDir + "unsupported.tflite", "wb").write(tflite_model)
" * SIN: unsupported operator";
// When adding support for new layers, change the model, not the test
-TEST(TFLITE_IMPORT_UNSUPPORTED, ImportModelWithUnsupportedLayers) {
+TEST(TFLITE_IMPORT_UNSUPPORTED, ImportModelWithUnsupportedLayers)
+{
std::string filename = std::string(TFLITE_TEST_DIR) + "unsupported.tflite";
std::cout << filename << "\n";
nnc::TfliteImporterPass importer{filename};
- try {
+ try
+ {
importer.importModel();
}
- catch (nnc::PassException &e) {
+ catch (nnc::PassException &e)
+ {
ASSERT_EQ(std::string(ErrorMsg), e.what());
importer.cleanup();
return;
using namespace mir;
using namespace nnc::cli;
-int main(int argc, const char **argv) {
+int main(int argc, const char **argv)
+{
cli::CommandLine::getParser()->parseCommandLine(argc, argv, false);
// FIXME: caffe2 input shapes are not provided by model and must be set from cli
nnc::Caffe2ImporterPass importer{cli::inputFile, cli::initNet, {cli::inputShapes}};
- try {
+ try
+ {
IrDotDumper dotDumper;
auto g = static_cast<Graph *>(importer.importModel());
g->accept(&dotDumper);
dotDumper.writeDot(std::cout);
}
- catch (PassException &e) {
+ catch (PassException &e)
+ {
std::cout << "Error: " << e.what() << std::endl;
return -1;
}
using namespace mir;
using namespace nnc::cli;
-int main(int argc, const char **argv) {
+int main(int argc, const char **argv)
+{
cli::CommandLine::getParser()->parseCommandLine(argc, argv, false);
nnc::CaffeImporterPass importer{cli::inputFile};
- try {
+ try
+ {
IrDotDumper dotDumper;
auto g = importer.importModel();
g->accept(&dotDumper);
dotDumper.writeDot(std::cout);
}
- catch (PassException &e) {
+ catch (PassException &e)
+ {
std::cout << "Error: " << e.what() << std::endl;
return -1;
}
(
'HDF5Data',
{
- 'source':
- 'in', # This is the name of the file WITH HDF5 FILENAMES 0_0
+ 'source': 'in', # This is the name of the file WITH HDF5 FILENAMES 0_0
# Top should have the same name as the dataset in the hdf5 file
# FIXME Requires Caffegen to be built with Caffe that supports LMDB
'batch_size': 1,
(
'ArgMax',
{
- 'out_max_val':
- False, # ok # if True, outputs pairs (argmax, maxval) # ok
+ 'out_max_val': False, # ok # if True, outputs pairs (argmax, maxval) # ok
'top_k': 1,
'axis': -1
}),
'base': -1.0, # ok
'scale': 1.0,
'shift': PH(float, (2.0, 10.0)),
- 'how_many' : 10
+ 'how_many': 10
}), # y = ln(shift + scale * x) (log_base() for base > 0)
(
'Power',
if self.args == None: self.args = dict()
self.num_inp = self.args.pop("inputs", 1)
self.num_out = self.args.pop("outputs", 1)
- self.special_shape = self.args.pop(
- "special_shape", False) # 2nd input has special shape
+ self.special_shape = self.args.pop("special_shape",
+ False) # 2nd input has special shape
self.is_data = self.args.pop("is_data", False)
self.is_notop = self.args.pop("is_notop", False)
net.data1 = L.DummyData(data_filler=cofil, shape={'dim': [1, 4]})
net.data2 = L.DummyData(data_filler=cofil, shape={'dim': [1, 1]})
- net.op = getattr(L, self.name)(net.data, net.data1, net.data2,
- **self.args)
+ net.op = getattr(L, self.name)(net.data, net.data1, net.data2, **self.args)
# this covers most cases
else:
net.data = L.Input(shape={'dim': [1, 3, LS, LS]})
if self.num_inp == 2:
- net.data1 = L.DummyData(
- data_filler=cofil, shape={'dim': [1, 3, LS, LS]})
+ net.data1 = L.DummyData(data_filler=cofil, shape={'dim': [1, 3, LS, LS]})
elif self.num_inp > 2:
for i in range(1, self.num_inp):
setattr(
net, "data" + str(i),
- L.DummyData(
- data_filler=cofil, shape={'dim': EXTRA_SHAPES[i]}))
+ L.DummyData(data_filler=cofil, shape={'dim': EXTRA_SHAPES[i]}))
if self.special_shape:
net.data = L.Input(shape={'dim': [1, 3, 1, 1]})
net.data1 = L.DummyData(
data_filler=cofil, shape={'dim': self.special_shape})
- net.op = getattr(L, self.name)(net.data, *[
- getattr(net, "data" + str(i)) for i in range(1, self.num_inp)
- ], **self.args)
+ net.op = getattr(L, self.name)(
+ net.data,
+ *[getattr(net, "data" + str(i))
+ for i in range(1, self.num_inp)], **self.args)
if self.is_notop:
net.op.fn.tops = OrderedDict()
self.how_many = self.args.pop("how_many", 1)
def make(self):
- return [
- Layer(self.name, traverse(self.args, mock))
- for i in range(self.how_many)
- ]
+ return [Layer(self.name, traverse(self.args, mock)) for i in range(self.how_many)]
layer_gen = chain(*map(lambda para: LayerMaker(para).make(), OPS))
n = layer.make_net()
counter[layer.name] += 1
- with open(filename.format(layer.name, counter[layer.name] - 1),
- 'w+') as ptxt_file:
+ with open(filename.format(layer.name, counter[layer.name] - 1), 'w+') as ptxt_file:
print(n.to_proto(), file=ptxt_file)
if layer.name == "Python": # Special case for python layer
import caffe
import numpy as np
+
class EuclideanLossLayer(caffe.Layer):
"""
Compute the Euclidean Loss in the same manner as the C++ EuclideanLossLayer
#include <fstream>
#include <cassert>
-int fileToArray(const std::string& source, const std::string& dest, const std::string& arrName) {
- FILE* fs = fopen(source.c_str(), "rb");
- if (!fs) {
+int fileToArray(const std::string &source, const std::string &dest, const std::string &arrName)
+{
+ FILE *fs = fopen(source.c_str(), "rb");
+ if (!fs)
+ {
std::cerr << "source file not found: <" << source << ">" << std::endl;
return -1;
}
std::ofstream fo(dest.c_str());
- if (fo.fail()) {
+ if (fo.fail())
+ {
std::cerr << "cannot generate file: <" << dest << ">" << std::endl;
fclose(fs);
return -1;
assert(!is_error);
(void)is_error;
size_t bytes;
- do {
+ do
+ {
char buf[1024];
bytes = fread(buf, 1, sizeof(buf), fs);
assert(!ferror(fs) && "file read error");
-
+
// convert line
- for (size_t i = 0; i < bytes; i++) {
+ for (size_t i = 0; i < bytes; i++)
+ {
fo << "0x" << std::hex << static_cast<int>(buf[i]) << ", ";
}
} while (bytes != 0);
return path;
}
-int main(int argc, char *argv[]) {
+int main(int argc, char *argv[])
+{
if (argc < 3)
return -1;
std::string OutPutDir = argv[1];
- for (int i = 2; i < argc; i++) {
+ for (int i = 2; i < argc; i++)
+ {
std::string sourceFullFileName = argv[i];
std::string filename = extractFileName(sourceFullFileName);
// NOLINTNEXTLINE (performance-inefficient-string-concatenation)
# -b - specifies path to nnkit build folder, inside which tools/run is located
# -f - specifies framework ('tfl' for tflite or 'caf' for caffe) that the model belogs to
# -t - specifies path to testcase folder (see it's structure in readme)
-# -p - allow some sort of parallelism by processing only a subset of files,
-# you need to specify number of processes and run as much of them
+# -p - allow some sort of parallelism by processing only a subset of files,
+# you need to specify number of processes and run as much of them
# manually with diferent numbers
# -r - infer all testcases regardless of whether the result files are present
# last argument(s) is the model to infer
"-t <testcases_dir> " + \
"[-p <nporc> <proc_num>] " + \
"[-r] " + \
- "(<tflite_model_file> | <caffe_prototxt_model> <caffe_caffemodel_file>)"
+ "(<tflite_model_file> | <caffe_prototxt_model> <caffe_caffemodel_file>)"
+
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
min_argc = 8
args = {}
-args['-p'] = (1, 1)
+args['-p'] = (1, 1)
args['-r'] = False
argc = len(sys.argv)
for i in range(argc):
arg = sys.argv[i]
- if arg =='-r':
+ if arg == '-r':
args[arg] = True
elif arg == '-b' or arg == '-f' or arg == '-t':
if i + 1 >= argc:
hdf_suffix = '.hdf5'
bin_suffix = '.dat'
+
def get_command_caf(infilename, outfilename, proto, caffemodel):
- return [build_path + "/tools/run/nnkit-run",
- "--pre", build_path + "/actions/HDF5/libnnkit_HDF5_import_action.so",
- "--pre-arg", infilename,
- "--backend", build_path + "/backends/caffe/libnnkit_caffe_backend.so",
- "--backend-arg", proto,
- "--backend-arg", caffemodel,
- "--post", build_path + "/actions/HDF5/libnnkit_HDF5_export_action.so",
- "--post-arg", outfilename]
+ return [
+ build_path + "/tools/run/nnkit-run", "--pre",
+ build_path + "/actions/HDF5/libnnkit_HDF5_import_action.so", "--pre-arg",
+ infilename, "--backend", build_path + "/backends/caffe/libnnkit_caffe_backend.so",
+ "--backend-arg", proto, "--backend-arg", caffemodel, "--post",
+ build_path + "/actions/HDF5/libnnkit_HDF5_export_action.so", "--post-arg",
+ outfilename
+ ]
+
def get_command_tfl(infilename, outfilename, model_file):
- return [build_path + "/tools/run/nnkit-run",
- "--pre", build_path + "/actions/HDF5/libnnkit_HDF5_import_action.so",
- "--pre-arg", infilename,
- "--backend", build_path + "/backends/tflite/libnnkit_tflite_backend.so",
- "--backend-arg", model_file,
- "--post", build_path + "/actions/builtin/libnnkit_show_action.so",
- "--post", build_path + "/actions/HDF5/libnnkit_HDF5_export_action.so",
- "--post-arg", outfilename]
+ return [
+ build_path + "/tools/run/nnkit-run", "--pre",
+ build_path + "/actions/HDF5/libnnkit_HDF5_import_action.so", "--pre-arg",
+ infilename, "--backend",
+ build_path + "/backends/tflite/libnnkit_tflite_backend.so", "--backend-arg",
+ model_file, "--post", build_path + "/actions/builtin/libnnkit_show_action.so",
+ "--post", build_path + "/actions/HDF5/libnnkit_HDF5_export_action.so",
+ "--post-arg", outfilename
+ ]
+
testcase_num = 0
testcases = glob.glob(testcases_dir + '/testcase*')
-#testcases = [t
-# for t in testcases
+#testcases = [t
+# for t in testcases
# if remove_existing
-# or len(glob.glob(t + '/output/output' + hdf_suffix)) == 0
+# or len(glob.glob(t + '/output/output' + hdf_suffix)) == 0
# or len(glob.glob(t + '/output/output' + bin_suffix)) == 0]
testcases = testcases[proc_num - 1::nproc]
else:
eprint(testcase, ': input not found')
except:
- eprint(testcase, 'failed')
-
-eprint('ended at', datetime.datetime.now())
+ eprint(testcase, 'failed')
+eprint('ended at', datetime.datetime.now())
import struct
import sys
-# This script takes hdf5 file and unfolds it in a vector of float values
+# This script takes hdf5 file and unfolds it in a vector of float values
# which is then writen in binary format to a given file
# This is used by infer_testcases.py
+
def res2bin(infilename, outfilename):
-# print("Input filename: ", infilename)
-# print("Output filename: " , outfilename)
-
- f = h5py.File(infilename)
- dset = f[list(f.keys())[0]]
-
- vals = np.zeros(np.shape(dset), dtype='float32')
- for i in range(np.size(dset,0)):
- vals[i,:] = np.asarray(dset[i], dtype='float32')
- vals = list(np.reshape(vals, (vals.size)))
-
- with open(outfilename, 'wb') as outfile:
- outfile.write(struct.pack('f'*len(vals), *vals))
+ # print("Input filename: ", infilename)
+ # print("Output filename: " , outfilename)
-if __name__ == '__main__':
- argc = len(sys.argv)
- if (argc > 2):
- res2bin(sys.argv[1], sys.argv[2])
- else:
- print("Not enough arguments, expected: hdf5 filename, output filename")
- exit()
+ f = h5py.File(infilename)
+ dset = f[list(f.keys())[0]]
+
+ vals = np.zeros(np.shape(dset), dtype='float32')
+ for i in range(np.size(dset, 0)):
+ vals[i, :] = np.asarray(dset[i], dtype='float32')
+ vals = list(np.reshape(vals, (vals.size)))
+ with open(outfilename, 'wb') as outfile:
+ outfile.write(struct.pack('f' * len(vals), *vals))
+
+
+if __name__ == '__main__':
+ argc = len(sys.argv)
+ if (argc > 2):
+ res2bin(sys.argv[1], sys.argv[2])
+ else:
+ print("Not enough arguments, expected: hdf5 filename, output filename")
+ exit()
class Tensor;
-static void iterate(Tensor& tensor, function<void(vector<int>&)> on_loop);
+static void iterate(Tensor &tensor, function<void(vector<int> &)> on_loop);
-class Tensor {
+class Tensor
+{
public:
- explicit Tensor(const vector<hsize_t>& shape) : _shape(shape), _data(0), _num_elems(1) {
+ explicit Tensor(const vector<hsize_t> &shape) : _shape(shape), _data(0), _num_elems(1)
+ {
_strides.resize(shape.size());
- for (int i = _shape.size() - 1; i >= 0; --i) {
+ for (int i = _shape.size() - 1; i >= 0; --i)
+ {
_strides[i] = _num_elems;
_num_elems *= _shape[i];
}
~Tensor() { delete[] _data; }
int rank() const { return _shape.size(); }
int dim(int d) const { return _shape[d]; }
- float* data() { return _data; }
+ float *data() { return _data; }
float numElems() const { return _num_elems; }
- float& at(const vector<int>& coords) {
+ float &at(const vector<int> &coords)
+ {
int offset = 0;
for (auto i = 0; i < coords.size(); ++i)
return _data[offset];
}
- Tensor transpose(const vector<hsize_t>& reshape) {
+ Tensor transpose(const vector<hsize_t> &reshape)
+ {
vector<hsize_t> tr_shape(_shape.size());
for (auto i = 0; i < _shape.size(); ++i)
tr_shape[i] = _shape[reshape[i]];
Tensor result(tr_shape);
- auto on_loop = [this, &reshape, &result](vector<int>& coords) {
+ auto on_loop = [this, &reshape, &result](vector<int> &coords) {
vector<int> tr_coords(_shape.size());
for (int i = 0; i < rank(); ++i)
private:
vector<hsize_t> _shape;
vector<hsize_t> _strides;
- float* _data;
+ float *_data;
hsize_t _num_elems;
};
-static void fillTensor(Tensor& tensor) {
+static void fillTensor(Tensor &tensor)
+{
int v = 10;
- for (int i = 0; i < tensor.numElems(); ++i) {
+ for (int i = 0; i < tensor.numElems(); ++i)
+ {
tensor.data()[i] = v;
v += 10;
}
}
-static void iterate(Tensor& tensor, function<void(vector<int>&)> on_loop) {
+static void iterate(Tensor &tensor, function<void(vector<int> &)> on_loop)
+{
int num_dims = tensor.rank();
vector<int> coords(num_dims, 0);
vector<int> dims(num_dims);
for (int i = 0; i < num_dims; ++i)
dims[i] = tensor.dim(i);
- for (;;) {
+ for (;;)
+ {
on_loop(coords);
int i;
- for (i = num_dims - 1; i >= 0; --i) {
- if (coords[i] < dims[i] - 1) {
+ for (i = num_dims - 1; i >= 0; --i)
+ {
+ if (coords[i] < dims[i] - 1)
+ {
++coords[i];
break;
}
if (i < 0)
break;
-
+
fill(coords.begin() + i + 1, coords.end(), 0);
}
}
-static void dumpTensor(Tensor& tensor) {
- auto on_loop = [&tensor](vector<int>& coords) {
- for (int i = 0; i < tensor.rank(); ++i) {
+static void dumpTensor(Tensor &tensor)
+{
+ auto on_loop = [&tensor](vector<int> &coords) {
+ for (int i = 0; i < tensor.rank(); ++i)
+ {
if (i > 0)
cout << ", ";
static vector<hsize_t> dimensions;
-static void writeTensorToDatFile(const string& file_name, Tensor& tensor) {
+static void writeTensorToDatFile(const string &file_name, Tensor &tensor)
+{
ofstream of(file_name + ".dat", ios_base::binary);
if (of.fail())
cout << "Could not output tensor to the: " << file_name + ".dat";
- of.write(reinterpret_cast<char*>(tensor.data()), tensor.numElems() * sizeof(float));
+ of.write(reinterpret_cast<char *>(tensor.data()), tensor.numElems() * sizeof(float));
}
-static void writeTensorToHDF5File(const string& tensor_name, const string& file_name, Tensor& tensor) {
+static void writeTensorToHDF5File(const string &tensor_name, const string &file_name,
+ Tensor &tensor)
+{
H5::H5File h5File(file_name + ".hdf5", H5F_ACC_TRUNC);
H5::DataSpace dataspace(dimensions.size(), &dimensions[0]);
auto dataset = h5File.createDataSet(tensor_name, H5::PredType::IEEE_F32BE, dataspace);
dataset.write(tensor.data(), H5::PredType::NATIVE_FLOAT);
}
-int main(int argc, char* argv[]) {
- if (argc < 4) {
- cout << "Usage: " << argv[0] << " <tensor name> <output file name> dim0, dim1, dim2, ..." << endl;
+int main(int argc, char *argv[])
+{
+ if (argc < 4)
+ {
+ cout << "Usage: " << argv[0] << " <tensor name> <output file name> dim0, dim1, dim2, ..."
+ << endl;
cout << "Where: dim0, dim1, dim2, ... are the generated tensor shape dimensions" << endl;
return 1;
}
- for (int i = 3; i < argc; ++i) {
- try {
+ for (int i = 3; i < argc; ++i)
+ {
+ try
+ {
int d = stoi(argv[i]);
- if (d <= 0) {
- cout << "The dimensions must be positive values. This is not a correct dimension value: " << d << endl;
+ if (d <= 0)
+ {
+ cout << "The dimensions must be positive values. This is not a correct dimension value: "
+ << d << endl;
return 1;
}
dimensions.push_back(d);
- } catch(const invalid_argument&) {
+ }
+ catch (const invalid_argument &)
+ {
cout << "The parameter does not look as an integer value: " << argv[i] << endl;
return 1;
- } catch(const out_of_range&) {
+ }
+ catch (const out_of_range &)
+ {
cout << "The value is out of the C++ \"int\" type range: " << argv[i] << endl;
return 1;
}
parser.add_argument(
'-m',
'--model',
- help=("specify input file with NN model, \n[depends from model, "
+ help=("specify input file with NN model, \n[depends from model, "
" two for caffe and caffe2, one for onnx and tflite]"),
nargs='+')
- parser.add_argument('-i', '--input', help=(" specify file with neural"
- " network input data, hdf5 for caffe caffe2 tflite "
- "and pb for onnx"), required=True)
- parser.add_argument('-o', '--output_path',
- help='here you specify which place will hold your output, default here', default='')
-
+ parser.add_argument(
+ '-i',
+ '--input',
+ help=(" specify file with neural"
+ " network input data, hdf5 for caffe caffe2 tflite "
+ "and pb for onnx"),
+ required=True)
+ parser.add_argument(
+ '-o',
+ '--output_path',
+ help='here you specify which place will hold your output, default here',
+ default='')
args = parser.parse_args()
# added to check is our input file or not. most simple way
except IOError as e:
print('model you enter doesnt exist, write correct PATH ')
-
return args
save_result(output_path, out)
print(out)
+
if __name__ == '__main__':
args = regular_step()
- run_caffe(args.model[0], args.model[1], args.input, args.output_path)
\ No newline at end of file
+ run_caffe(args.model[0], args.model[1], args.input, args.output_path)
from caffe2.python import workspace
-def run_caffe2(init_net, predict_net, input_path, output_path =''):
+def run_caffe2(init_net, predict_net, input_path, output_path=''):
x = read_input(input_path)
with open(init_net, 'rb') as f:
init_net = f.read()
print(results)
save_result(output_path, results)
+
if __name__ == '__main__':
args = regular_step()
- run_caffe2(args.model[0], args.model[1], args.input, args.output_path)
\ No newline at end of file
+ run_caffe2(args.model[0], args.model[1], args.input, args.output_path)
import onnx
import caffe2.python.onnx.backend
-def run_onnx(model, input_path, output_path=''): #args.model[0] , args.input
+
+def run_onnx(model, input_path, output_path=''): #args.model[0] , args.input
path = model
#I'll leave it in case anyone needs to read the .pb file.
print(output)
save_result(output_path, output)
+
if __name__ == '__main__':
args = regular_step()
from common_place import *
import tensorflow as tf
+
def run_tflite(model, input_path, output_path=''):
input = read_input(input_path)
print(output_data)
save_result(output_path, output_data)
+
if __name__ == '__main__':
args = regular_step()
# -i - specifies input node name of the model that will use them (required by nnkit)
# -r - if files already exist, rewrites them
# -b - enable binary file generation
-# -p - allow some sort of parallelism by processing only a subset of files,
-# you need to specify number of processes and run as much of them
+# -p - allow some sort of parallelism by processing only a subset of files,
+# you need to specify number of processes and run as much of them
# manually with diferent numbers
#
# Example:
if not '-i' in args:
if fw == 'caf':
inputname = 'data'
- elif fw =='tfl':
+ elif fw == 'tfl':
inputname = 'input'
else:
inputname = args['-i']
number = 0
for testcase in testcases:
- try:
- infilename = glob.glob(testcase + 'input/*.JPEG')
- if len(infilename) > 0:
- number += 1
- infilename = infilename[0]
- outfilename = testcase + 'input/' + infilename.split('/')[-1] + '.hdf5'
- binoutfilename = testcase + 'input/' + infilename.split('/')[-1] + '.dat'
- found_hdf = len(glob.glob(outfilename)) != 0
- found_bin = len(glob.glob(binoutfilename)) != 0
- if not found_hdf or (not found_bin and gen_binary) or remove_existing:
- with Image.open(infilename) as im:
- #TODO: check if order is correct here and in other places
- h = im.size[0]
- w = im.size[1]
- s = im.split()
- if len(s) == 3:
- r, g, b = s
- else:
- r = s[0]
- g = s[0]
- b = s[0]
- rf = r.convert('F')
- gf = g.convert('F')
- bf = b.convert('F')
- rfb = rf.tobytes()
- gfb = gf.tobytes()
- bfb = bf.tobytes()
-
- made_hdf = False
- if not found_hdf or remove_existing:
- if fw == 'tfl':
- reds = np.fromstring(rfb, count=(h * w), dtype='float32')
- greens = np.fromstring(gfb, count=(h * w), dtype='float32')
- blues = np.fromstring(bfb, count=(h * w), dtype='float32')
-
- dset_shape = (1, h, w, 3)
- narr = np.ndarray(shape=(0))
- mixed_ch = []
- for i in range(h * w):
- mixed_ch += [reds[i] / 255.0, greens[i] / 255.0, blues[i] / 255.0]
- narr = np.append(narr, mixed_ch)
- elif fw == 'caf':
- dset_shape = (1, 3, h, w)
- narr = np.fromstring(rfb + gfb + bfb, count=(3 * h * w), dtype='float32')
- for i in range(3 * h * w):
- narr[i] /= 255.0
- if remove_existing:
- subprocess.call(['rm', '-f', outfilename])
- with h5py.File(outfilename) as f:
- # nnkit hdf5_import asserts to use IEEE_F32BE, which is >f4 in numpy
- dset = f.require_dataset(inputname, dset_shape, dtype='>f4')
- dset[0] = np.reshape(narr, dset_shape)
- made_hdf = True
-
- if gen_binary and (not found_bin or remove_existing):
- if fw == 'tfl' and made_hdf:
- l = narr.tolist()
- else:
- reds = np.fromstring(rfb, count=(h * w), dtype='float32')
- greens = np.fromstring(gfb, count=(h * w), dtype='float32')
- blues = np.fromstring(bfb, count=(h * w), dtype='float32')
- l = np.ndarray(shape=(0))
- mixed_ch = []
- for i in range(h * w):
- mixed_ch += [reds[i] / 255.0, greens[i] / 255.0, blues[i] / 255.0]
- l = np.append(l, mixed_ch)
- l = l.tolist()
- with open(binoutfilename, 'wb') as out:
- out.write(struct.pack('f'*len(l), *l))
- print(number, ': ' + testcase + ' Done')
- else:
- print(testcase, ' nothing to do')
- else:
- print(testcase, ' JPEG not found')
- except:
- print(testcase, " FAILED")
-print('started at', ended.datetime.now())
+ try:
+ infilename = glob.glob(testcase + 'input/*.JPEG')
+ if len(infilename) > 0:
+ number += 1
+ infilename = infilename[0]
+ outfilename = testcase + 'input/' + infilename.split('/')[-1] + '.hdf5'
+ binoutfilename = testcase + 'input/' + infilename.split('/')[-1] + '.dat'
+ found_hdf = len(glob.glob(outfilename)) != 0
+ found_bin = len(glob.glob(binoutfilename)) != 0
+ if not found_hdf or (not found_bin and gen_binary) or remove_existing:
+ with Image.open(infilename) as im:
+ #TODO: check if order is correct here and in other places
+ h = im.size[0]
+ w = im.size[1]
+ s = im.split()
+ if len(s) == 3:
+ r, g, b = s
+ else:
+ r = s[0]
+ g = s[0]
+ b = s[0]
+ rf = r.convert('F')
+ gf = g.convert('F')
+ bf = b.convert('F')
+ rfb = rf.tobytes()
+ gfb = gf.tobytes()
+ bfb = bf.tobytes()
+
+ made_hdf = False
+ if not found_hdf or remove_existing:
+ if fw == 'tfl':
+ reds = np.fromstring(rfb, count=(h * w), dtype='float32')
+ greens = np.fromstring(gfb, count=(h * w), dtype='float32')
+ blues = np.fromstring(bfb, count=(h * w), dtype='float32')
+ dset_shape = (1, h, w, 3)
+ narr = np.ndarray(shape=(0))
+ mixed_ch = []
+ for i in range(h * w):
+ mixed_ch += [
+ reds[i] / 255.0, greens[i] / 255.0, blues[i] / 255.0
+ ]
+ narr = np.append(narr, mixed_ch)
+ elif fw == 'caf':
+ dset_shape = (1, 3, h, w)
+ narr = np.fromstring(
+ rfb + gfb + bfb, count=(3 * h * w), dtype='float32')
+ for i in range(3 * h * w):
+ narr[i] /= 255.0
+ if remove_existing:
+ subprocess.call(['rm', '-f', outfilename])
+ with h5py.File(outfilename) as f:
+ # nnkit hdf5_import asserts to use IEEE_F32BE, which is >f4 in numpy
+ dset = f.require_dataset(inputname, dset_shape, dtype='>f4')
+ dset[0] = np.reshape(narr, dset_shape)
+ made_hdf = True
+
+ if gen_binary and (not found_bin or remove_existing):
+ if fw == 'tfl' and made_hdf:
+ l = narr.tolist()
+ else:
+ reds = np.fromstring(rfb, count=(h * w), dtype='float32')
+ greens = np.fromstring(gfb, count=(h * w), dtype='float32')
+ blues = np.fromstring(bfb, count=(h * w), dtype='float32')
+ l = np.ndarray(shape=(0))
+ mixed_ch = []
+ for i in range(h * w):
+ mixed_ch += [
+ reds[i] / 255.0, greens[i] / 255.0, blues[i] / 255.0
+ ]
+ l = np.append(l, mixed_ch)
+ l = l.tolist()
+ with open(binoutfilename, 'wb') as out:
+ out.write(struct.pack('f' * len(l), *l))
+ print(number, ': ' + testcase + ' Done')
+ else:
+ print(testcase, ' nothing to do')
+ else:
+ print(testcase, ' JPEG not found')
+ except:
+ print(testcase, " FAILED")
+print('started at', ended.datetime.now())
using namespace mir;
using namespace nnc::cli;
-int main(int argc, const char **argv) {
+int main(int argc, const char **argv)
+{
cli::CommandLine::getParser()->parseCommandLine(argc, argv, false);
nnc::TfliteImporterPass importer{cli::inputFile};
- try {
+ try
+ {
importer.import();
IrDotDumper dotDumper;
auto g = importer.createIR();
g->accept(&dotDumper);
dotDumper.writeDot(std::cout);
- } catch (PassException &e) {
+ }
+ catch (PassException &e)
+ {
std::cout << "Error: " << e.what() << std::endl;
return -1;
}
using namespace modelgen;
using namespace treebuilder;
-int main(int argc, const char* argv[]) {
+int main(int argc, const char *argv[])
+{
std::unique_ptr<TreeBuilder> tree_builder(new TreeBuilder);
auto tree = tree_builder->buildTree();
#include "Tree.h"
-namespace modelgen {
+namespace modelgen
+{
/**
* @brief ModelSaver this class describes a common interface for saving model.
*/
-class ModelSaver {
+class ModelSaver
+{
public:
ModelSaver() = default;
virtual ~ModelSaver() = default;
* @brief RandomModelBuilder this class describe a common interface for building
* random neural network models.
*/
-class RandomModelBuilder {
+class RandomModelBuilder
+{
public:
-
/**
* @brief constructor for RandomModelBuilder.
* @details Be careful, opCreators's initializer list should save the order
* from the OpCode enum.
*/
- RandomModelBuilder() : _operatorCounts{0}, _gen(_rd()),
- _floatRand(std::numeric_limits<float>::min(),
- std::numeric_limits<float>::max()),
- _intRand(static_cast<int32_t>(OpCodes::opFirst),
- static_cast<int32_t>(OpCodes::opLast)) {
+ RandomModelBuilder()
+ : _operatorCounts{0}, _gen(_rd()),
+ _floatRand(std::numeric_limits<float>::min(), std::numeric_limits<float>::max()),
+ _intRand(static_cast<int32_t>(OpCodes::opFirst), static_cast<int32_t>(OpCodes::opLast))
+ {
_opCreators[static_cast<int>(OpCodes::opConv2d)] =
- [this](treebuilder::Tree* t, treebuilder::Operation* op) {
- createLayerCONV_2D(t, op);
- };
- _opCreators[static_cast<int>(OpCodes::opConcatenation)] =
- [this](treebuilder::Tree* t, treebuilder::Operation* op) {
- createLayerCONCATENATION(t, op);
- };
- _opCreators[static_cast<int>(OpCodes::opDepthwiseConv2d)] =
- [this](treebuilder::Tree* t, treebuilder::Operation* op) {
- createLayerDEPTHWISE_CONV_2D(t, op);
- };
- _opCreators[static_cast<int>(OpCodes::opOpMaxPool2d)] =
- [this](treebuilder::Tree* t, treebuilder::Operation* op) {
- createLayerX_POOL_2D(t, op, OpCodes::opOpMaxPool2d);
- };
- _opCreators[static_cast<int>(OpCodes::opAveragePool2d)] =
- [this](treebuilder::Tree* t, treebuilder::Operation* op) {
- createLayerX_POOL_2D(t, op, OpCodes::opAveragePool2d);
- };
+ [this](treebuilder::Tree *t, treebuilder::Operation *op) { createLayerCONV_2D(t, op); };
+ _opCreators[static_cast<int>(OpCodes::opConcatenation)] = [this](
+ treebuilder::Tree *t, treebuilder::Operation *op) { createLayerCONCATENATION(t, op); };
+ _opCreators[static_cast<int>(OpCodes::opDepthwiseConv2d)] = [this](
+ treebuilder::Tree *t, treebuilder::Operation *op) { createLayerDEPTHWISE_CONV_2D(t, op); };
+ _opCreators[static_cast<int>(OpCodes::opOpMaxPool2d)] = [this](treebuilder::Tree *t,
+ treebuilder::Operation *op) {
+ createLayerX_POOL_2D(t, op, OpCodes::opOpMaxPool2d);
+ };
+ _opCreators[static_cast<int>(OpCodes::opAveragePool2d)] = [this](treebuilder::Tree *t,
+ treebuilder::Operation *op) {
+ createLayerX_POOL_2D(t, op, OpCodes::opAveragePool2d);
+ };
_opCreators[static_cast<int>(OpCodes::opSoftmax)] =
- [this](treebuilder::Tree* t, treebuilder::Operation* op) {
- createLayerSOFTMAX(t, op);
- };
- _opCreators[static_cast<int>(OpCodes::opFullyConnected)] =
- [this](treebuilder::Tree* t, treebuilder::Operation* op) {
- createLayerFULLY_CONNECTED(t, op);
- };
+ [this](treebuilder::Tree *t, treebuilder::Operation *op) { createLayerSOFTMAX(t, op); };
+ _opCreators[static_cast<int>(OpCodes::opFullyConnected)] = [this](
+ treebuilder::Tree *t, treebuilder::Operation *op) { createLayerFULLY_CONNECTED(t, op); };
};
virtual ~RandomModelBuilder() = default;
- virtual void convertTreeToModel(treebuilder::Tree* t) = 0;
+ virtual void convertTreeToModel(treebuilder::Tree *t) = 0;
/**
* @brief getModelSaver does create unique_ptr to ModelSaver.
/**
* @Brief createInput does add input tensor to model.
*/
- virtual void createInput(treebuilder::Tree* t) = 0;
+ virtual void createInput(treebuilder::Tree *t) = 0;
/**
* @brief addOperator does add a new layer to model.
*/
- virtual void addOperator(treebuilder::Tree* t, treebuilder::Operation* op) = 0;
+ virtual void addOperator(treebuilder::Tree *t, treebuilder::Operation *op) = 0;
/**
* @brief createLayerXXX are creator for operators.
* @param input_tensor_id is id of input tensor.
*/
- virtual void createLayerCONV_2D(treebuilder::Tree*, treebuilder::Operation*) = 0;
- virtual void createLayerCONCATENATION(treebuilder::Tree* t, treebuilder::Operation* op) = 0;
- virtual void createLayerDEPTHWISE_CONV_2D(treebuilder::Tree* t, treebuilder::Operation* op) = 0;
- virtual void createLayerX_POOL_2D(treebuilder::Tree* t, treebuilder::Operation* op,
+ virtual void createLayerCONV_2D(treebuilder::Tree *, treebuilder::Operation *) = 0;
+ virtual void createLayerCONCATENATION(treebuilder::Tree *t, treebuilder::Operation *op) = 0;
+ virtual void createLayerDEPTHWISE_CONV_2D(treebuilder::Tree *t, treebuilder::Operation *op) = 0;
+ virtual void createLayerX_POOL_2D(treebuilder::Tree *t, treebuilder::Operation *op,
OpCodes opcode) = 0;
- virtual void createLayerSOFTMAX(treebuilder::Tree* t, treebuilder::Operation* op) = 0;
- virtual void createLayerFULLY_CONNECTED(treebuilder::Tree* t, treebuilder::Operation* op) = 0;
+ virtual void createLayerSOFTMAX(treebuilder::Tree *t, treebuilder::Operation *op) = 0;
+ virtual void createLayerFULLY_CONNECTED(treebuilder::Tree *t, treebuilder::Operation *op) = 0;
/**
* @brief opCreators this array contains a lambda with call of method
* like follow: opCreators[OpCodes::opCount]
* For example: opCreators[OpCodes::opConv2d](0) -- will lead to call createLayerCONV_2D method.
*/
- std::function<void(treebuilder::Tree*,
- treebuilder::Operation*)> _opCreators[static_cast<int32_t>(OpCodes::opCount)];
+ std::function<void(treebuilder::Tree *, treebuilder::Operation *)>
+ _opCreators[static_cast<int32_t>(OpCodes::opCount)];
/**
* @brief operatorCounts this array contains amount of used operators in generated model.
* @details For example: operatorCounts[Op_CONV_2D] -- amount of used 2D convolution operators.
#include "TFLiteRandomModelBuilder.h"
-namespace modelgen {
-static const char* modelFileOut = "model.tflite";
+namespace modelgen
+{
+static const char *modelFileOut = "model.tflite";
static const int notInitialized = -1;
-static const char* const opNames[] = {
+static const char *const opNames[] = {
#define DEF_OPERATOR(Name, OpCode, TFLiteOpCode, CreatorFunc) Name,
#include "Operator.def"
#undef DEF_OPERATOR
#undef DEF_OPERATOR
};
-void TFLiteModelSaver::saveModel() {
+void TFLiteModelSaver::saveModel()
+{
auto m = tflite::Model::Pack(_flatBufferBuilder, _model.get());
tflite::FinishModelBuffer(_flatBufferBuilder, m);
fclose(f);
}
-TFLiteRandomModelBuilder::TFLiteRandomModelBuilder() : RandomModelBuilder(),
- _model(new ModelT()) {
+TFLiteRandomModelBuilder::TFLiteRandomModelBuilder() : RandomModelBuilder(), _model(new ModelT())
+{
std::fill_n(_mapOperatorCode, static_cast<long>(OpCodes::opCount), notInitialized);
}
-void TFLiteRandomModelBuilder::convertTreeToModel(treebuilder::Tree* t) {
+void TFLiteRandomModelBuilder::convertTreeToModel(treebuilder::Tree *t)
+{
createInput(t);
- for (auto& op : t->opList) {
+ for (auto &op : t->opList)
+ {
addOperator(t, op.get());
}
}
-std::unique_ptr<ModelSaver> TFLiteRandomModelBuilder::createModelSaver() {
+std::unique_ptr<ModelSaver> TFLiteRandomModelBuilder::createModelSaver()
+{
return std::unique_ptr<ModelSaver>(new TFLiteModelSaver(std::move(_model)));
}
/**
* @todo Add support several inputs.
*/
-void TFLiteRandomModelBuilder::createInput(treebuilder::Tree* t) {
+void TFLiteRandomModelBuilder::createInput(treebuilder::Tree *t)
+{
assert(_model->subgraphs.empty() && "Subgraph is already created");
std::unique_ptr<SubGraphT> subgraph(new SubGraphT);
_model->version = 3;
}
-void TFLiteRandomModelBuilder::addOperator(treebuilder::Tree* t, treebuilder::Operation* op) {
+void TFLiteRandomModelBuilder::addOperator(treebuilder::Tree *t, treebuilder::Operation *op)
+{
assert(!_model->subgraphs.empty() && "Subgraph is not created");
std::cout << "Add operator [" << opNames[static_cast<int32_t>(op->opcode)] << "] on the level [ "
_model->subgraphs[0]->outputs[0] = (*_model->subgraphs[0]->operators.rbegin())->outputs[0];
}
-void TFLiteRandomModelBuilder::createLayerCONV_2D(treebuilder::Tree* t,
- treebuilder::Operation* op) {
+void TFLiteRandomModelBuilder::createLayerCONV_2D(treebuilder::Tree *t, treebuilder::Operation *op)
+{
std::string output_name(opNames[static_cast<int32_t>(OpCodes::opConv2d)]);
output_name += "_" + std::to_string(_operatorCounts[static_cast<int32_t>(OpCodes::opConv2d)]);
auto operator_ptr = createEmptyOperator(op);
auto kernel_ptr = createTensorWthBuffer(op->kernelShape, "Kernel");
auto bias_ptr = createTensorWthBuffer({op->outputShape[3]}, "bias");
- auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] :
- _operandTree2tensor[t->inputCnt + op->inputs[0]];
+ auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0]
+ : _operandTree2tensor[t->inputCnt + op->inputs[0]];
operator_ptr->inputs.push_back(input_tensor_id);
operator_ptr->inputs.push_back(static_cast<int32_t>(_model->subgraphs[0]->tensors.size()));
auto conv2D_opt = operator_ptr->builtin_options.AsConv2DOptions();
conv2D_opt->stride_w = conv2D_opt->stride_h = 1;
conv2D_opt->fused_activation_function =
- tflite::ActivationFunctionType::ActivationFunctionType_RELU6;
+ tflite::ActivationFunctionType::ActivationFunctionType_RELU6;
_model->subgraphs[0]->operators.push_back(std::move(operator_ptr));
}
-void TFLiteRandomModelBuilder::createLayerCONCATENATION(treebuilder::Tree* t,
- treebuilder::Operation* op) {
+void TFLiteRandomModelBuilder::createLayerCONCATENATION(treebuilder::Tree *t,
+ treebuilder::Operation *op)
+{
std::string output_name(opNames[static_cast<int32_t>(OpCodes::opConcatenation)]);
- output_name += "_" +
- std::to_string(_operatorCounts[static_cast<int32_t>(OpCodes::opConcatenation)]);
+ output_name +=
+ "_" + std::to_string(_operatorCounts[static_cast<int32_t>(OpCodes::opConcatenation)]);
auto operator_ptr = createEmptyOperator(op);
auto out_tensor_ptr = createEmptyTensor(op->outputShape, output_name.c_str());
std::cout << "Concatination inputs [ ";
- for (auto it : op->inputs) {
+ for (auto it : op->inputs)
+ {
std::cout << it << "/";
- auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] :
- _operandTree2tensor[t->inputCnt + it];
+ auto input_tensor_id =
+ op->levelOwner == 0 ? _operandTree2tensor[0] : _operandTree2tensor[t->inputCnt + it];
std::cout << input_tensor_id << " ";
operator_ptr->inputs.push_back(input_tensor_id);
}
operator_ptr->builtin_options.Set(tflite::ConcatenationOptionsT());
auto concat_opt = operator_ptr->builtin_options.AsConcatenationOptions();
concat_opt->fused_activation_function =
- tflite::ActivationFunctionType::ActivationFunctionType_RELU6;
+ tflite::ActivationFunctionType::ActivationFunctionType_RELU6;
concat_opt->axis = 0;
- for (auto it : op->inputShape) {
+ for (auto it : op->inputShape)
+ {
if (it == -1)
- break ;
+ break;
concat_opt->axis++;
}
_model->subgraphs[0]->operators.push_back(std::move(operator_ptr));
}
-void TFLiteRandomModelBuilder::createLayerDEPTHWISE_CONV_2D(treebuilder::Tree* t,
- treebuilder::Operation* op) {
+void TFLiteRandomModelBuilder::createLayerDEPTHWISE_CONV_2D(treebuilder::Tree *t,
+ treebuilder::Operation *op)
+{
std::string output_name(opNames[static_cast<int32_t>(OpCodes::opDepthwiseConv2d)]);
- output_name += "_" +
- std::to_string(_operatorCounts[static_cast<int32_t>(OpCodes::opDepthwiseConv2d)]);
+ output_name +=
+ "_" + std::to_string(_operatorCounts[static_cast<int32_t>(OpCodes::opDepthwiseConv2d)]);
auto operator_ptr = createEmptyOperator(op);
auto out_tensor_ptr = createEmptyTensor(op->outputShape, output_name.c_str());
auto kernel_ptr = createTensorWthBuffer(op->kernelShape, "Kernel");
auto bias_ptr = createTensorWthBuffer({op->outputShape[3]}, "bias");
- auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] :
- _operandTree2tensor[t->inputCnt + op->inputs[0]];
+ auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0]
+ : _operandTree2tensor[t->inputCnt + op->inputs[0]];
operator_ptr->inputs.push_back(input_tensor_id);
operator_ptr->inputs.push_back(static_cast<int32_t>(_model->subgraphs[0]->tensors.size()));
depthwise_conv2d_opt->stride_w = depthwise_conv2d_opt->stride_h = 1;
depthwise_conv2d_opt->depth_multiplier = 1;
depthwise_conv2d_opt->fused_activation_function =
- tflite::ActivationFunctionType::ActivationFunctionType_RELU6;
+ tflite::ActivationFunctionType::ActivationFunctionType_RELU6;
_model->subgraphs[0]->operators.push_back(std::move(operator_ptr));
}
-void TFLiteRandomModelBuilder::createLayerX_POOL_2D(treebuilder::Tree* t,
- treebuilder::Operation* op, OpCodes opcode) {
+void TFLiteRandomModelBuilder::createLayerX_POOL_2D(treebuilder::Tree *t,
+ treebuilder::Operation *op, OpCodes opcode)
+{
std::string output_name(opNames[static_cast<int32_t>(opcode)]);
- output_name += "_" +
- std::to_string(_operatorCounts[static_cast<int32_t>(opcode)]);
+ output_name += "_" + std::to_string(_operatorCounts[static_cast<int32_t>(opcode)]);
auto operator_ptr = createEmptyOperator(op);
auto out_tensor_ptr = createEmptyTensor(op->outputShape, output_name.c_str());
- auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] :
- _operandTree2tensor[t->inputCnt + op->inputs[0]];
+ auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0]
+ : _operandTree2tensor[t->inputCnt + op->inputs[0]];
operator_ptr->inputs.push_back(input_tensor_id);
auto output_tensor_id = static_cast<int32_t>(_model->subgraphs[0]->tensors.size());
_model->subgraphs[0]->operators.push_back(std::move(operator_ptr));
}
-void TFLiteRandomModelBuilder::createLayerSOFTMAX(treebuilder::Tree* t,
- treebuilder::Operation* op) {
+void TFLiteRandomModelBuilder::createLayerSOFTMAX(treebuilder::Tree *t, treebuilder::Operation *op)
+{
std::string output_name(opNames[static_cast<int32_t>(OpCodes::opSoftmax)]);
- output_name += "_" +
- std::to_string(_operatorCounts[static_cast<int32_t>(OpCodes::opSoftmax)]);
+ output_name += "_" + std::to_string(_operatorCounts[static_cast<int32_t>(OpCodes::opSoftmax)]);
auto operator_ptr = createEmptyOperator(op);
auto out_tensor_ptr = createEmptyTensor(op->outputShape, output_name.c_str());
- auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] :
- _operandTree2tensor[t->inputCnt + op->inputs[0]];
+ auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0]
+ : _operandTree2tensor[t->inputCnt + op->inputs[0]];
operator_ptr->inputs.push_back(input_tensor_id);
auto output_tensor_id = static_cast<int32_t>(_model->subgraphs[0]->tensors.size());
_model->subgraphs[0]->operators.push_back(std::move(operator_ptr));
}
-void TFLiteRandomModelBuilder::createLayerFULLY_CONNECTED(treebuilder::Tree* t,
- treebuilder::Operation* op) {
+void TFLiteRandomModelBuilder::createLayerFULLY_CONNECTED(treebuilder::Tree *t,
+ treebuilder::Operation *op)
+{
std::string output_name(opNames[static_cast<int32_t>(OpCodes::opFullyConnected)]);
- output_name += "_" +
- std::to_string(_operatorCounts[static_cast<int32_t>(OpCodes::opFullyConnected)]);
+ output_name +=
+ "_" + std::to_string(_operatorCounts[static_cast<int32_t>(OpCodes::opFullyConnected)]);
auto operator_ptr = createEmptyOperator(op);
auto out_tensor_ptr = createEmptyTensor(op->outputShape, output_name.c_str());
auto kernel_ptr = createTensorWthBuffer(op->kernelShape, "Kernel");
auto bias_ptr = createTensorWthBuffer({op->outputShape[3]}, "bias");
- auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0] :
- _operandTree2tensor[t->inputCnt + op->inputs[0]];
+ auto input_tensor_id = op->levelOwner == 0 ? _operandTree2tensor[0]
+ : _operandTree2tensor[t->inputCnt + op->inputs[0]];
operator_ptr->inputs.push_back(input_tensor_id);
operator_ptr->inputs.push_back(static_cast<int32_t>(_model->subgraphs[0]->tensors.size()));
operator_ptr->builtin_options.Set(tflite::FullyConnectedOptionsT());
auto fullcon_opt = operator_ptr->builtin_options.AsFullyConnectedOptions();
fullcon_opt->fused_activation_function =
- tflite::ActivationFunctionType::ActivationFunctionType_RELU6;
+ tflite::ActivationFunctionType::ActivationFunctionType_RELU6;
_model->subgraphs[0]->operators.push_back(std::move(operator_ptr));
}
std::unique_ptr<TensorT>
-TFLiteRandomModelBuilder::createEmptyTensor(const std::vector<int32_t>& shape,
- const char* name) {
+TFLiteRandomModelBuilder::createEmptyTensor(const std::vector<int32_t> &shape, const char *name)
+{
auto tensor_ptr = std::unique_ptr<TensorT>(new TensorT);
tensor_ptr->type = tflite::TensorType_FLOAT32;
}
std::unique_ptr<TensorT>
-TFLiteRandomModelBuilder::createTensorWthBuffer(const std::vector<int32_t>& shape,
- const char* name) {
+TFLiteRandomModelBuilder::createTensorWthBuffer(const std::vector<int32_t> &shape, const char *name)
+{
auto tensor_ptr = createEmptyTensor(shape, name);
size_t buffer_size = 1;
- for (auto s : shape) {
+ for (auto s : shape)
+ {
buffer_size *= s;
}
buffer_size *= sizeof(float);
_model->buffers[tensor_ptr->buffer]->data.resize(buffer_size);
- for (size_t i = 0; i < buffer_size; i += sizeof(float)) {
+ for (size_t i = 0; i < buffer_size; i += sizeof(float))
+ {
float val = _floatRand(_gen);
memcpy(_model->buffers[tensor_ptr->buffer]->data.data() + i, &val, sizeof(float));
}
return tensor_ptr;
}
-std::unique_ptr<OperatorT>
-TFLiteRandomModelBuilder::createEmptyOperator(treebuilder::Operation* op) {
+std::unique_ptr<OperatorT> TFLiteRandomModelBuilder::createEmptyOperator(treebuilder::Operation *op)
+{
auto operator_ptr = std::unique_ptr<OperatorT>(new OperatorT);
auto opcode_id = _mapOperatorCode[static_cast<int32_t>(op->opcode)];
auto tflite_opcode = internalOpCode2TFLiteOpCode[static_cast<int32_t>(op->opcode)];
- if (opcode_id == notInitialized) {
+ if (opcode_id == notInitialized)
+ {
auto opcode_ptr = std::unique_ptr<OperatorCodeT>(new OperatorCodeT);
opcode_ptr->builtin_code = tflite_opcode;
opcode_ptr->custom_code = tflite::EnumNamesBuiltinOperator()[tflite_opcode];
#include "RandomModelBuilder.h"
#include "schema_generated.h"
-namespace modelgen {
+namespace modelgen
+{
using namespace tflite;
/**
* @brief TFLiteModelSaver contains the unique_ptr to model and does convertation of model
* to FlatBuffer format and it's saving.
*/
-class TFLiteModelSaver : public ModelSaver {
+class TFLiteModelSaver : public ModelSaver
+{
public:
TFLiteModelSaver() = default;
~TFLiteModelSaver() override = default;
- TFLiteModelSaver(std::unique_ptr<ModelT>&& m) : ModelSaver(), _model(std::move(m)) {}
+ TFLiteModelSaver(std::unique_ptr<ModelT> &&m) : ModelSaver(), _model(std::move(m)) {}
void saveModel() override;
+
private:
flatbuffers::FlatBufferBuilder _flatBufferBuilder;
std::unique_ptr<ModelT> _model;
* @brief TFLiteRandomModelBuilder does build random TFLiteModel
* and gives unique_ptr to ModelSaver for export it to file.
*/
-class TFLiteRandomModelBuilder : public RandomModelBuilder {
+class TFLiteRandomModelBuilder : public RandomModelBuilder
+{
public:
TFLiteRandomModelBuilder();
~TFLiteRandomModelBuilder() override = default;
- void convertTreeToModel(treebuilder::Tree* t) override;
+ void convertTreeToModel(treebuilder::Tree *t) override;
std::unique_ptr<ModelSaver> createModelSaver() override;
+
protected:
- void createInput(treebuilder::Tree* t) override;
- void addOperator(treebuilder::Tree* t, treebuilder::Operation* op) override;
+ void createInput(treebuilder::Tree *t) override;
+ void addOperator(treebuilder::Tree *t, treebuilder::Operation *op) override;
/**
* Operations:
*/
- void createLayerCONV_2D(treebuilder::Tree* t, treebuilder::Operation* op) override;
- void createLayerCONCATENATION(treebuilder::Tree* t, treebuilder::Operation* op) override;
- void createLayerDEPTHWISE_CONV_2D(treebuilder::Tree* t, treebuilder::Operation* op) override;
- void createLayerX_POOL_2D(treebuilder::Tree* t, treebuilder::Operation* op,
+ void createLayerCONV_2D(treebuilder::Tree *t, treebuilder::Operation *op) override;
+ void createLayerCONCATENATION(treebuilder::Tree *t, treebuilder::Operation *op) override;
+ void createLayerDEPTHWISE_CONV_2D(treebuilder::Tree *t, treebuilder::Operation *op) override;
+ void createLayerX_POOL_2D(treebuilder::Tree *t, treebuilder::Operation *op,
OpCodes opcode) override;
- void createLayerSOFTMAX(treebuilder::Tree* t, treebuilder::Operation* op) override;
- void createLayerFULLY_CONNECTED(treebuilder::Tree* t, treebuilder::Operation* op) override;
+ void createLayerSOFTMAX(treebuilder::Tree *t, treebuilder::Operation *op) override;
+ void createLayerFULLY_CONNECTED(treebuilder::Tree *t, treebuilder::Operation *op) override;
+
private:
/**
* @brief createEmptyTensor does create tensor without buffer
* @param name is a name of tensor.
* @return unique_ptr to created tensor.
*/
- std::unique_ptr<TensorT> createEmptyTensor(const std::vector<int32_t>& shape,
- const char* name);
+ std::unique_ptr<TensorT> createEmptyTensor(const std::vector<int32_t> &shape, const char *name);
/**
* @brief createTensorWthBuffer does create tensor with buffer
* and add it to tensors array of SubGraphT.
* @param name is a name of tensor.
* @return unique_ptr to created tensor.
*/
- std::unique_ptr<TensorT> createTensorWthBuffer(const std::vector<int32_t>& shape,
- const char* name);
+ std::unique_ptr<TensorT> createTensorWthBuffer(const std::vector<int32_t> &shape,
+ const char *name);
/**
* @brief createEmptyOperator does create operator without tensors and
* add operator to operators array of SubGraphT
* @param opcode is operator's code.
* @return unique_ptr to created operator.
*/
- std::unique_ptr<OperatorT> createEmptyOperator(treebuilder::Operation* op);
+ std::unique_ptr<OperatorT> createEmptyOperator(treebuilder::Operation *op);
std::unique_ptr<ModelT> _model;
/**
#include "Tree.h"
-namespace modelgen {
-namespace treebuilder {
+namespace modelgen
+{
+namespace treebuilder
+{
static constexpr int levelsMin = 1;
static constexpr int levelsMax = 15;
static constexpr int fullyConnectedMaxWeight = 8;
static constexpr int fullyConnectedKernelDim = 2;
-TreeBuilder::TreeBuilder() : _gen(_rd()) { }
+TreeBuilder::TreeBuilder() : _gen(_rd()) {}
-std::unique_ptr<Tree> TreeBuilder::buildTree() {
+std::unique_ptr<Tree> TreeBuilder::buildTree()
+{
std::uniform_int_distribution<int> int_rand(levelsMin, levelsMax);
auto t = std::unique_ptr<Tree>(new Tree);
t->inputCnt = 1;
initTree(t.get());
std::cout << "Build " << t->hTree << " levels in tree" << std::endl;
- for (int i = 1; i < t->hTree; i++) {
+ for (int i = 1; i < t->hTree; i++)
+ {
buildLevel(t.get());
}
return t;
}
-void TreeBuilder::buildLevel(Tree* t) {
+void TreeBuilder::buildLevel(Tree *t)
+{
std::uniform_int_distribution<int32_t> int_rand(widthMin, widthMax);
auto levelId = t->widthLevel.size();
auto levelWidth = int_rand(_gen);
t->beginLevel.push_back(static_cast<int32_t>(t->opList.size()));
t->endLevel.push_back(static_cast<int32_t>(t->opList.size() + levelWidth - 1));
- for (int32_t i = 0; i < levelWidth; i++) {
+ for (int32_t i = 0; i < levelWidth; i++)
+ {
auto op = std::unique_ptr<Operation>(new Operation);
op->levelOwner = levelId;
/**
* If the operation was not created, then repeat the creation.
*/
- if (!buildSketchOperation(t, op.get())) {
+ if (!buildSketchOperation(t, op.get()))
+ {
i--;
continue;
}
}
}
-void TreeBuilder::initTree(Tree* t) {
+void TreeBuilder::initTree(Tree *t)
+{
std::uniform_int_distribution<int32_t> int_rand(shapeMin, shapeMax);
std::cout << "Build first level in tree" << std::endl;
t->inputShapeTree = {1, x, y, z};
std::cout << "Initialize first level with width = [ " << t->widthLevel[0] << " ]"
- << " and shape [ 1" << " " << x << " " << y << " " << z << " ]" << std::endl;
- for (int32_t i = 0; i < t->widthLevel[0]; i++) {
+ << " and shape [ 1"
+ << " " << x << " " << y << " " << z << " ]" << std::endl;
+ for (int32_t i = 0; i < t->widthLevel[0]; i++)
+ {
auto op = std::unique_ptr<Operation>(new Operation);
op->levelOwner = 0;
/**
* If the operation was not created, then repeat the creation.
*/
- if (!buildSketchOperation(t, op.get())) {
+ if (!buildSketchOperation(t, op.get()))
+ {
i--;
continue;
}
}
}
-bool TreeBuilder::buildSketchOperation(Tree* t, Operation* op) {
+bool TreeBuilder::buildSketchOperation(Tree *t, Operation *op)
+{
std::uniform_int_distribution<int32_t> opcode_rand(static_cast<int32_t>(OpCodes::opFirst),
static_cast<int32_t>(OpCodes::opLast));
op->opcode = static_cast<OpCodes>(opcode_rand(_gen));
- switch(op->opcode) {
+ switch (op->opcode)
+ {
case OpCodes::opConv2d:
buildSketchConv2D(t, op);
break;
* Currently, we can create fullyconnected operation only on last level.
* @todo fix it.
*/
- if (t->beginLevel.size() != static_cast<size_t>(t->hTree)) {
+ if (t->beginLevel.size() != static_cast<size_t>(t->hTree))
+ {
return false;
}
return true;
}
-void TreeBuilder::buildSketchConv2D(Tree* t, Operation* op) {
+void TreeBuilder::buildSketchConv2D(Tree *t, Operation *op)
+{
std::uniform_int_distribution<int32_t> int_rand(0, INT32_MAX);
- if (t->beginLevel.size() == 1) {
+ if (t->beginLevel.size() == 1)
+ {
op->inputShape = t->inputShapeTree;
buildSketchConv2DForShape(op->inputShape, op);
- return ;
+ return;
}
auto levelId = int_rand(_gen) % (t->beginLevel.size() - 1);
buildSketchConv2DForShape(op->inputShape, op);
}
-void TreeBuilder::buildSketchConcat(Tree* t, Operation* op) {
+void TreeBuilder::buildSketchConcat(Tree *t, Operation *op)
+{
std::uniform_int_distribution<int32_t> int_rand(2, INT32_MAX);
auto axis = 1 + (int_rand(_gen) + 3) % 3;
auto input_cnt = concatCntInputsMin + int_rand(_gen) % concatCntInputsMax;
/* Special case if there are only one level (input to neural network) */
- if (t->beginLevel.size() == 1) {
+ if (t->beginLevel.size() == 1)
+ {
op->inputShape = t->inputShapeTree;
op->outputShape = op->inputShape;
- for (int i = 0; i < input_cnt; i++) {
+ for (int i = 0; i < input_cnt; i++)
+ {
op->inputs.push_back(-1); /* -1 means that it is needed to specify amount inputs
* on the first level where input tensor for operation
* is a input tensor for neural network. */
addConcatInput(op->inputShape, axis, op);
}
op->inputShape[axis] = -1; /* specify a dimension for concatenation. */
- return ;
+ return;
}
/* Select the first operand */
op->outputShape = op->inputShape;
std::vector<int32_t> shape = op->inputShape;
shape[axis] = -1;
- for (int i = 0; i < input_cnt; i++) {
+ for (int i = 0; i < input_cnt; i++)
+ {
opId = lookupConsistentOutput(t, op, shape, t->beginLevel.size() - 1);
op->inputs.push_back(opId);
addConcatInput(t->opList[opId]->outputShape, axis, op);
op->inputShape[axis] = -1; /* specify a dimension for concatenation. */
}
-void TreeBuilder::buildSketchDepthwiseConv2D(Tree* t, Operation* op) {
+void TreeBuilder::buildSketchDepthwiseConv2D(Tree *t, Operation *op)
+{
std::uniform_int_distribution<int32_t> int_rand(1, INT32_MAX);
/**
* Currently, on the stage of building arbitrary tree it is enough
op->outputShape[3] = op->kernelShape[0] * op->kernelShape[3];
}
-void TreeBuilder::buildSketchPooling(Tree* t, Operation* op) {
+void TreeBuilder::buildSketchPooling(Tree *t, Operation *op)
+{
std::uniform_int_distribution<int32_t> int_rand(2, INT32_MAX);
- if (t->beginLevel.size() == 1) {
+ if (t->beginLevel.size() == 1)
+ {
op->inputShape = t->inputShapeTree;
op->outputShape = op->inputShape;
- return ;
+ return;
}
auto levelId = int_rand(_gen) % (t->beginLevel.size() - 1);
auto opId = t->beginLevel[levelId] + (int_rand(_gen) % t->widthLevel[levelId]);
-
+
std::cout << "input level [ " << levelId << " ] operation id [ " << opId << " ]" << std::endl;
op->inputs.push_back(opId);
op->outputShape = op->inputShape;
}
-void TreeBuilder::buildSketchSoftmax(Tree* t, Operation* op) {
+void TreeBuilder::buildSketchSoftmax(Tree *t, Operation *op)
+{
/**
* We need only select input node, the output shape will be same as input.
* That is why we use pooling's builder.
buildSketchPooling(t, op);
}
-void TreeBuilder::buildSketchFullyConnected(Tree* t, Operation* op) {
+void TreeBuilder::buildSketchFullyConnected(Tree *t, Operation *op)
+{
std::uniform_int_distribution<int32_t> int_rand(2, fullyConnectedMaxWeight);
/**
* 1. Select a input form previous nodes by means of buildSketchPooling
*/
op->kernelShape.resize(fullyConnectedKernelDim);
op->kernelShape[0] = int_rand(_gen);
- op->kernelShape[1] = op->inputShape[0] * op->inputShape[1] *
- op->inputShape[2] * op->inputShape[3];
+ op->kernelShape[1] =
+ op->inputShape[0] * op->inputShape[1] * op->inputShape[2] * op->inputShape[3];
op->outputShape.resize(2);
op->outputShape[0] = op->kernelShape[0];
// =========== private ===========
-int32_t TreeBuilder::lookupConsistentOutput(Tree* t, Operation* op, std::vector<int32_t>& shape,
- int32_t until_level) {
- for (int i =0, j = 0; i < t->beginLevel[until_level]; i++) {
- for (j = 0; j < 4; j++) {
- if (shape[j] != t->opList[i]->outputShape[j] && shape[j] != -1) {
+int32_t TreeBuilder::lookupConsistentOutput(Tree *t, Operation *op, std::vector<int32_t> &shape,
+ int32_t until_level)
+{
+ for (int i = 0, j = 0; i < t->beginLevel[until_level]; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ if (shape[j] != t->opList[i]->outputShape[j] && shape[j] != -1)
+ {
j = 0;
break;
}
* \ /
* op
*/
- const Operation* y = t->opList[op->inputs[0]].get();
+ const Operation *y = t->opList[op->inputs[0]].get();
std::unique_ptr<Operation> new_op = std::unique_ptr<Operation>(new Operation(*y));
/*
* reindex operations
*/
auto inser_pos = t->beginLevel[y->levelOwner];
- for (auto& in : op->inputs) {
+ for (auto &in : op->inputs)
+ {
if (in >= inser_pos)
in++;
}
- for (int i = inser_pos; i < static_cast<int32_t>(t->opList.size()); i++) {
- for (auto& in : t->opList[i]->inputs) {
- if (in >= inser_pos) {
+ for (int i = inser_pos; i < static_cast<int32_t>(t->opList.size()); i++)
+ {
+ for (auto &in : t->opList[i]->inputs)
+ {
+ if (in >= inser_pos)
+ {
in++;
}
}
t->endLevel[y->levelOwner]++;
t->widthLevel[y->levelOwner]++;
- for (int i = y->levelOwner + 1; i < static_cast<int32_t>(t->beginLevel.size()); i++) {
+ for (int i = y->levelOwner + 1; i < static_cast<int32_t>(t->beginLevel.size()); i++)
+ {
t->beginLevel[i]++;
t->endLevel[i]++;
}
return inser_pos;
}
-void TreeBuilder::buildSketchConv2DForShape(std::vector<int32_t>& input_shape, Operation* op) {
+void TreeBuilder::buildSketchConv2DForShape(std::vector<int32_t> &input_shape, Operation *op)
+{
std::uniform_int_distribution<int32_t> int_rand(shapeMin, shapeMax);
/* out channels */
std::cout << " ]" << std::endl;
}
-void TreeBuilder::addConcatInput(std::vector<int32_t>& input_shape, int32_t axis, Operation* op) {
- for (int i = 0 ; i < 4; i++) {
+void TreeBuilder::addConcatInput(std::vector<int32_t> &input_shape, int32_t axis, Operation *op)
+{
+ for (int i = 0; i < 4; i++)
+ {
if (input_shape[i] != op->inputShape[i] && i != axis)
assert(false && "Not consistency input shapes\n");
}
#include <stddef.h>
-namespace modelgen {
+namespace modelgen
+{
-enum class OpCodes {
+enum class OpCodes
+{
opConv2d,
opConcatenation,
opDepthwiseConv2d,
opLast = opCount - 1,
};
-namespace treebuilder {
+namespace treebuilder
+{
/**
* opcode is a code of operation.
* not the kernel but specific data for operation.
*
*/
-struct Operation {
+struct Operation
+{
OpCodes opcode;
std::vector<int32_t> inputs;
std::vector<int32_t> kernelShape;
* for example: beginLevel[4] contains the id of first operation on the level 4.
* id is index for opList array.
*/
-struct Tree {
+struct Tree
+{
int inputCnt;
int hTree;
std::vector<int32_t> inputShapeTree;
std::vector<std::unique_ptr<Operation>> opList;
};
-class TreeBuilder {
+class TreeBuilder
+{
public:
TreeBuilder();
* inside every operation as size of input. This method are used when there aren't
* operations on upper levels.
*/
- void initTree(Tree* t);
- void buildLevel(Tree* t);
+ void initTree(Tree *t);
+ void buildLevel(Tree *t);
- bool buildSketchOperation(Tree* t, Operation* op);
+ bool buildSketchOperation(Tree *t, Operation *op);
/**
* @details Currently Conv2D are build with stride = 1.
* @param input_shape is the shape of input tensor.
* @param op is the pointer to created operation.
*/
- void buildSketchConv2D(Tree* t, Operation* op);
- void buildSketchConcat(Tree* t, Operation* op);
- void buildSketchDepthwiseConv2D(Tree* t, Operation* op);
- void buildSketchPooling(Tree* t, Operation* op);
- void buildSketchSoftmax(Tree* t, Operation* op);
- void buildSketchFullyConnected(Tree* t, Operation* op);
+ void buildSketchConv2D(Tree *t, Operation *op);
+ void buildSketchConcat(Tree *t, Operation *op);
+ void buildSketchDepthwiseConv2D(Tree *t, Operation *op);
+ void buildSketchPooling(Tree *t, Operation *op);
+ void buildSketchSoftmax(Tree *t, Operation *op);
+ void buildSketchFullyConnected(Tree *t, Operation *op);
+
private:
/**
* @lookupConsistentOutput It Looks up operation with conststent output's shape.
* and return its id.
*
*/
- int32_t lookupConsistentOutput(Tree* t, Operation* op, std::vector<int32_t>& shape,
+ int32_t lookupConsistentOutput(Tree *t, Operation *op, std::vector<int32_t> &shape,
int32_t until_level);
- void buildSketchConv2DForShape(std::vector<int32_t>& input_shape, Operation* op);
- void addConcatInput(std::vector<int32_t>& input_shape, int32_t axis, Operation* op);
+ void buildSketchConv2DForShape(std::vector<int32_t> &input_shape, Operation *op);
+ void addConcatInput(std::vector<int32_t> &input_shape, int32_t axis, Operation *op);
std::random_device _rd;
std::mt19937 _gen;
} // namespace treebuilder
} // namespace modelgen
-#endif //NNCC_TREE_H
+#endif // NNCC_TREE_H