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); remainder7 = (byte)((((divisorHigh % 7UL) * 2UL) + (divisorLow % 7UL)) % 7UL);
remainder11 = (byte)((((divisorHigh % 11UL) * 5UL) + (divisorLow % 11UL)) % 11UL); remainder11 = (byte)((((divisorHigh % 11UL) * 5UL) + (divisorLow % 11UL)) % 11UL);
var gpu = HeuristicCombinedPrimeTesterAccelerator.Rent(1); var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
while (divisor.CompareTo(limit) <= 0) 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 // 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. // the corresponding Mersenne number because the order of 2 modulo the divisor is exactly p.
processedAll = true; processedAll = true;
HeuristicCombinedPrimeTesterAccelerator.Return(gpu); PrimeOrderCalculatorAccelerator.Return(gpu);
return true; return true;
} }
@@ -263,7 +263,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
remainder11 = AddMod11(remainder11, step11); remainder11 = AddMod11(remainder11, step11);
} }
HeuristicCombinedPrimeTesterAccelerator.Return(gpu); PrimeOrderCalculatorAccelerator.Return(gpu);
processedAll = true; processedAll = true;
return false; return false;
} }
@@ -289,7 +289,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
processedAll = false; processedAll = false;
bool canAdvance = step <= limit; bool canAdvance = step <= limit;
var gpu = HeuristicCombinedPrimeTesterAccelerator.Rent(1); var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
if (!canAdvance) if (!canAdvance)
{ {
if (divisor <= limit) if (divisor <= limit)
@@ -319,7 +319,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
if (divisorCycle == prime) if (divisorCycle == prime)
{ {
processedAll = true; processedAll = true;
HeuristicCombinedPrimeTesterAccelerator.Return(gpu); PrimeOrderCalculatorAccelerator.Return(gpu);
return true; return true;
} }
@@ -370,7 +370,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
if (divisorCycle == prime) if (divisorCycle == prime)
{ {
processedAll = true; processedAll = true;
HeuristicCombinedPrimeTesterAccelerator.Return(gpu); PrimeOrderCalculatorAccelerator.Return(gpu);
return true; 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. // 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(); AcceleratorStream stream = accelerator.CreateStream();
LastDigitGpuTables.WarmUp(i, stream); LastDigitGpuTables.WarmUp(i, stream);
HeuristicCombinedPrimeTesterAccelerator.WarmUp(i, stream); HeuristicGpuCombinedTables.WarmUp(i, stream);
// SharedHeuristicGpuTables.EnsureStaticTables(accelerator, stream); // SharedHeuristicGpuTables.EnsureStaticTables(accelerator, stream);
// _ = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.None); // _ = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.None);
// KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream); // KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream);
@@ -109,12 +109,16 @@ public sealed class PrimeOrderCalculatorAccelerator
public MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxFactors; public MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxFactors;
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxResult; public readonly MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxResult;
public readonly HeuristicGpuCombinedDivisorTables DivisorTables;
public readonly Kernel SmallPrimeSieveKernel; public readonly Kernel SmallPrimeSieveKernel;
public readonly Kernel CheckFactorsKernel; public readonly Kernel CheckFactorsKernel;
public readonly Kernel ConvertToStandardKernel; public readonly Kernel ConvertToStandardKernel;
public readonly Kernel HeuristicCombinedTrialDivisionKernel;
public readonly Kernel KeepMontgomeryKernel; public readonly Kernel KeepMontgomeryKernel;
public readonly Kernel PollardRhoKernel; public readonly Kernel PollardRhoKernel;
public readonly Kernel Pow2ModWideKernel; public readonly Kernel Pow2ModWideKernel;
public Kernel SharesFactorKernel; public Kernel SharesFactorKernel;
@@ -186,16 +190,19 @@ public sealed class PrimeOrderCalculatorAccelerator
SpecialMaxCandidates = accelerator.Allocate1D<ulong>(specialMaxFactorCapacity); SpecialMaxCandidates = accelerator.Allocate1D<ulong>(specialMaxFactorCapacity);
SpecialMaxResult = accelerator.Allocate1D<ulong>(1); SpecialMaxResult = accelerator.Allocate1D<ulong>(1);
var sharedTables = LastDigitGpuTables.EnsureStaticTables(acceleratorIndex); var lastDigitSharedTables = LastDigitGpuTables.EnsureStaticTables(acceleratorIndex);
DevicePrimesLastOne = sharedTables.DevicePrimesLastOne; DevicePrimesLastOne = lastDigitSharedTables.DevicePrimesLastOne;
DevicePrimesLastSeven = sharedTables.DevicePrimesLastSeven; DevicePrimesLastSeven = lastDigitSharedTables.DevicePrimesLastSeven;
DevicePrimesLastThree = sharedTables.DevicePrimesLastThree; DevicePrimesLastThree = lastDigitSharedTables.DevicePrimesLastThree;
DevicePrimesLastNine = sharedTables.DevicePrimesLastNine; DevicePrimesLastNine = lastDigitSharedTables.DevicePrimesLastNine;
DevicePrimesPow2LastOne = sharedTables.DevicePrimesPow2LastOne; DevicePrimesPow2LastOne = lastDigitSharedTables.DevicePrimesPow2LastOne;
DevicePrimesPow2LastSeven = sharedTables.DevicePrimesPow2LastSeven; DevicePrimesPow2LastSeven = lastDigitSharedTables.DevicePrimesPow2LastSeven;
DevicePrimesPow2LastThree = sharedTables.DevicePrimesPow2LastThree; DevicePrimesPow2LastThree = lastDigitSharedTables.DevicePrimesPow2LastThree;
DevicePrimesPow2LastNine = sharedTables.DevicePrimesPow2LastNine; 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); var checkFactorsKernel = accelerator.LoadStreamKernel<int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.CheckFactorsKernel);
CheckFactorsKernel = KernelUtil.GetKernel(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); var convertKernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelConvertToStandard);
ConvertToStandardKernel = KernelUtil.GetKernel(convertKernel); 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); var keepKernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelKeepMontgomery);
KeepMontgomeryKernel = KernelUtil.GetKernel(keepKernel); KeepMontgomeryKernel = KernelUtil.GetKernel(keepKernel);
@@ -109,7 +109,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
// GpuPrimeWorkLimiter(); // GpuPrimeWorkLimiter();
// int acceleratorIndex = AcceleratorPool.Shared.Rent(); // int acceleratorIndex = AcceleratorPool.Shared.Rent();
// var accelerator = _accelerators[acceleratorIndex]; // var accelerator = _accelerators[acceleratorIndex];
var gpu = HeuristicCombinedPrimeTesterAccelerator.Rent(batchCapacity); var gpu = PrimeOrderCalculatorAccelerator.Rent(batchCapacity);
var acceleratorIndex = gpu.AcceleratorIndex; var acceleratorIndex = gpu.AcceleratorIndex;
var accelerator = gpu.Accelerator; var accelerator = gpu.Accelerator;
var stream = AcceleratorStreamPool.Rent(acceleratorIndex); var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
@@ -144,7 +144,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
AcceleratorStreamPool.Return(acceleratorIndex, stream); AcceleratorStreamPool.Return(acceleratorIndex, stream);
ReturnBatchResources(resources); ReturnBatchResources(resources);
HeuristicCombinedPrimeTesterAccelerator.Return(gpu); PrimeOrderCalculatorAccelerator.Return(gpu);
// Monitor.Exit(gpuLease.ExecutionLock); // Monitor.Exit(gpuLease.ExecutionLock);
// GpuPrimeWorkLimiter.Release(); // GpuPrimeWorkLimiter.Release();
@@ -188,7 +188,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
} }
private static bool CheckDivisors( private static bool CheckDivisors(
HeuristicCombinedPrimeTesterAccelerator gpu, PrimeOrderCalculatorAccelerator gpu,
ulong prime, ulong prime,
ulong allowedMax, ulong allowedMax,
Action<AcceleratorStream, Index1D, ArrayView<GpuDivisorPartialData>, ArrayView<int>, ArrayView<int>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>, ArrayView<int>> kernel, 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)] [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) 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 static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
private readonly MersenneNumberDivisorByDivisorGpuTester _owner; private readonly MersenneNumberDivisorByDivisorGpuTester _owner;
private readonly HeuristicCombinedPrimeTesterAccelerator _primeTesterAccelerator; private readonly PrimeOrderCalculatorAccelerator _primeTesterAccelerator;
private readonly Accelerator _accelerator; private readonly Accelerator _accelerator;
private readonly AcceleratorStream _stream; private readonly AcceleratorStream _stream;
private Action<AcceleratorStream, Index1D, ArrayView<GpuDivisorPartialData>, ArrayView<int>, ArrayView<int>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>, ArrayView<int>> _kernel = null!; 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; _owner = owner;
// GpuPrimeWorkLimiter.Acquire(); // GpuPrimeWorkLimiter.Acquire();
_primeTesterAccelerator = HeuristicCombinedPrimeTesterAccelerator.Rent(); _primeTesterAccelerator = PrimeOrderCalculatorAccelerator.Rent(1);
Accelerator accelerator = _primeTesterAccelerator.Accelerator; Accelerator accelerator = _primeTesterAccelerator.Accelerator;
_accelerator = accelerator; _accelerator = accelerator;
_stream = accelerator.CreateStream(); _stream = accelerator.CreateStream();
@@ -173,20 +173,20 @@ public sealed class HeuristicCombinedPrimeTester
{ {
byte nMod10 = (byte)n.Mod10(); byte nMod10 = (byte)n.Mod10();
ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n); ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n);
var gpu = HeuristicCombinedPrimeTesterAccelerator.Rent(1); var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
bool isPrime = IsPrimeGpu(gpu, n, maxDivisorSquare, nMod10); bool isPrime = IsPrimeGpu(gpu, n, maxDivisorSquare, nMod10);
HeuristicCombinedPrimeTesterAccelerator.Return(gpu); PrimeOrderCalculatorAccelerator.Return(gpu);
return isPrime; return isPrime;
} }
public static bool IsPrimeGpu(HeuristicCombinedPrimeTesterAccelerator gpu, ulong n) public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n)
{ {
byte nMod10 = (byte)n.Mod10(); byte nMod10 = (byte)n.Mod10();
ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n); ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n);
return IsPrimeGpu(gpu, n, maxDivisorSquare, nMod10); 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? // TODO: Is this condition ever met on the execution path in EvenPerfectBitScanner?
if (maxDivisorSquare < 9UL) 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 acceleratorIndex = gpu.AcceleratorIndex;
var stream = AcceleratorStreamPool.Rent(acceleratorIndex); var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
var kernel = gpu.HeuristicCombinedTrialDivisionKernel; var kernel = gpu.HeuristicCombinedTrialDivisionKernel;
@@ -264,7 +262,6 @@ public sealed class HeuristicCombinedPrimeTester
// GpuPrimeWorkLimiter.Release(); // GpuPrimeWorkLimiter.Release();
compositeDetected = compositeFlag != 0; compositeDetected = compositeFlag != 0;
HeuristicCombinedPrimeTesterAccelerator.Return(gpu);
return compositeDetected; return compositeDetected;
} }
@@ -499,7 +496,7 @@ public sealed class HeuristicCombinedPrimeTester
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static ulong ResolveHeuristicCycleLength( internal static ulong ResolveHeuristicCycleLength(
HeuristicCombinedPrimeTesterAccelerator gpu, PrimeOrderCalculatorAccelerator gpu,
ulong exponent, ulong exponent,
in HeuristicDivisorPreparation preparation, in HeuristicDivisorPreparation preparation,
out bool cycleFromHint, out bool cycleFromHint,
+3 -3
View File
@@ -243,7 +243,7 @@ public sealed class HeuristicPrimeTester
private bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10) private bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10)
{ {
// GpuPrimeWorkLimiter.Acquire(); // GpuPrimeWorkLimiter.Acquire();
var gpu = HeuristicCombinedPrimeTesterAccelerator.Rent(1); var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
int acceleratorIndex = gpu.AcceleratorIndex; int acceleratorIndex = gpu.AcceleratorIndex;
var stream = AcceleratorStreamPool.Rent(acceleratorIndex); var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
var kernel = gpu.HeuristicCombinedTrialDivisionKernel; var kernel = gpu.HeuristicCombinedTrialDivisionKernel;
@@ -316,7 +316,7 @@ public sealed class HeuristicPrimeTester
// } // }
AcceleratorStreamPool.Return(acceleratorIndex, stream); AcceleratorStreamPool.Return(acceleratorIndex, stream);
gpu.Return(); PrimeOrderCalculatorAccelerator.Return(gpu);
// GpuPrimeWorkLimiter.Release(); // GpuPrimeWorkLimiter.Release();
return compositeDetected; return compositeDetected;
} }
@@ -466,7 +466,7 @@ public sealed class HeuristicPrimeTester
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static ulong ResolveHeuristicCycleLength( internal static ulong ResolveHeuristicCycleLength(
HeuristicCombinedPrimeTesterAccelerator gpu, PrimeOrderCalculatorAccelerator gpu,
ulong exponent, ulong exponent,
in HeuristicDivisorPreparation preparation, in HeuristicDivisorPreparation preparation,
out bool cycleFromHint, out bool cycleFromHint,
+4 -4
View File
@@ -52,7 +52,7 @@ public class MersenneDivisorCycles
return _smallCycles!; 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)) if (CycleEqualsExponentForMersenneCandidate(divisor, divisorData, exponent))
{ {
@@ -260,7 +260,7 @@ public class MersenneDivisorCycles
} }
public static bool TryCalculateCycleLengthForExponentCpu( public static bool TryCalculateCycleLengthForExponentCpu(
HeuristicCombinedPrimeTesterAccelerator gpu, PrimeOrderCalculatorAccelerator gpu,
ulong divisor, ulong divisor,
ulong exponent, ulong exponent,
in MontgomeryDivisorData divisorData, in MontgomeryDivisorData divisorData,
@@ -345,7 +345,7 @@ public class MersenneDivisorCycles
} }
private static bool AccumulateFactors( private static bool AccumulateFactors(
HeuristicCombinedPrimeTesterAccelerator gpu, PrimeOrderCalculatorAccelerator gpu,
ulong value, ulong value,
Dictionary<ulong, int> counts) Dictionary<ulong, int> counts)
{ {
@@ -377,7 +377,7 @@ public class MersenneDivisorCycles
// private static ulong _tryFactorIntoCountsInternalHits; // private static ulong _tryFactorIntoCountsInternalHits;
// private static ulong _tryCalculateCycleLengthHeuristicHits; // 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. // The EvenPerfectBitScanner only requests factors for values >= 2 here. Leave the guard documented without executing it.
// if (value <= 1UL) // if (value <= 1UL)
+21 -28
View File
@@ -55,39 +55,34 @@ internal static partial class PrimeOrderCalculator
ulong phi = prime - 1UL; ulong phi = prime - 1UL;
PrimeOrderCalculatorAccelerator gpu = PrimeOrderCalculatorAccelerator.Rent(1); PrimeOrderCalculatorAccelerator gpu = PrimeOrderCalculatorAccelerator.Rent(1);
HeuristicCombinedPrimeTesterAccelerator gpu2 = HeuristicCombinedPrimeTesterAccelerator.Rent(1);
if (IsGpuHeuristicDevice && PrimeOrderGpuHeuristics.TryCalculateOrder(prime, previousOrder, config, divisorData, out ulong gpuOrder)) if (IsGpuHeuristicDevice && PrimeOrderGpuHeuristics.TryCalculateOrder(prime, previousOrder, config, divisorData, out ulong gpuOrder))
{ {
PrimeOrderCalculatorAccelerator.Return(gpu); PrimeOrderCalculatorAccelerator.Return(gpu);
HeuristicCombinedPrimeTesterAccelerator.Return(gpu2);
return gpuOrder; return gpuOrder;
} }
PartialFactorResult phiFactors = PartialFactor(gpu, gpu2, phi, config); PartialFactorResult phiFactors = PartialFactor(gpu, phi, config);
ulong result; ulong result;
if (phiFactors.Factors is null) if (phiFactors.Factors is null)
{ {
result = prime <= PerfectNumberConstants.MaxQForDivisorCycles result = prime <= PerfectNumberConstants.MaxQForDivisorCycles
? CalculateByFactorizationGpu(gpu, gpu2, prime, divisorData) ? CalculateByFactorizationGpu(gpu, prime, divisorData)
: CalculateByFactorizationCpu(gpu, gpu2, prime, divisorData); : CalculateByFactorizationCpu(gpu, prime, divisorData);
phiFactors.Dispose(); phiFactors.Dispose();
PrimeOrderCalculatorAccelerator.Return(gpu); PrimeOrderCalculatorAccelerator.Return(gpu);
HeuristicCombinedPrimeTesterAccelerator.Return(gpu2);
return result; return result;
} }
result = RunHeuristicPipelineCpu(gpu, gpu2, prime, previousOrder, config, divisorData, phi, phiFactors); result = RunHeuristicPipelineCpu(gpu, prime, previousOrder, config, divisorData, phi, phiFactors);
phiFactors.Dispose(); phiFactors.Dispose();
PrimeOrderCalculatorAccelerator.Return(gpu); PrimeOrderCalculatorAccelerator.Return(gpu);
HeuristicCombinedPrimeTesterAccelerator.Return(gpu2);
return result; return result;
} }
private static ulong RunHeuristicPipelineCpu( private static ulong RunHeuristicPipelineCpu(
PrimeOrderCalculatorAccelerator gpu, PrimeOrderCalculatorAccelerator gpu,
HeuristicCombinedPrimeTesterAccelerator gpu2,
ulong prime, ulong prime,
ulong? previousOrder, ulong? previousOrder,
in PrimeOrderSearchConfig config, in PrimeOrderSearchConfig config,
@@ -104,7 +99,7 @@ internal static partial class PrimeOrderCalculator
ulong candidateOrder = InitializeStartingOrderCpu(gpu, prime, phi, divisorData); ulong candidateOrder = InitializeStartingOrderCpu(gpu, prime, phi, divisorData);
candidateOrder = ExponentLoweringCpu(candidateOrder, prime, phiFactors, 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(); // GpuPrimeWorkLimiter.Release();
return candidateOrder; return candidateOrder;
@@ -114,10 +109,10 @@ internal static partial class PrimeOrderCalculator
{ {
orderFactors?.Dispose(); orderFactors?.Dispose();
// GpuPrimeWorkLimiter.Release(); // 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(); // GpuPrimeWorkLimiter.Release();
return order; return order;
@@ -346,7 +341,6 @@ internal static partial class PrimeOrderCalculator
private static bool TryConfirmOrderCpu( private static bool TryConfirmOrderCpu(
PrimeOrderCalculatorAccelerator gpu, PrimeOrderCalculatorAccelerator gpu,
HeuristicCombinedPrimeTesterAccelerator gpu2,
ulong prime, ulong prime,
ulong order, ulong order,
in MontgomeryDivisorData divisorData, in MontgomeryDivisorData divisorData,
@@ -365,7 +359,7 @@ internal static partial class PrimeOrderCalculator
return false; return false;
} }
PartialFactorResult factorization = PartialFactor(gpu, gpu2, order, config); PartialFactorResult factorization = PartialFactor(gpu, order, config);
if (factorization.Factors is null) if (factorization.Factors is null)
{ {
factorization.Dispose(); factorization.Dispose();
@@ -510,7 +504,6 @@ internal static partial class PrimeOrderCalculator
private static bool TryHeuristicFinishCpu( private static bool TryHeuristicFinishCpu(
PrimeOrderCalculatorAccelerator gpu, PrimeOrderCalculatorAccelerator gpu,
HeuristicCombinedPrimeTesterAccelerator gpu2,
ulong prime, ulong prime,
ulong order, ulong order,
ulong? previousOrder, ulong? previousOrder,
@@ -528,7 +521,7 @@ internal static partial class PrimeOrderCalculator
} }
// Reuse the partial factorization from TryConfirmOrderCpu when available. // Reuse the partial factorization from TryConfirmOrderCpu when available.
PartialFactorResult orderFactors = cachedOrderFactors ?? PartialFactor(gpu, gpu2, order, config); PartialFactorResult orderFactors = cachedOrderFactors ?? PartialFactor(gpu, order, config);
try try
{ {
if (orderFactors.Factors is null) if (orderFactors.Factors is null)
@@ -644,7 +637,7 @@ internal static partial class PrimeOrderCalculator
bool equalsOne = powStepper.InitializeCpuIsUnity(candidate); bool equalsOne = powStepper.InitializeCpuIsUnity(candidate);
powStepperInitialized = true; 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) if (gpuPool is not null)
{ {
@@ -681,7 +674,7 @@ internal static partial class PrimeOrderCalculator
continue; continue;
} }
if (!TryConfirmCandidateCpu(gpu, gpu2, prime, candidate, divisorData, config, ref powUsed, powBudget)) if (!TryConfirmCandidateCpu(gpu, prime, candidate, divisorData, config, ref powUsed, powBudget))
{ {
continue; 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 try
{ {
if (factorization.Factors is null) if (factorization.Factors is null)
@@ -1092,7 +1085,7 @@ internal static partial class PrimeOrderCalculator
private static bool _goToGpu = true; 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) if (value <= 1UL)
{ {
@@ -1182,7 +1175,7 @@ internal static partial class PrimeOrderCalculator
bool goToGpu = Volatile.Read(ref _goToGpu); bool goToGpu = Volatile.Read(ref _goToGpu);
Volatile.Write(ref _goToGpu, !goToGpu); Volatile.Write(ref _goToGpu, !goToGpu);
bool isPrime = goToGpu bool isPrime = goToGpu
? HeuristicCombinedPrimeTester.IsPrimeGpu(gpu2, composite) ? HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite)
: PrimeTester.IsPrime(composite); : PrimeTester.IsPrime(composite);
// bool isPrime = Open.Numeric.Primes.Prime.Numbers.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)}"); // Console.WriteLine($"Partial factor pending hits {Volatile.Read(ref _partialFactorPendingHits)}");
// bool isPrime = PrimeTester.IsPrimeCpu(composite, CancellationToken.None); // 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); // bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite);
entry = entry.WithPrimality(isPrime); entry = entry.WithPrimality(isPrime);
@@ -1292,7 +1285,7 @@ internal static partial class PrimeOrderCalculator
// Atomic.Add(ref _partialFactorCofactorHits, 1UL); // Atomic.Add(ref _partialFactorCofactorHits, 1UL);
// Console.WriteLine($"Partial factor cofactor hits {Volatile.Read(ref _partialFactorCofactorHits)}"); // 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(gpu, cofactor);
// cofactorIsPrime = PrimeTester.IsPrimeGpu(cofactor); // cofactorIsPrime = PrimeTester.IsPrimeGpu(cofactor);
// cofactorIsPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(cofactor); // cofactorIsPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(cofactor);
@@ -1713,11 +1706,11 @@ internal static partial class PrimeOrderCalculator
exponents = newExponentSpan; 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; ulong phi = prime - 1UL;
Dictionary<ulong, int> counts = new(capacity: 8); Dictionary<ulong, int> counts = new(capacity: 8);
FactorCompletelyCpu(gpu2, phi, counts); FactorCompletelyCpu(gpu, phi, counts);
if (counts.Count == 0) if (counts.Count == 0)
{ {
return phi; return phi;
@@ -1761,7 +1754,7 @@ internal static partial class PrimeOrderCalculator
return order; 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); FactorCompletely(gpu, value, counts, knownComposite: false);
} }
@@ -1771,7 +1764,7 @@ internal static partial class PrimeOrderCalculator
// [ThreadStatic] // [ThreadStatic]
// private static HeuristicPrimeTester? _tester; // 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) if (value <= 1UL)
{ {
@@ -12,13 +12,13 @@ internal static partial class PrimeOrderCalculator
private const int GpuSmallPrimeFactorSlots = 64; 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; ulong phi = prime - 1UL;
Dictionary<ulong, int> counts = gpu.Pow2ModEntriesToTestOnHost; Dictionary<ulong, int> counts = gpu.Pow2ModEntriesToTestOnHost;
counts.Clear(); counts.Clear();
FactorCompletelyCpu(gpu2, phi, counts); FactorCompletelyCpu(gpu, phi, counts);
if (counts.Count == 0) if (counts.Count == 0)
{ {
return phi; return phi;