Add benchmarks

This commit is contained in:
Asriel Camora
2023-06-21 20:44:13 -07:00
parent dba76e319c
commit 0de1faa112
4 changed files with 97 additions and 12 deletions
+59
View File
@@ -0,0 +1,59 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Craftimizer.Benchmark;
[SimpleJob(RuntimeMoniker.Net70)]
[SimpleJob(RuntimeMoniker.NativeAot70)]
public class Bench
{
private float[] data;
private int[] dataLengths;
[Params(1000, 10000)]
public int N;
[GlobalSetup]
public void Setup()
{
var rand = new Random();
data = new float[N * 8];
dataLengths = new int[N];
for (var i = 0; i < data.Length; i += 8)
{
var len = rand.NextSingle() > .5 ? 8 : rand.Next(1, 9);
dataLengths[i / 8] = len;
for (var j = 0; j < len; ++j)
data[i + j] = rand.NextSingle();
for (var j = len; j < 8; ++j)
data[i + j] = float.NaN;
}
}
[Benchmark]
public int[] Scalar()
{
var d = new int[N];
var dataSpan = data.AsSpan();
for (var i = 0; i < N; ++i)
d[i] = Solver.Crafty.Solver.HMaxIndexScalar(new Vector<float>(dataSpan.Slice(i * 8, 8)), dataLengths[i]);
return d;
}
[Benchmark]
public int[] AVX2()
{
var d = new int[128];
var dataSpan = data.AsSpan();
for (var i = 0; i < 128; ++i)
d[i] = Solver.Crafty.Solver.HMaxIndexAVX2(new Vector<float>(dataSpan.Slice(i * 8, 8)), dataLengths[i]);
return d;
}
}
+1
View File
@@ -8,6 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.5" />
<PackageReference Include="Meziantou.Analyzer" Version="2.0.61">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+5 -1
View File
@@ -1,3 +1,4 @@
using BenchmarkDotNet.Running;
using Craftimizer.Simulator;
using Craftimizer.Simulator.Actions;
using Craftimizer.Solver.Crafty;
@@ -10,6 +11,9 @@ internal static class Program
{
private static void Main()
{
//var summary = BenchmarkRunner.Run<Bench>();
//return;
//TypeLayout.PrintLayout<ArenaNode<SimulationNode>>(true);
//return;
@@ -33,7 +37,7 @@ internal static class Program
var config = new SolverConfig()
{
Iterations = 1_000_000
Iterations = 30_000,//1_000_000
};
var s = Stopwatch.StartNew();
+32 -11
View File
@@ -99,23 +99,45 @@ public class Solver
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
// https://stackoverflow.com/a/23592221
private static (int, uint) HMaxIndex(Vector256<float> v, int len)
public static int HMaxIndexScalar(Vector<float> v, int len)
{
var vfilt = Avx.Blend(v, Vector256<float>.Zero, (byte)~((1 << len) - 1));
var m = 0;
for (var i = 1; i < len; ++i)
{
if (v[i] >= v[m])
m = i;
}
return m;
}
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
// https://stackoverflow.com/a/23592221
public static int HMaxIndexAVX2(Vector<float> v, int len)
{
// Remove NaNs
var vfilt = Avx.Blend(v.AsVector256(), Vector256<float>.Zero, (byte)~((1 << len) - 1));
// Find max value and broadcast to all lanes
var vmax128 = HMax(vfilt);
var vmax = Vector256.Create(vmax128, vmax128);
var vcmp = Avx.CompareEqual(v, vmax);
// Find the highest index with that value, respecting len
var vcmp = Avx.CompareEqual(vfilt, vmax);
var mask = unchecked((uint)Avx2.MoveMask(vcmp.AsByte()));
mask <<= (8 - len) << 2;
var inverseIdx = BitOperations.LeadingZeroCount(mask) >> 2;
var inverseIdx = BitOperations.LeadingZeroCount(mask << ((8 - len) << 2)) >> 2;
return (len - 1 - inverseIdx, mask);
return len - 1 - inverseIdx;
}
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int HMaxIndex(Vector<float> v, int len) =>
Avx2.IsSupported ?
HMaxIndexAVX2(v, len) :
HMaxIndexScalar(v, len);
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Node EvalBestChild(float parentVisits, ReadOnlySpan<Node> children)
@@ -134,7 +156,6 @@ public class Solver
var max = 0;
var maxScore = 0f;
for (var i = 0; i < length; i += vecLength)
{
var iterCount = i + vecLength > length ?
@@ -153,7 +174,7 @@ public class Solver
var exploration = Vector.SquareRoot(CVector / new Vector<float>(visits));
var evalScores = exploitation + exploration;
var (idx, mask) = HMaxIndex(evalScores.AsVector256(), iterCount);
var idx = HMaxIndex(evalScores, iterCount);
if (evalScores[idx] >= maxScore)
{
@@ -186,7 +207,7 @@ public class Solver
if (initialState.IsComplete)
return (initialNode, initialState.CompletionState, initialState.CalculateScore(Config.MaxStepCount) ?? 0);
var randomAction = initialState.AvailableActions.SelectRandom(Random);
var randomAction = initialState.AvailableActions.First();//.SelectRandom(Random);
initialState.AvailableActions.RemoveAction(randomAction);
var expandedNode = initialNode.Add(Execute(initialState.State, randomAction, true));
@@ -201,7 +222,7 @@ public class Solver
{
if (SimulationNode.GetCompletionState(currentCompletionState, currentActions) != CompletionState.Incomplete)
break;
randomAction = currentActions.SelectRandom(Random);
randomAction = currentActions.First();//.SelectRandom(Random);
actions[actionCount++] = randomAction;
(_, currentState) = Simulator.Execute(currentState, randomAction);
currentCompletionState = Simulator.CompletionState;