MethodImplOptions.AggressiveOptimization & MethodImplOptions.AggressiveInlining optimized. Small optimizations.

This commit is contained in:
mlemanczyk committed 2025-12-10 19:59:51 +01:00
1 parent 7a242b3bfa
commit 05d3061c47
23 files changed
+624 -555

No files matched your search

@@ -12,10 +12,7 @@ public class HeuristicCombinedPrimeTesterTests
[InlineData((byte)9)] [InlineData((byte)9)]
public void Enumerator_uses_one_a_one_b_schedule_by_default(byte lastDigit) public void Enumerator_uses_one_a_one_b_schedule_by_default(byte lastDigit)
{ {
Span<HeuristicCombinedPrimeTester.HeuristicGroupBSequenceState> groupBState = var enumerator = HeuristicCombinedPrimeTester.CreateHeuristicDivisorEnumerator(500UL * 500UL, lastDigit);
stackalloc HeuristicCombinedPrimeTester.HeuristicGroupBSequenceState[4];
var enumerator = HeuristicCombinedPrimeTester.CreateHeuristicDivisorEnumerator(500UL * 500UL, lastDigit, groupBState);
var results = new List<HeuristicCombinedPrimeTester.HeuristicDivisorCandidate>(32); var results = new List<HeuristicCombinedPrimeTester.HeuristicDivisorCandidate>(32);
while (results.Count < 20 && enumerator.TryGetNext(out var candidate)) while (results.Count < 20 && enumerator.TryGetNext(out var candidate))
@@ -7,7 +7,7 @@ public struct AscendingDivisorRemainderStepper
private readonly ulong _dividend; private readonly ulong _dividend;
private ulong _maxDivisor; private ulong _maxDivisor;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
public AscendingDivisorRemainderStepper(ulong value) public AscendingDivisorRemainderStepper(ulong value)
{ {
_dividend = value; _dividend = value;
@@ -20,10 +20,10 @@ public struct AscendingDivisorRemainderStepper
_maxDivisor = root; _maxDivisor = root;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public readonly bool ShouldContinue(ulong divisor) => divisor <= _maxDivisor; public readonly bool ShouldContinue(ulong divisor) => divisor <= _maxDivisor;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public bool Divides(ulong divisor) public bool Divides(ulong divisor)
{ {
ulong remainder = _dividend; ulong remainder = _dividend;
@@ -10,21 +10,21 @@ public struct BidirectionalCycleRemainderStepper(ulong modulus)
public readonly ulong Modulus public readonly ulong Modulus
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
get get
{ {
return _modulus; return _modulus;
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public void Initialize(ulong value) public void Initialize(ulong value)
{ {
_remainder = value.ReduceCycleRemainder(_modulus); _remainder = value.ReduceCycleRemainder(_modulus);
_previous = value; _previous = value;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public ulong Step(ulong value) public ulong Step(ulong value)
{ {
long delta = unchecked((long)value - (long)_previous); long delta = unchecked((long)value - (long)_previous);
@@ -1,3 +1,5 @@
using System.Runtime.CompilerServices;
namespace PerfectNumbers.Core.Cpu; namespace PerfectNumbers.Core.Cpu;
internal static class DeterministicRandomCpu internal static class DeterministicRandomCpu
@@ -7,6 +9,7 @@ internal static class DeterministicRandomCpu
private static long s_seedCounter; private static long s_seedCounter;
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong NextUInt64() public static ulong NextUInt64()
{ {
ulong state = s_threadState; ulong state = s_threadState;
@@ -22,6 +25,7 @@ internal static class DeterministicRandomCpu
return state * 2685821657736338717UL; return state * 2685821657736338717UL;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static UInt128 NextUInt128() public static UInt128 NextUInt128()
{ {
UInt128 high = (UInt128)NextUInt64(); UInt128 high = (UInt128)NextUInt64();
@@ -29,6 +33,7 @@ internal static class DeterministicRandomCpu
return (high << 64) | low; return (high << 64) | low;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static ulong InitializeThreadState() private static ulong InitializeThreadState()
{ {
ulong seed = (ulong)Interlocked.Increment(ref s_seedCounter); ulong seed = (ulong)Interlocked.Increment(ref s_seedCounter);
@@ -18,7 +18,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
private ulong _currentMontgomery = divisor.MontgomeryOne; private ulong _currentMontgomery = divisor.MontgomeryOne;
private static readonly ConcurrentDictionary<(ulong Cycle, ulong Delta), ulong> _cycleDeltaCache = new(); private static readonly ConcurrentDictionary<(ulong Cycle, ulong Delta), ulong> _cycleDeltaCache = new();
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public readonly bool MatchesDivisor(in MontgomeryDivisorData divisor, ulong cycleLength) public readonly bool MatchesDivisor(in MontgomeryDivisorData divisor, ulong cycleLength)
=> _modulus == divisor.Modulus && _nPrime == divisor.NPrime && _montgomeryOne == divisor.MontgomeryOne && _cycleLength == cycleLength; => _modulus == divisor.Modulus && _nPrime == divisor.NPrime && _montgomeryOne == divisor.MontgomeryOne && _cycleLength == cycleLength;
@@ -26,7 +26,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
/// Clears the cached Montgomery residue so the stepper can be reused for another divisor. /// Clears the cached Montgomery residue so the stepper can be reused for another divisor.
/// Callers must reinitialize the stepper before consuming any residues after a reset. /// Callers must reinitialize the stepper before consuming any residues after a reset.
/// </summary> /// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public void Reset() public void Reset()
{ {
PreviousExponent = 0UL; PreviousExponent = 0UL;
@@ -39,7 +39,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
/// </summary> /// </summary>
/// <param name="exponent">First exponent evaluated for the current divisor. The caller must reuse the same divisor metadata.</param> /// <param name="exponent">First exponent evaluated for the current divisor. The caller must reuse the same divisor metadata.</param>
/// <returns>The canonical residue produced by <c>2^exponent mod divisor</c>.</returns> /// <returns>The canonical residue produced by <c>2^exponent mod divisor</c>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public ulong InitializeCpu(ulong exponent) public ulong InitializeCpu(ulong exponent)
{ {
InitializeCpuState(exponent); InitializeCpuState(exponent);
@@ -51,7 +51,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
/// </summary> /// </summary>
/// <param name="exponent">First exponent evaluated for the current divisor. Must match the divisor passed to the constructor.</param> /// <param name="exponent">First exponent evaluated for the current divisor. Must match the divisor passed to the constructor.</param>
/// <returns><see langword="true"/> when the seed exponent produces a Montgomery residue equal to one.</returns> /// <returns><see langword="true"/> when the seed exponent produces a Montgomery residue equal to one.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public bool InitializeCpuIsUnity(ulong exponent) public bool InitializeCpuIsUnity(ulong exponent)
{ {
InitializeCpuState(exponent); InitializeCpuState(exponent);
@@ -64,7 +64,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
/// </summary> /// </summary>
/// <param name="exponent">Next exponent in the ascending sequence. Callers must never move backwards or reuse an older exponent.</param> /// <param name="exponent">Next exponent in the ascending sequence. Callers must never move backwards or reuse an older exponent.</param>
/// <returns>The canonical residue produced by <c>2^exponent mod divisor</c>.</returns> /// <returns>The canonical residue produced by <c>2^exponent mod divisor</c>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public ulong ComputeNextCpu(ulong exponent) public ulong ComputeNextCpu(ulong exponent)
{ {
ulong delta = exponent - PreviousExponent; ulong delta = exponent - PreviousExponent;
@@ -84,7 +84,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
/// </summary> /// </summary>
/// <param name="exponent">Next exponent in the ascending sequence.</param> /// <param name="exponent">Next exponent in the ascending sequence.</param>
/// <returns><see langword="true"/> when the canonical residue equals one.</returns> /// <returns><see langword="true"/> when the canonical residue equals one.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public bool ComputeNextIsUnity(ulong exponent) public bool ComputeNextIsUnity(ulong exponent)
{ {
ulong delta = exponent - PreviousExponent; ulong delta = exponent - PreviousExponent;
@@ -105,8 +105,8 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
/// <param name="montgomeryResult">Residue in Montgomery form produced externally for the configured divisor.</param> /// <param name="montgomeryResult">Residue in Montgomery form produced externally for the configured divisor.</param>
/// <param name="isUnity">Outputs whether the supplied residue equals Montgomery one.</param> /// <param name="isUnity">Outputs whether the supplied residue equals Montgomery one.</param>
/// <returns><see langword="true"/> when the residue is accepted and cached.</returns> /// <returns><see langword="true"/> when the residue is accepted and cached.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public bool TryInitializeFromMontgomeryResult(ulong exponent, ulong montgomeryResult, out bool isUnity) public bool TryInitializeFromMontgomeryResult(ulong exponent, ulong montgomeryResult, out bool isUnity)
{ {
_currentMontgomery = montgomeryResult; _currentMontgomery = montgomeryResult;
PreviousExponent = exponent; PreviousExponent = exponent;
@@ -122,7 +122,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
/// <param name="montgomeryDelta">Montgomery residue delta corresponding to the exponent gap.</param> /// <param name="montgomeryDelta">Montgomery residue delta corresponding to the exponent gap.</param>
/// <param name="isUnity">Outputs whether the resulting residue equals Montgomery one.</param> /// <param name="isUnity">Outputs whether the resulting residue equals Montgomery one.</param>
/// <returns><see langword="true"/> when the advance succeeds.</returns> /// <returns><see langword="true"/> when the advance succeeds.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public bool TryAdvanceWithMontgomeryDelta(ulong exponent, ulong montgomeryDelta, out bool isUnity) public bool TryAdvanceWithMontgomeryDelta(ulong exponent, ulong montgomeryDelta, out bool isUnity)
{ {
ulong delta = exponent - PreviousExponent; ulong delta = exponent - PreviousExponent;
@@ -149,7 +149,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
return true; return true;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private void InitializeCpuState(ulong exponent) private void InitializeCpuState(ulong exponent)
{ {
ulong rotation = ReduceDelta(exponent); ulong rotation = ReduceDelta(exponent);
@@ -159,10 +159,10 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
PreviousExponent = exponent; PreviousExponent = exponent;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private readonly ulong ReduceCurrent() => _currentMontgomery.MontgomeryMultiplyCpu(1UL, _modulus, _nPrime); private readonly ulong ReduceCurrent() => _currentMontgomery.MontgomeryMultiplyCpu(1UL, _modulus, _nPrime);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private readonly ulong ReduceDelta(ulong delta) private readonly ulong ReduceDelta(ulong delta)
{ {
ulong cycleLength = _cycleLength; ulong cycleLength = _cycleLength;
@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;
using ILGPU; using ILGPU;
using ILGPU.Runtime; using ILGPU.Runtime;
@@ -9,10 +10,13 @@ internal readonly struct HeuristicCombinedGpuTables
private static readonly HeuristicCombinedGpuTables[] _sharedTables = new HeuristicCombinedGpuTables[PerfectNumberConstants.RollingAccelerators]; private static readonly HeuristicCombinedGpuTables[] _sharedTables = new HeuristicCombinedGpuTables[PerfectNumberConstants.RollingAccelerators];
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
internal static void WarmUp(int acceleratorIndex, AcceleratorStream stream) => _sharedTables[acceleratorIndex] = new(_accelerators[acceleratorIndex], stream); internal static void WarmUp(int acceleratorIndex, AcceleratorStream stream) => _sharedTables[acceleratorIndex] = new(_accelerators[acceleratorIndex], stream);
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static HeuristicCombinedGpuTables GetStaticTables(int acceleratorIndex) => _sharedTables[acceleratorIndex]; internal static HeuristicCombinedGpuTables GetStaticTables(int acceleratorIndex) => _sharedTables[acceleratorIndex];
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
internal HeuristicCombinedGpuTables(Accelerator accelerator, AcceleratorStream stream) internal HeuristicCombinedGpuTables(Accelerator accelerator, AcceleratorStream stream)
{ {
var combinedEnding1 = HeuristicCombinedPrimeTester.CombinedDivisorsEnding1; var combinedEnding1 = HeuristicCombinedPrimeTester.CombinedDivisorsEnding1;
@@ -45,6 +49,7 @@ internal readonly struct HeuristicCombinedGpuTables
internal readonly MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding9; internal readonly MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding9;
internal readonly MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding9; internal readonly MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding9;
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal HeuristicCombinedGpuViews CreateViews() => new( internal HeuristicCombinedGpuViews CreateViews() => new(
HeuristicCombinedDivisorsEnding1.View, HeuristicCombinedDivisorsEnding1.View,
HeuristicCombinedDivisorsEnding3.View, HeuristicCombinedDivisorsEnding3.View,
@@ -55,6 +60,7 @@ internal readonly struct HeuristicCombinedGpuTables
HeuristicCombinedDivisorSquaresEnding7.View, HeuristicCombinedDivisorSquaresEnding7.View,
HeuristicCombinedDivisorSquaresEnding9.View); HeuristicCombinedDivisorSquaresEnding9.View);
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
internal void Dispose() internal void Dispose()
{ {
HeuristicCombinedDivisorsEnding1.Dispose(); HeuristicCombinedDivisorsEnding1.Dispose();
@@ -195,6 +195,7 @@ public sealed class PrimeOrderCalculatorAccelerator
public readonly Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>> SmallPrimeSieveKernelLauncher; public readonly Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>> SmallPrimeSieveKernelLauncher;
public readonly Action<AcceleratorStream, Index1D, ulong, ArrayView<ulong>, int, ulong, ArrayView<ulong>> SpecialMaxKernelLauncher; public readonly Action<AcceleratorStream, Index1D, ulong, ArrayView<ulong>, int, ulong, ArrayView<ulong>> SpecialMaxKernelLauncher;
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public void EnsureCalculateOrderWideCapacity(int newSize) public void EnsureCalculateOrderWideCapacity(int newSize)
{ {
if (newSize > Input.Length) if (newSize > Input.Length)
@@ -213,6 +214,7 @@ public sealed class PrimeOrderCalculatorAccelerator
} }
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public void EnsureCapacity(int factorsCount, int primeTesterCapacity) public void EnsureCapacity(int factorsCount, int primeTesterCapacity)
{ {
Accelerator accelerator = Accelerator; Accelerator accelerator = Accelerator;
@@ -325,6 +327,7 @@ public sealed class PrimeOrderCalculatorAccelerator
} }
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public void EnsureUlongInputOutputCapacity(int newSize) public void EnsureUlongInputOutputCapacity(int newSize)
{ {
var accelerator = Accelerator; var accelerator = Accelerator;
+2
View File
@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;
using ILGPU; using ILGPU;
using ILGPU.Runtime; using ILGPU.Runtime;
using PerfectNumbers.Core.Gpu.Accelerators; using PerfectNumbers.Core.Gpu.Accelerators;
@@ -74,6 +75,7 @@ public class GpuKernelPool
}); });
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
static void InitPow2ModKernelScan(Accelerator accelerator, KernelContainer kernels) static void InitPow2ModKernelScan(Accelerator accelerator, KernelContainer kernels)
{ {
InitOnce(ref kernels.Pow2Mod, () => InitOnce(ref kernels.Pow2Mod, () =>
@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;
using ILGPU; using ILGPU;
using ILGPU.Runtime; using ILGPU.Runtime;
@@ -6,6 +7,7 @@ namespace PerfectNumbers.Core.Gpu;
internal static class Pow2ModKernels internal static class Pow2ModKernels
{ {
/// This kernel always sets the result of the corresponding element. Callers don't need to clear the output buffers. /// This kernel always sets the result of the corresponding element. Callers don't need to clear the output buffers.
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static void Pow2ModKernelScan( public static void Pow2ModKernelScan(
Index1D index, Index1D index,
ulong exponent, ulong exponent,
@@ -107,6 +109,7 @@ internal static class Pow2ModKernels
/// This kernel doesn't always set the result of the found array. It sets the value only when it needs to. The callers /// This kernel doesn't always set the result of the found array. It sets the value only when it needs to. The callers
/// must clean the output buffer before the call to get a deterministic result. /// must clean the output buffer before the call to get a deterministic result.
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static void Pow2ModOrderKernelScan( public static void Pow2ModOrderKernelScan(
Index1D index, Index1D index,
ulong exponent, ulong exponent,
@@ -117,7 +117,7 @@ public static class Pow2MontgomeryKernels
return sumHigh; return sumHigh;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
private static void MultiplyPartsGpu(ulong left, ulong right, out ulong high, out ulong low) private static void MultiplyPartsGpu(ulong left, ulong right, out ulong high, out ulong low)
{ {
ulong leftLow = (uint)left; ulong leftLow = (uint)left;
@@ -135,13 +135,13 @@ public static class Pow2MontgomeryKernels
high = unchecked(highProduct + (cross1 >> 32) + (cross2 >> 32) + (carry >> 32)); high = unchecked(highProduct + (cross1 >> 32) + (cross2 >> 32) + (carry >> 32));
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static ulong Pow2MontgomeryModWindowedGpuKeepMontgomery(in MontgomeryDivisorDataGpu divisor, ulong exponent) internal static ulong Pow2MontgomeryModWindowedGpuKeepMontgomery(in MontgomeryDivisorDataGpu divisor, ulong exponent)
{ {
return Pow2MontgomeryModWindowedGpuMontgomeryResult(divisor, exponent); return Pow2MontgomeryModWindowedGpuMontgomeryResult(divisor, exponent);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong Pow2MontgomeryModWindowedGpuConvertToStandard(this MontgomeryDivisorDataGpu divisor, ulong exponent) public static ulong Pow2MontgomeryModWindowedGpuConvertToStandard(this MontgomeryDivisorDataGpu divisor, ulong exponent)
{ {
ulong modulus = divisor.Modulus; ulong modulus = divisor.Modulus;
@@ -150,7 +150,7 @@ public static class Pow2MontgomeryKernels
return MontgomeryMultiplyGpu(montgomeryResult, 1UL, modulus, nPrime); return MontgomeryMultiplyGpu(montgomeryResult, 1UL, modulus, nPrime);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static ulong Pow2MontgomeryModWindowedGpuMontgomeryResult(in MontgomeryDivisorDataGpu divisor, ulong exponent) private static ulong Pow2MontgomeryModWindowedGpuMontgomeryResult(in MontgomeryDivisorDataGpu divisor, ulong exponent)
{ {
ulong modulus = divisor.Modulus; ulong modulus = divisor.Modulus;
@@ -1182,6 +1182,7 @@ internal static partial class PrimeOrderKernels
return divisor.Pow2MontgomeryModWindowedGpuConvertToStandard(exponent) == 1UL; return divisor.Pow2MontgomeryModWindowedGpuConvertToStandard(exponent) == 1UL;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static ulong CalculateByDoublingKernel(ulong prime) private static ulong CalculateByDoublingKernel(ulong prime)
{ {
ulong order = 1UL; ulong order = 1UL;
@@ -1203,6 +1204,7 @@ internal static partial class PrimeOrderKernels
/// This kernel always sets the result of the corresponding element. Callers don't need to clear the output buffers. /// This kernel always sets the result of the corresponding element. Callers don't need to clear the output buffers.
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
internal static void Pow2ModKernel(Index1D index, ArrayView1D<ulong, Stride1D.Dense> exponents, ulong divisorModulus, ulong divisorNPrime, ulong divisorMontgomeryOne, ulong divisorMontgomeryTwo, ulong divisorMontgomeryTwoSquared, ArrayView1D<ulong, Stride1D.Dense> remainders) internal static void Pow2ModKernel(Index1D index, ArrayView1D<ulong, Stride1D.Dense> exponents, ulong divisorModulus, ulong divisorNPrime, ulong divisorMontgomeryOne, ulong divisorMontgomeryTwo, ulong divisorMontgomeryTwoSquared, ArrayView1D<ulong, Stride1D.Dense> remainders)
{ {
ulong exponent = exponents[index]; ulong exponent = exponents[index];
@@ -1211,12 +1213,14 @@ internal static partial class PrimeOrderKernels
} }
/// This kernel always sets the result of the corresponding element. Callers don't need to clear the output buffers. /// This kernel always sets the result of the corresponding element. Callers don't need to clear the output buffers.
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
internal static void Pow2ModKernelWide(Index1D index, ArrayView1D<GpuUInt128, Stride1D.Dense> exponents, GpuUInt128 modulus, ArrayView1D<GpuUInt128, Stride1D.Dense> remainders) internal static void Pow2ModKernelWide(Index1D index, ArrayView1D<GpuUInt128, Stride1D.Dense> exponents, GpuUInt128 modulus, ArrayView1D<GpuUInt128, Stride1D.Dense> remainders)
{ {
GpuUInt128 exponent = exponents[index]; GpuUInt128 exponent = exponents[index];
remainders[index] = Pow2ModKernelCore(exponent, modulus); remainders[index] = Pow2ModKernelCore(exponent, modulus);
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static GpuUInt128[] InitializeOddPowersTable(GpuUInt128 baseValue, GpuUInt128 modulus, int oddPowerCount) private static GpuUInt128[] InitializeOddPowersTable(GpuUInt128 baseValue, GpuUInt128 modulus, int oddPowerCount)
{ {
GpuUInt128[] result = new GpuUInt128[PerfectNumberConstants.MaxOddPowersCount]; GpuUInt128[] result = new GpuUInt128[PerfectNumberConstants.MaxOddPowersCount];
@@ -1242,6 +1246,7 @@ internal static partial class PrimeOrderKernels
return result; return result;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
internal static GpuUInt128 Pow2ModKernelCore(GpuUInt128 exponent, GpuUInt128 modulus) internal static GpuUInt128 Pow2ModKernelCore(GpuUInt128 exponent, GpuUInt128 modulus)
{ {
// This should never happen in production code. // This should never happen in production code.
@@ -23,6 +23,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
// requested by the caller, skip queuing additional block generation, and keep the snapshot cache untouched. // requested by the caller, skip queuing additional block generation, and keep the snapshot cache untouched.
// GPU residue variant: check 2^p % q == 1 for q = 2*p*k + 1. // GPU residue variant: check 2^p % q == 1 for q = 2*p*k + 1.
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public void Scan(PrimeOrderCalculatorAccelerator gpu, ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime) public void Scan(PrimeOrderCalculatorAccelerator gpu, ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
{ {
// GpuPrimeWorkLimiter.Acquire(); // GpuPrimeWorkLimiter.Acquire();
@@ -114,6 +115,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
// GpuPrimeWorkLimiter.Release(); // GpuPrimeWorkLimiter.Release();
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> GetPow2ModKernel(Accelerator accelerator) private static Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> GetPow2ModKernel(Accelerator accelerator)
{ {
@@ -128,6 +130,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
return cached; return cached;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> CreatePow2ModKernel(Accelerator accelerator) private static Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> CreatePow2ModKernel(Accelerator accelerator)
{ {
var loaded = accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2ModKernels.Pow2ModKernelScan); var loaded = accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2ModKernels.Pow2ModKernelScan);
@@ -140,6 +143,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static ResidueResources RentResources(Accelerator accelerator, int capacity) private static ResidueResources RentResources(Accelerator accelerator, int capacity)
{ {
var resourcePools = _resourcePools ??= new(); var resourcePools = _resourcePools ??= new();
@@ -152,6 +156,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
return new ResidueResources(accelerator, capacity); return new ResidueResources(accelerator, capacity);
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static void ReturnResources(ResidueResources resources) private static void ReturnResources(ResidueResources resources)
{ {
var resourcePools = _resourcePools ??= new(); var resourcePools = _resourcePools ??= new();
@@ -160,6 +165,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
private sealed class ResidueResources private sealed class ResidueResources
{ {
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
internal ResidueResources(Accelerator accelerator, int capacity) internal ResidueResources(Accelerator accelerator, int capacity)
{ {
Capacity = Math.Max(1, capacity); Capacity = Math.Max(1, capacity);
@@ -171,6 +177,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
OrderArray = ThreadStaticPools.UlongPool.Rent(Capacity); OrderArray = ThreadStaticPools.UlongPool.Rent(Capacity);
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
internal void EnsureCapacity(Accelerator accelerator, int capacity) internal void EnsureCapacity(Accelerator accelerator, int capacity)
{ {
if (OrderBuffer.Length >= capacity) if (OrderBuffer.Length >= capacity)
@@ -7,7 +7,7 @@ namespace PerfectNumbers.Core.Gpu;
public static class Pow2MontgomeryGpuCalculator public static class Pow2MontgomeryGpuCalculator
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong CalculateKeep(PrimeOrderCalculatorAccelerator gpu, ulong exponent, in MontgomeryDivisorData divisor) public static ulong CalculateKeep(PrimeOrderCalculatorAccelerator gpu, ulong exponent, in MontgomeryDivisorData divisor)
{ {
// GpuPrimeWorkLimiter.Acquire(); // GpuPrimeWorkLimiter.Acquire();
@@ -34,7 +34,7 @@ public static class Pow2MontgomeryGpuCalculator
return result; return result;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong CalculateConvert(PrimeOrderCalculatorAccelerator gpu, ulong exponent, in MontgomeryDivisorData divisor) public static ulong CalculateConvert(PrimeOrderCalculatorAccelerator gpu, ulong exponent, in MontgomeryDivisorData divisor)
{ {
ulong result = 0UL; ulong result = 0UL;
@@ -1,5 +1,6 @@
using System.Buffers; using System.Buffers;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using ILGPU.Runtime; using ILGPU.Runtime;
using PerfectNumbers.Core.Gpu.Accelerators; using PerfectNumbers.Core.Gpu.Accelerators;
@@ -16,6 +17,7 @@ internal enum GpuPow2ModStatus
internal static partial class PrimeOrderGpuHeuristics internal static partial class PrimeOrderGpuHeuristics
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static void PreloadStaticTables(AcceleratorStream stream) internal static void PreloadStaticTables(AcceleratorStream stream)
{ {
// _ = GetSmallPrimeDeviceCache(stream); // _ = GetSmallPrimeDeviceCache(stream);
@@ -31,16 +33,19 @@ internal static partial class PrimeOrderGpuHeuristics
internal static ConcurrentDictionary<ulong, byte> OverflowRegistry => OverflowedPrimes; internal static ConcurrentDictionary<ulong, byte> OverflowRegistry => OverflowedPrimes;
internal static ConcurrentDictionary<UInt128, byte> OverflowRegistryWide => OverflowedPrimesWide; internal static ConcurrentDictionary<UInt128, byte> OverflowRegistryWide => OverflowedPrimesWide;
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static void OverrideCapabilitiesForTesting(PrimeOrderGpuCapability capability) internal static void OverrideCapabilitiesForTesting(PrimeOrderGpuCapability capability)
{ {
s_capability = capability; s_capability = capability;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static void ResetCapabilitiesForTesting() internal static void ResetCapabilitiesForTesting()
{ {
s_capability = PrimeOrderGpuCapability.Default; s_capability = PrimeOrderGpuCapability.Default;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static bool TryPartialFactor( public static bool TryPartialFactor(
PrimeOrderCalculatorAccelerator gpu, PrimeOrderCalculatorAccelerator gpu,
ulong value, ulong value,
@@ -88,6 +93,7 @@ internal static partial class PrimeOrderGpuHeuristics
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators; private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static bool TryLaunchPartialFactorKernel( private static bool TryLaunchPartialFactorKernel(
PrimeOrderCalculatorAccelerator gpu, PrimeOrderCalculatorAccelerator gpu,
ulong value, ulong value,
@@ -156,6 +162,7 @@ internal static partial class PrimeOrderGpuHeuristics
return true; return true;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static GpuPow2ModStatus TryPow2Mod(PrimeOrderCalculatorAccelerator gpu, ulong exponent, ulong prime, out ulong remainder, in MontgomeryDivisorData? divisorData) public static GpuPow2ModStatus TryPow2Mod(PrimeOrderCalculatorAccelerator gpu, ulong exponent, ulong prime, out ulong remainder, in MontgomeryDivisorData? divisorData)
{ {
Span<ulong> exponents = stackalloc ulong[1]; Span<ulong> exponents = stackalloc ulong[1];
@@ -167,6 +174,7 @@ internal static partial class PrimeOrderGpuHeuristics
return status; return status;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static GpuPow2ModStatus TryPow2ModBatch(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<ulong> exponents, ulong prime, Span<ulong> remainders, in MontgomeryDivisorData? divisorData) public static GpuPow2ModStatus TryPow2ModBatch(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<ulong> exponents, ulong prime, Span<ulong> remainders, in MontgomeryDivisorData? divisorData)
{ {
// This will never occur in production code // This will never occur in production code
@@ -222,6 +230,7 @@ internal static partial class PrimeOrderGpuHeuristics
return computed ? GpuPow2ModStatus.Success : GpuPow2ModStatus.Unavailable; return computed ? GpuPow2ModStatus.Success : GpuPow2ModStatus.Unavailable;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static GpuPow2ModStatus TryPow2Mod(PrimeOrderCalculatorAccelerator gpu, in UInt128 exponent, in UInt128 prime, out UInt128 remainder) public static GpuPow2ModStatus TryPow2Mod(PrimeOrderCalculatorAccelerator gpu, in UInt128 exponent, in UInt128 prime, out UInt128 remainder)
{ {
Span<UInt128> exponents = stackalloc UInt128[1]; Span<UInt128> exponents = stackalloc UInt128[1];
@@ -233,11 +242,13 @@ internal static partial class PrimeOrderGpuHeuristics
return status; return status;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static GpuPow2ModStatus TryPow2ModBatch(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<UInt128> exponents, UInt128 prime, Span<UInt128> remainders) public static GpuPow2ModStatus TryPow2ModBatch(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<UInt128> exponents, UInt128 prime, Span<UInt128> remainders)
{ {
return TryPow2ModBatchInternal(gpu, exponents, prime, remainders); return TryPow2ModBatchInternal(gpu, exponents, prime, remainders);
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
internal static bool TryCalculateOrder( internal static bool TryCalculateOrder(
PrimeOrderCalculatorAccelerator gpu, PrimeOrderCalculatorAccelerator gpu,
ulong prime, ulong prime,
@@ -310,6 +321,7 @@ internal static partial class PrimeOrderGpuHeuristics
return order != 0UL; return order != 0UL;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static GpuPow2ModStatus TryPow2ModBatchInternal(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<UInt128> exponents, UInt128 prime, Span<UInt128> remainders) private static GpuPow2ModStatus TryPow2ModBatchInternal(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<UInt128> exponents, UInt128 prime, Span<UInt128> remainders)
{ {
if (exponents.Length == 0) if (exponents.Length == 0)
@@ -41,6 +41,7 @@ public sealed class HeuristicCombinedPrimeTester
CombinedDivisorsEnding9Squares = CombinedDivisorsEnding9OneAOneBSquares; CombinedDivisorsEnding9Squares = CombinedDivisorsEnding9OneAOneBSquares;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void EnsureInitialized() public static void EnsureInitialized()
{ {
// Intentionally left blank. Accessing this method forces the static constructor to run. // Intentionally left blank. Accessing this method forces the static constructor to run.
@@ -155,9 +156,10 @@ public sealed class HeuristicCombinedPrimeTester
public static HeuristicCombinedPrimeTester Exclusive => _tester ??= new(); public static HeuristicCombinedPrimeTester Exclusive => _tester ??= new();
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static bool IsPrimeCpu(ulong n) public static bool IsPrimeCpu(ulong n)
{ {
byte nMod10 = (byte)n.Mod10(); byte nMod10 = n.Mod10();
ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n); ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n);
if (maxDivisorSquare < 9UL) if (maxDivisorSquare < 9UL)
@@ -168,13 +170,15 @@ public sealed class HeuristicCombinedPrimeTester
return HeuristicTrialDivisionCpu(n, maxDivisorSquare, nMod10); return HeuristicTrialDivisionCpu(n, maxDivisorSquare, nMod10);
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n) public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n)
{ {
byte nMod10 = (byte)n.Mod10(); byte nMod10 = n.Mod10();
ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n); ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n);
return IsPrimeGpu(gpu, n, maxDivisorSquare, nMod10); return IsPrimeGpu(gpu, n, maxDivisorSquare, nMod10);
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n, ulong maxDivisorSquare, byte nMod10) public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n, ulong maxDivisorSquare, byte nMod10)
{ {
// TODO: Is this condition ever met on the execution path in EvenPerfectBitScanner? // TODO: Is this condition ever met on the execution path in EvenPerfectBitScanner?
@@ -187,6 +191,7 @@ public sealed class HeuristicCombinedPrimeTester
return !compositeDetected; return !compositeDetected;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static bool HeuristicTrialDivisionCpu(ulong n, ulong maxDivisorSquare, byte nMod10) private static bool HeuristicTrialDivisionCpu(ulong n, ulong maxDivisorSquare, byte nMod10)
{ {
ReadOnlySpan<ulong> combinedDivisors = GetCombinedDivisors(nMod10); ReadOnlySpan<ulong> combinedDivisors = GetCombinedDivisors(nMod10);
@@ -211,7 +216,7 @@ public sealed class HeuristicCombinedPrimeTester
return EvaluateWithOpenNumericFallback(n); return EvaluateWithOpenNumericFallback(n);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static int GetBatchSize(ulong n) => n switch internal static int GetBatchSize(ulong n) => n switch
{ {
< 1_000 => 8, < 1_000 => 8,
@@ -222,6 +227,7 @@ public sealed class HeuristicCombinedPrimeTester
}; };
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static bool HeuristicTrialDivisionGpuDetectsDivisor(PrimeOrderCalculatorAccelerator gpu, ulong n, ulong maxDivisorSquare, byte nMod10) private static bool HeuristicTrialDivisionGpuDetectsDivisor(PrimeOrderCalculatorAccelerator gpu, ulong n, ulong maxDivisorSquare, byte nMod10)
{ {
var acceleratorIndex = gpu.AcceleratorIndex; var acceleratorIndex = gpu.AcceleratorIndex;
@@ -254,13 +260,13 @@ public sealed class HeuristicCombinedPrimeTester
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static bool EvaluateWithOpenNumericFallback(ulong n) => Prime.Numbers.IsPrime(n); private static bool EvaluateWithOpenNumericFallback(ulong n) => Prime.Numbers.IsPrime(n);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static ulong ComputeHeuristicDivisorSquareLimit(ulong n) => n; internal static ulong ComputeHeuristicDivisorSquareLimit(ulong n) => n;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static ReadOnlySpan<ulong> GetCombinedDivisors(byte nMod10) => nMod10 switch private static ReadOnlySpan<ulong> GetCombinedDivisors(byte nMod10) => nMod10 switch
{ {
1 => CombinedDivisorsEnding1, 1 => CombinedDivisorsEnding1,
@@ -270,7 +276,7 @@ public sealed class HeuristicCombinedPrimeTester
_ => throw new InvalidOperationException($"Unsupported combined divisor selector for digit {nMod10}."), _ => throw new InvalidOperationException($"Unsupported combined divisor selector for digit {nMod10}."),
}; };
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static ReadOnlySpan<ulong> GetCombinedDivisorSquares(byte nMod10) => nMod10 switch private static ReadOnlySpan<ulong> GetCombinedDivisorSquares(byte nMod10) => nMod10 switch
{ {
1 => CombinedDivisorsEnding1Squares, 1 => CombinedDivisorsEnding1Squares,
@@ -280,7 +286,7 @@ public sealed class HeuristicCombinedPrimeTester
_ => throw new InvalidOperationException($"Unsupported combined divisor square selector for digit {nMod10}."), _ => throw new InvalidOperationException($"Unsupported combined divisor square selector for digit {nMod10}."),
}; };
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static ReadOnlySpan<ulong> GetCombinedDivisors(byte nMod10, CombinedDivisorPattern pattern) => pattern switch internal static ReadOnlySpan<ulong> GetCombinedDivisors(byte nMod10, CombinedDivisorPattern pattern) => pattern switch
{ {
CombinedDivisorPattern.TwoAOneB => nMod10 switch CombinedDivisorPattern.TwoAOneB => nMod10 switch
@@ -318,7 +324,7 @@ public sealed class HeuristicCombinedPrimeTester
_ => throw new InvalidOperationException($"Unsupported combined divisor pattern: {pattern}."), _ => throw new InvalidOperationException($"Unsupported combined divisor pattern: {pattern}."),
}; };
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static ReadOnlySpan<ulong> GetCombinedDivisorSquares(byte nMod10, CombinedDivisorPattern pattern) => pattern switch internal static ReadOnlySpan<ulong> GetCombinedDivisorSquares(byte nMod10, CombinedDivisorPattern pattern) => pattern switch
{ {
CombinedDivisorPattern.TwoAOneB => nMod10 switch CombinedDivisorPattern.TwoAOneB => nMod10 switch
@@ -428,6 +434,7 @@ public sealed class HeuristicCombinedPrimeTester
return result; return result;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static int GetGroupBStartIndex(ReadOnlySpan<uint> divisors) private static int GetGroupBStartIndex(ReadOnlySpan<uint> divisors)
{ {
int index = 0; int index = 0;
@@ -439,8 +446,10 @@ public sealed class HeuristicCombinedPrimeTester
return index; return index;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static bool IsGroupAPrefixValue(ulong value) => value is 3UL or 7UL or 11UL or 13UL; private static bool IsGroupAPrefixValue(ulong value) => value is 3UL or 7UL or 11UL or 13UL;
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static HeuristicDivisorGroup ResolveGroup(ulong value) => value switch private static HeuristicDivisorGroup ResolveGroup(ulong value) => value switch
{ {
3UL or 7UL or 11UL or 13UL => HeuristicDivisorGroup.GroupAConstant, 3UL or 7UL or 11UL or 13UL => HeuristicDivisorGroup.GroupAConstant,
@@ -448,6 +457,7 @@ public sealed class HeuristicCombinedPrimeTester
_ => HeuristicDivisorGroup.GroupB, _ => HeuristicDivisorGroup.GroupB,
}; };
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static ReadOnlySpan<uint> GetGroupBDivisors(byte ending) => ending switch private static ReadOnlySpan<uint> GetGroupBDivisors(byte ending) => ending switch
{ {
1 => DivisorGenerator.SmallPrimesLastOneWithoutLastThree, 1 => DivisorGenerator.SmallPrimesLastOneWithoutLastThree,
@@ -457,19 +467,19 @@ public sealed class HeuristicCombinedPrimeTester
_ => [], _ => [],
}; };
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static HeuristicDivisorEnumerator CreateHeuristicDivisorEnumerator(ulong maxDivisorSquare, byte nMod10, Span<HeuristicGroupBSequenceState> groupBBuffer) internal static HeuristicDivisorEnumerator CreateHeuristicDivisorEnumerator(ulong maxDivisorSquare, byte nMod10)
=> new(maxDivisorSquare, nMod10, groupBBuffer); => new(maxDivisorSquare, nMod10);
internal struct HeuristicGroupBSequenceState internal struct HeuristicGroupBSequenceState
{ {
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static MersenneHeuristicDivisorEnumerator CreateMersenneDivisorEnumerator(ulong exponent, ulong maxDivisor) internal static MersenneHeuristicDivisorEnumerator CreateMersenneDivisorEnumerator(ulong exponent, ulong maxDivisor)
=> new(exponent, maxDivisor); => new(exponent, maxDivisor);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static HeuristicDivisorPreparation PrepareHeuristicDivisor(in HeuristicDivisorCandidate candidate) internal static HeuristicDivisorPreparation PrepareHeuristicDivisor(in HeuristicDivisorCandidate candidate)
{ {
ulong divisor = candidate.Value; ulong divisor = candidate.Value;
@@ -478,7 +488,7 @@ public sealed class HeuristicCombinedPrimeTester
return new(candidate, divisorData, cycleLength, hasCycleHint); return new(candidate, divisorData, cycleLength, hasCycleHint);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static ulong ResolveHeuristicCycleLengthCpu( internal static ulong ResolveHeuristicCycleLengthCpu(
ulong exponent, ulong exponent,
in HeuristicDivisorPreparation preparation, in HeuristicDivisorPreparation preparation,
@@ -519,7 +529,7 @@ public sealed class HeuristicCombinedPrimeTester
return resolvedCycle; return resolvedCycle;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static ulong ResolveHeuristicCycleLengthGpu( internal static ulong ResolveHeuristicCycleLengthGpu(
PrimeOrderCalculatorAccelerator gpu, PrimeOrderCalculatorAccelerator gpu,
ulong exponent, ulong exponent,
@@ -561,7 +571,7 @@ public sealed class HeuristicCombinedPrimeTester
return resolvedCycle; return resolvedCycle;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
internal static bool TryGetCycleLengthHint(ulong divisor, out ulong cycleLength) internal static bool TryGetCycleLengthHint(ulong divisor, out ulong cycleLength)
{ {
ulong[] snapshot = HeuristicSmallCycleSnapshot; ulong[] snapshot = HeuristicSmallCycleSnapshot;
@@ -578,35 +588,26 @@ public sealed class HeuristicCombinedPrimeTester
return false; return false;
} }
internal ref struct HeuristicDivisorEnumerator internal ref struct HeuristicDivisorEnumerator(ulong maxDivisorSquare, byte nMod10)
{ {
private readonly ulong maxDivisorSquare; private readonly ulong _maxDivisorSquare = maxDivisorSquare;
private readonly ReadOnlySpan<ulong> combinedDivisors; private readonly ReadOnlySpan<ulong> _combinedDivisors = GetCombinedDivisors(nMod10);
private readonly ReadOnlySpan<ulong> combinedDivisorSquares; private readonly ReadOnlySpan<ulong> _combinedDivisorSquares = GetCombinedDivisorSquares(nMod10);
private int index; private int index = 0;
public HeuristicDivisorEnumerator(ulong maxDivisorSquare, byte nMod10, Span<HeuristicGroupBSequenceState> groupBBuffer)
{
this.maxDivisorSquare = maxDivisorSquare;
_ = groupBBuffer;
combinedDivisors = GetCombinedDivisors(nMod10);
combinedDivisorSquares = GetCombinedDivisorSquares(nMod10);
index = 0;
}
public bool TryGetNext(out HeuristicDivisorCandidate candidate) public bool TryGetNext(out HeuristicDivisorCandidate candidate)
{ {
while (index < combinedDivisors.Length) while (index < _combinedDivisors.Length)
{ {
int currentIndex = index; int currentIndex = index;
ulong divisorSquare = combinedDivisorSquares[currentIndex]; ulong divisorSquare = _combinedDivisorSquares[currentIndex];
if (divisorSquare > maxDivisorSquare) if (divisorSquare > _maxDivisorSquare)
{ {
index = combinedDivisors.Length; index = _combinedDivisors.Length;
break; break;
} }
ulong entry = combinedDivisors[currentIndex]; ulong entry = _combinedDivisors[currentIndex];
index = currentIndex + 1; index = currentIndex + 1;
HeuristicDivisorGroup group = ResolveGroup(entry); HeuristicDivisorGroup group = ResolveGroup(entry);
@@ -629,8 +630,6 @@ public sealed class HeuristicCombinedPrimeTester
private GpuUInt128 current; private GpuUInt128 current;
private MersenneDivisorResidueStepper residueStepper; private MersenneDivisorResidueStepper residueStepper;
private bool active; private bool active;
private ulong processedCount;
private ulong lastDivisor;
public MersenneHeuristicDivisorEnumerator(ulong exponent, ulong maxDivisor) public MersenneHeuristicDivisorEnumerator(ulong exponent, ulong maxDivisor)
{ {
@@ -649,8 +648,6 @@ public sealed class HeuristicCombinedPrimeTester
current = hasCandidates ? firstDivisor : GpuUInt128.Zero; current = hasCandidates ? firstDivisor : GpuUInt128.Zero;
residueStepper = hasCandidates ? new MersenneDivisorResidueStepper(exponent, stepLocal, firstDivisor) : default; residueStepper = hasCandidates ? new MersenneDivisorResidueStepper(exponent, stepLocal, firstDivisor) : default;
active = hasCandidates; active = hasCandidates;
processedCount = 0UL;
lastDivisor = 0UL;
} }
public bool TryGetNext(out HeuristicDivisorCandidate candidate) public bool TryGetNext(out HeuristicDivisorCandidate candidate)
@@ -658,9 +655,6 @@ public sealed class HeuristicCombinedPrimeTester
while (active) while (active)
{ {
ulong value = current.Low; ulong value = current.Low;
processedCount++;
lastDivisor = value;
bool admissible = residueStepper.IsAdmissible(); bool admissible = residueStepper.IsAdmissible();
Advance(); Advance();
@@ -691,12 +685,6 @@ public sealed class HeuristicCombinedPrimeTester
residueStepper.Advance(); residueStepper.Advance();
} }
public readonly ulong ProcessedCount => processedCount;
public readonly ulong LastDivisor => lastDivisor;
public readonly bool Exhausted => !active;
private static HeuristicDivisorCandidate CreateCandidate(ulong value) private static HeuristicDivisorCandidate CreateCandidate(ulong value)
{ {
byte ending = (byte)(value % 10UL); byte ending = (byte)(value % 10UL);
@@ -60,6 +60,7 @@ public static class MontgomeryDivisorDataPool
montgomeryTwoSquared); montgomeryTwoSquared);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static MontgomeryDivisorData Rent(this Queue<MontgomeryDivisorData> queue, ulong modulus, ulong nPrime, ulong montgomeryOne, ulong montgomeryTwo, ulong montgomeryTwoSquared) public static MontgomeryDivisorData Rent(this Queue<MontgomeryDivisorData> queue, ulong modulus, ulong nPrime, ulong montgomeryOne, ulong montgomeryTwo, ulong montgomeryTwoSquared)
{ {
if (queue.TryDequeue(out var pooled)) if (queue.TryDequeue(out var pooled))
File diff suppressed because it is too large. Load diff
@@ -1,4 +1,5 @@
using System.Buffers; using System.Buffers;
using System.Runtime.CompilerServices;
using ILGPU; using ILGPU;
using ILGPU.Runtime; using ILGPU.Runtime;
using PerfectNumbers.Core.Gpu; using PerfectNumbers.Core.Gpu;
@@ -86,6 +87,7 @@ internal static partial class PrimeOrderCalculator
return result; return result;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static UInt128 CalculateWideInternalGpu(PrimeOrderCalculatorAccelerator gpu, in UInt128 prime, in UInt128? previousOrder, in MontgomeryDivisorData? divisorData, in PrimeOrderCalculatorConfig config) private static UInt128 CalculateWideInternalGpu(PrimeOrderCalculatorAccelerator gpu, in UInt128 prime, in UInt128? previousOrder, in MontgomeryDivisorData? divisorData, in PrimeOrderCalculatorConfig config)
{ {
if (prime <= UInt128.One) if (prime <= UInt128.One)
@@ -361,7 +363,7 @@ internal static partial class PrimeOrderCalculator
orderFactors = orderFactors.WithAdditionalPrime(orderFactors.Cofactor); orderFactors = orderFactors.WithAdditionalPrime(orderFactors.Cofactor);
} }
int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecks * 4; int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecksCapacity;
List<UInt128> candidates = new(capacity); List<UInt128> candidates = new(capacity);
FactorEntry128[] factorArray = orderFactors.Factors!; FactorEntry128[] factorArray = orderFactors.Factors!;
BuildCandidatesWide(order, factorArray, orderFactors.Count, candidates, capacity); BuildCandidatesWide(order, factorArray, orderFactors.Count, candidates, capacity);
@@ -403,6 +405,7 @@ internal static partial class PrimeOrderCalculator
return false; return false;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static ulong CalculateByFactorizationGpu(PrimeOrderCalculatorAccelerator gpu, ulong prime, in MontgomeryDivisorData divisorData) private static ulong CalculateByFactorizationGpu(PrimeOrderCalculatorAccelerator gpu, ulong prime, in MontgomeryDivisorData divisorData)
{ {
ulong phi = prime - 1UL; ulong phi = prime - 1UL;
@@ -445,6 +448,7 @@ internal static partial class PrimeOrderCalculator
return order; return order;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static bool TryPopulateSmallPrimeFactorsGpu(PrimeOrderCalculatorAccelerator gpu, ulong value, uint limit, Dictionary<ulong, int> counts, out int factorCount, out ulong remaining) private static bool TryPopulateSmallPrimeFactorsGpu(PrimeOrderCalculatorAccelerator gpu, ulong value, uint limit, Dictionary<ulong, int> counts, out int factorCount, out ulong remaining)
{ {
var primeBufferArray = ThreadStaticPools.UlongPool.Rent(GpuSmallPrimeFactorSlots); var primeBufferArray = ThreadStaticPools.UlongPool.Rent(GpuSmallPrimeFactorSlots);
@@ -511,6 +515,7 @@ internal static partial class PrimeOrderCalculator
return true; return true;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static bool EvaluateSpecialMaxCandidatesGpu( private static bool EvaluateSpecialMaxCandidatesGpu(
PrimeOrderCalculatorAccelerator gpu, PrimeOrderCalculatorAccelerator gpu,
ReadOnlySpan<ulong> factors, ReadOnlySpan<ulong> factors,
@@ -548,6 +553,7 @@ internal static partial class PrimeOrderCalculator
return result != 0; return result != 0;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static UInt128 Pow2ModWideGpu(PrimeOrderCalculatorAccelerator gpu, in UInt128 exponent, in UInt128 modulus, in MontgomeryDivisorData? divisorData) private static UInt128 Pow2ModWideGpu(PrimeOrderCalculatorAccelerator gpu, in UInt128 exponent, in UInt128 modulus, in MontgomeryDivisorData? divisorData)
{ {
if (modulus == UInt128.One) if (modulus == UInt128.One)
@@ -30,6 +30,7 @@ internal static partial class PrimeOrderCalculator
public readonly uint SmallFactorLimit = smallFactorLimit; public readonly uint SmallFactorLimit = smallFactorLimit;
public readonly int PollardRhoMilliseconds = pollardRhoMilliseconds; public readonly int PollardRhoMilliseconds = pollardRhoMilliseconds;
public readonly int MaxPowChecks = maxPowChecks; public readonly int MaxPowChecks = maxPowChecks;
public readonly int MaxPowChecksCapacity = maxPowChecks << 2;
public readonly bool StrictMode = strictMode; public readonly bool StrictMode = strictMode;
} }
@@ -10,7 +10,7 @@ public sealed class PrimeTesterByLastDigit
[ThreadStatic] [ThreadStatic]
private static bool _mod10Initialized; private static bool _mod10Initialized;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static byte GetMod10(ulong value) private static byte GetMod10(ulong value)
{ {
if (!_mod10Initialized || _mod10Stepper.Modulus != 10UL) if (!_mod10Initialized || _mod10Stepper.Modulus != 10UL)
@@ -24,6 +24,7 @@ public sealed class PrimeTesterByLastDigit
return (byte)_mod10Stepper.Step(value); return (byte)_mod10Stepper.Step(value);
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static bool IsPrimeCpu(ulong n) public static bool IsPrimeCpu(ulong n)
{ {
// The below IFs never trigger in production code of EvenPerfectBitScanner on --mersenne=bydivisor path. // The below IFs never trigger in production code of EvenPerfectBitScanner on --mersenne=bydivisor path.
+6 -6
View File
@@ -5,7 +5,7 @@ namespace PerfectNumbers.Core;
public static partial class ULongExtensions public static partial class ULongExtensions
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong Pow2MontgomeryModWindowedKeepMontgomeryCpu(this ulong exponent, in MontgomeryDivisorData divisor) public static ulong Pow2MontgomeryModWindowedKeepMontgomeryCpu(this ulong exponent, in MontgomeryDivisorData divisor)
{ {
ulong modulus = divisor.Modulus; ulong modulus = divisor.Modulus;
@@ -75,7 +75,7 @@ public static partial class ULongExtensions
return result; return result;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong Pow2MontgomeryModWindowedConvertToStandardCpu(this ulong exponent, in MontgomeryDivisorData divisor) public static ulong Pow2MontgomeryModWindowedConvertToStandardCpu(this ulong exponent, in MontgomeryDivisorData divisor)
{ {
ulong modulus = divisor.Modulus; ulong modulus = divisor.Modulus;
@@ -146,7 +146,7 @@ public static partial class ULongExtensions
return result; return result;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static void InitializeMontgomeryOddPowersCpu(in MontgomeryDivisorData divisor, ulong modulus, ulong nPrime, Span<ulong> oddPowers) private static void InitializeMontgomeryOddPowersCpu(in MontgomeryDivisorData divisor, ulong modulus, ulong nPrime, Span<ulong> oddPowers)
{ {
oddPowers[0] = divisor.MontgomeryTwo; oddPowers[0] = divisor.MontgomeryTwo;
@@ -165,20 +165,20 @@ public static partial class ULongExtensions
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong Pow2MontgomeryModWithCycleConvertToStandardCpu(this ulong exponent, ulong cycleLength, in MontgomeryDivisorData divisor) public static ulong Pow2MontgomeryModWithCycleConvertToStandardCpu(this ulong exponent, ulong cycleLength, in MontgomeryDivisorData divisor)
{ {
ulong rotationCount = exponent % cycleLength; ulong rotationCount = exponent % cycleLength;
return Pow2MontgomeryModWindowedConvertToStandardCpu(rotationCount, divisor); return Pow2MontgomeryModWindowedConvertToStandardCpu(rotationCount, divisor);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong Pow2MontgomeryModFromCycleRemainderCpu(this ulong reducedExponent, in MontgomeryDivisorData divisor) public static ulong Pow2MontgomeryModFromCycleRemainderCpu(this ulong reducedExponent, in MontgomeryDivisorData divisor)
{ {
return Pow2MontgomeryModWindowedConvertToStandardCpu(reducedExponent, divisor); return Pow2MontgomeryModWindowedConvertToStandardCpu(reducedExponent, divisor);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong CalculateMersenneDivisorCycleLengthUnrolledHexCpu(this ulong divisor) public static ulong CalculateMersenneDivisorCycleLengthUnrolledHexCpu(this ulong divisor)
{ {
// EvenPerfectBitScanner only routes odd divisors here; keep the guard commented out for benchmarks. // EvenPerfectBitScanner only routes odd divisors here; keep the guard commented out for benchmarks.
+8 -8
View File
@@ -7,7 +7,7 @@ namespace PerfectNumbers.Core;
public static partial class ULongExtensions public static partial class ULongExtensions
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
[Obsolete("Use ULongExtensions.MulHighCpu or ULongExtensions.MulHighGpu.")] [Obsolete("Use ULongExtensions.MulHighCpu or ULongExtensions.MulHighGpu.")]
public static ulong MulHighGpuCompatible(this ulong x, ulong y) public static ulong MulHighGpuCompatible(this ulong x, ulong y)
{ {
@@ -16,7 +16,7 @@ public static partial class ULongExtensions
return product.High; return product.High;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
[Obsolete("Use ULongExtensions.MulModGpu for GPU-compatible host code or GpuUInt128.MulMod inside kernels.")] [Obsolete("Use ULongExtensions.MulModGpu for GPU-compatible host code or GpuUInt128.MulMod inside kernels.")]
public static ulong MulMod64Gpu(this ulong a, ulong b, ulong modulus) public static ulong MulMod64Gpu(this ulong a, ulong b, ulong modulus)
{ {
@@ -26,7 +26,7 @@ public static partial class ULongExtensions
return state.MulMod(b, modulus); return state.MulMod(b, modulus);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
[Obsolete("Use ULongExtensions.MulModGpu for GPU-compatible host code or GpuUInt128.MulMod inside kernels.")] [Obsolete("Use ULongExtensions.MulModGpu for GPU-compatible host code or GpuUInt128.MulMod inside kernels.")]
public static ulong MulMod64GpuDeferred(this ulong a, ulong b, ulong modulus) public static ulong MulMod64GpuDeferred(this ulong a, ulong b, ulong modulus)
{ {
@@ -36,29 +36,29 @@ public static partial class ULongExtensions
return state.MulModWithNativeModulo(b, modulus); return state.MulModWithNativeModulo(b, modulus);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong MulModGpu(this ulong left, ulong right, ulong modulus) public static ulong MulModGpu(this ulong left, ulong right, ulong modulus)
{ {
GpuUInt128 state = new(left); GpuUInt128 state = new(left);
return state.MulMod(right, modulus); return state.MulMod(right, modulus);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong Pow2MontgomeryModWindowedKeepGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor) public static ulong Pow2MontgomeryModWindowedKeepGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor)
=> Pow2MontgomeryGpuCalculator.CalculateKeep(gpu, exponent, divisor); => Pow2MontgomeryGpuCalculator.CalculateKeep(gpu, exponent, divisor);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong Pow2MontgomeryModWindowedConvertGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor) public static ulong Pow2MontgomeryModWindowedConvertGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor)
=> Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, exponent, divisor); => Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, exponent, divisor);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong Pow2MontgomeryModWithCycleGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, ulong cycleLength, in MontgomeryDivisorData divisor) public static ulong Pow2MontgomeryModWithCycleGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, ulong cycleLength, in MontgomeryDivisorData divisor)
{ {
ulong rotationCount = exponent % cycleLength; ulong rotationCount = exponent % cycleLength;
return Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, rotationCount, divisor); return Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, rotationCount, divisor);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong Pow2MontgomeryModFromCycleRemainderGpu(this ulong reducedExponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor) public static ulong Pow2MontgomeryModFromCycleRemainderGpu(this ulong reducedExponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor)
{ {
return Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, reducedExponent, divisor); return Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, reducedExponent, divisor);
+2 -2
View File
@@ -642,7 +642,7 @@ public static partial class ULongExtensions
return (ulong)(((UInt128)a * b) % modulus); return (ulong)(((UInt128)a * b) % modulus);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong MontgomeryMultiplyCpu(this ulong a, ulong b, ulong modulus, ulong nPrime) public static ulong MontgomeryMultiplyCpu(this ulong a, ulong b, ulong modulus, ulong nPrime)
{ {
ulong tLow = unchecked(a * b); ulong tLow = unchecked(a * b);
@@ -1133,7 +1133,7 @@ public static partial class ULongExtensions
return x1; return x1;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static ulong ReduceCycleRemainder(this ulong value, ulong modulus) public static ulong ReduceCycleRemainder(this ulong value, ulong modulus)
{ {
// BigIntegerExtensions.Track(modulus); // BigIntegerExtensions.Track(modulus);