From a4bda0f0eeec14b1ec18be40da60eb5a2ee18982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Lema=C5=84czyk?= Date: Wed, 24 Sep 2025 03:09:58 +0200 Subject: [PATCH] Tiny cleanup --- ...MersenneNumberDivisorByDivisorGpuTester.cs | 508 +++++++++--------- 1 file changed, 254 insertions(+), 254 deletions(-) diff --git a/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs b/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs index 315f2d0..e8782c5 100644 --- a/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs +++ b/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs @@ -24,9 +24,9 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester public readonly ulong MontgomeryTwo = montgomeryTwo; } - private readonly ConcurrentDictionary, ArrayView>> _kernelCache = new(); - private readonly ConcurrentDictionary, ArrayView>> _kernelByPrimeCache = new(); - private readonly ConcurrentBag _sessionPool = new(); + private readonly ConcurrentDictionary, ArrayView>> _kernelCache = new(); + private readonly ConcurrentDictionary, ArrayView>> _kernelByPrimeCache = new(); + private readonly ConcurrentBag _sessionPool = new(); private Action, ArrayView> GetKernel(Accelerator accelerator) => _kernelCache.GetOrAdd(accelerator, acc => acc.LoadAutoGroupedStreamKernel, ArrayView>(CheckKernel)); @@ -57,125 +57,125 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester public bool IsPrime(ulong prime, out bool divisorsExhausted) { - ulong allowedMax; - bool useCycles; - int batchCapacity; + ulong allowedMax; + bool useCycles; + int batchCapacity; - lock (_sync) - { - if (!_isConfigured) - { - throw new InvalidOperationException("ConfigureFromMaxPrime must be called before using the tester."); - } + lock (_sync) + { + if (!_isConfigured) + { + throw new InvalidOperationException("ConfigureFromMaxPrime must be called before using the tester."); + } - allowedMax = ComputeAllowedMaxDivisor(prime, _divisorLimit); - useCycles = _useDivisorCycles; - batchCapacity = _gpuBatchSize; - } + allowedMax = ComputeAllowedMaxDivisor(prime, _divisorLimit); + useCycles = _useDivisorCycles; + batchCapacity = _gpuBatchSize; + } - if (allowedMax < 3UL) - { - divisorsExhausted = true; - return true; - } + if (allowedMax < 3UL) + { + divisorsExhausted = true; + return true; + } - bool composite; - bool coveredRange; - ulong processedCount; - ulong lastProcessed; + bool composite; + bool coveredRange; + ulong processedCount; + ulong lastProcessed; - var gpuLease = GpuContextPool.RentPreferred(preferCpu: false); - var accelerator = gpuLease.Accelerator; - var kernel = GetKernel(accelerator); + var gpuLease = GpuContextPool.RentPreferred(preferCpu: false); + var accelerator = gpuLease.Accelerator; + var kernel = GetKernel(accelerator); - var divisorsBuffer = accelerator.Allocate1D(batchCapacity); - var hitsBuffer = accelerator.Allocate1D(batchCapacity); - ulong[] divisors = ArrayPool.Shared.Rent(batchCapacity); - byte[] hits = ArrayPool.Shared.Rent(batchCapacity); - MontgomeryDivisorData[] divisorData = ArrayPool.Shared.Rent(batchCapacity); + var divisorsBuffer = accelerator.Allocate1D(batchCapacity); + var hitsBuffer = accelerator.Allocate1D(batchCapacity); + ulong[] divisors = ArrayPool.Shared.Rent(batchCapacity); + byte[] hits = ArrayPool.Shared.Rent(batchCapacity); + MontgomeryDivisorData[] divisorData = ArrayPool.Shared.Rent(batchCapacity); - try - { - composite = CheckDivisors( - prime, - allowedMax, - useCycles, - accelerator, - kernel, - divisorsBuffer, - hitsBuffer, - divisors, - hits, - divisorData, - out lastProcessed, - out coveredRange, - out processedCount - ); - } - finally - { - ArrayPool.Shared.Return(hits, clearArray: true); - ArrayPool.Shared.Return(divisors, clearArray: true); - ArrayPool.Shared.Return(divisorData, clearArray: true); - hitsBuffer.Dispose(); - divisorsBuffer.Dispose(); - gpuLease.Dispose(); - } + try + { + composite = CheckDivisors( + prime, + allowedMax, + useCycles, + accelerator, + kernel, + divisorsBuffer, + hitsBuffer, + divisors, + hits, + divisorData, + out lastProcessed, + out coveredRange, + out processedCount + ); + } + finally + { + ArrayPool.Shared.Return(hits, clearArray: true); + ArrayPool.Shared.Return(divisors, clearArray: true); + ArrayPool.Shared.Return(divisorData, clearArray: true); + hitsBuffer.Dispose(); + divisorsBuffer.Dispose(); + gpuLease.Dispose(); + } - if (processedCount > 0UL) - { - lock (_sync) - { - UpdateStatusUnsafe(lastProcessed, processedCount); - } - } + if (processedCount > 0UL) + { + lock (_sync) + { + UpdateStatusUnsafe(lastProcessed, processedCount); + } + } - if (composite) - { - divisorsExhausted = true; - return false; + if (composite) + { + divisorsExhausted = true; + return false; } divisorsExhausted = coveredRange; return true; } - private bool CheckDivisors( - ulong prime, - ulong allowedMax, - bool useCycles, - Accelerator accelerator, - Action, ArrayView> kernel, - MemoryBuffer1D divisorsBuffer, - MemoryBuffer1D hitsBuffer, - ulong[] divisors, - byte[] hits, - MontgomeryDivisorData[] divisorData, - out ulong lastProcessed, - out bool coveredRange, - out ulong processedCount) - { - lastProcessed = 0UL; - processedCount = 0UL; + private bool CheckDivisors( + ulong prime, + ulong allowedMax, + bool useCycles, + Accelerator accelerator, + Action, ArrayView> kernel, + MemoryBuffer1D divisorsBuffer, + MemoryBuffer1D hitsBuffer, + ulong[] divisors, + byte[] hits, + MontgomeryDivisorData[] divisorData, + out ulong lastProcessed, + out bool coveredRange, + out ulong processedCount) + { + lastProcessed = 0UL; + processedCount = 0UL; - if (allowedMax < 3UL) - { - coveredRange = true; - return false; - } + if (allowedMax < 3UL) + { + coveredRange = true; + return false; + } - int batchCapacity = (int)divisorsBuffer.Length; + int batchCapacity = (int)divisorsBuffer.Length; - bool composite = false; - bool processedAll = false; - ulong cycle, divisor = 3UL, next; - int batchSize, i; - bool reachedEndInBatch; + bool composite = false; + bool processedAll = false; + ulong cycle, divisor = 3UL, next; + int batchSize, i; + bool reachedEndInBatch; - Span divisorDataSpan; - Span divisorSpan; - Span hitsSpan; - MersenneDivisorCycles divisorCycles = MersenneDivisorCycles.Shared; + Span divisorDataSpan; + Span divisorSpan; + Span hitsSpan; + MersenneDivisorCycles divisorCycles = MersenneDivisorCycles.Shared; ArrayView1D divisorView; ArrayView1D hitsView; @@ -184,45 +184,45 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester batchSize = 0; reachedEndInBatch = false; - while (batchSize < batchCapacity && divisor <= allowedMax) - { - ulong currentDivisor = divisor; - ulong nextDivisor = currentDivisor + 2UL; - processedCount++; + while (batchSize < batchCapacity && divisor <= allowedMax) + { + ulong currentDivisor = divisor; + ulong nextDivisor = currentDivisor + 2UL; + processedCount++; - if (useCycles) - { - cycle = divisorCycles!.GetCycle(currentDivisor); - if (cycle == 0UL || prime % cycle != 0UL) - { - lastProcessed = currentDivisor; + if (useCycles) + { + cycle = divisorCycles!.GetCycle(currentDivisor); + if (cycle == 0UL || prime % cycle != 0UL) + { + lastProcessed = currentDivisor; - if (nextDivisor <= currentDivisor) - { - reachedEndInBatch = true; - break; - } + if (nextDivisor <= currentDivisor) + { + reachedEndInBatch = true; + break; + } - if (nextDivisor > allowedMax) - { - divisor = nextDivisor; - reachedEndInBatch = true; - break; - } + if (nextDivisor > allowedMax) + { + divisor = nextDivisor; + reachedEndInBatch = true; + break; + } - divisor = nextDivisor; - continue; - } - } + divisor = nextDivisor; + continue; + } + } - divisors[batchSize++] = currentDivisor; - lastProcessed = currentDivisor; - next = nextDivisor; + divisors[batchSize++] = currentDivisor; + lastProcessed = currentDivisor; + next = nextDivisor; - // This will be only true when we exceed ulong.MaxValue - if (next <= divisor) - { - reachedEndInBatch = true; + // This will be only true when we exceed ulong.MaxValue + if (next <= divisor) + { + reachedEndInBatch = true; break; } @@ -236,15 +236,15 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester divisor = next; } - if (batchSize == 0) - { - if (reachedEndInBatch) - { - processedAll = true; - } + if (batchSize == 0) + { + if (reachedEndInBatch) + { + processedAll = true; + } - break; - } + break; + } divisorDataSpan = divisorData.AsSpan(0, batchSize); divisorView = divisorsBuffer.View.SubView(0, batchSize); @@ -263,20 +263,20 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester accelerator.Synchronize(); hitsView.CopyToCPU(ref MemoryMarshal.GetReference(hitsSpan), batchSize); - for (i = 0; i < batchSize; i++) - { - if (hitsSpan[i] != 0) - { - composite = true; - lastProcessed = divisorSpan[i]; - break; - } - } + for (i = 0; i < batchSize; i++) + { + if (hitsSpan[i] != 0) + { + composite = true; + lastProcessed = divisorSpan[i]; + break; + } + } - if (!composite) - { - lastProcessed = divisorSpan[batchSize - 1]; - } + if (!composite) + { + lastProcessed = divisorSpan[batchSize - 1]; + } if (composite) { break; @@ -289,10 +289,10 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester } } - coveredRange = composite || processedAll || divisor > allowedMax; + coveredRange = composite || processedAll || divisor > allowedMax; - return composite; - } + return composite; + } private static ulong ComputeDivisorLimitFromMaxPrime(ulong maxPrime) { @@ -309,44 +309,44 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester return (1UL << (int)(maxPrime - 1UL)) - 1UL; } - private static ulong ComputeAllowedMaxDivisor(ulong prime, ulong divisorLimit) - { - if (prime <= 1UL) - { - return 0UL; - } + private static ulong ComputeAllowedMaxDivisor(ulong prime, ulong divisorLimit) + { + if (prime <= 1UL) + { + return 0UL; + } - if (prime - 1UL >= 64UL) - { - return divisorLimit; - } + if (prime - 1UL >= 64UL) + { + return divisorLimit; + } - return Math.Min((1UL << (int)(prime - 1UL)) - 1UL, divisorLimit); - } + return Math.Min((1UL << (int)(prime - 1UL)) - 1UL, divisorLimit); + } - private void UpdateStatusUnsafe(ulong lastProcessed, ulong processedCount) - { - if (processedCount == 0UL) - { - return; - } + private void UpdateStatusUnsafe(ulong lastProcessed, ulong processedCount) + { + if (processedCount == 0UL) + { + return; + } - ulong interval = (ulong)PerfectNumberConstants.ConsoleInterval; - if (interval == 0UL) - { - _lastStatusDivisor = 0UL; - return; - } + ulong interval = (ulong)PerfectNumberConstants.ConsoleInterval; + if (interval == 0UL) + { + _lastStatusDivisor = 0UL; + return; + } - ulong total = _lastStatusDivisor + processedCount; - ulong messages = total / interval; - _lastStatusDivisor = total % interval; + ulong total = _lastStatusDivisor + processedCount; + ulong messages = total / interval; + _lastStatusDivisor = total % interval; - for (ulong i = 0; i < messages; i++) - { - Console.WriteLine($"...processed by-divisor candidate = {lastProcessed}"); - } - } + for (ulong i = 0; i < messages; i++) + { + Console.WriteLine($"...processed by-divisor candidate = {lastProcessed}"); + } + } private static void CheckKernel(Index1D index, ulong prime, ArrayView divisors, ArrayView hits) { @@ -361,41 +361,41 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester hits[index] = Pow2Mod(prime, divisor) == 1UL ? (byte)1 : (byte)0; } - public sealed class DivisorScanSession : IDisposable - { - private readonly MersenneNumberDivisorByDivisorGpuTester _owner; - private readonly GpuContextPool.GpuContextLease _lease; - private readonly Accelerator _accelerator; + public sealed class DivisorScanSession : IDisposable + { + private readonly MersenneNumberDivisorByDivisorGpuTester _owner; + private readonly GpuContextPool.GpuContextLease _lease; + private readonly Accelerator _accelerator; private readonly Action, ArrayView> _kernel; private readonly MemoryBuffer1D _primesBuffer; private readonly MemoryBuffer1D _hitsBuffer; private readonly ulong[] _primesHost; - private readonly byte[] _hitsHost; - private readonly int[] _indexHost; - private bool _disposed; + private readonly byte[] _hitsHost; + private readonly int[] _indexHost; + private bool _disposed; - internal DivisorScanSession(MersenneNumberDivisorByDivisorGpuTester owner) - { - _owner = owner; - _lease = GpuContextPool.RentPreferred(preferCpu: false); + internal DivisorScanSession(MersenneNumberDivisorByDivisorGpuTester owner) + { + _owner = owner; + _lease = GpuContextPool.RentPreferred(preferCpu: false); _accelerator = _lease.Accelerator; _kernel = owner.GetKernelByPrime(_accelerator); _primesBuffer = _accelerator.Allocate1D(owner._gpuBatchSize); _hitsBuffer = _accelerator.Allocate1D(owner._gpuBatchSize); _primesHost = ArrayPool.Shared.Rent(owner._gpuBatchSize); - _hitsHost = ArrayPool.Shared.Rent(owner._gpuBatchSize); - _indexHost = ArrayPool.Shared.Rent(owner._gpuBatchSize); - } + _hitsHost = ArrayPool.Shared.Rent(owner._gpuBatchSize); + _indexHost = ArrayPool.Shared.Rent(owner._gpuBatchSize); + } - internal void Reset() - { - _disposed = false; - } + internal void Reset() + { + _disposed = false; + } - public void CheckDivisor(ulong divisor, ReadOnlySpan primes, Span hits) - { - if (_disposed) - { + public void CheckDivisor(ulong divisor, ReadOnlySpan primes, Span hits) + { + if (_disposed) + { throw new ObjectDisposedException(nameof(DivisorScanSession)); } @@ -486,24 +486,24 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester offset += batchSize; } - } + } - public void Dispose() - { - if (_disposed) - { - return; - } + public void Dispose() + { + if (_disposed) + { + return; + } - _disposed = true; - _owner.ReturnSession(this); - } - } + _disposed = true; + _owner.ReturnSession(this); + } + } - internal void ReturnSession(DivisorScanSession session) - { - _sessionPool.Add(session); - } + internal void ReturnSession(DivisorScanSession session) + { + _sessionPool.Add(session); + } private static ulong Pow2Mod(ulong exponent, in MontgomeryDivisorData divisor) { @@ -540,7 +540,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester { ulong tLow = unchecked(a * b); ulong m = unchecked(tLow * nPrime); - + // We're reusing tLow variable as the result to perform just a little bit better tLow = unchecked(MultiplyHigh(a, b) + MultiplyHigh(m, modulus) + (unchecked(tLow + m * modulus) < tLow ? 1UL : 0UL)); if (tLow >= modulus) @@ -624,32 +624,32 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester { lock (_sync) { - if (!_isConfigured) - { - throw new InvalidOperationException("ConfigureFromMaxPrime must be called before using the tester."); - } + if (!_isConfigured) + { + throw new InvalidOperationException("ConfigureFromMaxPrime must be called before using the tester."); + } - return ComputeAllowedMaxDivisor(prime, _divisorLimit); - } - } + return ComputeAllowedMaxDivisor(prime, _divisorLimit); + } + } - public DivisorScanSession CreateDivisorSession() - { - lock (_sync) - { - if (!_isConfigured) - { - throw new InvalidOperationException("ConfigureFromMaxPrime must be called before using the tester."); - } + public DivisorScanSession CreateDivisorSession() + { + lock (_sync) + { + if (!_isConfigured) + { + throw new InvalidOperationException("ConfigureFromMaxPrime must be called before using the tester."); + } - if (_sessionPool.TryTake(out DivisorScanSession? session)) - { - session.Reset(); - return session; - } + if (_sessionPool.TryTake(out DivisorScanSession? session)) + { + session.Reset(); + return session; + } - return new DivisorScanSession(this); - } - } + return new DivisorScanSession(this); + } + } }