From f630bfb598dde3e0e8e330912ffd62b6a7bfe241 Mon Sep 17 00:00:00 2001 From: mlemanczyk Date: Mon, 17 Nov 2025 17:38:23 +0100 Subject: [PATCH] HeuristicCombinedPrimeTesterAccelerator integrated with PrimeOrderCalculatorAccelerator. --- ...MersenneNumberDivisorByDivisorCpuTester.cs | 12 +- ...HeuristicCombinedPrimeTesterAccelerator.cs | 147 ------------------ .../PrimeOrderCalculatorAccelerator.cs | 29 ++-- ...MersenneNumberDivisorByDivisorGpuTester.cs | 12 +- .../HeuristicCombinedPrimeTester.cs | 15 +- PerfectNumbers.Core/HeuristicPrimeTester.cs | 6 +- PerfectNumbers.Core/MersenneDivisorCycles.cs | 8 +- .../PrimeOrderCalculator.Cpu.cs | 49 +++--- .../PrimeOrderCalculator.Gpu.cs | 4 +- 9 files changed, 67 insertions(+), 215 deletions(-) delete mode 100644 PerfectNumbers.Core/Gpu/Accelerators/HeuristicCombinedPrimeTesterAccelerator.cs diff --git a/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs b/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs index bf90f6a..3fc4d28 100644 --- a/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs +++ b/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs @@ -202,7 +202,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv remainder7 = (byte)((((divisorHigh % 7UL) * 2UL) + (divisorLow % 7UL)) % 7UL); remainder11 = (byte)((((divisorHigh % 11UL) * 5UL) + (divisorLow % 11UL)) % 11UL); - var gpu = HeuristicCombinedPrimeTesterAccelerator.Rent(1); + var gpu = PrimeOrderCalculatorAccelerator.Rent(1); while (divisor.CompareTo(limit) <= 0) { @@ -245,7 +245,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv // A cycle equal to the tested exponent (which is prime in this path) guarantees that the candidate divides // the corresponding Mersenne number because the order of 2 modulo the divisor is exactly p. processedAll = true; - HeuristicCombinedPrimeTesterAccelerator.Return(gpu); + PrimeOrderCalculatorAccelerator.Return(gpu); return true; } @@ -263,7 +263,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv remainder11 = AddMod11(remainder11, step11); } - HeuristicCombinedPrimeTesterAccelerator.Return(gpu); + PrimeOrderCalculatorAccelerator.Return(gpu); processedAll = true; return false; } @@ -289,7 +289,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv processedAll = false; bool canAdvance = step <= limit; - var gpu = HeuristicCombinedPrimeTesterAccelerator.Rent(1); + var gpu = PrimeOrderCalculatorAccelerator.Rent(1); if (!canAdvance) { if (divisor <= limit) @@ -319,7 +319,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv if (divisorCycle == prime) { processedAll = true; - HeuristicCombinedPrimeTesterAccelerator.Return(gpu); + PrimeOrderCalculatorAccelerator.Return(gpu); return true; } @@ -370,7 +370,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv if (divisorCycle == prime) { processedAll = true; - HeuristicCombinedPrimeTesterAccelerator.Return(gpu); + PrimeOrderCalculatorAccelerator.Return(gpu); return true; } diff --git a/PerfectNumbers.Core/Gpu/Accelerators/HeuristicCombinedPrimeTesterAccelerator.cs b/PerfectNumbers.Core/Gpu/Accelerators/HeuristicCombinedPrimeTesterAccelerator.cs deleted file mode 100644 index 33ef3fe..0000000 --- a/PerfectNumbers.Core/Gpu/Accelerators/HeuristicCombinedPrimeTesterAccelerator.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System.Runtime.CompilerServices; -using ILGPU; -using ILGPU.Runtime; - -namespace PerfectNumbers.Core.Gpu.Accelerators; - -public sealed class HeuristicCombinedPrimeTesterAccelerator -{ - #region Pool - - [ThreadStatic] - private static Queue? Pool; - - public static void WarmUp(int acceleratorIndex, AcceleratorStream stream) - { - Console.WriteLine($"Preparing heuristic accelerator {acceleratorIndex}..."); - HeuristicGpuCombinedTables.WarmUp(acceleratorIndex, stream); - // _ = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.None); - // KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream); - // GpuStaticTableInitializer.EnsureStaticTables(accelerator, kernels, stream); - Console.WriteLine($"Heuristic accelerator {acceleratorIndex} is ready"); - } - - public static HeuristicCombinedPrimeTesterAccelerator Rent(int minBufferCapacity = 1) - { - var pool = Pool ??= new(); - if (!pool.TryDequeue(out var lease)) - { - lease = new HeuristicCombinedPrimeTesterAccelerator(minBufferCapacity); - } - else - { - lease.EnsureCapacity(minBufferCapacity); - } - - return lease; - } - - public static void Return(HeuristicCombinedPrimeTesterAccelerator lease) - { - var pool = Pool ??= new(); - pool.Enqueue(lease); - } - - public static void DisposeAll() - { - if (Pool != null) - { - while (Pool.TryDequeue(out var lease)) - { - lease.DisposeResources(); - } - } - } - - public static void Clear() - { - if (Pool != null) - { - var retained = new List(); - while (Pool.TryDequeue(out var lease)) - { - lease.DisposeResources(); - } - } - } - - #endregion - - public readonly HeuristicGpuCombinedDivisorTables DivisorTables; - internal readonly Context Context; - public readonly Accelerator Accelerator; - public readonly Kernel HeuristicCombinedTrialDivisionKernel; - - public MemoryBuffer1D? Input = null; - public MemoryBuffer1D? Output = null; - public MemoryBuffer1D? HeuristicFlag = null!; - public int BufferCapacity; - - private HeuristicGpuCombinedTables _sharedTables; - public MemoryBuffer1D HeuristicCombinedDivisorsEnding1 => _sharedTables.HeuristicCombinedDivisorsEnding1; - public MemoryBuffer1D HeuristicCombinedDivisorSquaresEnding1 => _sharedTables.HeuristicCombinedDivisorSquaresEnding1; - public MemoryBuffer1D HeuristicCombinedDivisorsEnding3 => _sharedTables.HeuristicCombinedDivisorsEnding3; - public MemoryBuffer1D HeuristicCombinedDivisorSquaresEnding3 => _sharedTables.HeuristicCombinedDivisorSquaresEnding3; - public MemoryBuffer1D HeuristicCombinedDivisorsEnding7 => _sharedTables.HeuristicCombinedDivisorsEnding7; - public MemoryBuffer1D HeuristicCombinedDivisorSquaresEnding7 => _sharedTables.HeuristicCombinedDivisorSquaresEnding7; - public MemoryBuffer1D HeuristicCombinedDivisorsEnding9 => _sharedTables.HeuristicCombinedDivisorsEnding9; - public MemoryBuffer1D HeuristicCombinedDivisorSquaresEnding9 => _sharedTables.HeuristicCombinedDivisorSquaresEnding9; - - private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators; - internal readonly int AcceleratorIndex; - - public HeuristicCombinedPrimeTesterAccelerator(int minBufferCapacity) - { - var acceleratorIndex = AcceleratorPool.Shared.Rent(); - AcceleratorIndex = acceleratorIndex; - Accelerator accelerator = _accelerators[acceleratorIndex]; - Context = accelerator.Context; - - Accelerator = accelerator; - EnsureCapacity(minBufferCapacity); - - HeuristicCombinedTrialDivisionKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel, ulong, ulong, HeuristicGpuCombinedDivisorTables>(PrimeTesterKernels.HeuristicTrialCombinedDivisionKernel)); - - AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex); - - // GpuStaticTableInitializer.EnsureStaticTables(accelerator, kernels, stream); - - _sharedTables = HeuristicGpuCombinedTables.GetStaticTables(acceleratorIndex); - DivisorTables = _sharedTables.CreateHeuristicDivisorTables(); - - stream.Synchronize(); - AcceleratorStreamPool.Return(acceleratorIndex, stream); - } - - public void EnsureCapacity(int minCapacity) - { - if (minCapacity <= BufferCapacity) - { - return; - } - - Input?.Dispose(); - Output?.Dispose(); - HeuristicFlag?.Dispose(); - - Input = Accelerator.Allocate1D(minCapacity); - Output = Accelerator.Allocate1D(minCapacity); - HeuristicFlag = Accelerator.Allocate1D(minCapacity); - - BufferCapacity = minCapacity; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Return() => Return(this); - - public void DisposeResources() - { - Input?.Dispose(); - Output?.Dispose(); - HeuristicFlag?.Dispose(); - // ReleaseSharedTables(_sharedTables); - // These resources are shared between GPU leases - // Accelerator.Dispose(); - // AcceleratorContext.Dispose(); - } -} diff --git a/PerfectNumbers.Core/Gpu/Accelerators/PrimeOrderCalculatorAccelerator.cs b/PerfectNumbers.Core/Gpu/Accelerators/PrimeOrderCalculatorAccelerator.cs index 0f2ba4e..cc9da8f 100644 --- a/PerfectNumbers.Core/Gpu/Accelerators/PrimeOrderCalculatorAccelerator.cs +++ b/PerfectNumbers.Core/Gpu/Accelerators/PrimeOrderCalculatorAccelerator.cs @@ -68,7 +68,7 @@ public sealed class PrimeOrderCalculatorAccelerator // Don't take this from the pool as quick uploads of data to the accelerator consumes much of GPU's memory and throws. AcceleratorStream stream = accelerator.CreateStream(); LastDigitGpuTables.WarmUp(i, stream); - HeuristicCombinedPrimeTesterAccelerator.WarmUp(i, stream); + HeuristicGpuCombinedTables.WarmUp(i, stream); // SharedHeuristicGpuTables.EnsureStaticTables(accelerator, stream); // _ = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.None); // KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream); @@ -109,12 +109,16 @@ public sealed class PrimeOrderCalculatorAccelerator public MemoryBuffer1D SpecialMaxFactors; public readonly MemoryBuffer1D SpecialMaxResult; + public readonly HeuristicGpuCombinedDivisorTables DivisorTables; + public readonly Kernel SmallPrimeSieveKernel; public readonly Kernel CheckFactorsKernel; public readonly Kernel ConvertToStandardKernel; + public readonly Kernel HeuristicCombinedTrialDivisionKernel; public readonly Kernel KeepMontgomeryKernel; public readonly Kernel PollardRhoKernel; public readonly Kernel Pow2ModWideKernel; + public Kernel SharesFactorKernel; @@ -186,16 +190,19 @@ public sealed class PrimeOrderCalculatorAccelerator SpecialMaxCandidates = accelerator.Allocate1D(specialMaxFactorCapacity); SpecialMaxResult = accelerator.Allocate1D(1); - var sharedTables = LastDigitGpuTables.EnsureStaticTables(acceleratorIndex); + var lastDigitSharedTables = LastDigitGpuTables.EnsureStaticTables(acceleratorIndex); - DevicePrimesLastOne = sharedTables.DevicePrimesLastOne; - DevicePrimesLastSeven = sharedTables.DevicePrimesLastSeven; - DevicePrimesLastThree = sharedTables.DevicePrimesLastThree; - DevicePrimesLastNine = sharedTables.DevicePrimesLastNine; - DevicePrimesPow2LastOne = sharedTables.DevicePrimesPow2LastOne; - DevicePrimesPow2LastSeven = sharedTables.DevicePrimesPow2LastSeven; - DevicePrimesPow2LastThree = sharedTables.DevicePrimesPow2LastThree; - DevicePrimesPow2LastNine = sharedTables.DevicePrimesPow2LastNine; + DevicePrimesLastOne = lastDigitSharedTables.DevicePrimesLastOne; + DevicePrimesLastSeven = lastDigitSharedTables.DevicePrimesLastSeven; + DevicePrimesLastThree = lastDigitSharedTables.DevicePrimesLastThree; + DevicePrimesLastNine = lastDigitSharedTables.DevicePrimesLastNine; + DevicePrimesPow2LastOne = lastDigitSharedTables.DevicePrimesPow2LastOne; + DevicePrimesPow2LastSeven = lastDigitSharedTables.DevicePrimesPow2LastSeven; + DevicePrimesPow2LastThree = lastDigitSharedTables.DevicePrimesPow2LastThree; + DevicePrimesPow2LastNine = lastDigitSharedTables.DevicePrimesPow2LastNine; + + var heuristicSharedTables = HeuristicGpuCombinedTables.GetStaticTables(acceleratorIndex); + DivisorTables = heuristicSharedTables.CreateHeuristicDivisorTables(); var checkFactorsKernel = accelerator.LoadStreamKernel, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D>(PrimeOrderGpuHeuristics.CheckFactorsKernel); CheckFactorsKernel = KernelUtil.GetKernel(checkFactorsKernel); @@ -203,6 +210,8 @@ public sealed class PrimeOrderCalculatorAccelerator var convertKernel = accelerator.LoadAutoGroupedStreamKernel, MontgomeryDivisorData, ArrayView1D>(Pow2MontgomeryKernels.Pow2MontgomeryKernelConvertToStandard); ConvertToStandardKernel = KernelUtil.GetKernel(convertKernel); + HeuristicCombinedTrialDivisionKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel, ulong, ulong, HeuristicGpuCombinedDivisorTables>(PrimeTesterKernels.HeuristicTrialCombinedDivisionKernel)); + var keepKernel = accelerator.LoadAutoGroupedStreamKernel, MontgomeryDivisorData, ArrayView1D>(Pow2MontgomeryKernels.Pow2MontgomeryKernelKeepMontgomery); KeepMontgomeryKernel = KernelUtil.GetKernel(keepKernel); diff --git a/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs b/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs index e90ba30..2237fb6 100644 --- a/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs +++ b/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs @@ -109,7 +109,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv // GpuPrimeWorkLimiter(); // int acceleratorIndex = AcceleratorPool.Shared.Rent(); // var accelerator = _accelerators[acceleratorIndex]; - var gpu = HeuristicCombinedPrimeTesterAccelerator.Rent(batchCapacity); + var gpu = PrimeOrderCalculatorAccelerator.Rent(batchCapacity); var acceleratorIndex = gpu.AcceleratorIndex; var accelerator = gpu.Accelerator; var stream = AcceleratorStreamPool.Rent(acceleratorIndex); @@ -144,7 +144,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv AcceleratorStreamPool.Return(acceleratorIndex, stream); ReturnBatchResources(resources); - HeuristicCombinedPrimeTesterAccelerator.Return(gpu); + PrimeOrderCalculatorAccelerator.Return(gpu); // Monitor.Exit(gpuLease.ExecutionLock); // GpuPrimeWorkLimiter.Release(); @@ -188,7 +188,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv } private static bool CheckDivisors( - HeuristicCombinedPrimeTesterAccelerator gpu, + PrimeOrderCalculatorAccelerator gpu, ulong prime, ulong allowedMax, Action, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView> kernel, @@ -382,7 +382,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static ulong ResolveDivisorCycle(HeuristicCombinedPrimeTesterAccelerator gpu, ulong divisor, ulong prime, in MontgomeryDivisorData divisorData) + private static ulong ResolveDivisorCycle(PrimeOrderCalculatorAccelerator gpu, ulong divisor, ulong prime, in MontgomeryDivisorData divisorData) { if (!MersenneDivisorCycles.TryCalculateCycleLengthForExponentCpu(gpu, divisor, prime, divisorData, out ulong computedCycle, out bool primeOrderFailed) || computedCycle == 0UL) { @@ -505,7 +505,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators; private readonly MersenneNumberDivisorByDivisorGpuTester _owner; - private readonly HeuristicCombinedPrimeTesterAccelerator _primeTesterAccelerator; + private readonly PrimeOrderCalculatorAccelerator _primeTesterAccelerator; private readonly Accelerator _accelerator; private readonly AcceleratorStream _stream; private Action, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView> _kernel = null!; @@ -524,7 +524,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv { _owner = owner; // GpuPrimeWorkLimiter.Acquire(); - _primeTesterAccelerator = HeuristicCombinedPrimeTesterAccelerator.Rent(); + _primeTesterAccelerator = PrimeOrderCalculatorAccelerator.Rent(1); Accelerator accelerator = _primeTesterAccelerator.Accelerator; _accelerator = accelerator; _stream = accelerator.CreateStream(); diff --git a/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs b/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs index a78e78d..e30099b 100644 --- a/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs +++ b/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs @@ -173,20 +173,20 @@ public sealed class HeuristicCombinedPrimeTester { byte nMod10 = (byte)n.Mod10(); ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n); - var gpu = HeuristicCombinedPrimeTesterAccelerator.Rent(1); + var gpu = PrimeOrderCalculatorAccelerator.Rent(1); bool isPrime = IsPrimeGpu(gpu, n, maxDivisorSquare, nMod10); - HeuristicCombinedPrimeTesterAccelerator.Return(gpu); + PrimeOrderCalculatorAccelerator.Return(gpu); return isPrime; } - public static bool IsPrimeGpu(HeuristicCombinedPrimeTesterAccelerator gpu, ulong n) + public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n) { byte nMod10 = (byte)n.Mod10(); ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n); return IsPrimeGpu(gpu, n, maxDivisorSquare, nMod10); } - public static bool IsPrimeGpu(HeuristicCombinedPrimeTesterAccelerator 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? if (maxDivisorSquare < 9UL) @@ -233,10 +233,8 @@ public sealed class HeuristicCombinedPrimeTester }; - private static bool HeuristicTrialDivisionGpuDetectsDivisor(HeuristicCombinedPrimeTesterAccelerator gpu, ulong n, ulong maxDivisorSquare, byte nMod10) + private static bool HeuristicTrialDivisionGpuDetectsDivisor(PrimeOrderCalculatorAccelerator gpu, ulong n, ulong maxDivisorSquare, byte nMod10) { - // GpuPrimeWorkLimiter.Acquire(); - // var gpu = HeuristicCombinedPrimeTesterAccelerator.Rent(1); var acceleratorIndex = gpu.AcceleratorIndex; var stream = AcceleratorStreamPool.Rent(acceleratorIndex); var kernel = gpu.HeuristicCombinedTrialDivisionKernel; @@ -264,7 +262,6 @@ public sealed class HeuristicCombinedPrimeTester // GpuPrimeWorkLimiter.Release(); compositeDetected = compositeFlag != 0; - HeuristicCombinedPrimeTesterAccelerator.Return(gpu); return compositeDetected; } @@ -499,7 +496,7 @@ public sealed class HeuristicCombinedPrimeTester [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ulong ResolveHeuristicCycleLength( - HeuristicCombinedPrimeTesterAccelerator gpu, + PrimeOrderCalculatorAccelerator gpu, ulong exponent, in HeuristicDivisorPreparation preparation, out bool cycleFromHint, diff --git a/PerfectNumbers.Core/HeuristicPrimeTester.cs b/PerfectNumbers.Core/HeuristicPrimeTester.cs index e0c3bde..8c19f45 100644 --- a/PerfectNumbers.Core/HeuristicPrimeTester.cs +++ b/PerfectNumbers.Core/HeuristicPrimeTester.cs @@ -243,7 +243,7 @@ public sealed class HeuristicPrimeTester private bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10) { // GpuPrimeWorkLimiter.Acquire(); - var gpu = HeuristicCombinedPrimeTesterAccelerator.Rent(1); + var gpu = PrimeOrderCalculatorAccelerator.Rent(1); int acceleratorIndex = gpu.AcceleratorIndex; var stream = AcceleratorStreamPool.Rent(acceleratorIndex); var kernel = gpu.HeuristicCombinedTrialDivisionKernel; @@ -316,7 +316,7 @@ public sealed class HeuristicPrimeTester // } AcceleratorStreamPool.Return(acceleratorIndex, stream); - gpu.Return(); + PrimeOrderCalculatorAccelerator.Return(gpu); // GpuPrimeWorkLimiter.Release(); return compositeDetected; } @@ -466,7 +466,7 @@ public sealed class HeuristicPrimeTester [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ulong ResolveHeuristicCycleLength( - HeuristicCombinedPrimeTesterAccelerator gpu, + PrimeOrderCalculatorAccelerator gpu, ulong exponent, in HeuristicDivisorPreparation preparation, out bool cycleFromHint, diff --git a/PerfectNumbers.Core/MersenneDivisorCycles.cs b/PerfectNumbers.Core/MersenneDivisorCycles.cs index 389ed8f..689707f 100644 --- a/PerfectNumbers.Core/MersenneDivisorCycles.cs +++ b/PerfectNumbers.Core/MersenneDivisorCycles.cs @@ -52,7 +52,7 @@ public class MersenneDivisorCycles return _smallCycles!; } - public static bool CycleEqualsExponent(HeuristicCombinedPrimeTesterAccelerator gpu, ulong divisor, in MontgomeryDivisorData divisorData, ulong exponent) + public static bool CycleEqualsExponent(PrimeOrderCalculatorAccelerator gpu, ulong divisor, in MontgomeryDivisorData divisorData, ulong exponent) { if (CycleEqualsExponentForMersenneCandidate(divisor, divisorData, exponent)) { @@ -260,7 +260,7 @@ public class MersenneDivisorCycles } public static bool TryCalculateCycleLengthForExponentCpu( - HeuristicCombinedPrimeTesterAccelerator gpu, + PrimeOrderCalculatorAccelerator gpu, ulong divisor, ulong exponent, in MontgomeryDivisorData divisorData, @@ -345,7 +345,7 @@ public class MersenneDivisorCycles } private static bool AccumulateFactors( - HeuristicCombinedPrimeTesterAccelerator gpu, + PrimeOrderCalculatorAccelerator gpu, ulong value, Dictionary counts) { @@ -377,7 +377,7 @@ public class MersenneDivisorCycles // private static ulong _tryFactorIntoCountsInternalHits; // private static ulong _tryCalculateCycleLengthHeuristicHits; - private static bool TryFactorIntoCountsInternal(HeuristicCombinedPrimeTesterAccelerator gpu, ulong value, Dictionary counts) + private static bool TryFactorIntoCountsInternal(PrimeOrderCalculatorAccelerator gpu, ulong value, Dictionary counts) { // The EvenPerfectBitScanner only requests factors for values >= 2 here. Leave the guard documented without executing it. // if (value <= 1UL) diff --git a/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs b/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs index 7123564..bf1b6a7 100644 --- a/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs +++ b/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs @@ -55,39 +55,34 @@ internal static partial class PrimeOrderCalculator ulong phi = prime - 1UL; PrimeOrderCalculatorAccelerator gpu = PrimeOrderCalculatorAccelerator.Rent(1); - HeuristicCombinedPrimeTesterAccelerator gpu2 = HeuristicCombinedPrimeTesterAccelerator.Rent(1); if (IsGpuHeuristicDevice && PrimeOrderGpuHeuristics.TryCalculateOrder(prime, previousOrder, config, divisorData, out ulong gpuOrder)) { PrimeOrderCalculatorAccelerator.Return(gpu); - HeuristicCombinedPrimeTesterAccelerator.Return(gpu2); return gpuOrder; } - PartialFactorResult phiFactors = PartialFactor(gpu, gpu2, phi, config); + PartialFactorResult phiFactors = PartialFactor(gpu, phi, config); ulong result; if (phiFactors.Factors is null) { result = prime <= PerfectNumberConstants.MaxQForDivisorCycles - ? CalculateByFactorizationGpu(gpu, gpu2, prime, divisorData) - : CalculateByFactorizationCpu(gpu, gpu2, prime, divisorData); + ? CalculateByFactorizationGpu(gpu, prime, divisorData) + : CalculateByFactorizationCpu(gpu, prime, divisorData); phiFactors.Dispose(); PrimeOrderCalculatorAccelerator.Return(gpu); - HeuristicCombinedPrimeTesterAccelerator.Return(gpu2); return result; } - result = RunHeuristicPipelineCpu(gpu, gpu2, prime, previousOrder, config, divisorData, phi, phiFactors); + result = RunHeuristicPipelineCpu(gpu, prime, previousOrder, config, divisorData, phi, phiFactors); phiFactors.Dispose(); PrimeOrderCalculatorAccelerator.Return(gpu); - HeuristicCombinedPrimeTesterAccelerator.Return(gpu2); return result; } private static ulong RunHeuristicPipelineCpu( PrimeOrderCalculatorAccelerator gpu, - HeuristicCombinedPrimeTesterAccelerator gpu2, ulong prime, ulong? previousOrder, in PrimeOrderSearchConfig config, @@ -104,7 +99,7 @@ internal static partial class PrimeOrderCalculator ulong candidateOrder = InitializeStartingOrderCpu(gpu, prime, phi, divisorData); candidateOrder = ExponentLoweringCpu(candidateOrder, prime, phiFactors, divisorData); - if (TryConfirmOrderCpu(gpu, gpu2, prime, candidateOrder, divisorData, config, out PartialFactorResult? orderFactors)) + if (TryConfirmOrderCpu(gpu, prime, candidateOrder, divisorData, config, out PartialFactorResult? orderFactors)) { // GpuPrimeWorkLimiter.Release(); return candidateOrder; @@ -114,10 +109,10 @@ internal static partial class PrimeOrderCalculator { orderFactors?.Dispose(); // GpuPrimeWorkLimiter.Release(); - return CalculateByFactorizationGpu(gpu, gpu2, prime, divisorData); + return CalculateByFactorizationGpu(gpu, prime, divisorData); } - if (TryHeuristicFinishCpu(gpu, gpu2, prime, candidateOrder, previousOrder, divisorData, config, phiFactors, orderFactors, out ulong order)) + if (TryHeuristicFinishCpu(gpu, prime, candidateOrder, previousOrder, divisorData, config, phiFactors, orderFactors, out ulong order)) { // GpuPrimeWorkLimiter.Release(); return order; @@ -346,7 +341,6 @@ internal static partial class PrimeOrderCalculator private static bool TryConfirmOrderCpu( PrimeOrderCalculatorAccelerator gpu, - HeuristicCombinedPrimeTesterAccelerator gpu2, ulong prime, ulong order, in MontgomeryDivisorData divisorData, @@ -365,7 +359,7 @@ internal static partial class PrimeOrderCalculator return false; } - PartialFactorResult factorization = PartialFactor(gpu, gpu2, order, config); + PartialFactorResult factorization = PartialFactor(gpu, order, config); if (factorization.Factors is null) { factorization.Dispose(); @@ -510,7 +504,6 @@ internal static partial class PrimeOrderCalculator private static bool TryHeuristicFinishCpu( PrimeOrderCalculatorAccelerator gpu, - HeuristicCombinedPrimeTesterAccelerator gpu2, ulong prime, ulong order, ulong? previousOrder, @@ -528,7 +521,7 @@ internal static partial class PrimeOrderCalculator } // Reuse the partial factorization from TryConfirmOrderCpu when available. - PartialFactorResult orderFactors = cachedOrderFactors ?? PartialFactor(gpu, gpu2, order, config); + PartialFactorResult orderFactors = cachedOrderFactors ?? PartialFactor(gpu, order, config); try { if (orderFactors.Factors is null) @@ -644,7 +637,7 @@ internal static partial class PrimeOrderCalculator bool equalsOne = powStepper.InitializeCpuIsUnity(candidate); powStepperInitialized = true; - if (equalsOne && TryConfirmCandidateCpu(gpu, gpu2, prime, candidate, divisorData, config, ref powUsed, powBudget)) + if (equalsOne && TryConfirmCandidateCpu(gpu, prime, candidate, divisorData, config, ref powUsed, powBudget)) { if (gpuPool is not null) { @@ -681,7 +674,7 @@ internal static partial class PrimeOrderCalculator continue; } - if (!TryConfirmCandidateCpu(gpu, gpu2, prime, candidate, divisorData, config, ref powUsed, powBudget)) + if (!TryConfirmCandidateCpu(gpu, prime, candidate, divisorData, config, ref powUsed, powBudget)) { continue; } @@ -892,9 +885,9 @@ internal static partial class PrimeOrderCalculator } } - private static bool TryConfirmCandidateCpu(PrimeOrderCalculatorAccelerator gpu, HeuristicCombinedPrimeTesterAccelerator gpu2, ulong prime, ulong candidate, in MontgomeryDivisorData divisorData, in PrimeOrderSearchConfig config, ref int powUsed, int powBudget) + private static bool TryConfirmCandidateCpu(PrimeOrderCalculatorAccelerator gpu, ulong prime, ulong candidate, in MontgomeryDivisorData divisorData, in PrimeOrderSearchConfig config, ref int powUsed, int powBudget) { - PartialFactorResult factorization = PartialFactor(gpu, gpu2, candidate, config); + PartialFactorResult factorization = PartialFactor(gpu, candidate, config); try { if (factorization.Factors is null) @@ -1092,7 +1085,7 @@ internal static partial class PrimeOrderCalculator private static bool _goToGpu = true; - private static PartialFactorResult PartialFactor(PrimeOrderCalculatorAccelerator gpu, HeuristicCombinedPrimeTesterAccelerator gpu2, ulong value, in PrimeOrderSearchConfig config) + private static PartialFactorResult PartialFactor(PrimeOrderCalculatorAccelerator gpu, ulong value, in PrimeOrderSearchConfig config) { if (value <= 1UL) { @@ -1182,7 +1175,7 @@ internal static partial class PrimeOrderCalculator bool goToGpu = Volatile.Read(ref _goToGpu); Volatile.Write(ref _goToGpu, !goToGpu); bool isPrime = goToGpu - ? HeuristicCombinedPrimeTester.IsPrimeGpu(gpu2, composite) + ? HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite) : PrimeTester.IsPrime(composite); // bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite); @@ -1255,7 +1248,7 @@ internal static partial class PrimeOrderCalculator // Console.WriteLine($"Partial factor pending hits {Volatile.Read(ref _partialFactorPendingHits)}"); // bool isPrime = PrimeTester.IsPrimeCpu(composite, CancellationToken.None); - bool isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu2, composite); + bool isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite); // bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite); entry = entry.WithPrimality(isPrime); @@ -1292,7 +1285,7 @@ internal static partial class PrimeOrderCalculator // Atomic.Add(ref _partialFactorCofactorHits, 1UL); // Console.WriteLine($"Partial factor cofactor hits {Volatile.Read(ref _partialFactorCofactorHits)}"); - cofactorIsPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu2, cofactor); + cofactorIsPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, cofactor); // cofactorIsPrime = PrimeTester.IsPrimeGpu(gpu, cofactor); // cofactorIsPrime = PrimeTester.IsPrimeGpu(cofactor); // cofactorIsPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(cofactor); @@ -1713,11 +1706,11 @@ internal static partial class PrimeOrderCalculator exponents = newExponentSpan; } - private static ulong CalculateByFactorizationCpu(PrimeOrderCalculatorAccelerator gpu, HeuristicCombinedPrimeTesterAccelerator gpu2, ulong prime, in MontgomeryDivisorData divisorData) + private static ulong CalculateByFactorizationCpu(PrimeOrderCalculatorAccelerator gpu, ulong prime, in MontgomeryDivisorData divisorData) { ulong phi = prime - 1UL; Dictionary counts = new(capacity: 8); - FactorCompletelyCpu(gpu2, phi, counts); + FactorCompletelyCpu(gpu, phi, counts); if (counts.Count == 0) { return phi; @@ -1761,7 +1754,7 @@ internal static partial class PrimeOrderCalculator return order; } - private static void FactorCompletelyCpu(HeuristicCombinedPrimeTesterAccelerator gpu, ulong value, Dictionary counts) + private static void FactorCompletelyCpu(PrimeOrderCalculatorAccelerator gpu, ulong value, Dictionary counts) { FactorCompletely(gpu, value, counts, knownComposite: false); } @@ -1771,7 +1764,7 @@ internal static partial class PrimeOrderCalculator // [ThreadStatic] // private static HeuristicPrimeTester? _tester; - private static void FactorCompletely(HeuristicCombinedPrimeTesterAccelerator gpu, ulong value, Dictionary counts, bool knownComposite) + private static void FactorCompletely(PrimeOrderCalculatorAccelerator gpu, ulong value, Dictionary counts, bool knownComposite) { if (value <= 1UL) { diff --git a/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs b/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs index e6ead45..b8bce1e 100644 --- a/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs +++ b/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs @@ -12,13 +12,13 @@ internal static partial class PrimeOrderCalculator private const int GpuSmallPrimeFactorSlots = 64; - private static ulong CalculateByFactorizationGpu(PrimeOrderCalculatorAccelerator gpu, HeuristicCombinedPrimeTesterAccelerator gpu2, ulong prime, in MontgomeryDivisorData divisorData) + private static ulong CalculateByFactorizationGpu(PrimeOrderCalculatorAccelerator gpu, ulong prime, in MontgomeryDivisorData divisorData) { ulong phi = prime - 1UL; Dictionary counts = gpu.Pow2ModEntriesToTestOnHost; counts.Clear(); - FactorCompletelyCpu(gpu2, phi, counts); + FactorCompletelyCpu(gpu, phi, counts); if (counts.Count == 0) { return phi;