From 8be03c62307224e45d9b3afd94cccebe94f9b995 Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Wed, 12 Jun 2024 07:50:19 +0200 Subject: [PATCH] rename TT funcs to TT_xxx() --- src/chessdefs.h | 6 +- src/hash.c | 144 +++++++++++++++++++++++++++++++++++++++++---- src/hash.h | 38 ++++++++++-- src/init.c | 2 +- test/movedo-test.c | 2 +- 5 files changed, 171 insertions(+), 21 deletions(-) diff --git a/src/chessdefs.h b/src/chessdefs.h index c531ed4..03658d5 100644 --- a/src/chessdefs.h +++ b/src/chessdefs.h @@ -16,8 +16,8 @@ #include "brlib.h" /* brlib types */ -#define ONE 1ull -#define U64(const_u64) const_u64##ULL +#define ONE 1ul +#define U64(const_u64) const_u64##UL #define BIT(i) ( (u64) (ONE << (i)) ) #define BOARDSIZE (8*8) @@ -176,7 +176,7 @@ s64 clock_elapsed_μs(mclock_t *clock); s64 clock_elapsed_ms(mclock_t *clock); double clock_elapsed_sec(mclock_t *clock); -#define RAND_SEED_DEFAULT U64(1) +#define RAND_SEED_DEFAULT U64(0xb0d1ccea) void rand_init(u64 seed); u64 rand64(void); diff --git a/src/hash.c b/src/hash.c index 5f3756e..e67cb70 100644 --- a/src/hash.c +++ b/src/hash.c @@ -12,6 +12,7 @@ */ #include +#include #include #include @@ -99,9 +100,17 @@ hkey_t zobrist_calc(pos_t *pos) * @return: True if Zobrist key is OK. */ #ifdef ZOBRIST_VERIFY + +#pragma push_macro("BUG_ON") /* force BUG_ON and WARN_ON */ +#pragma push_macro("WARN_ON") +#undef BUG_ON +#define BUG_ON +#undef WARN_ON +#define WARN_ON + bool zobrist_verify(pos_t *pos) { - key_t diff, key = zobrist_calc(pos); + hkey_t diff, key = zobrist_calc(pos); if (pos->key == key) return true; @@ -120,17 +129,19 @@ bool zobrist_verify(pos_t *pos) goto end; } } - for (castle_rights_t c = CASTLE_NONE; c <= CASTLE_ALL; ++c) + for (castle_rights_t c = CASTLE_NONE; c <= CASTLE_ALL; ++c) { if (diff == zobrist_castling[c]) { warn(true, "zobrist difference is castling:[%d]\n", c); goto end; } + } - for (file_t f = FILE_A; f <= FILE_H; ++f) + for (file_t f = FILE_A; f <= FILE_H; ++f) { if (diff == zobrist_ep[f]) { warn(true, "zobrist difference is ep:[%d]\n", f); goto end; } + } if (diff == zobrist_turn) { warn(true, "zobrist difference is turn\n"); goto end; @@ -138,11 +149,16 @@ bool zobrist_verify(pos_t *pos) warn(true, "zobrist diff %lx is unknown\n", diff); end: bug_on(false); + /* not reached */ + return true; } +#pragma pop_macro("WARN_ON") +#pragma pop_macro("BUG_ON") + #endif /** - * hash_create() - hashtable creation. + * tt_create() - create transposition table * @sizemb: s32 size of hash table in Mb * * Create a hash table of max @sizemb (or HASH_SIZE_MBif @sizemb <= 0) Mb size. @@ -164,7 +180,7 @@ end: * @return: hash table size in Mb. If memory allocation fails, the function does * not return. */ -int hash_create(s32 sizemb) +int tt_create(s32 sizemb) { size_t bytes, target_nbuckets; u32 nbits; @@ -185,7 +201,7 @@ int hash_create(s32 sizemb) if (hash_tt.nbits != nbits) { if (hash_tt.nbits) - hash_delete(); + tt_delete(); hash_tt.nbits = nbits; @@ -207,17 +223,17 @@ int hash_create(s32 sizemb) // printf("unchanged (cleared)\n"); //} /* attention - may fail ! */ - hash_clear(); + tt_clear(); return hash_tt.nbits; } /** - * hash_clear() - clear hashtable data. + * tt_clear() - clear transposition table * * Reset hashtable entries (if available) and statistic information. */ -void hash_clear() +void tt_clear() { if (hash_tt.keys) memset(hash_tt.keys, 0, hash_tt.bytes); @@ -228,13 +244,119 @@ void hash_clear() } /** - * hash_delete() - delete hashtable data. + * tt_delete() - delete transposition table * * free hashtable data. */ -void hash_delete() +void tt_delete() { if (hash_tt.keys) safe_free(hash_tt.keys); memset(&hash_tt, 0, sizeof(hash_tt)); } + +/** + * tt_probe() - probe tt for an entry + * + * + */ +hentry_t *tt_probe(hkey_t key) +{ + bucket_t *bucket; + hentry_t *entry; + int i; + + bug_on(!hash_tt.keys); + bucket = hash_tt.keys + (key & hash_tt.mask); + + /* find key in buckets */ + for (i = 0; i < NBUCKETS; ++i) { + entry = bucket->entry + i; + if (key == entry->key) + break; + } + if (i < NBUCKETS) + return entry; + return NULL; +} + +/** + * tt_probe_perft() - probe tt for an entry (perft version) + * @key: Zobrist (hkey_t) key + * @depth: depth from search root + * + * Search transposition for @key entry with @depth depth. + * + * @return: @hentry_t address is found, TT_MISS otherwise. + */ +hentry_t *tt_probe_perft(const hkey_t key, const u16 depth) +{ + bucket_t *bucket; + hentry_t *entry; + int i; + + bug_on(!hash_tt.keys); + bucket = hash_tt.keys + (key & hash_tt.mask); + + /* find key in buckets */ + for (i = 0; i < NBUCKETS; ++i) { + entry = bucket->entry + i; + if (key == entry->key && HASH_PERFT_DEPTH(entry->data) == depth) { + printf("tt hit: key=%lx bucket=%lu entry=%d!\n", + key, bucket - hash_tt.keys, i); + break; + } + } + if (i < NBUCKETS) + return entry; + printf("tt miss: key=%lx bucket=%lu\n", + key, bucket - hash_tt.keys); + return TT_MISS; +} + +/** + * tt_store_perft() - store a transposition table entry (perft version) + * @key: Zobrist (hkey_t) key + * @depth: depth from search root + * @nodes: value to store + * + */ +hentry_t *tt_store_perft(const hkey_t key, const u16 depth, const u64 nodes) +{ + bucket_t *bucket; + hentry_t *entry; + int replace = -1, i; + // uint mindepth = 0; + u64 data = HASH_PERFT(depth, nodes); + printf("tt_store: key=%lx data=%lx depth=%d=%d nodes=%lu=%lu\n", + key, data, depth, HASH_PERFT_DEPTH(data), nodes, HASH_PERFT_VAL(data)); + bug_on(!hash_tt.keys); + bucket = hash_tt.keys + (key & hash_tt.mask); + + /* find key in buckets */ + for (i = 0; i < NBUCKETS; ++i) { + entry = bucket->entry + i; + if (!entry->key) { + replace = i; + break; + } + /* + * else { + * /\* we replace hash if we are higher in tree *\/ + * if (key == entry->key && HASH_PERFT_DEPTH(entry->data) > mindepth) { + * mindepth = HASH_PERFT_DEPTH(entry->data); + * replace = i; + * } + * } + */ + } + if (replace >= 0) { + printf("replacing key=%lx=%lx bucket=%lu idx=%d val=%lu\n", + key, entry->key, bucket - hash_tt.keys, replace, nodes); + entry = bucket->entry + replace; + entry->key = key; + entry->data = data; + return entry; + } + return NULL; +} diff --git a/src/hash.h b/src/hash.h index a270c47..fb5ecaf 100644 --- a/src/hash.h +++ b/src/hash.h @@ -14,7 +14,7 @@ #ifndef HASH_H #define HASH_H -#include +#include #include "chessdefs.h" @@ -24,6 +24,8 @@ #define HASH_SIZE_MIN 4 #define HASH_SIZE_MAX 32768 /* 32Gb */ +#define TT_MISS NULL + typedef u64 hkey_t; /* cannot use typedef for key_t */ /** @@ -46,8 +48,18 @@ typedef struct { }; } hentry_t; +/* hentry perft data: + * 0-47: perft value + * 48-63: depth + */ +#define HASH_PERFT_MASK U64(0xffffffffffff) +#define HASH_PERFT(depth, val) ((((u64) depth) << 48) | ((val) & HASH_PERFT_MASK)) +#define HASH_PERFT_VAL(data) ((data) & HASH_PERFT_MASK) +#define HASH_PERFT_DEPTH(data) ((u16)((data) >> 48)) + + typedef struct { - hentry_t buckets[NBUCKETS]; + hentry_t entry[NBUCKETS]; } bucket_t; typedef struct { @@ -97,8 +109,24 @@ bool zobrist_verify(pos_t *pos); #define zobrist_verify(p) true #endif -int hash_create(int Mb); -void hash_clear(void); -void hash_delete(void); +/** + * tt_prefetch() - prefetch hash table entry + * @hash: u64 key + * + * Prefetch memory for @key. + */ +static inline void tt_prefetch(hkey_t key) +{ + bug_on(!hash_tt.keys); + __builtin_prefetch(hash_tt.keys + (key & hash_tt.mask)); +} + +int tt_create(int Mb); +void tt_clear(void); +void tt_delete(void); + +hentry_t *tt_probe(hkey_t key); +hentry_t *tt_probe_perft(const hkey_t key, const u16 depth); +hentry_t *tt_store_perft(const hkey_t key, const u16 depth, const u64 nodes); #endif /* HASH_H */ diff --git a/src/init.c b/src/init.c index 175594e..f62df6b 100644 --- a/src/init.c +++ b/src/init.c @@ -37,6 +37,6 @@ void init_all(void) /* zobrist tables & default tt hashtable */ zobrist_init(); - hash_create(HASH_SIZE_DEFAULT); + tt_create(HASH_SIZE_DEFAULT); } diff --git a/test/movedo-test.c b/test/movedo-test.c index 25fa11a..897db58 100644 --- a/test/movedo-test.c +++ b/test/movedo-test.c @@ -59,7 +59,7 @@ int main(int __unused ac, __unused char**av) //fflush(stdout); if (!pos_ok(pos, false)) { printf("*** fen %d [%s] move %d [%s] invalid position after move_do\n", - test_line, fen, j, move_str(movebuf, *move, 0)); + test_line, fen, j, move_to_str(movebuf, *move, 0)); exit(0); }