Files
Craftimizer/Solver/NodeScoresBuffer.cs
T
2024-03-03 19:11:48 -08:00

55 lines
1.7 KiB
C#

using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Craftimizer.Solver;
// Adapted from https://github.com/dtao/ConcurrentList/blob/4fcf1c76e93021a41af5abb2d61a63caeba2adad/ConcurrentList/ConcurrentList.cs
public struct NodeScoresBuffer
{
[StructLayout(LayoutKind.Auto)]
public readonly struct ScoresBatch
{
public readonly Memory<float> ScoreSum;
public readonly Memory<float> MaxScore;
public readonly Memory<int> Visits;
public ScoresBatch()
{
ScoreSum = new float[ArenaBuffer.BatchSize];
MaxScore = new float[ArenaBuffer.BatchSize];
Visits = new int[ArenaBuffer.BatchSize];
}
}
public ScoresBatch[] Data;
public int Count { get; private set; }
public void Add()
{
Data ??= new ScoresBatch[ArenaBuffer.BatchCount];
var idx = Count++;
var (arrayIdx, subIdx) = GetArrayIndex(idx);
if (subIdx == 0)
Data[arrayIdx] = new();
}
public readonly void Visit((int arrayIdx, int subIdx) at, float score)
{
Data[at.arrayIdx].ScoreSum.Span[at.subIdx] += score;
Data[at.arrayIdx].MaxScore.Span[at.subIdx] = Math.Max(Data[at.arrayIdx].MaxScore.Span[at.subIdx], score);
Data[at.arrayIdx].Visits.Span[at.subIdx]++;
}
public readonly int GetVisits((int arrayIdx, int subIdx) at) =>
Data[at.arrayIdx].Visits.Span[at.subIdx];
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static (int arrayIdx, int subIdx) GetArrayIndex(int idx) =>
(idx >> ArenaBuffer.BatchSizeBits, idx & ArenaBuffer.BatchSizeMask);
}