Disable GPU heuristic cycle benchmarks

This commit is contained in:
Marek Lemańczyk committed 2025-10-18 00:29:06 +02:00
1 parent 0d048ac078
commit 3412834f7d
42 files changed
+1416 -1833

No files matched your search

@@ -1,3 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using PerfectNumbers.Core;
@@ -6,33 +9,56 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod10_8_5_3Benchmarks
{
[Params(3UL, 8191UL, 131071UL, 2147483647UL)]
public ulong Value { get; set; }
public ulong Mod10R;
public ulong Mod8R;
public ulong Mod3R;
public ulong Mod5R;
private static readonly ulong[] ValueCases =
[
3UL,
6UL,
128UL,
256UL,
2047UL,
8191UL,
65535UL,
131071UL,
2147483647UL,
ulong.MaxValue - 1024UL,
ulong.MaxValue - 511UL,
ulong.MaxValue - 255UL,
ulong.MaxValue - 127UL,
ulong.MaxValue - 63UL,
ulong.MaxValue - 31UL,
ulong.MaxValue - 17UL,
];
public static IEnumerable<ulong> GetValues() => ValueCases;
/// <summary>
/// Baseline scalar modulo path; held steady between 1.13 ns and 1.14 ns across every value (1.138 ns at 3, 1.143 ns at 8191,
/// 1.134 ns at 131071, 1.141 ns at 2147483647), making it the fastest option overall.
/// Baseline scalar modulo path; previously 1.13-1.14 ns across the shared dataset and remains the reference point here.
/// </summary>
[Benchmark(Baseline = true)]
public (ulong Mod10, ulong Mod8, ulong Mod3, ulong Mod5) ModuloOperator()
[ArgumentsSource(nameof(GetValues))]
public (ulong Mod10, ulong Mod8, ulong Mod3, ulong Mod5) ModuloOperator(ulong value)
{
ulong value = Value;
return (value % 10UL, value % 8UL, value % 3UL, value % 5UL);
}
/// <summary>
/// Legacy folding helper; useful for cross-checks but stays at 2.83-3.07 ns (2.834 ns at 3, 3.038 ns at 8191, 3.067 ns at
/// 131071, 3.039 ns at 2147483647), roughly 2.5-2.7x slower than the baseline.
/// Legacy folding helper; 2.83-3.07 ns in the original suite, now exercised on the combined dataset.
/// </summary>
[Benchmark]
public (ulong Mod10, ulong Mod8, ulong Mod3, ulong Mod5) LegacyModulo()
[ArgumentsSource(nameof(GetValues))]
public (ulong Mod10, ulong Mod8, ulong Mod3, ulong Mod5) LegacyModulo(ulong value)
{
ulong mod10;
ulong mod8;
ulong mod3;
ulong mod5;
UInt128 zero = UInt128.Zero;
if (Value == zero)
if (value == 0UL)
{
mod3 = 0UL;
mod5 = 0UL;
@@ -41,8 +67,8 @@ public class Mod10_8_5_3Benchmarks
return (mod10, mod8, mod3, mod5);
}
UInt128 high = Value >> 64;
ulong result = Value;
UInt128 high = value >> 64;
ulong result = value;
mod8 = result & 7UL;
ulong modRem = (result % 3UL) + ((ulong)high % 3UL);
@@ -62,13 +88,86 @@ public class Mod10_8_5_3Benchmarks
}
/// <summary>
/// Method-based optimized helper; clocks in at 1.63 ns for value 3, 1.64 ns at 8191, 1.875 ns at 131071, and 2.164 ns at
/// 2147483647 (1.43-1.90x the baseline) so it trails the raw `%` but remains 1.6x quicker than the legacy fold.
/// Method-based optimized helper; 1.63-2.16 ns in the original benchmarks, roughly 1.4-1.9× slower than the raw modulo.
/// </summary>
[Benchmark]
public (ulong Mod10, ulong Mod8, ulong Mod3, ulong Mod5) ModMethodModulo()
[ArgumentsSource(nameof(GetValues))]
public (ulong Mod10, ulong Mod8, ulong Mod3, ulong Mod5) ModMethodModulo(ulong value)
{
Value.Mod10_8_5_3(out ulong mod10, out ulong mod8, out ulong mod5, out ulong mod3);
value.Mod10_8_5_3(out ulong mod10, out ulong mod8, out ulong mod5, out ulong mod3);
return (mod10, mod8, mod3, mod5);
}
/// <summary>
/// Legacy property-based helper; 2.35-2.46 ns at small values and up to 2.46 ns near <c>ulong.Max</c>.
/// </summary>
[Benchmark]
[ArgumentsSource(nameof(GetValues))]
public (ulong Mod10, ulong Mod8, ulong Mod5, ulong Mod3) LegacyPropertyModulo(ulong value)
{
UInt128 wideValue = value;
Mod10R = wideValue.Mod10();
Mod8R = Mod8(wideValue);
Mod5R = Mod5(wideValue);
Mod3R = Mod3(wideValue);
return (Mod10R, Mod8R, Mod5R, Mod3R);
}
/// <summary>
/// Method variant for the property helper; 2.79-4.34 ns in the original run, about 1.2-1.8× slower than the legacy property path.
/// </summary>
[Benchmark]
[ArgumentsSource(nameof(GetValues))]
public (ulong Mod10, ulong Mod8, ulong Mod3, ulong Mod5) ModMethodPropertyModulo(ulong value)
{
value.Mod10_8_5_3(out Mod10R, out Mod8R, out Mod5R, out Mod3R);
return (Mod10R, Mod8R, Mod3R, Mod5R);
}
/// <summary>
/// Legacy step-per-bit helper; 11.9-13.4 ns in the original suite and remains the slowest option.
/// </summary>
[Benchmark]
[ArgumentsSource(nameof(GetValues))]
public (ulong Mod10, ulong Mod8, ulong Mod3, ulong Mod5) LegacyStepsModulo(ulong value)
{
UInt128 wideValue = value;
ulong mod10 = (((ulong)(wideValue % 10UL)) << 1) % 10UL;
ulong mod8 = (((ulong)(wideValue & 7UL)) << 1) & 7UL;
ulong mod5 = (((ulong)(wideValue % 5UL)) << 1) % 5UL;
ulong mod3 = (((ulong)(wideValue % 3UL)) << 1) % 3UL;
return (mod10, mod8, mod3, mod5);
}
/// <summary>
/// Step helper exposed via <see cref="UInt128Extensions.Mod10_8_5_3Steps"/>; 3.58-3.77 ns previously, delivering 3.2-3.6× speedups over the legacy step path.
/// </summary>
[Benchmark]
[ArgumentsSource(nameof(GetValues))]
public (ulong Mod10, ulong Mod8, ulong Mod3, ulong Mod5) ModMethodStepsModulo(ulong value)
{
value.Mod10_8_5_3Steps(out ulong mod10, out ulong mod8, out ulong mod5, out ulong mod3);
return (mod10, mod8, mod3, mod5);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong Mod8(UInt128 value) => (ulong)value & 7UL;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong Mod3(UInt128 value)
{
ulong high = (ulong)(value >> 64);
ulong low = (ulong)value;
ulong rem = (low % 3UL) + (high % 3UL);
return rem >= 3UL ? rem - 3UL : rem;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong Mod5(UInt128 value)
{
ulong high = (ulong)(value >> 64);
ulong low = (ulong)value;
ulong rem = (low % 5UL) + (high % 5UL);
return rem >= 5UL ? rem - 5UL : rem;
}
}