diff options
| -rw-r--r-- | src/GNUmakefile | 6 | ||||
| -rwxr-xr-x | src/chess.h | 55 | ||||
| -rwxr-xr-x | src/eval.c | 44 | ||||
| -rw-r--r-- | src/evalhash.c | 173 | ||||
| -rwxr-xr-x | src/main.c | 7 | ||||
| -rwxr-xr-x | src/root.c | 2 | ||||
| -rwxr-xr-x | src/search.c | 3 | ||||
| -rwxr-xr-x | src/split.c | 4 | ||||
| -rwxr-xr-x | src/testeval.c | 1 |
9 files changed, 21 insertions, 274 deletions
diff --git a/src/GNUmakefile b/src/GNUmakefile index dbb74cf..ef80e95 100644 --- a/src/GNUmakefile +++ b/src/GNUmakefile @@ -4,7 +4,6 @@ # TEST=1: include self-test code in the binary produced # ASM=1: create assembly code, does not link final binary # EVAL_DUMP=1: make a version that can dump eval breakdowns -# EVAL_HASH=1: hash eval scores # EVAL_TIME=1: make a version that counts cycles spent in eval # PERF_COUNTERS=1: make version with perf counters enabled # BOUNDS_CHECKING=1: make version with bounds checking enabled @@ -91,14 +90,11 @@ ifdef CROUTINES endif ifdef EVERYTHING -PROFILE += -DEVAL_DUMP -DEVAL_HASH -DEVAL_TIME -DPERF_COUNTERS -DMP -DSMP -DTEST_NULL -DDUMP_TREE -fbounds-checking +PROFILE += -DEVAL_DUMP -DEVAL_TIME -DPERF_COUNTERS -DMP -DSMP -DTEST_NULL -DDUMP_TREE -fbounds-checking else ifdef EVAL_DUMP PROFILE += -DEVAL_DUMP endif -ifdef EVAL_HASH -PROFILE += -DEVAL_HASH -endif ifdef EVAL_TIME PROFILE += -DEVAL_TIME endif diff --git a/src/chess.h b/src/chess.h index 9689189..630f090 100755 --- a/src/chess.h +++ b/src/chess.h @@ -907,7 +907,6 @@ typedef struct _SPLIT_INFO INT iPositionExtend; // positional extension SCORE iAlpha; // original alpha at split SCORE iBeta; // beta at split - ULONG uSplitPositional; // pos->uPositional at split CUMULATIVE_SEARCH_FLAGS sSearchFlags; // flags at split time // output from the split node @@ -953,38 +952,6 @@ typedef struct _PLY_INFO } PLY_INFO; -// #define EVAL_HASH -#ifdef EVAL_HASH -#define EVAL_HASH_TABLE_SIZE (2097152) // 32Mb (per thread) - -// -// bvFlags values for EVAL_HASH_ENTRY. EXACT means iEval is the real, -// fully-computed static eval. UPPER/LOWER mean the entry came from a -// lazy-eval early exit: iEval is the (uncorrected) partial score that -// would be returned and iBound is the proven bound on the true, fully -// computed eval (true score <= iBound for UPPER, true score >= iBound -// for LOWER). Because the bound is a fact about the position -- not -// about whatever alpha/beta window triggered the lazy exit -- it can -// be reused by a later probe with a different window, as long as that -// window is still resolved by the bound (mirrors HASH_FLAG_UPPER / -// HASH_FLAG_LOWER in the main hash table). -// -#define EVAL_HASH_EXACT 0x1 -#define EVAL_HASH_UPPER 0x2 -#define EVAL_HASH_LOWER 0x4 - -typedef struct _EVAL_HASH_ENTRY -{ - UINT64 u64Key; - SCORE iEval; - SCORE iBound; - UCHAR bvFlags; - ULONG uPositional; - COOR cTrapped[2]; - -} EVAL_HASH_ENTRY; -#endif - #define PAWN_HASH_TABLE_SIZE (131072) // 5.5Mb (per thread) typedef struct _PAWN_HASH_ENTRY { @@ -1014,7 +981,6 @@ PAWN_HASH_ENTRY; typedef struct _SEARCHER_THREAD_CONTEXT { ULONG uPly; // its distance from root - ULONG uPositional; // positional component of score POSITION sPosition; // the board MOVE_STACK sMoveStack; // the move stack CUMULATIVE_SEARCH_FLAGS sSearchFlags; @@ -1035,9 +1001,6 @@ typedef struct _SEARCHER_THREAD_CONTEXT SCORE iRootScore; ULONG uRootDepth; PAWN_HASH_ENTRY rgPawnHash[PAWN_HASH_TABLE_SIZE]; -#ifdef EVAL_HASH - EVAL_HASH_ENTRY rgEvalHash[EVAL_HASH_TABLE_SIZE]; -#endif CHAR szLastPV[SMALL_STRING_LEN_CHAR]; } SEARCHER_THREAD_CONTEXT; @@ -1060,7 +1023,6 @@ SEARCHER_THREAD_CONTEXT; typedef struct _LIGHTWEIGHT_SEARCHER_CONTEXT { ULONG uPly; - ULONG uPositional; POSITION sPosition; MOVE_STACK sMoveStack; CUMULATIVE_SEARCH_FLAGS sSearchFlags; @@ -2309,7 +2271,7 @@ IsDraw(SEARCHER_THREAD_CONTEXT *ctx); // search.c // #define QPLIES_OF_NON_CAPTURE_CHECKS (2) -#define FUTILITY_BASE_MARGIN (50) // + ctx->uPositional (min 100) +#define FUTILITY_BASE_MARGIN (50) #define DO_IID #define IID_R_FACTOR (TWO_PLY + HALF_PLY) @@ -3029,25 +2991,10 @@ RecognLookup(SEARCHER_THREAD_CONTEXT *ctx, SCORE *piScore, FLAG fProbeEGTB); -#ifdef EVAL_HASH -void -ClearEvalHashStats(void); - -void -ReportEvalHashStats(void); - -SCORE -ProbeEvalHash(SEARCHER_THREAD_CONTEXT *ctx, SCORE iAlpha, SCORE iBeta); - SCORE GetRoughEvalScore(IN SEARCHER_THREAD_CONTEXT *ctx, IN SCORE iAlpha, IN SCORE iBeta, IN FLAG fUseHash); -void -StoreEvalHash(SEARCHER_THREAD_CONTEXT *ctx, SCORE iScore, SCORE iBound, - UCHAR bvFlags); -#endif // EVAL_HASH - #endif // CHESS @@ -5561,18 +5561,6 @@ Return value: pos->uMinMobility[BLACK] = pos->uMinMobility[WHITE] = 100; pos->cTrapped[BLACK] = pos->cTrapped[WHITE] = ILLEGAL_COOR; -#ifdef EVAL_HASH - // - // Check the eval hash - // - iScoreForSideToMove = ProbeEvalHash(ctx, iAlpha, iBeta); - if (iScoreForSideToMove != INVALID_SCORE) - { - INC(ctx->sCounters.tree.u64EvalHashHits); - goto end; - } -#endif - pos->iScore[BLACK] = (pos->uPawnMaterial[BLACK] + pos->uNonPawnMaterial[BLACK]); pos->iScore[WHITE] = @@ -5690,16 +5678,6 @@ Return value: { *piPositional = iAlphaMargin; } -#ifdef EVAL_HASH - // - // The true eval can't reach iAlpha; that's a fact about - // the position (not this particular window), so remember - // it as a proven upper bound for reuse by later probes. - // - StoreEvalHash(ctx, iScoreForSideToMove, - (SCORE)(iScoreForSideToMove + iAlphaMargin), - EVAL_HASH_UPPER); -#endif goto end; } else if (iScoreForSideToMove - iBetaMargin >= iBeta) @@ -5709,11 +5687,6 @@ Return value: { *piPositional = iBetaMargin; } -#ifdef EVAL_HASH - StoreEvalHash(ctx, iScoreForSideToMove, - (SCORE)(iScoreForSideToMove - iBetaMargin), - EVAL_HASH_LOWER); -#endif goto end; } } @@ -6090,15 +6063,6 @@ Return value: { *piPositional = iAlphaMargin; } - if ((ULONG)iAlphaMargin > ctx->uPositional) - { - ctx->uPositional = (ULONG)iAlphaMargin; - } - else - { - ctx->uPositional -= (ctx->uPositional - (ULONG)iAlphaMargin) / 4; - ctx->uPositional = MAXU(ctx->uPositional, VALUE_PAWN); - } g_Options.iLastEvalScore = iScoreForSideToMove; #ifdef EVAL_TIME @@ -6107,13 +6071,6 @@ Return value: #endif INC(ctx->sCounters.tree.u64FullEvals); -#ifdef EVAL_HASH - // - // Store in eval hash. - // - StoreEvalHash(ctx, iScoreForSideToMove, 0, EVAL_HASH_EXACT); -#endif - end: ASSERT(IS_VALID_SCORE(iScoreForSideToMove)); ASSERT((iScoreForSideToMove > -NMATE) && @@ -6122,6 +6079,5 @@ Return value: ASSERT(abs(ctx->sPlyInfo[ctx->uPly].iKingScore[WHITE]) < 700); ASSERT(ctx->sPlyInfo[ctx->uPly].uMinMobility[BLACK] <= 100); ASSERT(ctx->sPlyInfo[ctx->uPly].uMinMobility[WHITE] <= 100); - ASSERT((ctx->uPositional < 2500) && (ctx->uPositional >= VALUE_PAWN)); return(iScoreForSideToMove); } diff --git a/src/evalhash.c b/src/evalhash.c index fc29b88..4df6e23 100644 --- a/src/evalhash.c +++ b/src/evalhash.c @@ -8,7 +8,11 @@ Module Name: Abstract: - Evaluation score hashing code. + Rough (mid-tree) eval estimation. Used to hold the eval-score + hashing code (EVAL_HASH) too; that subsystem was cut for good + (measured as slow as or slower than just computing eval) and is + not coming back in this form, so this file is now just + GetRoughEvalScore(). Author: @@ -20,8 +24,6 @@ Revision History: #include "chess.h" -extern ULONG g_uIterateDepth; - SCORE GetRoughEvalScore(IN OUT SEARCHER_THREAD_CONTEXT *ctx, IN SCORE iAlpha, @@ -34,23 +36,22 @@ Routine description: This is meant to be the "one place" that code looks when it needs to get an idea of the estimated evaluation of a position (in mid tree, not at the leaves... at the leaves just call Eval directly). - - The thought is that: - - 1. The top of the tree (near the root) represents very few nodes - which have big subtrees. Use the real Eval here. - - 2. Otherwise possibly probe the eval hash -- if there's a score in - it then we can return quickly. - - 3. Otherwise do a (very) rough material estimate. + + Just calls Eval() -- its own lazy-exit machinery already is the + cheap, calibrated estimate this function exists to provide, so + there's no separate "rough" estimator to maintain here. Used to + fall back to material + a stale ctx->uPositional EWMA left over + from whatever full eval last ran anywhere in the tree, fed by an + eval-hash probe (fUseHash); both are gone now (see the commit + removing ctx->uPositional and EVAL_HASH), and this is the direct + replacement. Parameters: IN OUT SEARCHER_THREAD_CONTEXT *ctx, IN SCORE iAlpha, IN SCORE iBeta, - IN FLAG fUseHash + IN FLAG fUseHash : unused, kept for call-site compatibility Return value: @@ -58,148 +59,6 @@ Return value: --*/ { - POSITION *pos = &(ctx->sPosition); - UINT64 u64Key; - ULONG u; - - if (ctx->uPly <= 4) - { - return Eval(ctx, iAlpha, iBeta, NULL); - } -#ifdef EVAL_HASH - else if ((fUseHash) || (ctx->uPly <= (g_uIterateDepth / 2))) - { - u64Key = (pos->u64PawnSig ^ pos->u64NonPawnSig); - u = (ULONG)u64Key & (EVAL_HASH_TABLE_SIZE - 1); - if (ctx->rgEvalHash[u].u64Key == u64Key) - { - switch(ctx->rgEvalHash[u].bvFlags) - { - case EVAL_HASH_EXACT: - ctx->uPositional = ctx->rgEvalHash[u].uPositional; - return(ctx->rgEvalHash[u].iEval); - case EVAL_HASH_UPPER: - if (ctx->rgEvalHash[u].iBound <= iAlpha) - { - return(ctx->rgEvalHash[u].iEval); - } - break; - case EVAL_HASH_LOWER: - if (ctx->rgEvalHash[u].iBound >= iBeta) - { - return(ctx->rgEvalHash[u].iEval); - } - break; - } - } - } -#else - (void)u64Key; - (void)u; (void)fUseHash; -#endif - return(pos->iMaterialBalance[pos->uToMove] + ctx->uPositional); -} - -#ifdef EVAL_HASH - - -SCORE -ProbeEvalHash(IN OUT SEARCHER_THREAD_CONTEXT *ctx, IN SCORE iAlpha, IN SCORE iBeta) -/*++ - -Routine description: - - Probe the eval hash; return a real score if there's a hit - otherwise return INVALID_SCORE. An EXACT entry is always usable. - An UPPER/LOWER entry (recorded from a lazy-eval early exit) is - only usable if the bound it proved still resolves the caller's - current alpha/beta window; otherwise it's treated as a miss and - the caller must actually compute something. - -Parameters: - - IN OUT SEARCHER_THREAD_CONTEXT *ctx : note that in the case - of a hit, *ctx is modified also. - IN SCORE iAlpha, IN SCORE iBeta : caller's current window - -Return value: - - SCORE - ---*/ -{ - POSITION *pos = &(ctx->sPosition); - UINT64 u64Key = (pos->u64PawnSig ^ pos->u64NonPawnSig); - ULONG u = (ULONG)u64Key & (EVAL_HASH_TABLE_SIZE - 1); - - if (ctx->rgEvalHash[u].u64Key == u64Key) - { - switch(ctx->rgEvalHash[u].bvFlags) - { - case EVAL_HASH_EXACT: - ctx->uPositional = ctx->rgEvalHash[u].uPositional; - pos->cTrapped[WHITE] = ctx->rgEvalHash[u].cTrapped[WHITE]; - pos->cTrapped[BLACK] = ctx->rgEvalHash[u].cTrapped[BLACK]; - return(ctx->rgEvalHash[u].iEval); - case EVAL_HASH_UPPER: - if (ctx->rgEvalHash[u].iBound <= iAlpha) - { - return(ctx->rgEvalHash[u].iEval); - } - break; - case EVAL_HASH_LOWER: - if (ctx->rgEvalHash[u].iBound >= iBeta) - { - return(ctx->rgEvalHash[u].iEval); - } - break; - } - } - return(INVALID_SCORE); -} - -void -StoreEvalHash(IN OUT SEARCHER_THREAD_CONTEXT *ctx, - IN SCORE iScore, - IN SCORE iBound, - IN UCHAR bvFlags) -/*++ - -Routine description: - - Store a score in the eval hash table (which is pointed to - indirectly via ctx). bvFlags is EVAL_HASH_EXACT for a fully - computed eval (iBound ignored) or EVAL_HASH_UPPER/EVAL_HASH_LOWER - for a bound proven by a lazy-eval early exit (iScore is the - uncorrected partial score that would be returned, iBound is the - proven bound on the true eval). - -Parameters: - - SEARCHER_THREAD_CONTEXT *ctx, - SCORE iScore, - SCORE iBound, - UCHAR bvFlags - -Return value: - - void - ---*/ -{ - POSITION *pos = &(ctx->sPosition); - UINT64 u64Key = (pos->u64PawnSig ^ pos->u64NonPawnSig); - ULONG u = (ULONG)u64Key & (EVAL_HASH_TABLE_SIZE - 1); - ctx->rgEvalHash[u].u64Key = u64Key; - ctx->rgEvalHash[u].iEval = iScore; - ctx->rgEvalHash[u].iBound = iBound; - ctx->rgEvalHash[u].bvFlags = bvFlags; - if (bvFlags == EVAL_HASH_EXACT) - { - ctx->rgEvalHash[u].uPositional = ctx->uPositional; - ctx->rgEvalHash[u].cTrapped[WHITE] = pos->cTrapped[WHITE]; - ctx->rgEvalHash[u].cTrapped[BLACK] = pos->cTrapped[BLACK]; - } + return Eval(ctx, iAlpha, iBeta, NULL); } -#endif // EVAL_HASH @@ -79,16 +79,9 @@ Return value: #ifdef DUMP_TREE Trace(" Search tree dumpfile generation enabled\n"); #endif -#ifdef EVAL_HASH - Trace(" Hash sizes: %u Mb (main), %u Mb / thread (pawn), %u Mb / thread (eval)\n", - (g_uHashTableSizeEntries * sizeof(HASH_ENTRY)) / MB, - PAWN_HASH_TABLE_SIZE * sizeof(PAWN_HASH_ENTRY) / MB, - EVAL_HASH_TABLE_SIZE * sizeof(EVAL_HASH_ENTRY) / MB); -#else Trace(" Hash sizes: %u Mb (main), %u Mb / thread (pawn)\n", (g_uHashTableSizeEntries * sizeof(HASH_ENTRY)) / MB, PAWN_HASH_TABLE_SIZE * sizeof(PAWN_HASH_ENTRY) / MB); -#endif Trace(" QCheckPlies: %u\n", QPLIES_OF_NON_CAPTURE_CHECKS); Trace(" FutilityBase: %u\n", FUTILITY_BASE_MARGIN); p = ExportEvalDNA(); @@ -296,7 +296,6 @@ Return value: memmove(&(ctx->sPosition), pos, sizeof(POSITION)); } ctx->uPly = 0; - ctx->uPositional = 133; memset(&(ctx->sCounters), 0, sizeof(COUNTERS)); } @@ -375,7 +374,6 @@ Return value: memmove(&(ctx->sPosition), pos, sizeof(POSITION)); } ctx->uPly = 0; - ctx->uPositional = 133; ctx->sMoveStack.uUnblockedKeyValue[0] = 1; for (u = 1; u < MAX_PLY_PER_SEARCH; diff --git a/src/search.c b/src/search.c index ce867b6..6c8a945 100755 --- a/src/search.c +++ b/src/search.c @@ -1147,7 +1147,8 @@ QSearch(IN SEARCHER_THREAD_CONTEXT *ctx, // set and valid, it means this is not a "quiet" position. If the // side on the move has not been able to stand pat yet, don't let // them now -- force them to play a move and recurse. - if (0 != ValueOfMaterialInTroubleDespiteMove(ctx, pos->uToMove)) + if (0 != ValueOfMaterialInTroubleDespiteMove(ctx, pos->uToMove) && + FALSE == ctx->sSearchFlags.fCouldStandPat[pos->uToMove]) { iBestScore = iAlpha; } diff --git a/src/split.c b/src/split.c index 2672c0c..8558e3c 100755 --- a/src/split.c +++ b/src/split.c @@ -182,8 +182,7 @@ Return value: uIdleLoops = 0; ReInitializeSearcherContext(&(g_SplitInfo[u].sRootPosition), ctx); ctx->pSplitInfo[0] = &(g_SplitInfo[u]); - ctx->uPositional = g_SplitInfo[u].uSplitPositional; - + // // Note: the main thread could have already exhausted the // split and decremented it from 3->2. When we leave it @@ -597,7 +596,6 @@ Return value: g_SplitInfo[u].iPositionExtend = iPositionExtend; g_SplitInfo[u].iAlpha = *piAlpha; g_SplitInfo[u].iBeta = iBeta; - g_SplitInfo[u].uSplitPositional = ctx->uPositional; g_SplitInfo[u].sSearchFlags = ctx->sSearchFlags; ASSERT(FALSE == ctx->sSearchFlags.fAvoidNullmove); g_SplitInfo[u].mvBest = *pmvBest; diff --git a/src/testeval.c b/src/testeval.c index 0c4b1cf..ee9c6a2 100755 --- a/src/testeval.c +++ b/src/testeval.c @@ -422,7 +422,6 @@ Return value: u < ARRAY_LENGTH(x); u++) { - ctx.uPositional = 0; if (FALSE == FenToPosition(&(ctx.sPosition), x[u].szFen)) { UtilPanic(INCONSISTENT_STATE, |
