public void BatchGenerate(MCTSIterator context, Span <MCTSNode> nodes, EvalResultTarget resultTarget) { try { if (EvaluatorDef.Location == NNEvaluatorDef.LocationType.Remote) { throw new NotImplementedException(); //SetBatch(context, nodes); //RunRemote(nodes, resultTarget); } else { SetBatch(context, nodes); RunLocal(nodes, resultTarget); } } catch (Exception exc) { Console.WriteLine("Error in NodeEvaluatorNN " + exc); throw exc; } NUM_BATCHES_EVALUATED++; NUM_POSITIONS_EVALUATED += (ulong)Batch.NumPos; }
void RunLocal(Span <MCTSNode> nodes, EvalResultTarget resultTarget) { // Span<NodeEvaluatorResult> resultSpan; const bool RETRIEVE_SUPPLEMENTAL = false; IPositionEvaluationBatch result; if (localEvaluator.InputsRequired > NNEvaluator.InputTypes.Boards) { bool hasPositions = localEvaluator.InputsRequired.HasFlag(NNEvaluator.InputTypes.Positions); bool hasHashes = localEvaluator.InputsRequired.HasFlag(NNEvaluator.InputTypes.Hashes); bool hasMoves = localEvaluator.InputsRequired.HasFlag(NNEvaluator.InputTypes.Moves); if (hasPositions && Batch.Positions == null) { Batch.Positions = new MGPosition[Batch.MaxBatchSize]; } if (hasHashes && Batch.PositionHashes == null) { Batch.PositionHashes = new ulong[Batch.MaxBatchSize]; } if (hasMoves && Batch.Moves == null) { Batch.Moves = new MGMoveList[Batch.MaxBatchSize]; } for (int i = 0; i < nodes.Length; i++) { MCTSNode node = nodes[i]; if (hasPositions) { Batch.Positions[i] = node.Annotation.PosMG; } if (hasHashes) { Batch.PositionHashes[i] = node.Annotation.PositionHashForCaching; } if (hasMoves) { Batch.Moves[i] = node.Annotation.Moves; } } } // Note that we call EvaluateBatchIntoBuffers instead of EvaluateBatch for performance reasons // (we immediately extract from buffers in RetrieveResults below) result = localEvaluator.EvaluateIntoBuffers(Batch, RETRIEVE_SUPPLEMENTAL); Debug.Assert(!FP16.IsNaN(result.GetWinP(0)) && !FP16.IsNaN(result.GetLossP(0))); RetrieveResults(nodes, result, resultTarget); // if (MCTSParamsFixed.MONITORING) EventSourceCeres.Log.WriteMetric("MCTS.NodeEvaluatorNN_Local.Hit", counterNumHits++); }
/// <summary> /// /// TODO: this method similar to one below, try to unify them /// </summary> /// <param name="nodes"></param> /// <param name="results"></param> void RetrieveResults(Span <MCTSNode> nodes, IPositionEvaluationBatch results, EvalResultTarget resultTarget) { for (int i = 0; i < nodes.Length; i++) { MCTSNode node = nodes[i]; FP16 winP; FP16 lossP; FP16 rawM = results.GetM(i); // Copy WinP FP16 rawWinP = results.GetWinP(i); Debug.Assert(!float.IsNaN(rawWinP)); // Copy LossP FP16 rawLossP = results.GetLossP(i); Debug.Assert(!float.IsNaN(rawLossP)); // Assign win and loss probabilities // If they look like non-WDL result, try to rewrite them // in equivalent way that avoids negative probabilities if (rawWinP < 0 && rawLossP == 0) { winP = 0; lossP = -rawWinP; } else { winP = rawWinP; lossP = rawLossP; } LeafEvaluationResult evalResult = new LeafEvaluationResult(GameResult.Unknown, winP, lossP, rawM); evalResult.PolicyInArray = results.GetPolicy(i); // Copy policy if (resultTarget == EvalResultTarget.PrimaryEvalResult) { node.EvalResult = evalResult; } else if (resultTarget == EvalResultTarget.SecondaryEvalResult) { node.EvalResultSecondary = evalResult; } else { throw new Exception("Internal error: unexpected EvalResultTarget"); } // Save back to cache if (SaveToCache) { Cache.Store(node.Annotation.PositionHashForCaching, GameResult.Unknown, rawWinP, rawLossP, rawM, in node.EvalResult.PolicyRef); } } }