stellar

Stellar - UCI Chess engine written in C++20
git clone git://git.dimitrijedobrota.com/stellar.git
Log | Files | Refs | README | LICENSE

commit 1ecc793cac68e9c8768895ee4d358cb6b3ce1c31
parent eb0c42bd2bf2f52666067bf7f1fad41dfe4948a9
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Fri, 28 Jul 2023 15:28:19 +0200

Add Multithreaded PERFT

Diffstat:
Msrc/engine.c | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 92 insertions(+), 27 deletions(-)

diff --git a/src/engine.c b/src/engine.c @@ -826,9 +826,9 @@ void uci_loop(void) { struct MoveList_T moveList[10]; long nodes; -void perft_driver(CBoard_T board, int depth) { +void perft_driver(CBoard_T board, struct MoveList_T *moveList, int depth, unsigned long long *nodes) { if (depth == 0) { - nodes++; + (*nodes)++; return; } @@ -839,8 +839,9 @@ void perft_driver(CBoard_T board, int depth) { CBoard_copy(board, copy); if (!Move_make(MoveList_move(list, i), copy, 0)) continue; - perft_driver(copy, depth - 1); + perft_driver(copy, moveList, depth - 1, nodes); } + MoveList_reset(list); CBoard_free(&copy); } @@ -856,24 +857,96 @@ void perft_test(CBoard_T board, int depth) { for (int i = 0; i < MoveList_size(list); i++) { CBoard_copy(board, copy); Move move = MoveList_move(list, i); - if (!Move_make(MoveList_move(list, i), copy, 0)) - continue; - long cummulative_nodes = nodes; - perft_driver(copy, depth - 1); - long old_nodes = nodes - cummulative_nodes; - printf("%s%s: %ld\n", square_to_coordinates[Move_source(move)], - square_to_coordinates[Move_target(move)], old_nodes); + if (!Move_make(MoveList_move(list, i), copy, 0)) continue; + unsigned long long node = 0; + perft_driver(copy, moveList, depth - 1, &node); + printf("%s%s: %llu\n", square_to_coordinates[Move_source(move)], + square_to_coordinates[Move_target(move)], node); + nodes+=node; } MoveList_reset(list); CBoard_free(&copy); printf("\nNodes searched: %ld\n\n", nodes); - return; printf("\n Depth: %d\n", depth); printf(" Nodes: %ld\n", nodes); printf(" Time: %ld\n\n", get_time_ms() - start); } + #include <semaphore.h> + #include <pthread.h> + +typedef struct perf_shared perf_shared; +struct perf_shared { + CBoard_T board; + MoveList_T list; + int depth; + sem_t* mutex; + int* index; + sem_t* finish; + unsigned long long *total; +}; + +void* perft_thread(void *arg) { + perf_shared *shared = (perf_shared *)arg; + CBoard_T board = CBoard_new(); + unsigned long long node_count = 0; + + struct MoveList_T moveList[10]; + + while(1) { + sem_wait(shared->mutex); + *shared->total += node_count; + if(*shared->index >= MoveList_size(shared->list)) { + sem_post(shared->mutex); + break; + } + Move move = MoveList_move(shared->list, (*shared->index)++); + sem_post(shared->mutex); + + CBoard_copy(shared->board, board); + if(!Move_make(move, board, 0)) continue; + + node_count = 0; + perft_driver(board, moveList, shared->depth, &node_count); + printf("%s%s: %llu\n", square_to_coordinates[Move_source(move)], + square_to_coordinates[Move_target(move)], node_count); + } + CBoard_free(&board); + sem_post(shared->finish); + return NULL; +} + +void perft_test_threaded(CBoard_T board, int depth) { + MoveList_T list = MoveList_generate(NULL, board); + int size = 8; + + unsigned long long total = 0; + perf_shared shared[size]; + pthread_t threads[size]; + sem_t mutex, finish; + + + int index = 0; + sem_init(&mutex, 0, 1); + sem_init(&finish, 0, 0); + for(int i=0; i<size; i++) { + shared[i].board = board; + shared[i].list = list; + shared[i].depth = depth - 1; + shared[i].mutex = &mutex; + shared[i].index = &index; + shared[i].finish = &finish; + shared[i].total = &total; + pthread_create(threads + i, NULL, perft_thread, (void *)(shared + i)); + } + + for(int i=0; i<size; i++) sem_wait(&finish); + MoveList_free(&list); + + printf("Nodes processed: %llu\n", total); +} + /* MAIN */ void init_all() { @@ -881,23 +954,15 @@ void init_all() { init_sliders_attacks(); } + int main(void) { init_all(); - int debug = 1; - if (debug) { - CBoard_T board = NULL; - MoveList_T list = NULL; - Instruction_T inst = NULL; - (void)inst; - (void)list; - - board = CBoard_fromFEN(board, tricky_position); - CBoard_print(board); - /* MoveList_print(MoveList_generate(NULL, board)); */ - perft_test(board, 5); - /* search_position(board, 5); */ - CBoard_free(&board); - } else - uci_loop(); + + CBoard_T board = NULL; + board = CBoard_fromFEN(board, start_position); + CBoard_print(board); + //perft_test(board, 7); + perft_test_threaded(board, 7); + CBoard_free(&board); return 0; }