Skip to content

Conversation

@tsoj
Copy link
Contributor

@tsoj tsoj commented Aug 3, 2025

Bench: 3035862

STC: https://tests.stockfishchess.org/tests/view/68894d577b562f5f7b73273b
LLR: 2.98 (-2.94,2.94) <0.00,2.00>
Total: 155072 W: 40651 L: 40150 D: 74271
Ptnml(0-2): 609, 18271, 39292, 18738, 626

LTC: https://tests.stockfishchess.org/tests/view/688c2705502b34dd5e71127a
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 321012 W: 82891 L: 81995 D: 156126
Ptnml(0-2): 227, 34421, 90285, 35375, 198

This commit was generated using qwen3-235b-a22b-thinking-2507:

Prompt: https://rentry.co/iqtaoht7

Reasoning/thinking: https://rentry.co/wm6t9hye

Final response

Analysis and Improvement of Stockfish Search Code

I've selected the same search technique step as in example number 15, which targets the full-depth search section when Late Move Reductions (LMR) are skipped. This occurs for promising moves (captures, checks, killer moves, etc.) that would normally get full-depth searches but aren't the very first move.

Current Implementation Analysis

The current code handles this scenario as follows:

// Step 18. Full-depth search when LMR is skipped
else if (!PvNode || moveCount > 1)
{
    // Increase reduction if ttMove is not present
    if (!ttData.move)
        r += 1139;

    // Note that if expected reduction is high, we reduce search depth here
    value = -search<NonPV>(pos, ss + 1, -(alpha + 1), -alpha,
                           newDepth - (r > 3200) - (r > 4600 && newDepth > 2), !cutNode);
}

This code:

  1. Increases the expected reduction by 1139 if there's no TT move (indicating worse move ordering)
  2. Then conditionally reduces the search depth by 1 or 2 plies based on whether the expected reduction r exceeds certain thresholds (3200 or 4600)

The key insight from Stockfish search development is that "Applying aggressive LMR at very low depths (e.g., starting from depth 2) can be surprisingly effective, potentially leading to deeper selective searches in key lines." The current implementation applies the same reduction thresholds regardless of search depth, but search behavior should be more aggressive at shallow depths where the search is faster and covering more ground is beneficial.

Critical Analysis

The current implementation has a significant limitation: it uses fixed thresholds (3200 and 4600) for depth reduction regardless of the current search depth. This is suboptimal because:

  1. At very low depths (≤ 4), the search is extremely fast, and the marginal benefit of searching one more move often outweighs the marginal cost of slightly shallower search for each move.

  2. The notes indicate that "search optimizations should be heavily focused on shallow depths, as the vast majority of nodes (over 99%) are at low depths (e.g., depth <= 10)."

  3. The current approach doesn't leverage the opportunity to be more selective at low depths, which could improve move ordering for deeper iterations.

  4. Research shows that "LMR is far more effective at cut nodes compared to PV nodes" and should be applied more aggressively when possible.

The proposed improvement introduces depth-dependent thresholds that lower the reduction barriers at low depths. This makes the search more aggressive with reductions specifically when depth is shallow (≤ 4), allowing the engine to examine more moves at these critical early search stages. This approach scales well with longer time controls because better early move ordering leads to more efficient deeper searches.

Final Patch

search.cpp:

// Step 18. Full-depth search when LMR is skipped
else if (!PvNode || moveCount > 1)
{
    // Increase reduction if ttMove is not present
    if (!ttData.move)
        r += 1139;

    // Note that if expected reduction is high, we reduce search depth here
    value = -search<NonPV>(pos, ss + 1, -(alpha + 1), -alpha,
                           newDepth - (r > 3200) - (r > 4600 && newDepth > 2), !cutNode);
}

Improved search.cpp:

// Step 18. Full-depth search when LMR is skipped
else if (!PvNode || moveCount > 1)
{
    // Increase reduction if ttMove is not present
    if (!ttData.move)
        r += 1139;

    // Lower thresholds for reductions at low depths to search more moves
    // At shallow depths, being more aggressive with reductions allows examining more moves
    // which improves early move ordering for deeper iterations (*Scaler)
    const int threshold1 = depth <= 4 ? 2000 : 3200;
    const int threshold2 = depth <= 4 ? 3500 : 4600;

    // Note that if expected reduction is high, we reduce search depth here
    value = -search<NonPV>(pos, ss + 1, -(alpha + 1), -alpha,
                           newDepth - (r > threshold1) - (r > threshold2 && newDepth > 2), !cutNode);
}

Branch name: lmr_aggressive_at_low_depths_scaler


@vondele vondele requested a review from Copilot August 4, 2025 12:11
@vondele
Copy link
Member

vondele commented Aug 4, 2025

only appropriate to let copilot review qwen

@vondele
Copy link
Member

vondele commented Aug 4, 2025

@tsoj add yourself to the authors list..

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements depth-dependent reduction thresholds for full-depth re-search in Stockfish's search algorithm. The change makes the engine more aggressive with reductions at shallow depths (≤ 4) to allow examining more moves, which can improve move ordering for subsequent deeper iterations.

  • Introduces dynamic thresholds that vary based on search depth rather than using fixed values
  • Makes reduction thresholds more aggressive at shallow depths (2000/3500 vs 3200/4600)
  • Maintains existing behavior at deeper search levels where selectivity is more important

@tsoj
Copy link
Contributor Author

tsoj commented Aug 4, 2025

@tsoj add yourself to the authors list..

done!

@vondele vondele added the to be merged Will be merged shortly label Aug 4, 2025
@vondele vondele closed this in 377a3a5 Aug 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🚀 gainer to be merged Will be merged shortly

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants