Skip to content

Commit

Permalink
⚡ Make SearchResult.Moves an array and optimize its population (#986)
Browse files Browse the repository at this point in the history
Make `SearchResult.Moves` an array and optimize its population from `_pvTable` using `Span`.
  • Loading branch information
eduherminio authored Sep 10, 2024
1 parent 72f3573 commit ffadbb6
Show file tree
Hide file tree
Showing 8 changed files with 18 additions and 26 deletions.
5 changes: 3 additions & 2 deletions src/Lynx.Benchmark/InfoCommand_Benchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,13 @@
namespace Lynx.Benchmark;
public class InfoCommand_Benchmark : BaseBenchmark
{
public static IEnumerable<SearchResult> Data => new[] {
public static IEnumerable<SearchResult> Data =>
[
new SearchResult(33592128, 27, 20, [33592128], -500, +500 ),
new SearchResult(33592128, 27, 20, [33591088, 33975472, 112608, 480352, 109456, 477200, 47968, 495952, 187344, 417008, 24220320, 18256304], -500, +500 ),
new SearchResult(33592128, 27, 20, [33592128, 33974432, 112608, 477200, 109456, 33976512, 166864, 412848, 44848, 536656, 101055424, 480352, 93856, 18312528, 24276512, 101390400, 43808, 544800, 177056, 19426624], -500, +500 ),
new SearchResult(33592128, 27, 20, [352512, 684368, 345472, 691648, 344336, 675376, 353536, 699696, 345488, 701104, 344336, 709312, 345344, 706368, 346384, 699152, 345376, 689824, 344336, 688656, 345344, 697856, 344336, 705168, 345344, 714496, 338192, 671632, 345248, 678128, 353552, 714080, 346512, 693136, 345376, 676416, 352528, 717120, 345472], -500, +500),
};
];

[Benchmark(Baseline = true)]
[ArgumentsSource(nameof(Data))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,13 @@
namespace Lynx.Benchmark;
public class InfoCommand_CopilotRefactoring_Benchmark : BaseBenchmark
{
public static IEnumerable<SearchResult> Data => new[] {
public static IEnumerable<SearchResult> Data =>
[
new SearchResult(33592128, 27, 20, [33592128], -500, +500 ),
new SearchResult(33592128, 27, 20, [33591088, 33975472, 112608, 480352, 109456, 477200, 47968, 495952, 187344, 417008, 24220320, 18256304], -500, +500 ),
new SearchResult(33592128, 27, 20, [33592128, 33974432, 112608, 477200, 109456, 33976512, 166864, 412848, 44848, 536656, 101055424, 480352, 93856, 18312528, 24276512, 101390400, 43808, 544800, 177056, 19426624], -500, +500 ),
new SearchResult(33592128, 27, 20, [352512, 684368, 345472, 691648, 344336, 675376, 353536, 699696, 345488, 701104, 344336, 709312, 345344, 706368, 346384, 699152, 345376, 689824, 344336, 688656, 345344, 697856, 344336, 705168, 345344, 714496, 338192, 671632, 345248, 678128, 353552, 714080, 346512, 693136, 345376, 676416, 352528, 717120, 345472], -500, +500),
};
];

[Benchmark(Baseline = true)]
[ArgumentsSource(nameof(Data))]
Expand Down Expand Up @@ -166,7 +167,7 @@ public static string SearchResultInfo_Copilot(SearchResult searchResult)
}

// Remove the trailing space
if (searchResult.Moves.Count > 0)
if (searchResult.Moves.Length > 0)
{
sb.Length--;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Lynx/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ public void Search(GoCommand goCommand)
}

// We print best move even in case of go ponder + stop, and IDEs are expected to ignore it
_moveToPonder = searchResult.Moves.Count >= 2 ? searchResult.Moves[1] : null;
_moveToPonder = searchResult.Moves.Length >= 2 ? searchResult.Moves[1] : null;
_engineWriter.TryWrite(BestMoveCommand.BestMove(searchResult.BestMove, _moveToPonder));
}
catch (Exception e)
Expand Down
16 changes: 2 additions & 14 deletions src/Lynx/Model/SearchResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ public class SearchResult
public Move BestMove { get; init; }
public int Evaluation { get; init; }
public int Depth { get; set; }
public List<Move> Moves { get; init; }
public Move[] Moves { get; init; }
public int Alpha { get; init; }
public int Beta { get; init; }
public int Mate { get; init; }
Expand All @@ -24,7 +24,7 @@ public class SearchResult

public (int WDLWin, int WDLDraw, int WDLLoss)? WDL { get; set; } = null;

public SearchResult(Move bestMove, int evaluation, int targetDepth, List<Move> moves, int alpha, int beta, int mate = default)
public SearchResult(Move bestMove, int evaluation, int targetDepth, Move[] moves, int alpha, int beta, int mate = default)
{
BestMove = bestMove;
Evaluation = evaluation;
Expand All @@ -34,16 +34,4 @@ public SearchResult(Move bestMove, int evaluation, int targetDepth, List<Move> m
Beta = beta;
Mate = mate;
}

public SearchResult(SearchResult previousSearchResult)
{
BestMove = previousSearchResult.Moves.ElementAtOrDefault(2);
Evaluation = previousSearchResult.Evaluation;
Depth = previousSearchResult.Depth - 2;
DepthReached = previousSearchResult.DepthReached - 2;
Moves = previousSearchResult.Moves.Skip(2).ToList();
Alpha = previousSearchResult.Alpha;
Beta = previousSearchResult.Beta;
Mate = previousSearchResult.Mate == 0 ? 0 : (int)Math.CopySign(Math.Abs(previousSearchResult.Mate) - 1, previousSearchResult.Mate);
}
}
6 changes: 4 additions & 2 deletions src/Lynx/Search/IDDFS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public SearchResult IDDFS(int maxDepth, int softLimitTimeBound)
_logger.Info("Search cancellation requested after {0}ms (depth {1}, nodes {2}), best move will be returned", _stopWatch.ElapsedMilliseconds, depth, _nodes);
#pragma warning restore S6667 // Logging in a catch clause should pass the caught exception as a parameter.

for (int i = 0; i < lastSearchResult?.Moves.Count; ++i)
for (int i = 0; i < lastSearchResult?.Moves.Length; ++i)
{
_pVTable[i] = lastSearchResult.Moves[i];
}
Expand Down Expand Up @@ -309,7 +309,9 @@ private bool OnlyOneLegalMove(ref Move firstLegalMove, [NotNullWhen(true)] out S
private SearchResult UpdateLastSearchResult(SearchResult? lastSearchResult,
int bestEvaluation, int alpha, int beta, int depth, int mate)
{
var pvMoves = _pVTable.TakeWhile(m => m != default).ToList();
var pvTableSpan = _pVTable.AsSpan();
var pvMoves = pvTableSpan[..(pvTableSpan.IndexOf(0))].ToArray();

var maxDepthReached = _maxDepthReached.LastOrDefault(item => item != default);

var elapsedTime = _stopWatch.ElapsedMilliseconds;
Expand Down
2 changes: 1 addition & 1 deletion src/Lynx/Search/OnlineTablebase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public sealed partial class Engine

if (tablebaseResult.BestMove != 0)
{
var searchResult = new SearchResult(tablebaseResult.BestMove, evaluation: 0, targetDepth: 0, new List<Move> { tablebaseResult.BestMove }, MinValue, MaxValue, mate: tablebaseResult.MateScore)
var searchResult = new SearchResult(tablebaseResult.BestMove, evaluation: 0, targetDepth: 0, [tablebaseResult.BestMove], MinValue, MaxValue, mate: tablebaseResult.MateScore)
{
DepthReached = 0,
Nodes = 666, // In case some guis proritize the info command with biggest depth
Expand Down
2 changes: 1 addition & 1 deletion src/Lynx/UCI/Commands/Engine/InfoCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public static string SearchResultInfo(SearchResult searchResult)
}

// Remove the trailing space
if (searchResult.Moves.Count > 0)
if (searchResult.Moves.Length > 0)
{
sb.Length--;
}
Expand Down
4 changes: 2 additions & 2 deletions tests/Lynx.Test/BestMove/RegressionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public void TrashInPVTable(int depth, string fen, string notExpectedMove)
var engine = GetEngine(fen);
var bestResult = engine.BestMove(goCommand);

if (bestResult.Moves.Count > depth)
if (bestResult.Moves.Length > depth)
{
Assert.AreNotEqual(notExpectedMove, bestResult.Moves[depth].UCIString());
}
Expand Down Expand Up @@ -250,7 +250,7 @@ public void InvalidPV(string positionCommand)

var bestMove = engine.BestMove(new GoCommand($"go depth {5}"));
Assert.Zero(bestMove.Evaluation);
Assert.AreEqual(1, bestMove.Moves.Count);
Assert.AreEqual(1, bestMove.Moves.Length);
Assert.AreEqual("b8c7", bestMove.BestMove.UCIString());
}

Expand Down

0 comments on commit ffadbb6

Please sign in to comment.