mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-06-21 18:17:03 +08:00
feat(world): add dynamic thread pool resizing
This commit is contained in:
@@ -26,7 +26,7 @@ constexpr float DEFAULT_G = 22.5f;
|
|||||||
constexpr int SIZE_X = CHUNK_SIZE;
|
constexpr int SIZE_X = CHUNK_SIZE;
|
||||||
constexpr int SIZE_Y = WORLD_SIZE_Y;
|
constexpr int SIZE_Y = WORLD_SIZE_Y;
|
||||||
constexpr int SIZE_Z = CHUNK_SIZE;
|
constexpr int SIZE_Z = CHUNK_SIZE;
|
||||||
|
constexpr int RESERVED_THREADS = 3;
|
||||||
constexpr ChunkPos CHUNK_DIR[]{{1, 0}, {-1, 0}, {0, 1}, {0, -1},
|
constexpr ChunkPos CHUNK_DIR[]{{1, 0}, {-1, 0}, {0, 1}, {0, -1},
|
||||||
{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
|
{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ private:
|
|||||||
|
|
||||||
std::thread m_gen_thread;
|
std::thread m_gen_thread;
|
||||||
std::thread m_server_thread;
|
std::thread m_server_thread;
|
||||||
std::unique_ptr<ThreadPool> m_gen_thread_pool;
|
std::atomic<std::shared_ptr<ThreadPool>> m_gen_thread_pool;
|
||||||
std::stop_source m_server_stop_source;
|
std::stop_source m_server_stop_source;
|
||||||
|
|
||||||
std::atomic<int> m_per_tick_time = DEFAULT_PER_TICK_TIME; // ms
|
std::atomic<int> m_per_tick_time = DEFAULT_PER_TICK_TIME; // ms
|
||||||
@@ -159,6 +159,8 @@ public:
|
|||||||
|
|
||||||
bool is_tick_running() const;
|
bool is_tick_running() const;
|
||||||
void tick_running(bool run);
|
void tick_running(bool run);
|
||||||
|
|
||||||
|
void change_pool_threads(int threads);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
|
|||||||
@@ -43,20 +43,7 @@ public:
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~ThreadPool() {
|
~ThreadPool() { stop(); }
|
||||||
m_stopping = true;
|
|
||||||
for (auto& w : m_workers) {
|
|
||||||
w.request_stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_cv.notify_all();
|
|
||||||
|
|
||||||
for (auto& w : m_workers) {
|
|
||||||
if (w.joinable()) {
|
|
||||||
w.join();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template <typename F> auto enqueue(F&& f) {
|
template <typename F> auto enqueue(F&& f) {
|
||||||
|
|
||||||
using R = std::invoke_result_t<F>;
|
using R = std::invoke_result_t<F>;
|
||||||
@@ -74,6 +61,20 @@ public:
|
|||||||
m_cv.notify_one();
|
m_cv.notify_one();
|
||||||
return fut;
|
return fut;
|
||||||
}
|
}
|
||||||
|
void stop() {
|
||||||
|
m_stopping = true;
|
||||||
|
for (auto& w : m_workers) {
|
||||||
|
w.request_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cv.notify_all();
|
||||||
|
|
||||||
|
for (auto& w : m_workers) {
|
||||||
|
if (w.joinable()) {
|
||||||
|
w.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
size_t thread_sum() const { return m_thread_sum.load(); }
|
size_t thread_sum() const { return m_thread_sum.load(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,11 @@ World::~World() {
|
|||||||
stop_gen_thread();
|
stop_gen_thread();
|
||||||
stop_server_thread();
|
stop_server_thread();
|
||||||
wait_all_chunk_tasks();
|
wait_all_chunk_tasks();
|
||||||
m_gen_thread_pool.reset();
|
auto pool_ptr = m_gen_thread_pool.load();
|
||||||
|
if (pool_ptr) {
|
||||||
|
pool_ptr->stop();
|
||||||
|
}
|
||||||
|
m_gen_thread_pool.store(nullptr);
|
||||||
|
|
||||||
m_chunks.clear();
|
m_chunks.clear();
|
||||||
{
|
{
|
||||||
@@ -86,10 +90,7 @@ void World::init_world() {
|
|||||||
m_river_worm.init(ChunkGenerator::seed());
|
m_river_worm.init(ChunkGenerator::seed());
|
||||||
m_chunks.reserve(MAX_DISTANCE * MAX_DISTANCE * 4);
|
m_chunks.reserve(MAX_DISTANCE * MAX_DISTANCE * 4);
|
||||||
int max_thread = std::thread::hardware_concurrency();
|
int max_thread = std::thread::hardware_concurrency();
|
||||||
int used_thread = std::max(max_thread - 3, 1);
|
change_pool_threads(max_thread - RESERVED_THREADS);
|
||||||
Logger::info("Max Support Thread is {}, use {} threads to gen", max_thread,
|
|
||||||
used_thread);
|
|
||||||
m_gen_thread_pool = std::make_unique<ThreadPool>(used_thread);
|
|
||||||
|
|
||||||
auto t1 = std::chrono::system_clock::now();
|
auto t1 = std::chrono::system_clock::now();
|
||||||
|
|
||||||
@@ -170,8 +171,12 @@ void World::gen_chunks_internal() {
|
|||||||
{
|
{
|
||||||
std::scoped_lock lock{m_cave_carcer.path_mutex(),
|
std::scoped_lock lock{m_cave_carcer.path_mutex(),
|
||||||
m_river_worm.paths_mutex()};
|
m_river_worm.paths_mutex()};
|
||||||
parallel_do(*m_gen_thread_pool, temp_neighbor.begin(),
|
auto pool_ptr = m_gen_thread_pool.load();
|
||||||
temp_neighbor.end(), m_gen_thread_pool->thread_sum(),
|
if (!pool_ptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parallel_do(*pool_ptr, temp_neighbor.begin(), temp_neighbor.end(),
|
||||||
|
pool_ptr->thread_sum(),
|
||||||
[this](std::pair<ChunkPos, Chunk>& new_chunk) {
|
[this](std::pair<ChunkPos, Chunk>& new_chunk) {
|
||||||
auto& [pos, chunk] = new_chunk;
|
auto& [pos, chunk] = new_chunk;
|
||||||
chunk.gen_phase_one();
|
chunk.gen_phase_one();
|
||||||
@@ -251,10 +256,14 @@ void World::sync_and_collect_missing_chunks(
|
|||||||
|
|
||||||
void World::submit_new_chunks() {
|
void World::submit_new_chunks() {
|
||||||
std::lock_guard lock(m_new_chunk_mutex);
|
std::lock_guard lock(m_new_chunk_mutex);
|
||||||
|
auto pool_ptr = m_gen_thread_pool.load();
|
||||||
|
if (!pool_ptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (auto& [pos, task] : new_chunks) {
|
for (auto& [pos, task] : new_chunks) {
|
||||||
if (!task.future.valid()) {
|
if (!task.future.valid()) {
|
||||||
task.future = m_gen_thread_pool->enqueue(
|
task.future =
|
||||||
[&task]() { task.chunk.gen_chunk(); });
|
pool_ptr->enqueue([&task]() { task.chunk.gen_chunk(); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -648,4 +657,13 @@ void World::per_tick_time(int ms) { m_per_tick_time = ms; }
|
|||||||
|
|
||||||
bool World::is_tick_running() const { return m_tick_running.load(); }
|
bool World::is_tick_running() const { return m_tick_running.load(); }
|
||||||
void World::tick_running(bool run) { m_tick_running = run; }
|
void World::tick_running(bool run) { m_tick_running = run; }
|
||||||
|
void World::change_pool_threads(int threads) {
|
||||||
|
int max_thread = std::thread::hardware_concurrency();
|
||||||
|
if (max_thread < 1) {
|
||||||
|
max_thread = 4;
|
||||||
|
}
|
||||||
|
int used_thread = std::clamp(threads, 1, max_thread);
|
||||||
|
Logger::info("Create New Thread Pool Use {} Threads", used_thread);
|
||||||
|
m_gen_thread_pool.store(std::make_shared<ThreadPool>(used_thread));
|
||||||
|
}
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
Reference in New Issue
Block a user