TODOs added

This commit is contained in:
Marek Lemańczyk committed 2025-09-25 01:07:58 +02:00
1 parent ed8b093472
commit bc4e526946
2 files changed
+643 -639

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -39,17 +39,17 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
private Action<Index1D, ulong, ArrayView<ulong>, ArrayView<byte>> GetCycleKernel(Accelerator accelerator) => private Action<Index1D, ulong, ArrayView<ulong>, ArrayView<byte>> GetCycleKernel(Accelerator accelerator) =>
_cycleKernelCache.GetOrAdd(accelerator, acc => acc.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView<ulong>, ArrayView<byte>>(CheckPrimeCycleKernel)); _cycleKernelCache.GetOrAdd(accelerator, acc => acc.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView<ulong>, ArrayView<byte>>(CheckPrimeCycleKernel));
public int GpuBatchSize public int GpuBatchSize
{ {
get => _gpuBatchSize; get => _gpuBatchSize;
set => _gpuBatchSize = Math.Max(1, value); set => _gpuBatchSize = Math.Max(1, value);
} }
int IMersenneNumberDivisorByDivisorTester.BatchSize int IMersenneNumberDivisorByDivisorTester.BatchSize
{ {
get => GpuBatchSize; get => GpuBatchSize;
set => GpuBatchSize = value; set => GpuBatchSize = value;
} }
public bool UseDivisorCycles public bool UseDivisorCycles
{ {
@@ -301,6 +301,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
return Math.Min((1UL << (int)(prime - 1UL)) - 1UL, divisorLimit); return Math.Min((1UL << (int)(prime - 1UL)) - 1UL, divisorLimit);
} }
// TODO: Since lastProcessed is unused, let's remove it.
private void UpdateStatusUnsafe(ulong lastProcessed, ulong processedCount) private void UpdateStatusUnsafe(ulong lastProcessed, ulong processedCount)
{ {
if (processedCount == 0UL) if (processedCount == 0UL)
@@ -315,47 +316,46 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
return; return;
} }
// Can we avoid the modulo calculation here? For the higher divisors it may become very expensive. Do we need to calculate the total, too?
ulong total = _lastStatusDivisor + processedCount; ulong total = _lastStatusDivisor + processedCount;
_lastStatusDivisor = total % interval; _lastStatusDivisor = total % interval;
// 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;
} }
ulong exponent = prime; ulong exponent = prime;
if (useCycleChecks != 0) if (useCycleChecks != 0)
{ {
ulong cycle = MersenneDivisorCycles.CalculateCycleLengthGpu(modulus); ulong cycle = MersenneDivisorCycles.CalculateCycleLengthGpu(modulus);
if (cycle == 0UL) if (cycle == 0UL)
{ {
hits[index] = 0; hits[index] = 0;
return; return;
} }
// TODO: Can we move this back before the GPU call and let CPU handle it? We significantly slowed down after this was moved to GPU.
ulong remainder = prime % cycle;
if (remainder != 0UL)
{
hits[index] = 0;
return;
}
ulong remainder = prime % cycle; exponent = remainder;
if (remainder != 0UL) }
{
hits[index] = 0;
return;
}
exponent = remainder; hits[index] = exponent.Pow2MontgomeryMod(divisor) == 1UL ? (byte)1 : (byte)0;
} }
hits[index] = exponent.Pow2MontgomeryMod(divisor) == 1UL ? (byte)1 : (byte)0; public sealed class DivisorScanSession : IMersenneNumberDivisorByDivisorTester.IDivisorScanSession
} {
public sealed class DivisorScanSession : IMersenneNumberDivisorByDivisorTester.IDivisorScanSession
{
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;
@@ -442,8 +442,8 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
return; return;
} }
ulong cycle = divisorCycle; ulong cycle = divisorCycle;
bool cycleEnabled = owner._useDivisorCycles && cycle != 0UL; 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;
@@ -469,18 +469,19 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
int computeCount = 0; int computeCount = 0;
Span<byte> cycleMaskSpan = default; Span<byte> cycleMaskSpan = default;
if (cycleEnabled) if (cycleEnabled)
{ {
cycleMaskSpan = _cycleMaskHost.AsSpan(0, batchSize); // TODO: Can we move this back before the GPU call and let CPU handle it? We significantly slowed down after this was moved to GPU.
ArrayView1D<ulong, Stride1D.Dense> primeInputView = _resultsBuffer.View.SubView(0, batchSize); cycleMaskSpan = _cycleMaskHost.AsSpan(0, batchSize);
primeInputView.CopyFromCPU(ref MemoryMarshal.GetReference(primesSlice), batchSize); ArrayView1D<ulong, Stride1D.Dense> primeInputView = _resultsBuffer.View.SubView(0, batchSize);
ArrayView1D<byte, Stride1D.Dense> cycleMaskView = cycleMaskViewFull.SubView(0, batchSize); primeInputView.CopyFromCPU(ref MemoryMarshal.GetReference(primesSlice), batchSize);
cycleKernel(batchSize, cycle, primeInputView, cycleMaskView); ArrayView1D<byte, Stride1D.Dense> cycleMaskView = cycleMaskViewFull.SubView(0, batchSize);
accelerator.Synchronize(); cycleKernel(batchSize, cycle, primeInputView, cycleMaskView);
cycleMaskView.CopyToCPU(ref MemoryMarshal.GetReference(cycleMaskSpan), batchSize); accelerator.Synchronize();
} 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)
{ {
@@ -488,6 +489,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
continue; continue;
} }
// TODO: Avoid one-time use variables like prime here.
ulong prime = primesSlice[i]; ulong prime = primesSlice[i];
primeSpan[computeCount] = prime; primeSpan[computeCount] = prime;
positionSpan[computeCount] = i; positionSpan[computeCount] = i;
@@ -497,32 +499,32 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
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];
ulong exponentValue; ulong exponentValue;
if (hasDeltaSource) if (hasDeltaSource)
{ {
exponentValue = prime - currentPrime; exponentValue = prime - currentPrime;
} }
else else
{ {
exponentValue = prime; exponentValue = prime;
hasDeltaSource = true; hasDeltaSource = true;
} }
if (cycleEnabled) if (cycleEnabled)
{ {
exponentValue %= cycle; exponentValue %= cycle;
} }
exponentSlice[i] = exponentValue; exponentSlice[i] = exponentValue;
currentPrime = prime; 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);
@@ -537,6 +539,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
for (int i = 0; i < computeCount; i++) for (int i = 0; i < computeCount; i++)
{ {
// TODO: Avoid one-time use variables like prime and position here.
int position = positionSpan[i]; int position = positionSpan[i];
ulong stepResidue = exponentSlice[i]; ulong stepResidue = exponentSlice[i];
ulong prime = primeSpan[i]; ulong prime = primeSpan[i];
@@ -760,11 +763,11 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
} }
} }
public DivisorScanSession CreateDivisorSession() public DivisorScanSession CreateDivisorSession()
{ {
lock (_sync) lock (_sync)
{ {
if (!_isConfigured) if (!_isConfigured)
{ {
throw new InvalidOperationException("ConfigureFromMaxPrime must be called before using the tester."); throw new InvalidOperationException("ConfigureFromMaxPrime must be called before using the tester.");
} }
@@ -773,15 +776,15 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
{ {
session.Reset(); session.Reset();
return session; return session;
} }
return new DivisorScanSession(this); return new DivisorScanSession(this);
} }
} }
IMersenneNumberDivisorByDivisorTester.IDivisorScanSession IMersenneNumberDivisorByDivisorTester.CreateDivisorSession() IMersenneNumberDivisorByDivisorTester.IDivisorScanSession IMersenneNumberDivisorByDivisorTester.CreateDivisorSession()
{ {
return CreateDivisorSession(); return CreateDivisorSession();
} }
} }