HeuristicCombinedPrimeTesterAccelerator integrated with PrimeOrderCalculatorAccelerator.

This commit is contained in:
mlemanczyk committed 2025-11-17 17:38:23 +01:00
1 parent 183b147135
commit f630bfb598
9 files changed
+67 -215

No files matched your search

@@ -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;
}
@@ -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<HeuristicCombinedPrimeTesterAccelerator>? 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<HeuristicCombinedPrimeTesterAccelerator>();
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<ulong, Stride1D.Dense>? Input = null;
public MemoryBuffer1D<byte, Stride1D.Dense>? Output = null;
public MemoryBuffer1D<int, Stride1D.Dense>? HeuristicFlag = null!;
public int BufferCapacity;
private HeuristicGpuCombinedTables _sharedTables;
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding1 => _sharedTables.HeuristicCombinedDivisorsEnding1;
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding1 => _sharedTables.HeuristicCombinedDivisorSquaresEnding1;
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding3 => _sharedTables.HeuristicCombinedDivisorsEnding3;
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding3 => _sharedTables.HeuristicCombinedDivisorSquaresEnding3;
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding7 => _sharedTables.HeuristicCombinedDivisorsEnding7;
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding7 => _sharedTables.HeuristicCombinedDivisorSquaresEnding7;
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding9 => _sharedTables.HeuristicCombinedDivisorsEnding9;
public MemoryBuffer1D<ulong, Stride1D.Dense> 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<Index1D, byte, ArrayView<int>, 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<ulong>(minCapacity);
Output = Accelerator.Allocate1D<byte>(minCapacity);
HeuristicFlag = Accelerator.Allocate1D<int>(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();
}
}
@@ -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<ulong, Stride1D.Dense> SpecialMaxFactors;
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> 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<ulong>(specialMaxFactorCapacity);
SpecialMaxResult = accelerator.Allocate1D<ulong>(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<int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.CheckFactorsKernel);
CheckFactorsKernel = KernelUtil.GetKernel(checkFactorsKernel);
@@ -203,6 +210,8 @@ public sealed class PrimeOrderCalculatorAccelerator
var convertKernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelConvertToStandard);
ConvertToStandardKernel = KernelUtil.GetKernel(convertKernel);
HeuristicCombinedTrialDivisionKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicGpuCombinedDivisorTables>(PrimeTesterKernels.HeuristicTrialCombinedDivisionKernel));
var keepKernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelKeepMontgomery);
KeepMontgomeryKernel = KernelUtil.GetKernel(keepKernel);
@@ -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<AcceleratorStream, Index1D, ArrayView<GpuDivisorPartialData>, ArrayView<int>, ArrayView<int>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>, ArrayView<int>> 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<AcceleratorStream, Index1D, ArrayView<GpuDivisorPartialData>, ArrayView<int>, ArrayView<int>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>, ArrayView<int>> _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();
@@ -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,
+3 -3
View File
@@ -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,
+4 -4
View File
@@ -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<ulong, int> 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<ulong, int> counts)
private static bool TryFactorIntoCountsInternal(PrimeOrderCalculatorAccelerator gpu, ulong value, Dictionary<ulong, int> counts)
{
// The EvenPerfectBitScanner only requests factors for values >= 2 here. Leave the guard documented without executing it.
// if (value <= 1UL)
+21 -28
View File
@@ -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<ulong, int> 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<ulong, int> counts)
private static void FactorCompletelyCpu(PrimeOrderCalculatorAccelerator gpu, ulong value, Dictionary<ulong, int> 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<ulong, int> counts, bool knownComposite)
private static void FactorCompletely(PrimeOrderCalculatorAccelerator gpu, ulong value, Dictionary<ulong, int> counts, bool knownComposite)
{
if (value <= 1UL)
{
@@ -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<ulong, int> counts = gpu.Pow2ModEntriesToTestOnHost;
counts.Clear();
FactorCompletelyCpu(gpu2, phi, counts);
FactorCompletelyCpu(gpu, phi, counts);
if (counts.Count == 0)
{
return phi;