From 8914b2b492f964de97d42e976ab8e2cb537778da Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Thu, 19 Jan 2023 20:21:17 +0800 Subject: [PATCH] perf: enhance Analyse module --- src/analyse/analyse.cc | 108 +++++++++++++-------------------------- src/analyse/analyse.h | 43 ++++++++-------- src/fast_cal/cal_core.cc | 5 +- src/fast_cal/fast_cal.cc | 1 - src/fast_cal/fast_cal.h | 2 + src/main.cc | 59 ++++++++++----------- 6 files changed, 88 insertions(+), 130 deletions(-) diff --git a/src/analyse/analyse.cc b/src/analyse/analyse.cc index 96629bd..ca5a6ca 100644 --- a/src/analyse/analyse.cc +++ b/src/analyse/analyse.cc @@ -1,13 +1,21 @@ #include -#include "core.h" #include "analyse.h" -#include -#include -#include "raw_code.h" -#include "common.h" +Core Analyse::init(uint64_t code) { + /// reset working data + cases.clear(); + cases.reserve(ANY_MAP_RESERVE); // hashmap pre-reserve + std::queue{}.swap(cache); -Core Analyse::init() { + /// insert root node + cache.emplace(&cases.emplace(code, analyse_t { + .code = code, + .mask = 0, + .step = 0, + .src = std::list{}, // without parent node + }).first->second); + + /// import klotski core return Core( [this](auto &&code, auto &&mask) { // lambda as function pointer new_case(std::forward(code), std::forward(mask)); @@ -15,95 +23,49 @@ Core Analyse::init() { ); } - +/// callback function for new case +void Analyse::new_case(uint64_t code, uint64_t mask) { + auto current = cases.find(code); + if (current != cases.end()) { // new case already exist + if (current->second.step == cache.front()->step + 1) { // new case at next layer + current->second.mask |= mask; // update mask info + current->second.src.emplace_back(cache.front()); // link more parent case + } + } else { // new case not exist + cache.emplace(&cases.emplace(code, analyse_t { // record new case + .code = code, + .mask = mask, + .step = cache.front()->step + 1, + .src = std::list{cache.front()}, // link parent case + }).first->second); + } +} void Analyse::build(uint64_t code) { - - auto core = init(); - - cases.clear(); - cases.reserve(65536); - - std::queue{}.swap(cache); - - cache.emplace(&cases.emplace(code, analyse_t { - .code = code, - .mask = 0, - .step = 0, - .src = std::list{}, - }).first->second); - + auto core = init(code); while (!cache.empty()) { core.next_cases(cache.front()->code, cache.front()->mask); cache.pop(); } - - std::cout << "size: " << cases.size() << std::endl; - } -std::vector Analyse::build_until(uint64_t code, const Analyse::match_t &match) { - - auto core = init(); - - cases.clear(); - cases.reserve(65536); - - std::queue{}.swap(cache); - - cache.emplace(&cases.emplace(code, analyse_t { - .code = code, - .mask = 0, - .step = 0, - .src = std::list{}, - }).first->second); - - +std::vector Analyse::build_until(uint64_t code, const match_t &match) { + auto core = init(code); auto layer_end = cache.back(); std::vector matched; // matched list - - + /// start BFS search while (!cache.empty()) { if (match(cache.front()->code)) { // match target matched.emplace_back(cache.front()->code); } - core.next_cases(cache.front()->code, cache.front()->mask); - if (cache.front() == layer_end) { // reach layer ending if (!matched.empty()) { - - std::cout << "size: " << cases.size() << std::endl; - return matched; // stop at first matched layer } layer_end = cache.back(); // reset layer ending } - cache.pop(); } - - std::cout << "size: " << cases.size() << std::endl; - return std::vector{}; // no target found - -} - - -void Analyse::new_case(uint64_t code, uint64_t mask) { - auto current = cases.find(code); - if (current != cases.end()) { // new case already exist - if (current->second.step == cache.front()->step + 1) { // new case at next layer - current->second.mask |= mask; // update mask info - current->second.src.emplace_back(cache.front()); // link more parent case - } - } else { // new case not exist - cache.emplace(&cases.emplace(code, analyse_t { // record new case - .code = code, - .mask = mask, - .step = cache.front()->step + 1, - .src = std::list{cache.front()}, // link parent case - }).first->second); - } } - diff --git a/src/analyse/analyse.h b/src/analyse/analyse.h index 93e8400..2a9f222 100644 --- a/src/analyse/analyse.h +++ b/src/analyse/analyse.h @@ -1,26 +1,39 @@ #pragma once +#include #include #include +#include #include +#include "core.h" -#include -#include -#include +const uint32_t ANY_MAP_RESERVE = 65536; class Analyse { public: + typedef std::function match_t; + + void build(uint64_t code); + std::vector build_until(uint64_t code, const match_t &match); + +private: struct analyse_t { uint64_t code; uint64_t mask; uint32_t step; - std::list src; -// std::vector src; -// std::set src; -// std::unordered_set src; }; + uint64_t root; + std::queue cache; + std::unordered_map cases; + + inline Core init(uint64_t code); + void new_case(uint64_t code, uint64_t mask); + + + /// backtrack definitions + // struct backtrack_t { // uint64_t code; // uint32_t layer_num; @@ -28,24 +41,8 @@ public: // std::list next; // }; - std::queue cache; - std::unordered_map cases; - -// inline Core new_core(); - // TODO: backtrack for multi-codes // void backtrack(uint64_t code); // void backtrack(const std::vector &raw_code_list); - typedef std::function match_t; - - void build(uint64_t code); - - std::vector build_until(uint64_t code, const match_t &match); - -// inline Core init(uint64_t code); - inline Core init(); - - void new_case(uint64_t code, uint64_t mask); - }; diff --git a/src/fast_cal/cal_core.cc b/src/fast_cal/cal_core.cc index 4380aed..b7cac3c 100644 --- a/src/fast_cal/cal_core.cc +++ b/src/fast_cal/cal_core.cc @@ -1,4 +1,3 @@ -#include "core.h" #include "fast_cal.h" Core FastCal::init(uint64_t code) { // initialize process @@ -39,7 +38,6 @@ void FastCal::new_case(uint64_t code, uint64_t mask) { /// build total search tree void FastCal::build() { auto core = init(root); - /// start BFS search while (!cache.empty()) { core.next_cases(cache.front()->code, cache.front()->mask); cache.pop(); @@ -49,7 +47,6 @@ void FastCal::build() { /// found first matched target RawCode FastCal::target(const match_t &match) { auto core = init(root); - /// start BFS search while (!cache.empty()) { if (match(cache.front()->code)) { return RawCode::unsafe_create(cache.front()->code); // match target @@ -84,7 +81,7 @@ std::vector FastCal::furthest() { } /// found multi-targets matched in first same layer -std::vector FastCal::target_multi(const FastCal::match_t &match) { +std::vector FastCal::target_multi(const match_t &match) { auto core = init(root); auto layer_end = cache.back(); std::vector matched; // matched list diff --git a/src/fast_cal/fast_cal.cc b/src/fast_cal/fast_cal.cc index 1ea6fd2..3629e3f 100644 --- a/src/fast_cal/fast_cal.cc +++ b/src/fast_cal/fast_cal.cc @@ -1,5 +1,4 @@ #include -#include "core.h" #include "common.h" #include "fast_cal.h" #include "raw_code.h" diff --git a/src/fast_cal/fast_cal.h b/src/fast_cal/fast_cal.h index 6967386..32e0664 100644 --- a/src/fast_cal/fast_cal.h +++ b/src/fast_cal/fast_cal.h @@ -3,7 +3,9 @@ #include #include #include +#include #include +#include "core.h" #include "raw_code.h" const uint32_t FC_MAP_RESERVE = 65536; diff --git a/src/main.cc b/src/main.cc index 9bc5837..636f6cc 100644 --- a/src/main.cc +++ b/src/main.cc @@ -16,45 +16,46 @@ int main() { BasicRanges::build(); +// AllCases::build(); + - std::vector test_cases; - { - AllCases::build(); - std::vector all_cases; - for (uint64_t head = 0; head < 16; ++head) { - for (const auto &range : AllCases::fetch()[head]) { - all_cases.emplace_back(head << 32 | range); - } - } - for (uint32_t i = 0; i < 1000; ++i) { - test_cases.emplace_back( - RawCode::from_common_code(all_cases.at(i * 29334)) - ); - } - } - std::cout << "test size -> " << test_cases.size() << std::endl; +// std::vector test_cases; +// { +// AllCases::build(); +// std::vector all_cases; +// for (uint64_t head = 0; head < 16; ++head) { +// for (const auto &range : AllCases::fetch()[head]) { +// all_cases.emplace_back(head << 32 | range); +// } +// } +// for (uint32_t i = 0; i < 1000; ++i) { +// test_cases.emplace_back( +// RawCode::from_common_code(all_cases.at(i * 29334)) +// ); +// } +// } +// std::cout << "test size -> " << test_cases.size() << std::endl; // std::cout << "wait 3s" << std::endl; // sleep(3); - std::cout << "start benchmark" << std::endl; +// std::cout << "start benchmark" << std::endl; auto start_time = clock(); -// AllCases::build(); +// { +// auto fc = FastCal(RawCode::unsafe_create(0)); +// for (auto code : test_cases) { +// fc.set_root(code); +// fc.solve(); +// } +// } - { - auto fc = FastCal(RawCode::unsafe_create(0)); - for (auto code : test_cases) { - fc.set_root(code); - fc.solve(); - } - } + auto a = Analyse(); + a.build((uint64_t)RawCode::from_common_code("1a9bf0c")); -// auto a = Analyse(); -// a.build((uint64_t)RawCode::from_common_code("1a9bf0c")); // auto ret = a.build_until((uint64_t)RawCode::from_common_code("1a9bf0c"), [](uint64_t code) { // return ((code >> (3 * 0xD)) & 0b111) == B_2x2; // }); @@ -99,9 +100,9 @@ int main() { // std::cout << CommonCode::from_short_code("AXCZN") << std::endl; - std::cerr << (clock() - start_time) / CLOCKS_PER_SEC << "s" << std::endl; +// std::cerr << (clock() - start_time) / CLOCKS_PER_SEC << "s" << std::endl; // std::cerr << (clock() - start_time) * 1000 / CLOCKS_PER_SEC << "ms" << std::endl; -// std::cerr << (clock() - start_time) * 1000000 / CLOCKS_PER_SEC << "us" << std::endl; + std::cerr << (clock() - start_time) * 1000000 / CLOCKS_PER_SEC << "us" << std::endl; std::cout << "complete benchmark" << std::endl;