82 lines
2.2 KiB
C#
82 lines
2.2 KiB
C#
using System.Collections.Generic;
|
|
using System.Runtime.CompilerServices;
|
|
using BenchmarkDotNet.Attributes;
|
|
using BenchmarkDotNet.Jobs;
|
|
using PerfectNumbers.Core.Gpu;
|
|
|
|
namespace EvenPerfectBitScanner.Benchmarks;
|
|
|
|
[SimpleJob(RuntimeMoniker.Net80)]
|
|
[MemoryDiagnoser]
|
|
public class GpuUInt128BinaryGcdBenchmarks
|
|
{
|
|
private static readonly BinaryGcdInput[] Inputs = new BinaryGcdInput[]
|
|
{
|
|
new(new GpuUInt128(0UL, 48UL), new GpuUInt128(0UL, 18UL), "SmallOperands"),
|
|
new(
|
|
new GpuUInt128(0x0123_4567_89AB_CDEFUL, 0xFEDC_BA98_7654_3210UL),
|
|
new GpuUInt128(0x0FED_CBA9_8765_4321UL, 0x0123_4567_89AB_CDEFUL),
|
|
"HighEntropy"),
|
|
new(new GpuUInt128(0UL, ulong.MaxValue), new GpuUInt128(0UL, ulong.MaxValue - 1UL), "LowWordHeavy"),
|
|
new(new GpuUInt128(0x8000_0000_0000_0000UL, 0UL), new GpuUInt128(0x7FFF_FFFF_FFFF_FFFFUL, 0UL), "HighWordOnly"),
|
|
};
|
|
|
|
[ParamsSource(nameof(GetInputs))]
|
|
public BinaryGcdInput Input { get; set; }
|
|
|
|
public static IEnumerable<BinaryGcdInput> GetInputs() => Inputs;
|
|
|
|
[Benchmark(Baseline = true)]
|
|
public GpuUInt128 ReusedVariables()
|
|
{
|
|
return GpuUInt128.BinaryGcd(Input.Left, Input.Right);
|
|
}
|
|
|
|
[Benchmark]
|
|
public GpuUInt128 TemporaryStructPerIteration()
|
|
{
|
|
return BinaryGcdWithTemporary(Input.Left, Input.Right);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static GpuUInt128 BinaryGcdWithTemporary(GpuUInt128 u, GpuUInt128 v)
|
|
{
|
|
if (u.IsZero)
|
|
{
|
|
return v;
|
|
}
|
|
|
|
if (v.IsZero)
|
|
{
|
|
return u;
|
|
}
|
|
|
|
int shift = GpuUInt128.TrailingZeroCount(new GpuUInt128(u.High | v.High, u.Low | v.Low));
|
|
int zu = GpuUInt128.TrailingZeroCount(u);
|
|
u >>= zu;
|
|
|
|
do
|
|
{
|
|
int zv = GpuUInt128.TrailingZeroCount(v);
|
|
v >>= zv;
|
|
if (u > v)
|
|
{
|
|
(u, v) = (v, u);
|
|
}
|
|
|
|
v -= u;
|
|
}
|
|
while (!v.IsZero);
|
|
|
|
return u << shift;
|
|
}
|
|
|
|
public readonly record struct BinaryGcdInput(GpuUInt128 Left, GpuUInt128 Right, string Name)
|
|
{
|
|
public override string ToString()
|
|
{
|
|
return Name;
|
|
}
|
|
}
|
|
}
|