Cache GPU remainder configs and fold constant modulos
This commit is contained in:
1 parent
0b43880959
commit
c6008a65b4
3 files changed
+32
-13
No files matched your search
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
@@ -122,6 +123,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
resources.CycleCandidates,
|
resources.CycleCandidates,
|
||||||
resources.CycleLengths,
|
resources.CycleLengths,
|
||||||
resources.CycleCapacity,
|
resources.CycleCapacity,
|
||||||
|
resources,
|
||||||
out lastProcessed,
|
out lastProcessed,
|
||||||
out coveredRange,
|
out coveredRange,
|
||||||
out processedCount
|
out processedCount
|
||||||
@@ -186,6 +188,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
ulong[] cycleCandidates,
|
ulong[] cycleCandidates,
|
||||||
ulong[] cycleLengths,
|
ulong[] cycleLengths,
|
||||||
int cycleCapacity,
|
int cycleCapacity,
|
||||||
|
BatchResources resources,
|
||||||
out ulong lastProcessed,
|
out ulong lastProcessed,
|
||||||
out bool coveredRange,
|
out bool coveredRange,
|
||||||
out ulong processedCount)
|
out ulong processedCount)
|
||||||
@@ -340,10 +343,10 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
|
|
||||||
gapView.CopyFromCPU(ref MemoryMarshal.GetReference(gapSpan), chunkCount);
|
gapView.CopyFromCPU(ref MemoryMarshal.GetReference(gapSpan), chunkCount);
|
||||||
|
|
||||||
ComputeRemaindersOnGpu(chunkCount, remainder10, 10, gapView, deltaView, remainder10View, remainderDeltaKernel, remainderScanKernel);
|
ComputeRemaindersOnGpu(chunkCount, remainder10, 10, gapView, deltaView, remainder10View, remainderDeltaKernel, remainderScanKernel, resources.GetRemainderScanConfig);
|
||||||
ComputeRemaindersOnGpu(chunkCount, remainder8, 8, gapView, deltaView, remainder8View, remainderDeltaKernel, remainderScanKernel);
|
ComputeRemaindersOnGpu(chunkCount, remainder8, 8, gapView, deltaView, remainder8View, remainderDeltaKernel, remainderScanKernel, resources.GetRemainderScanConfig);
|
||||||
ComputeRemaindersOnGpu(chunkCount, remainder5, 5, gapView, deltaView, remainder5View, remainderDeltaKernel, remainderScanKernel);
|
ComputeRemaindersOnGpu(chunkCount, remainder5, 5, gapView, deltaView, remainder5View, remainderDeltaKernel, remainderScanKernel, resources.GetRemainderScanConfig);
|
||||||
ComputeRemaindersOnGpu(chunkCount, remainder3, 3, gapView, deltaView, remainder3View, remainderDeltaKernel, remainderScanKernel);
|
ComputeRemaindersOnGpu(chunkCount, remainder3, 3, gapView, deltaView, remainder3View, remainderDeltaKernel, remainderScanKernel, resources.GetRemainderScanConfig);
|
||||||
|
|
||||||
BuildCandidateMaskOnGpu(chunkCount, remainder10View, remainder8View, remainder5View, remainder3View, lastIsSevenFlag, maskView, maskSpan, candidateMaskKernel);
|
BuildCandidateMaskOnGpu(chunkCount, remainder10View, remainder8View, remainder5View, remainder3View, lastIsSevenFlag, maskView, maskSpan, candidateMaskKernel);
|
||||||
|
|
||||||
@@ -461,7 +464,8 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
ArrayView1D<byte, Stride1D.Dense> deltaView,
|
ArrayView1D<byte, Stride1D.Dense> deltaView,
|
||||||
ArrayView1D<byte, Stride1D.Dense> remainderView,
|
ArrayView1D<byte, Stride1D.Dense> remainderView,
|
||||||
Action<Index1D, ArrayView<ulong>, ArrayView<byte>, byte> deltaKernel,
|
Action<Index1D, ArrayView<ulong>, ArrayView<byte>, byte> deltaKernel,
|
||||||
Action<KernelConfig, Index1D, ArrayView<byte>, ArrayView<byte>, byte, byte> scanKernel)
|
Action<KernelConfig, Index1D, ArrayView<byte>, ArrayView<byte>, byte, byte> scanKernel,
|
||||||
|
Func<int, KernelConfig> configProvider)
|
||||||
{
|
{
|
||||||
// GPU batches always contain at least one divisor gap, so the empty-count guard remains commented
|
// GPU batches always contain at least one divisor gap, so the empty-count guard remains commented
|
||||||
// to eliminate redundant branching.
|
// to eliminate redundant branching.
|
||||||
@@ -471,10 +475,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
deltaKernel(count, gapView, deltaView, modulus);
|
deltaKernel(count, gapView, deltaView, modulus);
|
||||||
SharedMemoryConfig sharedMemoryConfig = SharedMemoryConfig.RequestDynamic<int>(count);
|
KernelConfig kernelConfig = configProvider(count);
|
||||||
Index1D gridDim = new Index1D(1);
|
|
||||||
Index1D groupDim = new Index1D(count);
|
|
||||||
KernelConfig kernelConfig = new KernelConfig(gridDim, groupDim, sharedMemoryConfig);
|
|
||||||
|
|
||||||
scanKernel(kernelConfig, new Index1D(count), deltaView, remainderView, baseRemainder, modulus);
|
scanKernel(kernelConfig, new Index1D(count), deltaView, remainderView, baseRemainder, modulus);
|
||||||
}
|
}
|
||||||
@@ -906,10 +907,24 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
internal readonly Action<KernelConfig, Index1D, ArrayView<byte>, ArrayView<byte>, byte, byte> RemainderScanKernel;
|
internal readonly Action<KernelConfig, Index1D, ArrayView<byte>, ArrayView<byte>, byte, byte> RemainderScanKernel;
|
||||||
internal readonly Action<Index1D, ArrayView<byte>, ArrayView<byte>, ArrayView<byte>, ArrayView<byte>, byte, ArrayView<byte>> CandidateMaskKernel;
|
internal readonly Action<Index1D, ArrayView<byte>, ArrayView<byte>, ArrayView<byte>, ArrayView<byte>, byte, ArrayView<byte>> CandidateMaskKernel;
|
||||||
|
|
||||||
|
private readonly Dictionary<int, KernelConfig> _remainderScanConfigs = new();
|
||||||
|
|
||||||
internal readonly int Capacity;
|
internal readonly int Capacity;
|
||||||
|
|
||||||
internal readonly int CycleCapacity;
|
internal readonly int CycleCapacity;
|
||||||
|
|
||||||
|
internal KernelConfig GetRemainderScanConfig(int count)
|
||||||
|
{
|
||||||
|
if (!_remainderScanConfigs.TryGetValue(count, out KernelConfig config))
|
||||||
|
{
|
||||||
|
SharedMemoryConfig sharedMemoryConfig = SharedMemoryConfig.RequestDynamic<int>(count);
|
||||||
|
config = new KernelConfig(new Index1D(1), new Index1D(count), sharedMemoryConfig);
|
||||||
|
_remainderScanConfigs[count] = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
DivisorsBuffer.Dispose();
|
DivisorsBuffer.Dispose();
|
||||||
|
|||||||
@@ -1611,7 +1611,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
private static ulong CalculateByDoublingKernel(ulong prime)
|
private static ulong CalculateByDoublingKernel(ulong prime)
|
||||||
{
|
{
|
||||||
ulong order = 1UL;
|
ulong order = 1UL;
|
||||||
ulong value = 2UL % prime;
|
ulong value = 2UL; // Candidate primes exceed two, so the modulo would always return two.
|
||||||
|
|
||||||
while (value != 1UL)
|
while (value != 1UL)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -530,7 +530,9 @@ public static class ULongExtensions
|
|||||||
ulong modulus = divisor.Modulus;
|
ulong modulus = divisor.Modulus;
|
||||||
if (exponent == 0UL)
|
if (exponent == 0UL)
|
||||||
{
|
{
|
||||||
return keepMontgomery ? divisor.MontgomeryOne : 1UL % modulus;
|
return keepMontgomery
|
||||||
|
? divisor.MontgomeryOne
|
||||||
|
: 1UL; // Montgomery moduli stay above one on the scanning path, so the modulo would always yield one.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exponent <= Pow2WindowFallbackThreshold)
|
if (exponent <= Pow2WindowFallbackThreshold)
|
||||||
@@ -622,7 +624,9 @@ public static class ULongExtensions
|
|||||||
ulong modulus = divisor.Modulus;
|
ulong modulus = divisor.Modulus;
|
||||||
if (exponent == 0UL)
|
if (exponent == 0UL)
|
||||||
{
|
{
|
||||||
return keepMontgomery ? divisor.MontgomeryOne : 1UL % modulus;
|
return keepMontgomery
|
||||||
|
? divisor.MontgomeryOne
|
||||||
|
: 1UL; // Montgomery moduli stay above one on the scanning path, so the modulo would always yield one.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exponent <= Pow2WindowFallbackThreshold)
|
if (exponent <= Pow2WindowFallbackThreshold)
|
||||||
@@ -769,7 +773,7 @@ public static class ULongExtensions
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong baseValue = 2UL % modulus;
|
ulong baseValue = 2UL; // Moduli arrive as odd primes greater than two, so the modulo would always return two.
|
||||||
destination[0] = baseValue;
|
destination[0] = baseValue;
|
||||||
if (oddPowerCount == 1)
|
if (oddPowerCount == 1)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user