Hybrid device mode implemented as the current --mersenne=bydivisor CPU execution path. CPU path is now limited to CPU calculations, only.

This commit is contained in:
mlemanczyk committed 2025-12-01 03:45:39 +01:00
1 parent 353a121d03
commit 941733905b
49 files changed
+4965 -1726

No files matched your search

@@ -511,13 +511,12 @@ public sealed partial class MersenneNumberDivisorByDivisorGpuTester : IMersenneN
return composite;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
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.TryCalculateCycleLengthForExponentGpu(gpu, divisor, prime, divisorData, out ulong computedCycle, out bool primeOrderFailed) || computedCycle == 0UL)
{
return MersenneDivisorCycles.CalculateCycleLength(gpu, divisor, divisorData, skipPrimeOrderHeuristic: primeOrderFailed);
return MersenneDivisorCycles.CalculateCycleLengthGpu(gpu, divisor, divisorData, skipPrimeOrderHeuristic: primeOrderFailed);
}
return computedCycle;
@@ -729,9 +728,9 @@ public sealed partial class MersenneNumberDivisorByDivisorGpuTester : IMersenneN
var gpu = _primeOrderCalculatorAccelerator;
if (cycle == 0UL)
{
if (!MersenneDivisorCycles.TryCalculateCycleLengthForExponentCpu(gpu, divisor, firstPrime, divisorData, out ulong computedCycle, out bool primeOrderFailed) || computedCycle == 0UL)
if (!MersenneDivisorCycles.TryCalculateCycleLengthForExponentCpu(divisor, firstPrime, divisorData, out ulong computedCycle, out bool primeOrderFailed) || computedCycle == 0UL)
{
cycle = MersenneDivisorCycles.CalculateCycleLength(gpu, divisor, divisorData, skipPrimeOrderHeuristic: primeOrderFailed);
cycle = MersenneDivisorCycles.CalculateCycleLengthGpu(gpu, divisor, divisorData, skipPrimeOrderHeuristic: primeOrderFailed);
}
else
{
@@ -125,7 +125,6 @@ public sealed class MersenneNumberDivisorGpuTester
}
UInt128 kMul2;
var divisorCycles = MersenneDivisorCycles.Shared;
UInt128 maxK2 = UInt128.MaxValue / ((UInt128)p << 1);
ulong limit = divisorCyclesSearchLimit;
if ((UInt128)limit > maxK2)
@@ -143,7 +142,7 @@ public sealed class MersenneNumberDivisorGpuTester
continue;
}
UInt128 cycle128 = MersenneDivisorCycles.GetCycle(gpu, d);
UInt128 cycle128 = MersenneDivisorCycles.GetCycleGpu(gpu, d);
if ((UInt128)p % cycle128 != UInt128.Zero)
{
continue;
@@ -143,7 +143,7 @@ public class MersenneNumberLucasLehmerGpuTester
return false;
}
if ((exponent & 3UL) == 1UL && exponent.SharesFactorWithExponentMinusOne(gpu))
if ((exponent & 3UL) == 1UL && exponent.SharesFactorWithExponentMinusOneGpu(gpu))
{
return false;
}
@@ -2,6 +2,7 @@ using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using ILGPU;
using ILGPU.Runtime;
using PerfectNumbers.Core.Gpu.Accelerators;
namespace PerfectNumbers.Core.Gpu;
@@ -21,18 +22,16 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
// TODO: When cycles are missing for larger q values, compute only the single required cycle on the device
// requested by the caller, skip queuing additional block generation, and keep the snapshot cache untouched.
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
// GPU residue variant: check 2^p % q == 1 for q = 2*p*k + 1.
public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
public void Scan(PrimeOrderCalculatorAccelerator gpu, ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
{
// GpuPrimeWorkLimiter.Acquire();
var acceleratorIndex = AcceleratorPool.Shared.Rent();
var accelerator = _accelerators[acceleratorIndex];
var acceleratorIndex = gpu.AcceleratorIndex;
var accelerator = gpu.Accelerator;
// Monitor.Enter(gpuLease.ExecutionLock);
var stream = accelerator.CreateStream();
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
var kernel = GetPow2ModKernel(accelerator);
var resources = RentResources(accelerator, GpuConstants.ScanBatchSize);
var gpuKernels = GpuKernelPool.GetOrAddKernels(acceleratorIndex, stream, KernelType.SmallCycles | KernelType.SmallPrimes);
@@ -109,7 +108,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
}
ReturnResources(resources);
stream.Dispose();
AcceleratorStreamPool.Return(acceleratorIndex, stream);
// Monitor.Exit(gpuLease.ExecutionLock);
gpuKernels.Dispose();
// GpuPrimeWorkLimiter.Release();
@@ -248,18 +248,9 @@ internal static partial class PrimeOrderGpuHeuristics
{
order = 0UL;
// GpuPrimeWorkLimiter.Acquire();
int acceleratorIndex = gpu.AcceleratorIndex;
var smallPrimesView = gpu.SmallPrimeFactorPrimes;
var smallSquaresView = gpu.SmallPrimeFactorSquares;
// var phiFactorBufferView = gpu.PhiFactorBufferView;
// var phiExponentBufferView = gpu.PhiExponentBufferView;
// var workFactorBufferView = gpu.WorkFactorBufferView;
// var workExponentBufferView = gpu.WorkExponentBufferView;
// var candidateBufferView = gpu.CandidateBufferView;
// var stackIndexBufferView = gpu.StackIndexBufferView;
// var stackExponentBufferView = gpu.StackExponentBufferView;
// var stackProductBufferView = gpu.StackProductBufferView;
var resultBufferView = gpu.OutputUlongView2;
var statusBufferView = gpu.OutputByteView;
@@ -274,14 +265,6 @@ internal static partial class PrimeOrderGpuHeuristics
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
// TODO: Remove the cleaning after the order kernel is modified to always set the result.
// phiFactorBufferView.MemSetToZero(stream);
// phiExponentBufferView.MemSetToZero(stream);
// workFactorBufferView.MemSetToZero(stream);
// workExponentBufferView.MemSetToZero(stream);
// candidateBufferView.MemSetToZero(stream);
// stackIndexBufferView.MemSetToZero(stream);
// stackExponentBufferView.MemSetToZero(stream);
// stackProductBufferView.MemSetToZero(stream);
resultBufferView.MemSetToZero(stream);
statusBufferView.MemSetToZero(stream);
@@ -307,7 +290,6 @@ internal static partial class PrimeOrderGpuHeuristics
stream.Synchronize();
AcceleratorStreamPool.Return(acceleratorIndex, stream);
// GpuPrimeWorkLimiter.Release();
PrimeOrderKernelStatus kernelStatus = (PrimeOrderKernelStatus)status;
if (kernelStatus == PrimeOrderKernelStatus.Fallback)