From f672ff520c52cd0b8e062c3ea91a1b957294ccbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Lema=C5=84czyk?= Date: Thu, 23 Oct 2025 01:16:58 +0200 Subject: [PATCH 1/4] Avoid redundant compaction buffer clearing on GPU --- PerfectNumbers.Core/Gpu/Kernels/DivisorByDivisorKernels.cs | 6 ++++-- .../Gpu/MersenneNumberDivisorByDivisorGpuTester.cs | 1 - PerfectNumbers.Core/MersenneNumberDivisorByDivisorTester.cs | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/PerfectNumbers.Core/Gpu/Kernels/DivisorByDivisorKernels.cs b/PerfectNumbers.Core/Gpu/Kernels/DivisorByDivisorKernels.cs index 1540c09..eece679 100644 --- a/PerfectNumbers.Core/Gpu/Kernels/DivisorByDivisorKernels.cs +++ b/PerfectNumbers.Core/Gpu/Kernels/DivisorByDivisorKernels.cs @@ -232,8 +232,10 @@ internal static class DivisorByDivisorKernels int lastLaneMask = globalIndex == length - 1 ? 1 : 0; int countValue = shared[prefixBase + localIndex]; - int storedCount = lastLaneMask != 0 ? countValue : 0; - Atomic.Max(ref compactedCount[0], storedCount); + if (lastLaneMask != 0) + { + compactedCount[0] = countValue; + } } public static void PublishFirstHitKernel( diff --git a/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs b/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs index 0af37c0..33ed320 100644 --- a/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs +++ b/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs @@ -600,7 +600,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv // return 0; // } - countView.MemSetToZero(); SharedMemoryConfig sharedMemoryConfig = SharedMemoryConfig.RequestDynamic(count * 3); Index1D gridDim = new Index1D(1); Index1D groupDim = new Index1D(count); diff --git a/PerfectNumbers.Core/MersenneNumberDivisorByDivisorTester.cs b/PerfectNumbers.Core/MersenneNumberDivisorByDivisorTester.cs index ce66960..008ddd5 100644 --- a/PerfectNumbers.Core/MersenneNumberDivisorByDivisorTester.cs +++ b/PerfectNumbers.Core/MersenneNumberDivisorByDivisorTester.cs @@ -73,7 +73,7 @@ public static class MersenneNumberDivisorByDivisorTester candidateCount = candidateSpan.Length; } - pool.Return(recordedCandidates, clearArray: true); + pool.Return(recordedCandidates, clearArray: false); } if (skippedByPreviousResults > 0) @@ -211,8 +211,8 @@ public static class MersenneNumberDivisorByDivisorTester filteredPrimes.Add(prime); } - pool.Return(allowedMaxBatch, clearArray: true); - pool.Return(primeBatch, clearArray: true); + pool.Return(allowedMaxBatch, clearArray: false); + pool.Return(primeBatch, clearArray: false); // The filtered list mirrors primesToTest in the CPU flow, so the guard below never triggers after the earlier // emptiness checks. From f0b4cdf6e2193ebc3b63e9b935773a57adf53ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Lema=C5=84czyk?= Date: Thu, 23 Oct 2025 01:48:02 +0200 Subject: [PATCH 2/4] Avoid redundant clearing in CPU divisor sessions --- .../Cpu/MersenneCpuDivisorScanSession.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/PerfectNumbers.Core/Cpu/MersenneCpuDivisorScanSession.cs b/PerfectNumbers.Core/Cpu/MersenneCpuDivisorScanSession.cs index c6d936e..2ab7e20 100644 --- a/PerfectNumbers.Core/Cpu/MersenneCpuDivisorScanSession.cs +++ b/PerfectNumbers.Core/Cpu/MersenneCpuDivisorScanSession.cs @@ -35,8 +35,14 @@ internal sealed class MersenneCpuDivisorScanSession : IMersenneNumberDivisorByDi divisorCycle = DivisorCycleCache.Shared.GetCycleLength(divisor); if (divisorCycle == 0UL) { - hits.Clear(); - return; + divisorCycle = MersenneDivisorCycles.CalculateCycleLength( + divisor, + cachedData, + skipPrimeOrderHeuristic: true); + if (divisorCycle == 0UL) + { + throw new InvalidOperationException($"Failed to compute a cycle for divisor {divisor}."); + } } } @@ -45,8 +51,7 @@ internal sealed class MersenneCpuDivisorScanSession : IMersenneNumberDivisorByDi var exponentStepper = new ExponentRemainderStepper(cachedData); if (!exponentStepper.IsValidModulus) { - hits.Clear(); - return; + throw new InvalidOperationException($"Invalid modulus {cachedData.Modulus} for divisor scans."); } var cycleStepper = new CycleRemainderStepper(divisorCycle); From ff9b0122c05c4d30c64720aded922579d3a20253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Lema=C5=84czyk?= Date: Thu, 23 Oct 2025 01:48:06 +0200 Subject: [PATCH 3/4] Restore hit clearing when divisor cycle is missing --- .../Cpu/MersenneCpuDivisorScanSession.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/PerfectNumbers.Core/Cpu/MersenneCpuDivisorScanSession.cs b/PerfectNumbers.Core/Cpu/MersenneCpuDivisorScanSession.cs index 2ab7e20..1dcd49b 100644 --- a/PerfectNumbers.Core/Cpu/MersenneCpuDivisorScanSession.cs +++ b/PerfectNumbers.Core/Cpu/MersenneCpuDivisorScanSession.cs @@ -35,14 +35,8 @@ internal sealed class MersenneCpuDivisorScanSession : IMersenneNumberDivisorByDi divisorCycle = DivisorCycleCache.Shared.GetCycleLength(divisor); if (divisorCycle == 0UL) { - divisorCycle = MersenneDivisorCycles.CalculateCycleLength( - divisor, - cachedData, - skipPrimeOrderHeuristic: true); - if (divisorCycle == 0UL) - { - throw new InvalidOperationException($"Failed to compute a cycle for divisor {divisor}."); - } + hits.Clear(); + return; } } From c697a7e127f822b01cbc6336aad73985005a8273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Lema=C5=84czyk?= Date: Thu, 23 Oct 2025 01:48:11 +0200 Subject: [PATCH 4/4] Throw when divisor cycle resolution fails --- PerfectNumbers.Core/Cpu/MersenneCpuDivisorScanSession.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PerfectNumbers.Core/Cpu/MersenneCpuDivisorScanSession.cs b/PerfectNumbers.Core/Cpu/MersenneCpuDivisorScanSession.cs index 1dcd49b..1279369 100644 --- a/PerfectNumbers.Core/Cpu/MersenneCpuDivisorScanSession.cs +++ b/PerfectNumbers.Core/Cpu/MersenneCpuDivisorScanSession.cs @@ -35,8 +35,8 @@ internal sealed class MersenneCpuDivisorScanSession : IMersenneNumberDivisorByDi divisorCycle = DivisorCycleCache.Shared.GetCycleLength(divisor); if (divisorCycle == 0UL) { - hits.Clear(); - return; + // DivisorCycleCache guarantees a positive cycle for divisors greater than one. + throw new InvalidOperationException($"Divisor cycle solver returned zero for divisor {divisor}."); } }