From 15513d199cf17f2383b59d1140516c9aa4ff6d0f Mon Sep 17 00:00:00 2001 From: Ye Kuang Date: Wed, 7 Oct 2020 21:01:52 +0900 Subject: [PATCH 1/5] [test] Add a benchmark for SFG's two-level map --- tests/cpp/benchmark_sfg_edges.cpp | 219 ++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 tests/cpp/benchmark_sfg_edges.cpp diff --git a/tests/cpp/benchmark_sfg_edges.cpp b/tests/cpp/benchmark_sfg_edges.cpp new file mode 100644 index 0000000000000..6021db46381cb --- /dev/null +++ b/tests/cpp/benchmark_sfg_edges.cpp @@ -0,0 +1,219 @@ +#include +#include // std::chrono::system_clock +#include // std::default_random_engine +#include +#include +#include + +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "taichi/system/profiler.h" +#include "taichi/util/testing.h" + +TLANG_NAMESPACE_BEGIN + +using PairData = std::pair; + +using UnorderedMapSet = std::unordered_map>; +using LLVMVecSet = llvm::SmallVector>, 4>; +using LLVMVecVec = + llvm::SmallVector>, 4>; +using StlVecSet = std::vector>>; +using StlVecVec = std::vector>>; + +// https://stackoverflow.com/a/1055563/12003165 +// Over-engineering a bit. typeid().name() is mangled and hard to read... +template +struct TypeNameTraits; + +#define REGISTER_TYPE_NAME(X) \ + template <> \ + struct TypeNameTraits { \ + static const char *name; \ + }; \ + const char *TypeNameTraits::name = #X + +REGISTER_TYPE_NAME(LLVMVecSet); +REGISTER_TYPE_NAME(LLVMVecVec); +REGISTER_TYPE_NAME(StlVecSet); +REGISTER_TYPE_NAME(StlVecVec); + +void insert(const PairData &d, UnorderedMapSet *m) { + TI_PROFILER("UnorderedMapSet insert"); + (*m)[d.first].insert(d.second); +} + +bool lookup(const PairData &d, const UnorderedMapSet &m) { + TI_PROFILER("UnorderedMapSet lookup"); + auto itr = m.find(d.first); + if (itr == m.end()) { + return false; + } + return itr->second.count(d.second) > 0; +} + +template +void insert_vecset(const PairData &d, VecSet *m) { + auto pname = fmt::format("{} insert", TypeNameTraits::name); + TI_PROFILER(pname); + int i1 = 0; + for (; i1 < m->size(); ++i1) { + if ((*m)[i1].first == d.first) { + break; + } + } + if (i1 == m->size()) { + m->push_back({}); + m->back().first = d.first; + } + (*m)[i1].second.insert(d.second); +} + +template +bool lookup_vecset(const PairData &d, const VecSet &m) { + auto pname = fmt::format("{} lookup", TypeNameTraits::name); + TI_PROFILER(pname); + int i1 = 0; + for (; i1 < m.size(); ++i1) { + if (m[i1].first == d.first) { + break; + } + } + if (i1 == m.size()) { + return false; + } + return m[i1].second.count(d.second) > 0; +} + +template +void insert_vecvec(const PairData &d, VecVec *m) { + auto pname = fmt::format("{} insert", TypeNameTraits::name); + TI_PROFILER(pname); + int i1 = 0; + for (; i1 < m->size(); ++i1) { + if ((*m)[i1].first == d.first) { + break; + } + } + if (i1 == m->size()) { + m->push_back({}); + m->back().first = d.first; + } + + auto &v2 = (*m)[i1].second; + for (int i2 = 0; i2 < v2.size(); ++i2) { + if (v2[i2] == d.second) { + return; + } + } + v2.push_back(d.second); +} + +template +bool lookup_vecvec(const PairData &d, const VecVec &m) { + auto pname = fmt::format("{} lookup", TypeNameTraits::name); + TI_PROFILER(pname); + int i1 = 0; + for (; i1 < m.size(); ++i1) { + if (m[i1].first == d.first) { + break; + } + } + if (i1 == m.size()) { + return false; + } + const auto &v2 = m[i1].second; + for (int i2 = 0; i2 < v2.size(); ++i2) { + if (v2[i2] == d.second) { + return true; + } + } + return false; +} + +template +void insert(const PairData &d, C *m) { + if constexpr (std::is_same_v || std::is_same_v) { + insert_vecset(d, m); + } else if constexpr (std::is_same_v || + std::is_same_v) { + insert_vecvec(d, m); + } +} + +template +bool lookup(const PairData &d, const C &m) { + if constexpr (std::is_same_v || std::is_same_v) { + return lookup_vecset(d, m); + } else if constexpr (std::is_same_v || + std::is_same_v) { + return lookup_vecvec(d, m); + } +} + +template +void run_test(const std::vector &data, + const std::vector &non_exists) { + for (int i = 0; i < 10; ++i) { + M m; + for (const auto &p : data) { + insert(p, &m); + } + + for (const auto &p : data) { + bool l = lookup(p, m); + TI_CHECK(l); + } + + for (const auto &p : non_exists) { + bool l = lookup(p, m); + TI_CHECK(!l); + } + } +} + +// Basic tests within a basic block +TI_TEST("benchmark_sfg") { + std::vector data = { + {0, 0}, {0, 2}, {0, 2}, {0, 5}, // 0 + {1, 1}, {1, 2}, {1, 3}, {1, 3}, {1, 6}, {1, 6}, // 1 + {2, 0}, {2, 0}, {2, 2}, // 2 + {3, 5}, {3, 6}, {3, 7}, // 3 + {5, 0}, {5, 2}, {5, 2}, {5, 2}, {5, 2}, // 5 + {6, 1}, {6, 2}, {6, 2}, // 6 + {9, 9}, // 9 + }; + std::vector non_exists = { + {0, 1}, {0, 3}, // 0 + {1, 4}, {1, 5}, // 1 + {3, 0}, {3, 1}, {3, 2}, // 3 + {4, 1}, // 4 + {6, 3}, // 6 + {7, 8}, // 7 + }; + unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); + std::shuffle(data.begin(), data.end(), std::default_random_engine(seed)); + + SECTION("UnorderedMapSet") { + run_test(data, non_exists); + } + + SECTION("LLVMVecSet") { + run_test(data, non_exists); + } + + SECTION("LLVMVecVec") { + run_test(data, non_exists); + } + + SECTION("StlVecSet") { + run_test(data, non_exists); + } + + SECTION("StlVecVec") { + run_test(data, non_exists); + } + Profiling::get_instance().print_profile_info(); +} + +TLANG_NAMESPACE_END From 6886ec9e87227e045e0d26e49e7e0837ecd9b3de Mon Sep 17 00:00:00 2001 From: Ye Kuang Date: Wed, 7 Oct 2020 21:14:17 +0900 Subject: [PATCH 2/5] shuffle --- tests/cpp/benchmark_sfg_edges.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/cpp/benchmark_sfg_edges.cpp b/tests/cpp/benchmark_sfg_edges.cpp index 6021db46381cb..7b4d48e329dcc 100644 --- a/tests/cpp/benchmark_sfg_edges.cpp +++ b/tests/cpp/benchmark_sfg_edges.cpp @@ -191,8 +191,10 @@ TI_TEST("benchmark_sfg") { {6, 3}, // 6 {7, 8}, // 7 }; - unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); - std::shuffle(data.begin(), data.end(), std::default_random_engine(seed)); + const auto seed = std::chrono::system_clock::now().time_since_epoch().count(); + std::default_random_engine rng(seed); + std::shuffle(data.begin(), data.end(), rng); + std::shuffle(non_exists.begin(), non_exists.end(), rng); SECTION("UnorderedMapSet") { run_test(data, non_exists); From 3125fbe605edd77e6cc12f0ee93e4edddc3a1d61 Mon Sep 17 00:00:00 2001 From: Ye Kuang Date: Wed, 7 Oct 2020 21:16:56 +0900 Subject: [PATCH 3/5] found/not found --- tests/cpp/benchmark_sfg_edges.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/tests/cpp/benchmark_sfg_edges.cpp b/tests/cpp/benchmark_sfg_edges.cpp index 7b4d48e329dcc..425b41031b211 100644 --- a/tests/cpp/benchmark_sfg_edges.cpp +++ b/tests/cpp/benchmark_sfg_edges.cpp @@ -1,6 +1,7 @@ #include #include // std::chrono::system_clock #include // std::default_random_engine +#include #include #include #include @@ -43,8 +44,9 @@ void insert(const PairData &d, UnorderedMapSet *m) { (*m)[d.first].insert(d.second); } -bool lookup(const PairData &d, const UnorderedMapSet &m) { - TI_PROFILER("UnorderedMapSet lookup"); +bool lookup(const PairData &d, const UnorderedMapSet &m, + const std::string &found) { + TI_PROFILER("UnorderedMapSet lookup " + found); auto itr = m.find(d.first); if (itr == m.end()) { return false; @@ -70,8 +72,8 @@ void insert_vecset(const PairData &d, VecSet *m) { } template -bool lookup_vecset(const PairData &d, const VecSet &m) { - auto pname = fmt::format("{} lookup", TypeNameTraits::name); +bool lookup_vecset(const PairData &d, const VecSet &m, const std::string& found) { + auto pname = fmt::format("{} lookup {}", TypeNameTraits::name, found); TI_PROFILER(pname); int i1 = 0; for (; i1 < m.size(); ++i1) { @@ -110,8 +112,8 @@ void insert_vecvec(const PairData &d, VecVec *m) { } template -bool lookup_vecvec(const PairData &d, const VecVec &m) { - auto pname = fmt::format("{} lookup", TypeNameTraits::name); +bool lookup_vecvec(const PairData &d, const VecVec &m, const std::string& found) { + auto pname = fmt::format("{} lookup {}", TypeNameTraits::name, found); TI_PROFILER(pname); int i1 = 0; for (; i1 < m.size(); ++i1) { @@ -142,12 +144,12 @@ void insert(const PairData &d, C *m) { } template -bool lookup(const PairData &d, const C &m) { +bool lookup(const PairData &d, const C &m, const std::string& found) { if constexpr (std::is_same_v || std::is_same_v) { - return lookup_vecset(d, m); + return lookup_vecset(d, m, found); } else if constexpr (std::is_same_v || std::is_same_v) { - return lookup_vecvec(d, m); + return lookup_vecvec(d, m, found); } } @@ -161,12 +163,12 @@ void run_test(const std::vector &data, } for (const auto &p : data) { - bool l = lookup(p, m); + bool l = lookup(p, m, "found"); TI_CHECK(l); } for (const auto &p : non_exists) { - bool l = lookup(p, m); + bool l = lookup(p, m, "not found"); TI_CHECK(!l); } } From 5027822110775de2ae350b1392d31c7ea0e9895f Mon Sep 17 00:00:00 2001 From: Taichi Gardener Date: Wed, 7 Oct 2020 08:17:23 -0400 Subject: [PATCH 4/5] [skip ci] enforce code format --- tests/cpp/benchmark_sfg_edges.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/cpp/benchmark_sfg_edges.cpp b/tests/cpp/benchmark_sfg_edges.cpp index 425b41031b211..030ddde8b537f 100644 --- a/tests/cpp/benchmark_sfg_edges.cpp +++ b/tests/cpp/benchmark_sfg_edges.cpp @@ -44,7 +44,8 @@ void insert(const PairData &d, UnorderedMapSet *m) { (*m)[d.first].insert(d.second); } -bool lookup(const PairData &d, const UnorderedMapSet &m, +bool lookup(const PairData &d, + const UnorderedMapSet &m, const std::string &found) { TI_PROFILER("UnorderedMapSet lookup " + found); auto itr = m.find(d.first); @@ -72,7 +73,9 @@ void insert_vecset(const PairData &d, VecSet *m) { } template -bool lookup_vecset(const PairData &d, const VecSet &m, const std::string& found) { +bool lookup_vecset(const PairData &d, + const VecSet &m, + const std::string &found) { auto pname = fmt::format("{} lookup {}", TypeNameTraits::name, found); TI_PROFILER(pname); int i1 = 0; @@ -112,7 +115,9 @@ void insert_vecvec(const PairData &d, VecVec *m) { } template -bool lookup_vecvec(const PairData &d, const VecVec &m, const std::string& found) { +bool lookup_vecvec(const PairData &d, + const VecVec &m, + const std::string &found) { auto pname = fmt::format("{} lookup {}", TypeNameTraits::name, found); TI_PROFILER(pname); int i1 = 0; @@ -144,7 +149,7 @@ void insert(const PairData &d, C *m) { } template -bool lookup(const PairData &d, const C &m, const std::string& found) { +bool lookup(const PairData &d, const C &m, const std::string &found) { if constexpr (std::is_same_v || std::is_same_v) { return lookup_vecset(d, m, found); } else if constexpr (std::is_same_v || From 21b26abe90f43904f16a868931a6c33ad460750a Mon Sep 17 00:00:00 2001 From: Ye Kuang Date: Fri, 9 Oct 2020 20:28:45 +0900 Subject: [PATCH 5/5] add Empty, FlattenSet and FlattenVec --- tests/cpp/benchmark_sfg_edges.cpp | 60 ++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/tests/cpp/benchmark_sfg_edges.cpp b/tests/cpp/benchmark_sfg_edges.cpp index 030ddde8b537f..9fb6d21f28224 100644 --- a/tests/cpp/benchmark_sfg_edges.cpp +++ b/tests/cpp/benchmark_sfg_edges.cpp @@ -15,6 +15,7 @@ TLANG_NAMESPACE_BEGIN using PairData = std::pair; +struct Empty {}; using UnorderedMapSet = std::unordered_map>; using LLVMVecSet = llvm::SmallVector>, 4>; using LLVMVecVec = @@ -22,6 +23,9 @@ using LLVMVecVec = using StlVecSet = std::vector>>; using StlVecVec = std::vector>>; +using FlattenSet = llvm::SmallSet; +using FlattenVec = llvm::SmallVector; + // https://stackoverflow.com/a/1055563/12003165 // Over-engineering a bit. typeid().name() is mangled and hard to read... template @@ -39,6 +43,15 @@ REGISTER_TYPE_NAME(LLVMVecVec); REGISTER_TYPE_NAME(StlVecSet); REGISTER_TYPE_NAME(StlVecVec); +void insert(const PairData &d, Empty *m) { + TI_PROFILER("Empty insert"); +} + +bool lookup(const PairData &d, const Empty &m, const std::string &found) { + TI_PROFILER("Empty lookup " + found); + return false; +} + void insert(const PairData &d, UnorderedMapSet *m) { TI_PROFILER("UnorderedMapSet insert"); (*m)[d.first].insert(d.second); @@ -158,6 +171,36 @@ bool lookup(const PairData &d, const C &m, const std::string &found) { } } +void insert(const PairData &d, FlattenSet *m) { + TI_PROFILER("FlattenSet insert"); + m->insert(d); +} + +bool lookup(const PairData &d, const FlattenSet &m, const std::string &found) { + TI_PROFILER("FlattenSet lookup " + found); + return m.count(d) > 0; +} + +bool lookup(const PairData &d, const FlattenVec &m, const std::string &found) { + TI_PROFILER("FlattenVec lookup " + found); + + auto itr = std::lower_bound(m.begin(), m.end(), d); + return (itr != m.end()) && (*itr == d); +} + +void insert(const PairData &d, FlattenVec *m) { + TI_PROFILER("FlattenVec insert"); + + auto itr = std::lower_bound(m->begin(), m->end(), d); + if ((itr != m->end()) && (*itr == d)) { + return; + } + + m->insert(itr, d); + // m->push_back(d); + // std::sort(m->begin(), m->end()); +} + template void run_test(const std::vector &data, const std::vector &non_exists) { @@ -169,7 +212,9 @@ void run_test(const std::vector &data, for (const auto &p : data) { bool l = lookup(p, m, "found"); - TI_CHECK(l); + if constexpr (!std::is_same_v) { + TI_CHECK(l); + } } for (const auto &p : non_exists) { @@ -203,6 +248,11 @@ TI_TEST("benchmark_sfg") { std::shuffle(data.begin(), data.end(), rng); std::shuffle(non_exists.begin(), non_exists.end(), rng); + SECTION("Empty") { + // Get an idea of the overhead of the profiler itself. + run_test(data, non_exists); + } + SECTION("UnorderedMapSet") { run_test(data, non_exists); } @@ -222,6 +272,14 @@ TI_TEST("benchmark_sfg") { SECTION("StlVecVec") { run_test(data, non_exists); } + + SECTION("FlattenSet") { + run_test(data, non_exists); + } + + SECTION("FlattenVec") { + run_test(data, non_exists); + } Profiling::get_instance().print_profile_info(); }