From f6bb9002592a4ab217fbd9c585f018acb8449219 Mon Sep 17 00:00:00 2001 From: Andrey Golubev Date: Wed, 14 Aug 2019 10:03:52 +0300 Subject: [PATCH] Merge pull request #15238 from andrey-golubev:fluid_fix_journal G-API: Fix Journal usage in Fluid backend (#15238) * Fix Journal usage in Fluid backend * Delete dumpDotRequired(): invalid check * Update mem consumption test * Test that new test works * Debug memory consumption function * Increase iterations in test * Re-write memory consumption measurement part * Restore correct fix for Fluid journals --- .../gapi/src/backends/fluid/gfluidbackend.cpp | 2 + modules/gapi/src/compiler/gmodel.cpp | 10 ++++ modules/gapi/src/compiler/gmodel.hpp | 2 + modules/gapi/test/gapi_fluid_test.cpp | 57 +++++++++++++++++++ 4 files changed, 71 insertions(+) diff --git a/modules/gapi/src/backends/fluid/gfluidbackend.cpp b/modules/gapi/src/backends/fluid/gfluidbackend.cpp index 1e10783e52..6e2f1aa589 100644 --- a/modules/gapi/src/backends/fluid/gfluidbackend.cpp +++ b/modules/gapi/src/backends/fluid/gfluidbackend.cpp @@ -943,6 +943,8 @@ namespace fd.skew = 0; fd.max_consumption = 0; } + + GModel::log_clear(g, node); } } diff --git a/modules/gapi/src/compiler/gmodel.cpp b/modules/gapi/src/compiler/gmodel.cpp index 8c6ce334c4..a5e4f2c760 100644 --- a/modules/gapi/src/compiler/gmodel.cpp +++ b/modules/gapi/src/compiler/gmodel.cpp @@ -185,6 +185,16 @@ void GModel::log(Graph &g, ade::EdgeHandle eh, std::string &&msg, ade::NodeHandl } } +void GModel::log_clear(Graph &g, ade::NodeHandle node) +{ + if (g.metadata(node).contains()) + { + // according to documentation, clear() doesn't deallocate (__capacity__ of vector preserved) + g.metadata(node).get().messages.clear(); + } +} + + ade::NodeHandle GModel::detail::dataNodeOf(const ConstLayoutGraph &g, const GOrigin &origin) { // FIXME: Does it still work with graph transformations, e.g. redirectWriter()?? diff --git a/modules/gapi/src/compiler/gmodel.hpp b/modules/gapi/src/compiler/gmodel.hpp index af6cfc78f8..d5e03d5497 100644 --- a/modules/gapi/src/compiler/gmodel.hpp +++ b/modules/gapi/src/compiler/gmodel.hpp @@ -226,6 +226,8 @@ namespace GModel // appear in the dumped .dot file.x GAPI_EXPORTS void log(Graph &g, ade::NodeHandle op, std::string &&message, ade::NodeHandle updater = ade::NodeHandle()); GAPI_EXPORTS void log(Graph &g, ade::EdgeHandle op, std::string &&message, ade::NodeHandle updater = ade::NodeHandle()); + // Clears logged messages of a node. + GAPI_EXPORTS void log_clear(Graph &g, ade::NodeHandle node); GAPI_EXPORTS void linkIn (Graph &g, ade::NodeHandle op, ade::NodeHandle obj, std::size_t in_port); GAPI_EXPORTS void linkOut (Graph &g, ade::NodeHandle op, ade::NodeHandle obj, std::size_t out_port); diff --git a/modules/gapi/test/gapi_fluid_test.cpp b/modules/gapi/test/gapi_fluid_test.cpp index 949ef2739e..baccb5802d 100644 --- a/modules/gapi/test/gapi_fluid_test.cpp +++ b/modules/gapi/test/gapi_fluid_test.cpp @@ -826,4 +826,61 @@ TEST(Fluid, InvalidROIs) } } + +namespace +{ +#if defined(__linux__) +uint64_t currMemoryConsumption() +{ + // check self-state via /proc information + constexpr const char stat_file_path[] = "/proc/self/statm"; + std::ifstream proc_stat(stat_file_path); + if (!proc_stat.is_open() || !proc_stat.good()) + { + CV_LOG_WARNING(NULL, "Failed to open stat file: " << stat_file_path); + return static_cast(0); + } + std::string stat_line; + std::getline(proc_stat, stat_line); + uint64_t unused, rss; + // using resident set size + std::istringstream(stat_line) >> unused >> rss; + CV_Assert(rss != 0); + return rss; +} +#else +// FIXME: implement this part (at least for Windows?), right now it's enough to check Linux only +uint64_t currMemoryConsumption() { return static_cast(0); } +#endif +} // anonymous namespace + +TEST(Fluid, MemoryConsumptionDoesNotGrowOnReshape) +{ + cv::GMat in; + cv::GMat a, b, c; + std::tie(a, b, c) = cv::gapi::split3(in); + cv::GMat merged = cv::gapi::merge4(a, b, c, a); + cv::GMat d, e, f, g; + std::tie(d, e, f, g) = cv::gapi::split4(merged); + cv::GMat out = cv::gapi::merge3(d, e, f); + + cv::Mat in_mat(cv::Size(8, 8), CV_8UC3); + cv::randu(in_mat, cv::Scalar::all(0), cv::Scalar::all(100)); + cv::Mat out_mat; + + const auto compile_args = [] () { + return cv::compile_args(cv::gapi::core::fluid::kernels()); + }; + + cv::GCompiled compiled = cv::GComputation(cv::GIn(in), cv::GOut(out)).compile( + cv::descr_of(in_mat), compile_args()); + ASSERT_TRUE(compiled.canReshape()); + + const auto mem_before = currMemoryConsumption(); + for (int _ = 0; _ < 1000; ++_) compiled.reshape(cv::descr_of(cv::gin(in_mat)), compile_args()); + const auto mem_after = currMemoryConsumption(); + + ASSERT_GE(mem_before, mem_after); +} + } // namespace opencv_test