mirror of https://github.com/dnomd343/klotski.git
Dnomd343
3 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