mirror of https://github.com/dnomd343/klotski.git
Dnomd343
2 months ago
12 changed files with 102 additions and 188 deletions
@ -1,91 +0,0 @@ |
|||||
#include <BS_thread_pool.hpp> |
|
||||
|
|
||||
#include "codec.h" |
|
||||
|
|
||||
using klotski::cases::AllCases; |
|
||||
using klotski::cases::ALL_CASES_NUM_; |
|
||||
|
|
||||
void head_parallel(std::function<void(uint64_t head)> &&func) { |
|
||||
constexpr auto heads = std::to_array({ |
|
||||
0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14 |
|
||||
}); |
|
||||
BS::thread_pool pool; |
|
||||
for (auto head : heads) { |
|
||||
pool.detach_task([head, &func] { |
|
||||
func(head); |
|
||||
}); |
|
||||
} |
|
||||
pool.wait(); |
|
||||
} |
|
||||
|
|
||||
std::vector<uint64_t> all_common_codes() { |
|
||||
// TODO: using `std::ranges`
|
|
||||
std::vector<uint64_t> common_codes; |
|
||||
common_codes.reserve(ALL_CASES_NUM_); |
|
||||
for (uint64_t head = 0; head < 16; ++head) { |
|
||||
for (auto range : AllCases::instance().fetch()[head]) { |
|
||||
common_codes.emplace_back(head << 32 | range); |
|
||||
} |
|
||||
} |
|
||||
return common_codes; |
|
||||
} |
|
||||
|
|
||||
void common_code_parallel(std::function<void(std::span<CommonCode>)> &&func) { |
|
||||
|
|
||||
static auto codes = AllCases::instance().fetch().codes(); |
|
||||
|
|
||||
BS::thread_pool pool; |
|
||||
|
|
||||
// TODO: enhance performance
|
|
||||
|
|
||||
pool.detach_blocks((uint64_t)0, codes.size(), [func = std::move(func)](auto start, auto end) { |
|
||||
|
|
||||
func(std::span<CommonCode> {codes.data() + start, end - start}); |
|
||||
|
|
||||
}, 16); |
|
||||
|
|
||||
pool.wait(); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
static std::vector<RawCode> convert(const std::vector<CommonCode> &codes) { |
|
||||
std::vector<RawCode> result; |
|
||||
result.reserve(29334498); |
|
||||
for (auto code : codes) { |
|
||||
result.emplace_back(RawCode::from_common_code(code)); |
|
||||
} |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
void raw_code_parallel(std::function<void(std::span<RawCode>)> &&func) { |
|
||||
|
|
||||
static auto codes = convert(AllCases::instance().fetch().codes()); |
|
||||
|
|
||||
BS::thread_pool pool; |
|
||||
pool.detach_blocks((uint64_t)0, codes.size(), [func = std::move(func)](auto start, auto end) { |
|
||||
|
|
||||
func(std::span<RawCode> {codes.data() + start, end - start}); |
|
||||
|
|
||||
}, 16); |
|
||||
|
|
||||
pool.wait(); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
void short_code_parallel(std::function<void(std::span<ShortCode>)> &&func) { |
|
||||
static auto codes = []() { |
|
||||
std::vector<uint32_t> v (klotski::codec::SHORT_CODE_LIMIT); |
|
||||
std::iota(v.begin(), v.end(), 0); |
|
||||
return v; |
|
||||
}(); |
|
||||
|
|
||||
BS::thread_pool pool; |
|
||||
pool.detach_blocks((uint64_t)0, codes.size(), [func = std::move(func)](auto start, auto end) { |
|
||||
|
|
||||
auto span = std::span<uint32_t> {codes.data() + start, end - start}; |
|
||||
func(std::bit_cast<std::span<ShortCode>>(span)); |
|
||||
|
|
||||
}, 16); |
|
||||
|
|
||||
pool.wait(); |
|
||||
} |
|
@ -1,66 +0,0 @@ |
|||||
#pragma once |
|
||||
|
|
||||
#include <span> |
|
||||
#include <functional> |
|
||||
|
|
||||
#include "raw_code/raw_code.h" |
|
||||
#include "all_cases/all_cases.h" |
|
||||
#include "short_code/short_code.h" |
|
||||
#include "common_code/common_code.h" |
|
||||
|
|
||||
using klotski::codec::RawCode; |
|
||||
using klotski::codec::ShortCode; |
|
||||
using klotski::codec::CommonCode; |
|
||||
|
|
||||
/// Build all valid CommonCodes.
|
|
||||
std::vector<uint64_t> all_common_codes(); |
|
||||
|
|
||||
// ----------------------------------------------------------------------------------------- //
|
|
||||
|
|
||||
/// Capture ostream output as string.
|
|
||||
template <typename T> |
|
||||
std::string ostream_capture(T obj) { |
|
||||
std::ostringstream out; |
|
||||
out << obj; // ostream capture
|
|
||||
return out.str(); |
|
||||
} |
|
||||
|
|
||||
#define EXPECT_OSTREAM(obj, expect) EXPECT_EQ(ostream_capture(obj), expect) |
|
||||
|
|
||||
// ----------------------------------------------------------------------------------------- //
|
|
||||
|
|
||||
/// Spawn all valid RawCodes in parallel.
|
|
||||
void raw_code_parallel(std::function<void(std::span<RawCode>)> &&func); |
|
||||
|
|
||||
/// Spawn all valid ShortCodes in parallel.
|
|
||||
void short_code_parallel(std::function<void(std::span<ShortCode>)> &&func); |
|
||||
|
|
||||
/// Spawn all valid CommonCodes in parallel.
|
|
||||
void common_code_parallel(std::function<void(std::span<CommonCode>)> &&func); |
|
||||
|
|
||||
#define CODE_PARALLEL(Type, type, impl) \ |
|
||||
type##_code_parallel([](std::span<Type##Code> codes) { \ |
|
||||
for (auto code : codes) {impl} \ |
|
||||
}) |
|
||||
|
|
||||
#define RAW_CODE_PARALLEL(impl) CODE_PARALLEL(Raw, raw, impl) |
|
||||
#define SHORT_CODE_PARALLEL(impl) CODE_PARALLEL(Short, short, impl) |
|
||||
#define COMMON_CODE_PARALLEL(impl) CODE_PARALLEL(Common, common, impl) |
|
||||
|
|
||||
// ----------------------------------------------------------------------------------------- //
|
|
||||
|
|
||||
/// Calculate multiple ranges separately and combine the results.
|
|
||||
template<typename T, typename F> |
|
||||
requires std::is_integral_v<T> && std::is_invocable_v<F, T, T> |
|
||||
auto parallel_spawn(T limit, F &&func) -> std::invoke_result_t<F, T, T> { |
|
||||
BS::thread_pool pool; |
|
||||
std::invoke_result_t<F, T, T> result; |
|
||||
for (auto &&future : pool.submit_blocks((T)0, limit, func, 0x1000)) { |
|
||||
const auto data = future.get(); |
|
||||
result.insert(result.end(), std::begin(data), std::end(data)); // combine sections
|
|
||||
} |
|
||||
pool.wait(); |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
// ----------------------------------------------------------------------------------------- //
|
|
@ -0,0 +1,18 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <string> |
||||
|
#include <gtest/gtest.h> |
||||
|
|
||||
|
// ----------------------------------------------------------------------------------------- //
|
||||
|
|
||||
|
/// Capture ostream output as string.
|
||||
|
template <typename T> |
||||
|
std::string ostream_capture(T obj) { |
||||
|
std::ostringstream out; |
||||
|
out << obj; // ostream capture
|
||||
|
return out.str(); |
||||
|
} |
||||
|
|
||||
|
#define EXPECT_OSTREAM(obj, expect) EXPECT_EQ(ostream_capture(obj), expect) |
||||
|
|
||||
|
// ----------------------------------------------------------------------------------------- //
|
@ -0,0 +1,20 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <BS_thread_pool.hpp> |
||||
|
|
||||
|
namespace helper { |
||||
|
|
||||
|
template<typename T, typename F> |
||||
|
requires std::is_integral_v<T> && std::is_invocable_v<F, T, T> |
||||
|
auto scope_parallel(T limit, F &&func) -> std::invoke_result_t<F, T, T> { |
||||
|
BS::thread_pool pool; |
||||
|
std::invoke_result_t<F, T, T> result; |
||||
|
for (auto &&future : pool.submit_blocks((T)0, limit, func, 0x1000)) { |
||||
|
const auto data = future.get(); |
||||
|
result.insert(result.end(), std::begin(data), std::end(data)); // combine sections |
||||
|
} |
||||
|
pool.wait(); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
} // namespace helper |
@ -0,0 +1,3 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
// TODO: mirror convert of RawCode
|
Loading…
Reference in new issue