From 342ceb1c9124ced53650d6c422a8cfa32e0b12ef Mon Sep 17 00:00:00 2001 From: Joona Kiiski Date: Wed, 8 Apr 2009 17:35:36 +0300 Subject: [PATCH 1/3] Make futility and razor margins more tunable Restructure RazorMargins and FutilityMargins arrays so that their values can be more easily tuned. Add RazorApprMargins array which replaces razorAtDepthOne concept, because setting RazorApprMargin very high value at ply one is same as not razoring there at all. Comment out setting razoring and futility margins through uci to avoid errors while tuning. Signed-off-by: Marco Costalba --- src/search.cpp | 43 +++++++++++++++++++++++-------------------- src/ucioption.cpp | 8 ++++---- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index a3077680..a3912603 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -180,14 +180,21 @@ namespace { // Margins for futility pruning in the quiescence search, and at frontier // and near frontier nodes - Value FutilityMarginQS; - Value FutilityMargins[6] = { Value(0x100), Value(0x200), Value(0x250), - Value(0x2A0), Value(0x340), Value(0x3A0) }; + const Value FutilityMarginQS = Value(0x80); + + //remaining depth: 1 ply 1.5 ply 2 ply 2.5 ply 3 ply 3.5 ply + const Value FutilityMargins[12] = { Value(0x100), Value(0x120), Value(0x200), Value(0x220), Value(0x250), Value(0x270), + // 4 ply 4.5 ply 5 ply 5.5 ply 6 ply 6.5 ply + Value(0x2A0), Value(0x2C0), Value(0x340), Value(0x360), Value(0x3A0), Value(0x3C0)}; // Razoring - const bool RazorAtDepthOne = false; - Depth RazorDepth; - Value RazorMargin; + const Depth RazorDepth = 4*OnePly; + + //remaining depth: 1 ply 1.5 ply 2 ply 2.5 ply 3 ply 3.5 ply + const Value RazorMargins[6] = { Value(0x180), Value(0x300), Value(0x300), Value(0x3C0), Value(0x3C0), Value(0x3C0) }; + + //remaining depth: 1 ply 1.5 ply 2 ply 2.5 ply 3 ply 3.5 ply + const Value RazorApprMargins[6] = { Value(0x100000), Value(0x300), Value(0x300), Value(0x300), Value(0x300), Value(0x300) }; // Last seconds noise filtering (LSN) bool UseLSNFiltering; @@ -437,13 +444,13 @@ void think(const Position &pos, bool infinite, bool ponder, int side_to_move, UseQSearchFutilityPruning = get_option_value_bool("Futility Pruning (Quiescence Search)"); UseFutilityPruning = get_option_value_bool("Futility Pruning (Main Search)"); - FutilityMarginQS = value_from_centipawns(get_option_value_int("Futility Margin (Quiescence Search)")); - int fmScale = get_option_value_int("Futility Margin Scale Factor (Main Search)"); - for (int i = 0; i < 6; i++) - FutilityMargins[i] = (FutilityMargins[i] * fmScale) / 100; + //FutilityMarginQS = value_from_centipawns(get_option_value_int("Futility Margin (Quiescence Search)")); + //int fmScale = get_option_value_int("Futility Margin Scale Factor (Main Search)"); + //for (int i = 0; i < 6; i++) + // FutilityMargins[i] = (FutilityMargins[i] * fmScale) / 100; - RazorDepth = (get_option_value_int("Maximum Razoring Depth") + 1) * OnePly; - RazorMargin = value_from_centipawns(get_option_value_int("Razoring Margin")); + //RazorDepth = (get_option_value_int("Maximum Razoring Depth") + 1) * OnePly; + //RazorMargin = value_from_centipawns(get_option_value_int("Razoring Margin")); UseLSNFiltering = get_option_value_bool("LSN filtering"); LSNTime = get_option_value_int("LSN Time Margin (sec)") * 1000; @@ -1310,17 +1317,14 @@ namespace { } // Null move search not allowed, try razoring else if ( !value_is_mate(beta) - && approximateEval < beta - RazorMargin && depth < RazorDepth - && (RazorAtDepthOne || depth > OnePly) + && approximateEval < beta - RazorApprMargins[int(depth) - 2] && ttMove == MOVE_NONE && !pos.has_pawn_on_7th(pos.side_to_move())) { Value v = qsearch(pos, ss, beta-1, beta, Depth(0), ply, threadID); - if ( (v < beta - RazorMargin - RazorMargin / 4) - || (depth <= 2*OnePly && v < beta - RazorMargin) - || (depth <= OnePly && v < beta - RazorMargin / 2)) - return v; + if (v < beta - RazorMargins[int(depth) - 2]) + return v; } // Go with internal iterative deepening if we don't have a TT move @@ -1379,8 +1383,7 @@ namespace { { if (futilityValue == VALUE_NONE) futilityValue = evaluate(pos, ei, threadID) - + FutilityMargins[int(depth)/2 - 1] - + 32 * (depth & 1); + + FutilityMargins[int(depth) - 2]; if (futilityValue < beta) { diff --git a/src/ucioption.cpp b/src/ucioption.cpp index ab76997f..d7b3b5b4 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -128,10 +128,10 @@ namespace { o["Selective Plies"] = Option(7, 0, 10); o["Futility Pruning (Main Search)"] = Option(true); o["Futility Pruning (Quiescence Search)"] = Option(true); - o["Futility Margin (Quiescence Search)"] = Option(50, 0, 1000); - o["Futility Margin Scale Factor (Main Search)"] = Option(100, 0, 1000); - o["Maximum Razoring Depth"] = Option(3, 0, 4); - o["Razoring Margin"] = Option(300, 150, 600); + //o["Futility Margin (Quiescence Search)"] = Option(50, 0, 1000); + //o["Futility Margin Scale Factor (Main Search)"] = Option(100, 0, 1000); + //o["Maximum Razoring Depth"] = Option(3, 0, 4); + //o["Razoring Margin"] = Option(300, 150, 600); o["LSN filtering"] = Option(true); o["LSN Time Margin (sec)"] = Option(4, 1, 10); o["LSN Value Margin"] = Option(200, 100, 600); From d20e0cf048c7e901f422f61259cd2fbfdba0b209 Mon Sep 17 00:00:00 2001 From: Joona Kiiski Date: Thu, 9 Apr 2009 07:29:13 +0300 Subject: [PATCH 2/3] Razor again at depth one Some time ago it was found by Marco Costalba that it's better to disable razoring at depth one, because given the very low evaluation of the node, futility pruning would already do the job at very low cost and avoiding missing important moves. Now enable razoring there again, but only when our quickly evaluated material advantage is more than a rook. The idea is to try razoring only when it's extremely likely that it will succeed. Extreme lightning speed test show promising result: Orig - Mod: +1285 =1495 -1348 This needs to be tested with longer time controls though. Signed-off-by: Marco Costalba --- src/search.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index a3912603..5ccc72c8 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -193,8 +193,8 @@ namespace { //remaining depth: 1 ply 1.5 ply 2 ply 2.5 ply 3 ply 3.5 ply const Value RazorMargins[6] = { Value(0x180), Value(0x300), Value(0x300), Value(0x3C0), Value(0x3C0), Value(0x3C0) }; - //remaining depth: 1 ply 1.5 ply 2 ply 2.5 ply 3 ply 3.5 ply - const Value RazorApprMargins[6] = { Value(0x100000), Value(0x300), Value(0x300), Value(0x300), Value(0x300), Value(0x300) }; + //remaining depth: 1 ply 1.5 ply 2 ply 2.5 ply 3 ply 3.5 ply + const Value RazorApprMargins[6] = { Value(0x520), Value(0x300), Value(0x300), Value(0x300), Value(0x300), Value(0x300) }; // Last seconds noise filtering (LSN) bool UseLSNFiltering; From bd26374f2105dcbbafeb3376d4fcce24d78ba215 Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Sun, 19 Apr 2009 17:23:30 +0100 Subject: [PATCH 3/3] Small code tidy up and test results When testing at 1'+0" time control results are still reasonably good. We have made two sessions on two different PC. After 840 games Mod - Orig: +221 -194 =425 +10 ELO (two CPU) After 935 games Mod - Orig: +246 -222 =467 +9 ELO (single CPU) So it seems that with fast CPU and/or longer time controls benefits of the patch are a bit reduced. This could be due to the fact that only 3% of nodes are pruned by razoring at depth one and these nodes are very swallow ones, mostly get pruned anyway with only a slightly additional cost, even without performing any do_move() call. Another reason is that sometime (0,3%% of cases) a possible good move is missed typically in positions when moving side gives check, as example in the following one 3r2k1/pbpp1nbp/1p6/3P3q/6RP/1P4P1/P4Pb1/3Q2K1 w - - The winning move Rxg7+ is missed. Bottom line is that patch seems good for blitz times, perhaps also for longer times. We should test against a third engine (Toga ?) to have a final answer regarding this new setup. Signed-off-by: Marco Costalba --- src/search.cpp | 29 ++++++++++------------------- src/ucioption.cpp | 4 ---- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 5ccc72c8..4e5103f0 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -182,19 +182,18 @@ namespace { // and near frontier nodes const Value FutilityMarginQS = Value(0x80); - //remaining depth: 1 ply 1.5 ply 2 ply 2.5 ply 3 ply 3.5 ply - const Value FutilityMargins[12] = { Value(0x100), Value(0x120), Value(0x200), Value(0x220), Value(0x250), Value(0x270), - // 4 ply 4.5 ply 5 ply 5.5 ply 6 ply 6.5 ply - Value(0x2A0), Value(0x2C0), Value(0x340), Value(0x360), Value(0x3A0), Value(0x3C0)}; + // Remaining depth: 1 ply 1.5 ply 2 ply 2.5 ply 3 ply 3.5 ply + const Value FutilityMargins[12] = { Value(0x100), Value(0x120), Value(0x200), Value(0x220), Value(0x250), Value(0x270), + // 4 ply 4.5 ply 5 ply 5.5 ply 6 ply 6.5 ply + Value(0x2A0), Value(0x2C0), Value(0x340), Value(0x360), Value(0x3A0), Value(0x3C0) }; + // Razoring + const Depth RazorDepth = 4*OnePly; - // Razoring - const Depth RazorDepth = 4*OnePly; + // Remaining depth: 1 ply 1.5 ply 2 ply 2.5 ply 3 ply 3.5 ply + const Value RazorMargins[6] = { Value(0x180), Value(0x300), Value(0x300), Value(0x3C0), Value(0x3C0), Value(0x3C0) }; - //remaining depth: 1 ply 1.5 ply 2 ply 2.5 ply 3 ply 3.5 ply - const Value RazorMargins[6] = { Value(0x180), Value(0x300), Value(0x300), Value(0x3C0), Value(0x3C0), Value(0x3C0) }; - - //remaining depth: 1 ply 1.5 ply 2 ply 2.5 ply 3 ply 3.5 ply - const Value RazorApprMargins[6] = { Value(0x520), Value(0x300), Value(0x300), Value(0x300), Value(0x300), Value(0x300) }; + // Remaining depth: 1 ply 1.5 ply 2 ply 2.5 ply 3 ply 3.5 ply + const Value RazorApprMargins[6] = { Value(0x520), Value(0x300), Value(0x300), Value(0x300), Value(0x300), Value(0x300) }; // Last seconds noise filtering (LSN) bool UseLSNFiltering; @@ -444,14 +443,6 @@ void think(const Position &pos, bool infinite, bool ponder, int side_to_move, UseQSearchFutilityPruning = get_option_value_bool("Futility Pruning (Quiescence Search)"); UseFutilityPruning = get_option_value_bool("Futility Pruning (Main Search)"); - //FutilityMarginQS = value_from_centipawns(get_option_value_int("Futility Margin (Quiescence Search)")); - //int fmScale = get_option_value_int("Futility Margin Scale Factor (Main Search)"); - //for (int i = 0; i < 6; i++) - // FutilityMargins[i] = (FutilityMargins[i] * fmScale) / 100; - - //RazorDepth = (get_option_value_int("Maximum Razoring Depth") + 1) * OnePly; - //RazorMargin = value_from_centipawns(get_option_value_int("Razoring Margin")); - UseLSNFiltering = get_option_value_bool("LSN filtering"); LSNTime = get_option_value_int("LSN Time Margin (sec)") * 1000; LSNValue = value_from_centipawns(get_option_value_int("LSN Value Margin")); diff --git a/src/ucioption.cpp b/src/ucioption.cpp index d7b3b5b4..63c27403 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -128,10 +128,6 @@ namespace { o["Selective Plies"] = Option(7, 0, 10); o["Futility Pruning (Main Search)"] = Option(true); o["Futility Pruning (Quiescence Search)"] = Option(true); - //o["Futility Margin (Quiescence Search)"] = Option(50, 0, 1000); - //o["Futility Margin Scale Factor (Main Search)"] = Option(100, 0, 1000); - //o["Maximum Razoring Depth"] = Option(3, 0, 4); - //o["Razoring Margin"] = Option(300, 150, 600); o["LSN filtering"] = Option(true); o["LSN Time Margin (sec)"] = Option(4, 1, 10); o["LSN Value Margin"] = Option(200, 100, 600);