Cache GPU divisor partial data on GPU path
This commit is contained in:
1 parent
cc281ab423
commit
69acd3dad9
5 files changed
+71
-17
No files matched your search
@@ -15,17 +15,17 @@ internal struct ExponentRemainderStepperGpu
|
|||||||
private GpuUInt128 _currentResidue;
|
private GpuUInt128 _currentResidue;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public ExponentRemainderStepperGpu(in MontgomeryDivisorData divisor)
|
public ExponentRemainderStepperGpu(in GpuDivisorPartialData divisor)
|
||||||
{
|
{
|
||||||
ulong modulus = divisor.Modulus;
|
ulong modulus = divisor.Modulus;
|
||||||
_modulus = modulus;
|
_modulus = modulus;
|
||||||
_modulusWide = new ReadOnlyGpuUInt128(modulus);
|
_modulusWide = divisor.ModulusWide;
|
||||||
PreviousExponent = 0UL;
|
PreviousExponent = 0UL;
|
||||||
_currentResidue = new GpuUInt128(1UL);
|
_currentResidue = new GpuUInt128(1UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public bool MatchesDivisor(in MontgomeryDivisorData divisor)
|
public bool MatchesDivisor(in GpuDivisorPartialData divisor)
|
||||||
{
|
{
|
||||||
return _modulus == divisor.Modulus;
|
return _modulus == divisor.Modulus;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using PerfectNumbers.Core;
|
||||||
|
|
||||||
|
namespace PerfectNumbers.Core.Gpu;
|
||||||
|
|
||||||
|
internal readonly struct GpuDivisorPartialData
|
||||||
|
{
|
||||||
|
public readonly ulong Modulus;
|
||||||
|
public readonly ReadOnlyGpuUInt128 ModulusWide;
|
||||||
|
private readonly MontgomeryDivisorData _montgomeryData;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private GpuDivisorPartialData(ulong modulus, ReadOnlyGpuUInt128 modulusWide, in MontgomeryDivisorData montgomeryData)
|
||||||
|
{
|
||||||
|
Modulus = modulus;
|
||||||
|
ModulusWide = modulusWide;
|
||||||
|
_montgomeryData = montgomeryData;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static GpuDivisorPartialData Create(ulong modulus)
|
||||||
|
{
|
||||||
|
MontgomeryDivisorData montgomery = MontgomeryDivisorData.FromModulus(modulus);
|
||||||
|
return new GpuDivisorPartialData(modulus, new ReadOnlyGpuUInt128(modulus), in montgomery);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static GpuDivisorPartialData FromMontgomery(in MontgomeryDivisorData divisor)
|
||||||
|
{
|
||||||
|
return new GpuDivisorPartialData(divisor.Modulus, new ReadOnlyGpuUInt128(divisor.Modulus), in divisor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MontgomeryDivisorData MontgomeryData
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => _montgomeryData;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,7 +30,7 @@ internal static class DivisorByDivisorKernels
|
|||||||
|
|
||||||
public static void EvaluateDivisorWithStepperKernel(
|
public static void EvaluateDivisorWithStepperKernel(
|
||||||
Index1D _,
|
Index1D _,
|
||||||
MontgomeryDivisorData divisor,
|
GpuDivisorPartialData divisor,
|
||||||
ulong divisorCycle,
|
ulong divisorCycle,
|
||||||
ulong firstCycleRemainder,
|
ulong firstCycleRemainder,
|
||||||
ArrayView<ulong> exponents,
|
ArrayView<ulong> exponents,
|
||||||
@@ -101,12 +101,12 @@ internal static class DivisorByDivisorKernels
|
|||||||
hits[globalIndex] = montgomeryResult == 1UL ? (byte)1 : (byte)0;
|
hits[globalIndex] = montgomeryResult == 1UL ? (byte)1 : (byte)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ComputeMontgomeryExponentKernel(Index1D index, MontgomeryDivisorData divisor, ArrayView<ulong> exponents, ArrayView<ulong> results)
|
public static void ComputeMontgomeryExponentKernel(Index1D index, GpuDivisorPartialData divisor, ArrayView<ulong> exponents, ArrayView<ulong> results)
|
||||||
{
|
{
|
||||||
ulong modulus = divisor.Modulus;
|
ulong modulus = divisor.Modulus;
|
||||||
// Each divisor flowing through this kernel follows q = 2kp + 1 with k >= 1, so modulus is always odd and exceeds one.
|
// Each divisor flowing through this kernel follows q = 2kp + 1 with k >= 1, so modulus is always odd and exceeds one.
|
||||||
ulong exponent = exponents[index];
|
ulong exponent = exponents[index];
|
||||||
ulong montgomeryResult = ULongExtensions.Pow2MontgomeryModWindowedGpuKeepMontgomery(divisor, exponent);
|
ulong montgomeryResult = ULongExtensions.Pow2MontgomeryModWindowedGpuKeepMontgomery(divisor.MontgomeryData, exponent);
|
||||||
results[index] = montgomeryResult;
|
results[index] = montgomeryResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@ using ILGPU.Runtime;
|
|||||||
namespace PerfectNumbers.Core.Gpu;
|
namespace PerfectNumbers.Core.Gpu;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Scans Mersenne divisors on the GPU for prime exponents p >= 31 using per-divisor Montgomery data.
|
/// Scans Mersenne divisors on the GPU for prime exponents p >= 31 using cached GPU divisor partial data.
|
||||||
/// Consumers must call <see cref="ConfigureFromMaxPrime"/> before invoking other members so the divisor limits are populated.
|
/// Consumers must call <see cref="ConfigureFromMaxPrime"/> before invoking other members so the divisor limits are populated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDivisorByDivisorTester
|
public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDivisorByDivisorTester
|
||||||
@@ -24,7 +24,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
// private bool _isConfigured;
|
// private bool _isConfigured;
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<Accelerator, Action<Index1D, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>, ArrayView<int>>> _kernelCache = new();
|
private readonly ConcurrentDictionary<Accelerator, Action<Index1D, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>, ArrayView<int>>> _kernelCache = new();
|
||||||
private readonly ConcurrentDictionary<Accelerator, Action<Index1D, MontgomeryDivisorData, ulong, ulong, ArrayView<ulong>, ArrayView<byte>>> _stepperKernelCache = new(AcceleratorReferenceComparer.Instance);
|
private readonly ConcurrentDictionary<Accelerator, Action<Index1D, GpuDivisorPartialData, ulong, ulong, ArrayView<ulong>, ArrayView<byte>>> _stepperKernelCache = new(AcceleratorReferenceComparer.Instance);
|
||||||
private readonly ConcurrentDictionary<Accelerator, ConcurrentBag<BatchResources>> _resourcePools = new(AcceleratorReferenceComparer.Instance);
|
private readonly ConcurrentDictionary<Accelerator, ConcurrentBag<BatchResources>> _resourcePools = new(AcceleratorReferenceComparer.Instance);
|
||||||
private readonly ConcurrentBag<GpuContextPool.GpuContextLease> _acceleratorPool = new();
|
private readonly ConcurrentBag<GpuContextPool.GpuContextLease> _acceleratorPool = new();
|
||||||
private readonly ConcurrentBag<DivisorScanSession> _sessionPool = new();
|
private readonly ConcurrentBag<DivisorScanSession> _sessionPool = new();
|
||||||
@@ -32,8 +32,8 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
private Action<Index1D, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>, ArrayView<int>> GetKernel(Accelerator accelerator) =>
|
private Action<Index1D, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>, ArrayView<int>> GetKernel(Accelerator accelerator) =>
|
||||||
_kernelCache.GetOrAdd(accelerator, acc => acc.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>, ArrayView<int>>(DivisorByDivisorKernels.CheckKernel));
|
_kernelCache.GetOrAdd(accelerator, acc => acc.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>, ArrayView<int>>(DivisorByDivisorKernels.CheckKernel));
|
||||||
|
|
||||||
private Action<Index1D, MontgomeryDivisorData, ulong, ulong, ArrayView<ulong>, ArrayView<byte>> GetStepperKernel(Accelerator accelerator) =>
|
private Action<Index1D, GpuDivisorPartialData, ulong, ulong, ArrayView<ulong>, ArrayView<byte>> GetStepperKernel(Accelerator accelerator) =>
|
||||||
_stepperKernelCache.GetOrAdd(accelerator, acc => acc.LoadAutoGroupedStreamKernel<Index1D, MontgomeryDivisorData, ulong, ulong, ArrayView<ulong>, ArrayView<byte>>(DivisorByDivisorKernels.EvaluateDivisorWithStepperKernel));
|
_stepperKernelCache.GetOrAdd(accelerator, acc => acc.LoadAutoGroupedStreamKernel<Index1D, GpuDivisorPartialData, ulong, ulong, ArrayView<ulong>, ArrayView<byte>>(DivisorByDivisorKernels.EvaluateDivisorWithStepperKernel));
|
||||||
|
|
||||||
|
|
||||||
public int GpuBatchSize
|
public int GpuBatchSize
|
||||||
@@ -258,7 +258,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
for (int i = 0; i < filteredCount; i++)
|
for (int i = 0; i < filteredCount; i++)
|
||||||
{
|
{
|
||||||
ulong divisorValue = filteredDivisorsSpan[i];
|
ulong divisorValue = filteredDivisorsSpan[i];
|
||||||
MontgomeryDivisorData divisorDataValue = MontgomeryDivisorData.FromModulus(divisorValue);
|
GpuDivisorPartialData divisorDataValue = GpuDivisorPartialData.Create(divisorValue);
|
||||||
ulong divisorCycle = ResolveDivisorCycle(divisorValue, prime, divisorDataValue);
|
ulong divisorCycle = ResolveDivisorCycle(divisorValue, prime, divisorDataValue);
|
||||||
if (divisorCycle != prime)
|
if (divisorCycle != prime)
|
||||||
{
|
{
|
||||||
@@ -305,11 +305,11 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static ulong ResolveDivisorCycle(ulong divisor, ulong prime, in MontgomeryDivisorData divisorData)
|
private static ulong ResolveDivisorCycle(ulong divisor, ulong prime, in GpuDivisorPartialData divisorData)
|
||||||
{
|
{
|
||||||
if (!MersenneDivisorCycles.TryCalculateCycleLengthForExponentGpu(divisor, prime, divisorData, out ulong computedCycle, out bool primeOrderFailed) || computedCycle == 0UL)
|
if (!MersenneDivisorCycles.TryCalculateCycleLengthForExponentGpu(divisor, prime, divisorData, out ulong computedCycle, out bool primeOrderFailed) || computedCycle == 0UL)
|
||||||
{
|
{
|
||||||
return MersenneDivisorCycles.CalculateCycleLength(divisor, divisorData, skipPrimeOrderHeuristic: primeOrderFailed);
|
return MersenneDivisorCycles.CalculateCycleLengthGpu(divisor, divisorData, skipPrimeOrderHeuristic: primeOrderFailed);
|
||||||
}
|
}
|
||||||
|
|
||||||
return computedCycle;
|
return computedCycle;
|
||||||
@@ -384,7 +384,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
private readonly MersenneNumberDivisorByDivisorGpuTester _owner;
|
private readonly MersenneNumberDivisorByDivisorGpuTester _owner;
|
||||||
private readonly GpuContextPool.GpuContextLease _lease;
|
private readonly GpuContextPool.GpuContextLease _lease;
|
||||||
private readonly Accelerator _accelerator;
|
private readonly Accelerator _accelerator;
|
||||||
private Action<Index1D, MontgomeryDivisorData, ulong, ulong, ArrayView<ulong>, ArrayView<byte>> _stepperKernel = null!;
|
private Action<Index1D, GpuDivisorPartialData, ulong, ulong, ArrayView<ulong>, ArrayView<byte>> _stepperKernel = null!;
|
||||||
private MemoryBuffer1D<ulong, Stride1D.Dense> _exponentsBuffer = null!;
|
private MemoryBuffer1D<ulong, Stride1D.Dense> _exponentsBuffer = null!;
|
||||||
private MemoryBuffer1D<byte, Stride1D.Dense> _hitBuffer = null!;
|
private MemoryBuffer1D<byte, Stride1D.Dense> _hitBuffer = null!;
|
||||||
private ulong[] _hostBuffer = null!;
|
private ulong[] _hostBuffer = null!;
|
||||||
@@ -459,10 +459,10 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
MontgomeryDivisorData cachedData = divisorData;
|
GpuDivisorPartialData cachedData = GpuDivisorPartialData.FromMontgomery(divisorData);
|
||||||
if (cachedData.Modulus != divisor)
|
if (cachedData.Modulus != divisor)
|
||||||
{
|
{
|
||||||
cachedData = MontgomeryDivisorData.FromModulus(divisor);
|
cachedData = GpuDivisorPartialData.Create(divisor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong cycle = divisorCycle;
|
ulong cycle = divisorCycle;
|
||||||
@@ -472,7 +472,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
{
|
{
|
||||||
if (!MersenneDivisorCycles.TryCalculateCycleLengthForExponentGpu(divisor, firstPrime, cachedData, out ulong computedCycle, out bool primeOrderFailed) || computedCycle == 0UL)
|
if (!MersenneDivisorCycles.TryCalculateCycleLengthForExponentGpu(divisor, firstPrime, cachedData, out ulong computedCycle, out bool primeOrderFailed) || computedCycle == 0UL)
|
||||||
{
|
{
|
||||||
cycle = MersenneDivisorCycles.CalculateCycleLength(divisor, cachedData, skipPrimeOrderHeuristic: primeOrderFailed);
|
cycle = MersenneDivisorCycles.CalculateCycleLengthGpu(divisor, cachedData, skipPrimeOrderHeuristic: primeOrderFailed);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -408,6 +408,22 @@ public class MersenneDivisorCycles
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static bool TryCalculateCycleLengthForExponentGpu(
|
||||||
|
ulong divisor,
|
||||||
|
ulong exponent,
|
||||||
|
in GpuDivisorPartialData divisorData,
|
||||||
|
out ulong cycleLength,
|
||||||
|
out bool primeOrderFailed) =>
|
||||||
|
TryCalculateCycleLengthForExponentGpu(divisor, exponent, divisorData.MontgomeryData, out cycleLength, out primeOrderFailed);
|
||||||
|
|
||||||
|
internal static ulong CalculateCycleLengthGpu(
|
||||||
|
ulong divisor,
|
||||||
|
in GpuDivisorPartialData divisorData,
|
||||||
|
bool skipPrimeOrderHeuristic = false)
|
||||||
|
{
|
||||||
|
return CalculateCycleLength(divisor, divisorData.MontgomeryData, skipPrimeOrderHeuristic);
|
||||||
|
}
|
||||||
|
|
||||||
private static bool AccumulateFactors(
|
private static bool AccumulateFactors(
|
||||||
ulong value,
|
ulong value,
|
||||||
Dictionary<ulong, int> counts)
|
Dictionary<ulong, int> counts)
|
||||||
|
|||||||
Reference in new issue
Block a user