Skip to content

Commit

Permalink
🧹 Move TT outside of Engine: class wrapper (#1184)
Browse files Browse the repository at this point in the history
  • Loading branch information
eduherminio authored Nov 26, 2024
1 parent eaec907 commit 741768f
Show file tree
Hide file tree
Showing 15 changed files with 360 additions and 293 deletions.
52 changes: 1 addition & 51 deletions src/Lynx.Cli/Program.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
using Lynx;
using Lynx.Cli;
using Lynx.UCI.Commands.Engine;
using Microsoft.Extensions.Configuration;
using NLog;
using NLog.Extensions.Logging;
using System.Threading.Channels;

#if DEBUG
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
Expand All @@ -26,54 +24,6 @@
LogManager.Configuration = new NLogLoggingConfiguration(config.GetSection("NLog"));
}

var uciChannel = Channel.CreateBounded<string>(new BoundedChannelOptions(100) { SingleReader = true, SingleWriter = true, FullMode = BoundedChannelFullMode.Wait });
var engineChannel = Channel.CreateBounded<object>(new BoundedChannelOptions(2 * Configuration.EngineSettings.MaxDepth) { SingleReader = true, SingleWriter = false, FullMode = BoundedChannelFullMode.DropOldest });

using CancellationTokenSource source = new();
CancellationToken cancellationToken = source.Token;

var engine = new Engine(engineChannel);
var uciHandler = new UCIHandler(uciChannel, engineChannel, engine);

var tasks = new List<Task>
{
Task.Run(() => new Writer(engineChannel).Run(cancellationToken)),
Task.Run(() => new Searcher(uciChannel, engineChannel, engine).Run(cancellationToken)),
Task.Run(() => new Listener(uciHandler).Run(cancellationToken, args)),
uciChannel.Reader.Completion,
engineChannel.Reader.Completion
};

try
{
Console.WriteLine($"{IdCommand.EngineName} {IdCommand.GetVersion()} by {IdCommand.EngineAuthor}");
await Task.WhenAny(tasks);
}
catch (AggregateException ae)
{
foreach (var e in ae.InnerExceptions)
{
if (e is TaskCanceledException taskCanceledException)
{
Console.WriteLine("Cancellation requested: {0}", taskCanceledException.Message);
}
else
{
Console.WriteLine("Exception: {0}", e.GetType().Name);
}
}
}
catch (Exception e)
{
Console.WriteLine("Unexpected exception");
Console.WriteLine(e.Message);
}
finally
{
engineChannel.Writer.TryComplete();
uciChannel.Writer.TryComplete();
//source.Cancel();
LogManager.Shutdown(); // Flush and close down internal threads and timers
}
await Runner.Run(args);

Thread.Sleep(2_000);
69 changes: 69 additions & 0 deletions src/Lynx.Cli/Runner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using Lynx.UCI.Commands.Engine;
using NLog;
using System.Threading.Channels;

namespace Lynx.Cli;

public static class Runner
{
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();

public static async Task Run(params string[] args)
{
var uciChannel = Channel.CreateBounded<string>(new BoundedChannelOptions(100) { SingleReader = true, SingleWriter = true, FullMode = BoundedChannelFullMode.Wait });
var engineChannel = Channel.CreateBounded<object>(new BoundedChannelOptions(2 * Configuration.EngineSettings.MaxDepth) { SingleReader = true, SingleWriter = false, FullMode = BoundedChannelFullMode.DropOldest });

using CancellationTokenSource source = new();
CancellationToken cancellationToken = source.Token;

var searcher = new Searcher(uciChannel, engineChannel);
var uciHandler = new UCIHandler(uciChannel, engineChannel, searcher);
var writer = new Writer(engineChannel);
var listener = new Listener(uciHandler);

var tasks = new List<Task>
{
Task.Run(() => writer.Run(cancellationToken)),
Task.Run(() => searcher.Run(cancellationToken)),
Task.Run(() => listener.Run(cancellationToken, args)),
uciChannel.Reader.Completion,
engineChannel.Reader.Completion
};

try
{
Console.WriteLine($"{IdCommand.EngineName} {IdCommand.GetVersion()} by {IdCommand.EngineAuthor}");
await Task.WhenAny(tasks);
}
catch (AggregateException ae)
{
foreach (var e in ae.InnerExceptions)
{
if (e is TaskCanceledException taskCanceledException)
{
Console.WriteLine("Cancellation requested exception: {0}", taskCanceledException.Message);
_logger.Fatal(ae, "Cancellation requested exception: {0}", taskCanceledException.Message);
}
else
{
Console.WriteLine("Exception {0}: {1}", e.GetType().Name, e.Message);
_logger.Fatal(ae, "Exception {0}: {1}", e.GetType().Name, e.Message);
}
}
}
catch (Exception e)
{
Console.WriteLine("Unexpected exception");
Console.WriteLine(e.Message);

_logger.Fatal(e, "Unexpected exception: {Exception}", e.Message);
}
finally
{
engineChannel.Writer.TryComplete();
uciChannel.Writer.TryComplete();
//source.Cancel();
LogManager.Shutdown(); // Flush and close down internal threads and timers
}
}
}
21 changes: 11 additions & 10 deletions src/Lynx.Dev/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
//FileAndRankMasks();
//EnhancedPawnEvaluation();
//RookEvaluation();
//TranspositionTable();
//TranspositionTableMethod();
//UnmakeMove();
//PieceSquareTables();
//NewMasks();
Expand Down Expand Up @@ -1038,21 +1038,21 @@ static void RookEvaluation()
Console.WriteLine(eval);
}

static void TranspositionTable()
static void TranspositionTableMethod()
{
static void TesSize(int size)
{
Console.WriteLine("Hash: {0} MB", size);
var length = TranspositionTableExtensions.CalculateLength(size);
var length = TranspositionTable.CalculateLength(size);

var lengthMb = length / 1024 / 1024;

Console.WriteLine("TT memory: {0} MB", lengthMb * Marshal.SizeOf(typeof(TranspositionTableElement)));
Console.WriteLine("TT memory: {0} MB", lengthMb * Marshal.SizeOf<TranspositionTableElement>());
Console.WriteLine("TT array length: {0}MB, (0x{1}, {2} items)", lengthMb, length.ToString("X"), length);
Console.WriteLine("TT mask: 0x{0} ({1})\n", (length - 1).ToString("X"), Convert.ToString((length - 1), 2));
Console.WriteLine("TT mask: 0x{0} ({1})\n", (length - 1).ToString("X"), Convert.ToString(length - 1, 2));
}

Console.WriteLine($"{nameof(TranspositionTableElement)} size: {Marshal.SizeOf(typeof(TranspositionTableElement))} bytes\n");
Console.WriteLine($"{nameof(TranspositionTableElement)} size: {Marshal.SizeOf<TranspositionTableElement>()} bytes\n");

TesSize(2);
TesSize(4);
Expand All @@ -1064,19 +1064,20 @@ static void TesSize(int size)
TesSize(512);
TesSize(1024);

var ttLength = TranspositionTableExtensions.CalculateLength(Configuration.EngineSettings.TranspositionTableSize);
var transpositionTable = new TranspositionTableElement[ttLength];
var ttLength = TranspositionTable.CalculateLength(Configuration.EngineSettings.TranspositionTableSize);
var transpositionTable = new TranspositionTable();

var position = new Position(Constants.InitialPositionFEN);
position.Print();
Console.WriteLine($"Hash: {position.UniqueIdentifier}");

var hashKey = position.UniqueIdentifier % 0x400000;
Console.WriteLine(hashKey);

var hashKey2 = TranspositionTableExtensions.CalculateTTIndex(position.UniqueIdentifier, ttLength);
var hashKey2 = transpositionTable.CalculateTTIndex(position.UniqueIdentifier);
Console.WriteLine(hashKey2);

Array.Clear(transpositionTable);
transpositionTable.Reset();

//transpositionTable.RecordHash(position, depth: 3, maxDepth: 5, move: 1234, eval: +5, nodeType: NodeType.Alpha);
//var entry = transpositionTable.ProbeHash(position, maxDepth: 5, depth: 3, alpha: 1, beta: 2);
Expand Down
30 changes: 6 additions & 24 deletions src/Lynx/Engine.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Lynx.Model;
using Lynx.UCI.Commands.Engine;
using Lynx.UCI.Commands.GUI;
using NLog;
using System.Diagnostics;
Expand All @@ -14,6 +13,7 @@ public sealed partial class Engine

private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
private readonly ChannelWriter<object> _engineWriter;
private readonly TranspositionTable _tt;

private bool _isSearching;

Expand All @@ -39,24 +39,24 @@ public sealed partial class Engine

public double AverageDepth { get; private set; }

public RegisterCommand? Registration { get; set; }

public Game Game { get; private set; }

public bool PendingConfirmation { get; set; }

private CancellationTokenSource _searchCancellationTokenSource;
private CancellationTokenSource _absoluteSearchCancellationTokenSource;

public Engine(ChannelWriter<object> engineWriter)
public Engine(ChannelWriter<object> engineWriter) : this(engineWriter, new()) { }

public Engine(ChannelWriter<object> engineWriter, TranspositionTable tt)
{
AverageDepth = 0;
Game = new Game(Constants.InitialPositionFEN);
_isNewGameComing = true;
_searchCancellationTokenSource = new();
_absoluteSearchCancellationTokenSource = new();
_engineWriter = engineWriter;

_tt = tt;
// Update ResetEngine() after any changes here

_quietHistory = new int[12][];
Expand All @@ -71,8 +71,6 @@ public Engine(ChannelWriter<object> engineWriter)
_killerMoves[i] = new Move[3];
}

AllocateTT();

#if !DEBUG
// Temporary channel so that no output is generated
_engineWriter = Channel.CreateUnbounded<object>(new UnboundedChannelOptions() { SingleReader = true, SingleWriter = false }).Writer;
Expand All @@ -89,14 +87,6 @@ public Engine(ChannelWriter<object> engineWriter)
#pragma warning restore S1215 // "GC.Collect" should not be called
}

private void AllocateTT()
{
_currentTranspositionTableSize = Configuration.EngineSettings.TranspositionTableSize;

var ttLength = TranspositionTableExtensions.CalculateLength(_currentTranspositionTableSize);
_tt = GC.AllocateArray<TranspositionTableElement>(ttLength, pinned: true);
}

#pragma warning disable S1144 // Unused private types or members should be removed - used in Release mode
private void WarmupEngine()
{
Expand All @@ -122,15 +112,7 @@ private void WarmupEngine()

private void ResetEngine()
{
if (_currentTranspositionTableSize == Configuration.EngineSettings.TranspositionTableSize)
{
Array.Clear(_tt);
}
else
{
_logger.Info("Resizing TT ({CurrentSize} MB -> {NewSize} MB)", _currentTranspositionTableSize, Configuration.EngineSettings.TranspositionTableSize);
AllocateTT();
}
_tt.Reset();

// Clear histories
for (int i = 0; i < 12; ++i)
Expand Down
4 changes: 0 additions & 4 deletions src/Lynx/Lynx.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@
<ProjectReference Include="..\Lynx.Generator\Lynx.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>

<ItemGroup>
<Using Include="Lynx.Model.TranspositionTableElement[]" Alias="TranspositionTable" />
</ItemGroup>

<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
Expand Down
2 changes: 2 additions & 0 deletions src/Lynx/Model/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public sealed class Game : IDisposable

public Position PositionBeforeLastSearch { get; private set; }

public string FEN => CurrentPosition.FEN(HalfMovesWithoutCaptureOrPawnMove);

public Game(ReadOnlySpan<char> fen) : this(fen, [], [], [])
{
}
Expand Down
Loading

0 comments on commit 741768f

Please sign in to comment.