/// <summary> /// Runs CPU benchmark and outputs summary results, /// with an overall statistic provided (index to 100 on a Intel Skylake 6142). /// </summary> /// <returns>Relative CPU index (baseline 100)</returns> static int DumpCPUBenchmark() { Console.WriteLine("-----------------------------------------------------------------------------------"); Console.WriteLine("CPU BENCHMARK"); Position ps = Position.StartPosition; EncodedPositionBoard zb = default; MGMove nmove = ConverterMGMoveEncodedMove.EncodedMoveToMGChessMove(new EncodedMove("e2e4"), MGChessPositionConverter.MGChessPositionFromFEN(ps.FEN)); float ops1 = Benchmarking.DumpOperationTimeAndMemoryStats(() => MGPosition.FromPosition(ps), "MGPosition.FromPosition"); float ops2 = Benchmarking.DumpOperationTimeAndMemoryStats(() => MGChessPositionConverter.MGChessPositionFromFEN(ps.FEN), "MGChessPositionFromFEN"); float ops3 = Benchmarking.DumpOperationTimeAndMemoryStats(() => ConverterMGMoveEncodedMove.MGChessMoveToEncodedMove(nmove), "MGChessMoveToLZPositionMove"); float ops4 = Benchmarking.DumpOperationTimeAndMemoryStats(() => EncodedBoardZobrist.ZobristHash(zb), "ZobristHash"); // Performance metric is against a baseline system (Intel Skylake 6142) const float REFERENCE_BM1_OPS = 2160484; const float REFERENCE_BM2_OPS = 448074; const float REFERENCE_BM3_OPS = 157575582; const float REFERENCE_BM4_OPS = 112731351; float relative1 = ops1 / REFERENCE_BM1_OPS; float relative2 = ops2 / REFERENCE_BM2_OPS; float relative3 = ops3 / REFERENCE_BM3_OPS; float relative4 = ops4 / REFERENCE_BM4_OPS; float avg = StatUtils.Average(relative1, relative2, relative3, relative4); Console.WriteLine(); Console.WriteLine($"CERES CPU BENCHMARK SCORE: {avg*100,4:F0}"); return((int)MathF.Round(avg * 100, 0)); }
/// <summary> /// /// </summary> /// <param name="node"></param> /// <param name="parentAnnotation">optionally a precomputed parent annotation (otherwise computed)</param> /// <returns></returns> public unsafe void Annotate(MCTSNode node) { if (node.Annotation.IsInitialized) { return; } NumAnnotations++; // Get the position corresponding to this node MGPosition newPos; if (!node.IsRoot) { // Apply move for this node to the prior position node.Parent.Annotate(); newPos = node.Parent.Annotation.PosMG; newPos.MakeMove(ConverterMGMoveEncodedMove.EncodedMoveToMGChessMove(node.PriorMove, in newPos, true)); } else { newPos = PriorMoves.FinalPosMG; } MGMove priorMoveMG = default; if (!node.IsRoot) { priorMoveMG = ConverterMGMoveEncodedMove.EncodedMoveToMGChessMove(node.PriorMove, in node.Parent.Annotation.PosMG, true); } bool isRoot = node.IsRoot; Position newPosAsPos = newPos.ToPosition; // Create history, with prepended move representing this move Span <Position> posHistory = GetPriorHistoryPositions(node.Parent, in newPosAsPos, PosScratchBuffer, node.Context.ParamsSearch.DrawByRepetitionLookbackPlies, true); // Determine the set (possibly a subset) of positions over which to compute hash Span <Position> posHistoryForCaching = posHistory; int numCacheHashPositions = node.Context.EvaluatorDef.NumCacheHashPositions; if (posHistory.Length > numCacheHashPositions) { posHistoryForCaching = posHistory.Slice(posHistory.Length - numCacheHashPositions, numCacheHashPositions); } // Compute the actual hash ulong zobristHashForCaching = EncodedBoardZobrist.ZobristHash(posHistoryForCaching, node.Context.EvaluatorDef.HashMode); node.LastAccessedSequenceCounter = node.Context.Tree.SEQUENCE_COUNTER++; node.Annotation.PriorMoveMG = priorMoveMG; node.Annotation.Pos = posHistory[^ 1]; // this will have had its repetition count set