From 21fa2ed3a6d4d3069698686e13b98326888982d1 Mon Sep 17 00:00:00 2001 From: Jihoon Lee Date: Mon, 12 Apr 2021 18:33:10 +0900 Subject: [PATCH] [IniSerializer] Add `serialize` to ini **Changes proposed in this PR:** - implements ini interpreter::serialize - add corresponding test (reference shoud be equal to serialize->deserialized graph) - Fix some const correctness **Self evaluation:** 1. Build test: [X]Passed [ ]Failed [ ]Skipped 2. Run test: [X]Passed [ ]Failed [ ]Skipped Signed-off-by: Jihoon Lee --- nntrainer/compiler/ini_interpreter.cpp | 16 +++++-- nntrainer/graph/network_graph.cpp | 2 +- nntrainer/graph/network_graph.h | 2 +- nntrainer/utils/ini_wrapper.cpp | 6 ++- nntrainer/utils/ini_wrapper.h | 9 +++- test/unittest/compiler/unittest_interpreter.cpp | 60 ++++++++++++++++--------- 6 files changed, 67 insertions(+), 28 deletions(-) diff --git a/nntrainer/compiler/ini_interpreter.cpp b/nntrainer/compiler/ini_interpreter.cpp index 0c9406a..2449805 100644 --- a/nntrainer/compiler/ini_interpreter.cpp +++ b/nntrainer/compiler/ini_interpreter.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -275,12 +276,21 @@ void IniGraphInterpreter::serialize( IniSection s(layer->getName()); s.setEntry("type", layer->getType()); - /// @todo: implement export a property - std::cout << layer->getName() << std::endl; + Exporter e; + layer->export_to(e); + + const auto key_val_pairs = + e.get_result(); + + for (const auto &pair : key_val_pairs) { + s.setEntry(pair.first, pair.second); + } + + sections.push_back(s); } auto ini = IniWrapper(out, sections); - ini.save_ini(); + ini.save_ini(out); } std::shared_ptr diff --git a/nntrainer/graph/network_graph.cpp b/nntrainer/graph/network_graph.cpp index 29fa8b6..c794961 100644 --- a/nntrainer/graph/network_graph.cpp +++ b/nntrainer/graph/network_graph.cpp @@ -724,7 +724,7 @@ NetworkGraph::getUnsortedLayers(const std::string &input_layer, return ret; } -std::vector> NetworkGraph::getLayers() { +std::vector> NetworkGraph::getLayers() const { std::vector> ret; if (compiled) { std::transform(Sorted.begin(), Sorted.end(), std::back_inserter(ret), diff --git a/nntrainer/graph/network_graph.h b/nntrainer/graph/network_graph.h index bf8cefd..fa020eb 100644 --- a/nntrainer/graph/network_graph.h +++ b/nntrainer/graph/network_graph.h @@ -151,7 +151,7 @@ public: * @note these layers will be in sorted order if the model is compiled, * otherwise the order is the order of addition of layers in the model. */ - std::vector> getLayers(); + std::vector> getLayers() const; /** * @brief join passed graph into the existing graph model diff --git a/nntrainer/utils/ini_wrapper.cpp b/nntrainer/utils/ini_wrapper.cpp index 519502b..79075ac 100644 --- a/nntrainer/utils/ini_wrapper.cpp +++ b/nntrainer/utils/ini_wrapper.cpp @@ -113,8 +113,10 @@ void IniWrapper::updateSections(const Sections §ions_) { } } -void IniWrapper::save_ini() { - std::ofstream out(getIniName().c_str(), std::ios_base::out); +void IniWrapper::save_ini() { save_ini(getIniName()); } + +void IniWrapper::save_ini(const std::string &ini_name) { + std::ofstream out(ini_name.c_str(), std::ios_base::out); NNTR_THROW_IF(!out.good(), std::runtime_error) << "cannot open ini"; for (auto &it : sections) { diff --git a/nntrainer/utils/ini_wrapper.h b/nntrainer/utils/ini_wrapper.h index 2dda96d..43ca4c5 100644 --- a/nntrainer/utils/ini_wrapper.h +++ b/nntrainer/utils/ini_wrapper.h @@ -305,9 +305,16 @@ public: std::string getName() const { return name; } /** - * @brief save ini to a file + * @brief save ini to a file, (getIniName() is used to save) */ void save_ini(); + + /** + * @brief save ini by ini_name + * + * @param ini_name ini name to svae + */ + void save_ini(const std::string &ini_name); /** * @brief erase ini * diff --git a/test/unittest/compiler/unittest_interpreter.cpp b/test/unittest/compiler/unittest_interpreter.cpp index 790434d..346b412 100644 --- a/test/unittest/compiler/unittest_interpreter.cpp +++ b/test/unittest/compiler/unittest_interpreter.cpp @@ -46,6 +46,41 @@ auto ini_interpreter = std::make_shared(ac, pathResolver); /** + * @brief prototypical version of checking graph is equal + * + * @param lhs compiled(later, finalized) graph to be compared + * @param rhs compiled(later, finalized) graph to be compared + * @return true graph is equal + * @return false graph is not equal + */ +static void graphEqual(const nntrainer::GraphRepresentation &lhs, + const nntrainer::GraphRepresentation &rhs) { + auto layers = lhs.getLayers(); + auto ref_layers = rhs.getLayers(); + EXPECT_EQ(layers.size(), ref_layers.size()); + + auto is_node_equal = [](const nntrainer::Layer &l, + const nntrainer::Layer &r) { + nntrainer::Exporter lhs_export; + nntrainer::Exporter rhs_export; + + l.export_to(lhs_export); + r.export_to(rhs_export); + + /*** fixme, there is one caveat that order matters in this form */ + EXPECT_EQ( + lhs_export.get_result(), + rhs_export.get_result()); + }; + + if (layers.size() == ref_layers.size()) { + for (unsigned int i = 0; i < layers.size(); ++i) { + is_node_equal(*layers[i], *ref_layers[i]); + } + } +} + +/** * @brief nntrainer Interpreter Test setup * * @note Proposing an evolutional path of current test @@ -90,24 +125,11 @@ TEST_P(nntrainerInterpreterTest, graphEqual) { status = g->compile(nntrainer::LossType::LOSS_NONE); EXPECT_EQ(status, ML_ERROR_NONE); - /// @todo: make a graph equal + /// @todo: make a proper graph equal /// 1. having same number of nodes /// 2. layer name is identical (this is too strict though) /// 3. attributes of layer is identical - // EXPECT_EQ(*graph, *interpreter->deserialize(file_path)); - - auto layers = g->getLayers(); - auto ref_layers = reference->getLayers(); - EXPECT_EQ(layers.size(), ref_layers.size()); - - if (layers.size() == ref_layers.size()) { - for (auto &layer : layers) { - std::shared_ptr ref_layer; - EXPECT_NO_THROW(ref_layer = reference->getLayer(layer->getName())); - - /// @todo: layer->getProperties() and do check on each properties - } - } + graphEqual(*g, *reference); } /** @@ -123,13 +145,11 @@ TEST_P(nntrainerInterpreterTest, graphSerializeAfterDeserialize) { int status = g->compile(nntrainer::LossType::LOSS_NONE); EXPECT_EQ(status, ML_ERROR_NONE); interpreter->serialize(g, out_file_path); + auto new_g = interpreter->deserialize(out_file_path); - // auto new_g = interpreter->deserialize(out_file_path); + graphEqual(*g, *new_g); - /// @todo: enable this - /// check if graph is the same - // EXPECT_EQ(*g, *new_g); - // EXPECT_EQ(remove(out_file_path.c_str()), 0); + EXPECT_EQ(remove(out_file_path.c_str()), 0) << strerror(errno); } auto fc0 = LayerReprentation("fully_connected", -- 2.7.4