Optimize by-divisor cycle exponent reductions

This commit is contained in:
Marek Lemańczyk committed 2025-09-24 22:33:41 +02:00
1 parent a1abe71279
commit 760b941c06
1 file changed
+67 -48
@@ -315,28 +315,38 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
// Removed noisy console output; status is tracked internally only. // Removed noisy console output; status is tracked internally only.
} }
private static void CheckKernel(Index1D index, ulong prime, byte useCycleChecks, ArrayView<MontgomeryDivisorData> divisors, ArrayView<byte> hits) private static void CheckKernel(Index1D index, ulong prime, byte useCycleChecks, ArrayView<MontgomeryDivisorData> divisors, ArrayView<byte> hits)
{ {
MontgomeryDivisorData divisor = divisors[index]; MontgomeryDivisorData divisor = divisors[index];
ulong modulus = divisor.Modulus; ulong modulus = divisor.Modulus;
if (modulus <= 1UL || (modulus & 1UL) == 0UL) if (modulus <= 1UL || (modulus & 1UL) == 0UL)
{ {
hits[index] = 0; hits[index] = 0;
return; return;
} }
if (useCycleChecks != 0) ulong exponent = prime;
{ if (useCycleChecks != 0)
ulong cycle = MersenneDivisorCycles.CalculateCycleLengthGpu(modulus); {
if (cycle == 0UL || prime % cycle != 0UL) ulong cycle = MersenneDivisorCycles.CalculateCycleLengthGpu(modulus);
{ if (cycle == 0UL)
hits[index] = 0; {
return; hits[index] = 0;
} return;
} }
hits[index] = prime.Pow2MontgomeryMod(divisor) == 1UL ? (byte)1 : (byte)0; ulong remainder = prime % cycle;
} if (remainder != 0UL)
{
hits[index] = 0;
return;
}
exponent = remainder;
}
hits[index] = exponent.Pow2MontgomeryMod(divisor) == 1UL ? (byte)1 : (byte)0;
}
public sealed class DivisorScanSession : IDisposable public sealed class DivisorScanSession : IDisposable
{ {
@@ -426,7 +436,8 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
return; return;
} }
bool cycleEnabled = owner._useDivisorCycles && divisorCycle != 0UL; ulong cycle = divisorCycle;
bool cycleEnabled = owner._useDivisorCycles && cycle != 0UL;
Accelerator accelerator = _accelerator; Accelerator accelerator = _accelerator;
Action<Index1D, MontgomeryDivisorData, ArrayView<ulong>, ArrayView<ulong>> kernel = _kernel; Action<Index1D, MontgomeryDivisorData, ArrayView<ulong>, ArrayView<ulong>> kernel = _kernel;
@@ -452,18 +463,18 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
int computeCount = 0; int computeCount = 0;
Span<byte> cycleMaskSpan = default; Span<byte> cycleMaskSpan = default;
if (cycleEnabled) if (cycleEnabled)
{ {
cycleMaskSpan = _cycleMaskHost.AsSpan(0, batchSize); cycleMaskSpan = _cycleMaskHost.AsSpan(0, batchSize);
ArrayView1D<ulong, Stride1D.Dense> primeInputView = _resultsBuffer.View.SubView(0, batchSize); ArrayView1D<ulong, Stride1D.Dense> primeInputView = _resultsBuffer.View.SubView(0, batchSize);
primeInputView.CopyFromCPU(ref MemoryMarshal.GetReference(primesSlice), batchSize); primeInputView.CopyFromCPU(ref MemoryMarshal.GetReference(primesSlice), batchSize);
ArrayView1D<byte, Stride1D.Dense> cycleMaskView = cycleMaskViewFull.SubView(0, batchSize); ArrayView1D<byte, Stride1D.Dense> cycleMaskView = cycleMaskViewFull.SubView(0, batchSize);
cycleKernel(batchSize, divisorCycle, primeInputView, cycleMaskView); cycleKernel(batchSize, cycle, primeInputView, cycleMaskView);
accelerator.Synchronize(); accelerator.Synchronize();
cycleMaskView.CopyToCPU(ref MemoryMarshal.GetReference(cycleMaskSpan), batchSize); cycleMaskView.CopyToCPU(ref MemoryMarshal.GetReference(cycleMaskSpan), batchSize);
} }
for (int i = 0; i < batchSize; i++) for (int i = 0; i < batchSize; i++)
{ {
if (cycleEnabled && cycleMaskSpan[i] == 0) if (cycleEnabled && cycleMaskSpan[i] == 0)
{ {
@@ -480,24 +491,32 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
if (computeCount > 0) if (computeCount > 0)
{ {
Span<ulong> exponentSlice = hostSpan[..computeCount]; Span<ulong> exponentSlice = hostSpan[..computeCount];
ulong currentPrime = hasPreviousResidue ? previousPrime : 0UL; ulong currentPrime = hasPreviousResidue ? previousPrime : 0UL;
bool hasDeltaSource = hasPreviousResidue; bool hasDeltaSource = hasPreviousResidue;
for (int i = 0; i < computeCount; i++) for (int i = 0; i < computeCount; i++)
{ {
ulong prime = primeSpan[i]; ulong prime = primeSpan[i];
if (hasDeltaSource) ulong exponentValue;
{ if (hasDeltaSource)
exponentSlice[i] = prime - currentPrime; {
} exponentValue = prime - currentPrime;
else }
{ else
exponentSlice[i] = prime; {
hasDeltaSource = true; exponentValue = prime;
} hasDeltaSource = true;
}
currentPrime = prime; if (cycleEnabled)
} {
exponentValue %= cycle;
}
exponentSlice[i] = exponentValue;
currentPrime = prime;
}
ArrayView1D<ulong, Stride1D.Dense> exponentView = exponentsView.SubView(0, computeCount); ArrayView1D<ulong, Stride1D.Dense> exponentView = exponentsView.SubView(0, computeCount);
exponentView.CopyFromCPU(ref MemoryMarshal.GetReference(exponentSlice), computeCount); exponentView.CopyFromCPU(ref MemoryMarshal.GetReference(exponentSlice), computeCount);