diff --git a/src/Makefile b/src/Makefile index 0b2f99ed..f2c4d269 100644 --- a/src/Makefile +++ b/src/Makefile @@ -59,8 +59,7 @@ SRCS = benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp main.cpp learn/sfen_packer.cpp \ learn/learn.cpp \ learn/gensfen.cpp \ - learn/convert.cpp \ - learn/multi_think.cpp + learn/convert.cpp OBJS = $(notdir $(SRCS:.cpp=.o)) diff --git a/src/learn/convert.cpp b/src/learn/convert.cpp index a7528b02..dfd30509 100644 --- a/src/learn/convert.cpp +++ b/src/learn/convert.cpp @@ -1,7 +1,5 @@ #include "convert.h" -#include "multi_think.h" - #include "uci.h" #include "misc.h" #include "thread.h" diff --git a/src/learn/multi_think.cpp b/src/learn/multi_think.cpp deleted file mode 100644 index bf1ab29b..00000000 --- a/src/learn/multi_think.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "multi_think.h" - -#include "tt.h" -#include "uci.h" -#include "types.h" -#include "search.h" - -#include "nnue/evaluate_nnue.h" - -#include - -void MultiThink::go_think() -{ - // Call the derived class's init(). - init(); - - // The loop upper limit is set with set_loop_max(). - loop_count = 0; - done_count = 0; - - // Create threads as many as Options["Threads"] and start thinking. - std::vector threads; - auto thread_num = (size_t)Options["Threads"]; - - // Secure end flag of worker thread - threads_finished=0; - - // start worker thread - for (size_t i = 0; i < thread_num; ++i) - { - threads.push_back(std::thread([i, this] - { - // exhaust all processor threads. - WinProcGroup::bindThisThread(i); - - // execute the overridden process - this->thread_worker(i); - - // Set the end flag because the thread has ended - this->threads_finished++; - })); - } - - // wait for all threads to finish - // for (auto& th :threads) - // th.join(); - // If you write like, the thread will rush here while it is still working, - // During that time, callback_func() cannot be called and you cannot save. - // Therefore, you need to check the end flag yourself. - - // function to determine if all threads have finished - auto threads_done = [&]() - { - return threads_finished == thread_num; - }; - - // Call back if the callback function is set. - auto do_a_callback = [&]() - { - if (callback_func) - callback_func(); - }; - - - for (uint64_t i = 0 ; ; ) - { - // If all threads have finished, exit the loop. - if (threads_done()) - break; - - sleep(1000); - - // callback_func() is called every callback_seconds. - if (++i == callback_seconds) - { - do_a_callback(); - // Since I am returning from ↑, I reset the counter, so - // no matter how long it takes to save() etc. in do_a_callback() - // The next call will take a certain amount of time. - i = 0; - } - } - - // Last save. - std::cout << std::endl << "finalize.."; - - // do_a_callback(); - // → It should be saved by the caller, so I feel that it is not necessary here. - - // It is possible that the exit code of the thread is running but the exit code of the thread is running, so - // We need to wait for the end with join(). - for (auto& th : threads) - th.join(); - - // The file writing thread etc. are still running only when all threads are finished - // Since the work itself may not have completed, output only that all threads have finished. - std::cout << "all threads are joined." << std::endl; -} diff --git a/src/learn/multi_think.h b/src/learn/multi_think.h deleted file mode 100644 index 7e541909..00000000 --- a/src/learn/multi_think.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef _MULTI_THINK_ -#define _MULTI_THINK_ - -#include "learn.h" - -#include "misc.h" -#include "thread_win32_osx.h" - -#include -#include -#include -#include -#include -#include - - -// Learning from a game record, when making yourself think and generating a fixed track, etc. -// Helper class used when multiple threads want to call Search::think() individually. -// Derive and use this class. -struct MultiThink -{ - static constexpr std::uint64_t LOOP_COUNT_FINISHED = std::numeric_limits::max(); - - MultiThink() : prng{}, loop_count(0) { } - - MultiThink(std::uint64_t seed) : prng(seed), loop_count(0) { } - - MultiThink(const std::string& seed) : prng(seed), loop_count(0) { } - - // Call this function from the master thread, each thread will think, - // Return control when the thought ending condition is satisfied. - // Do something else. - // ・It is safe for each thread to call Learner::search(),qsearch() - // Separates the substitution table for each thread. (It will be restored after the end.) - // ・Book is not thread safe when in on the fly mode, so temporarily change this mode. - // Turn it off. - // [Requirements] - // 1) Override thread_worker() - // 2) Set the loop count with set_loop_max() - // 3) set a function to be called back periodically (if necessary) - // callback_func and callback_interval - void go_think(); - - // If there is something you want to initialize on the derived class side, override this, - // Called when initialization is completed with go_think(). - // It is better to read the fixed trace at that timing. - virtual void init() {} - - // A thread worker that is called by creating a thread when you go_think() - // Override and use this. - virtual void thread_worker(size_t thread_id) = 0; - - // Called back every callback_seconds [seconds] when go_think(). - std::function callback_func; - uint64_t callback_seconds = 600; - - // Set the number of times worker processes (calls Search::think()). - void set_loop_max(uint64_t loop_max_) { loop_max = loop_max_; } - - // Get the value set by set_loop_max(). - uint64_t get_loop_max() const { return loop_max; } - - // [ASYNC] Take the value of the loop counter and add the loop counter after taking it out. - // If the loop counter has reached loop_max, return UINT64_MAX. - // If you want to generate a phase, you must call this function at the time of generating the phase, - // Please note that the number of generated phases and the value of the counter will not match. - uint64_t get_next_loop_count() { - std::unique_lock lk(loop_mutex); - if (loop_count >= loop_max) - return LOOP_COUNT_FINISHED; - return loop_count++; - } - - // [ASYNC] For returning the processed number. Each time it is called, it returns a counter that is incremented. - uint64_t get_done_count() { - std::unique_lock lk(loop_mutex); - return ++done_count; - } - - // Mutex when worker thread accesses I/O - std::mutex io_mutex; - -protected: - // Random number generator body - AsyncPRNG prng; - -private: - // number of times worker processes (calls Search::think()) - std::atomic loop_max; - // number of times the worker has processed (calls Search::think()) - std::atomic loop_count; - // To return the number of times it has been processed. - std::atomic done_count; - - // Mutex when changing the variables in ↑ - std::mutex loop_mutex; - - // Thread end flag. - std::atomic threads_finished; -}; - -// Mechanism to process task during idle time. -// master passes the task with push_task_async() whenever you like. -// When slave executes on_idle() in its spare time, it retrieves one task and continues execution until there is no queue. -// Convenient to use when you want to write MultiThink thread worker in master-slave method. -struct TaskDispatcher -{ - typedef std::function Task; - - // slave calls this function during idle. - void on_idle(size_t thread_id) - { - Task task; - while ((task = get_task_async()) != nullptr) - task(thread_id); - - sleep(1); - } - - // Stack [ASYNC] task. - void push_task_async(Task task) - { - std::unique_lock lk(task_mutex); - tasks.push_back(task); - } - - // Allocate size array elements for task in advance. - void task_reserve(size_t size) - { - tasks.reserve(size); - } - -protected: - // set of tasks - std::vector tasks; - - // Take out one [ASYNC] task. Called from on_idle(). - Task get_task_async() - { - std::unique_lock lk(task_mutex); - if (tasks.size() == 0) - return nullptr; - Task task = *tasks.rbegin(); - tasks.pop_back(); - return task; - } - - // a mutex for accessing tasks - std::mutex task_mutex; -}; - -#endif