diff options
| author | Scott Gasch <[email protected]> | 2026-08-30 18:51:38 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-08-30 18:51:38 -0700 |
| commit | dbf71219abeb51d386b0f7294f1664f2906d2b82 (patch) | |
| tree | 77dc53e1cb3f223ee04a45130b559b08c91991cc /src/split.c | |
| parent | fd1460b2c135f6cef502fd167d1df0edf223e312 (diff) | |
Plumb iImprovement into LMR and futiltiy and parallel search.
Fix a bug (iEval) in HelpSearch
This commit changes the heuristics for: nullmove pruning, LMR, and EFP slightly.
Diffstat (limited to 'src/split.c')
| -rwxr-xr-x | src/split.c | 87 |
1 files changed, 45 insertions, 42 deletions
diff --git a/src/split.c b/src/split.c index 8bc4e60..b3fc659 100755 --- a/src/split.c +++ b/src/split.c @@ -246,7 +246,7 @@ Return value: v++) { ctx->sMoveStack.mvf[v] = g_SplitInfo[u].mvf[v]; - ASSERT(SanityCheckMove(&ctx->sPosition, + ASSERT(SanityCheckMove(&ctx->sPosition, g_SplitInfo[u].mvf[v].mv)); } @@ -459,6 +459,7 @@ SCORE StartParallelSearch(IN SEARCHER_THREAD_CONTEXT *ctx, IN OUT SCORE *piAlpha, IN SCORE iBeta, + IN SCORE iImprovement, IN OUT SCORE *piBestScore, IN OUT MOVE *pmvBest, IN ULONG uMoveNum, @@ -565,6 +566,8 @@ Return value: memcpy(&(g_SplitInfo[u].sRootPosition), GetRootPosition(), sizeof(POSITION)); + g_SplitInfo[u].iEval = ctx->sPlyInfo[ctx->uPly].iEval; + g_SplitInfo[u].iImprovement = iImprovement; #if DEBUG g_SplitInfo[u].uSplitPly = ctx->uPly; memcpy(&(g_SplitInfo[u].sSplitPosition), @@ -579,7 +582,7 @@ Return value: // useless. Before we grab any helper threads, see if we // need to bail out of this split. // - if (g_MoveTimer.bvFlags & TIMER_STOPPING) + if (g_MoveTimer.bvFlags & TIMER_STOPPING) { g_uNumSplitsAvailable++; g_SplitInfo[u].uNumThreadsHelping = 0; @@ -690,11 +693,11 @@ Return value: // Update the context of the thread that is initiating the // split with a pointer to the split info node we are using. // - for (uSplitNum = 0; - uSplitNum < NUM_SPLIT_PTRS_IN_CONTEXT; - uSplitNum++) + for (uSplitNum = 0; + uSplitNum < NUM_SPLIT_PTRS_IN_CONTEXT; + uSplitNum++) { - if (ctx->pSplitInfo[uSplitNum] == NULL) + if (ctx->pSplitInfo[uSplitNum] == NULL) { ctx->pSplitInfo[uSplitNum] = &(g_SplitInfo[u]); break; @@ -726,7 +729,7 @@ Return value: if (g_fExitProgram) break; } - // + // // Note: past this point we are the only ones using the // split until we return it to the pool by making its // refcount zero again. @@ -848,7 +851,7 @@ Parameters: MOVE mv : move it just searched SCORE iScore : score of the move's subtree ULONG u : split node number - + Return value: static void @@ -856,13 +859,13 @@ Return value: **/ { ULONG v; - + AcquireSpinLock(&(g_SplitInfo[u].uLock)); // // See if this split is shutting down // - if (TRUE == g_SplitInfo[u].fTerminate) + if (TRUE == g_SplitInfo[u].fTerminate) { ReleaseSpinLock(&(g_SplitInfo[u].uLock)); return; @@ -909,8 +912,8 @@ Return value: } -static void -_SetFinalStats(IN SEARCHER_THREAD_CONTEXT *ctx, +static void +_SetFinalStats(IN SEARCHER_THREAD_CONTEXT *ctx, IN ULONG u) /** @@ -934,13 +937,13 @@ Return value: // Before we stop searching this node, update some stuff. // AcquireSpinLock(&(g_SplitInfo[u].uLock)); - + // // Counters to persist in the main counter struct via the split. // - g_SplitInfo[u].sCounters.tree.u64TotalNodeCount += + g_SplitInfo[u].sCounters.tree.u64TotalNodeCount += ctx->sCounters.tree.u64TotalNodeCount; - g_SplitInfo[u].sCounters.tree.u64BetaCutoffs += + g_SplitInfo[u].sCounters.tree.u64BetaCutoffs += ctx->sCounters.tree.u64BetaCutoffs; g_SplitInfo[u].sCounters.tree.u64BetaCutoffsOnFirstMove += ctx->sCounters.tree.u64BetaCutoffsOnFirstMove; @@ -954,11 +957,11 @@ Return value: // // TODO: Any other counters we care about? // - + // // IDEA: Save the killers from this context to bring back to main // - + // // Decrement threadcount in this split. Note: the main thread // incremented it by two. @@ -970,18 +973,18 @@ Return value: } -static MOVE -_GetNextParallelMove(OUT SCORE *piAlpha, - OUT SCORE *piBestScore, +static MOVE +_GetNextParallelMove(OUT SCORE *piAlpha, + OUT SCORE *piBestScore, OUT ULONG *puMoveNumber, IN ULONG u) /** - + Routine description: Retrieve the next parallel move to search at the split node. Also update alpha and bestscore. - + Parameters: SCORE *piAlpha : current alpha @@ -995,7 +998,7 @@ Return value: **/ { MOVE mv = {0}; - + AcquireSpinLock(&(g_SplitInfo[u].uLock)); if (g_SplitInfo[u].fTerminate) { @@ -1012,7 +1015,7 @@ Return value: #ifdef DEBUG ASSERT(!(g_SplitInfo[u].mvf[g_SplitInfo[u].uOnDeckMove].bvFlags & MVF_MOVE_SEARCHED)); - g_SplitInfo[u].mvf[g_SplitInfo[u].uOnDeckMove].bvFlags |= + g_SplitInfo[u].mvf[g_SplitInfo[u].uOnDeckMove].bvFlags |= MVF_MOVE_SEARCHED; ASSERT(mv.uMove); ASSERT(SanityCheckMove(&g_SplitInfo[u].sSplitPosition, mv)); @@ -1029,8 +1032,8 @@ Return value: } -void -HelpSearch(IN OUT SEARCHER_THREAD_CONTEXT *ctx, +void +HelpSearch(IN OUT SEARCHER_THREAD_CONTEXT *ctx, IN ULONG u) /** @@ -1063,7 +1066,7 @@ Return value: SCORE iCheckSee; #ifdef DEBUG POSITION board; - + memcpy(&board, &ctx->sPosition, sizeof(POSITION)); ASSERT(PositionsAreEquivalent(&board, &g_SplitInfo[u].sSplitPosition)); #endif @@ -1072,21 +1075,24 @@ Return value: iBeta = g_SplitInfo[u].iBeta; uOrigDepth = g_SplitInfo[u].uDepth; ctx->sSearchFlags = g_SplitInfo[u].sSearchFlags; + SCORE iEval = g_SplitInfo[u].iEval; + SCORE iImprovement = g_SplitInfo[u].iImprovement; + do { iExtend = iOrigExtend; uDepth = uOrigDepth; ASSERT(ctx->uPly == g_SplitInfo[u].uSplitPly); - + mv = _GetNextParallelMove(&iAlpha, - &iBestScore, + &iBestScore, &uMoveNum, u); if (mv.uMove == 0) break; // Split is terminating ASSERT(IS_VALID_SCORE(iBestScore)); ASSERT(uMoveNum < MAX_MOVES_PER_PLY); - ASSERT(IS_SAME_MOVE(mv, + ASSERT(IS_SAME_MOVE(mv, ctx->sMoveStack.mvf[ctx->sMoveStack.uBegin[ctx->uPly]+uMoveNum].mv)); ASSERT(uDepth <= MAX_DEPTH_PER_SEARCH); ASSERT(IS_VALID_SCORE(iAlpha)); @@ -1094,7 +1100,7 @@ Return value: ASSERT(iAlpha < iBeta); ASSERT(iExtend >= -ONE_PLY); ASSERT(iExtend <= +ONE_PLY); - + // SEE on the PRE-move position -- see search.c's identical comment. iCheckSee = 0; if (IS_CHECKING_MOVE(mv)) @@ -1105,25 +1111,21 @@ Return value: uMoveNum); } - if (MakeMove(ctx, mv)) + if (TRUE == MakeMove(ctx, mv)) { - ASSERT((IS_CHECKING_MOVE(mv) && - InCheck(&ctx->sPosition, ctx->sPosition.uToMove)) || - (!IS_CHECKING_MOVE(mv) && - !InCheck(&ctx->sPosition, ctx->sPosition.uToMove))); - iRoughEval = GetRoughEvalScore(ctx, iAlpha, iBeta, TRUE); + ASSERT((IS_CHECKING_MOVE(mv) && InCheck(&ctx->sPosition, ctx->sPosition.uToMove)) || + (!IS_CHECKING_MOVE(mv) && !InCheck(&ctx->sPosition, ctx->sPosition.uToMove))); // Compute extension ComputeMoveExtension(ctx, iAlpha, iBeta, - (ctx->sMoveStack.uBegin[ctx->uPly - 1] + - uMoveNum), - iRoughEval, + (ctx->sMoveStack.uBegin[ctx->uPly - 1] + uMoveNum), + iEval, uDepth, iCheckSee, &iExtend); - + // // Cap total extension plies spent on this line, same as the // non-split move loop in search.c does. @@ -1139,9 +1141,10 @@ Return value: // Decide how much (if any) to reduce this move's depth. // { - INT iLMR = GetLMRReduction(iRoughEval, + INT iLMR = GetLMRReduction(iEval, iAlpha, iBeta, + iImprovement, ctx, uDepth, (g_SplitInfo[u].uAlreadyDone + |
