From 2d103a96627ecc52bf8237f662f9084dc5e98dc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Lema=C5=84czyk?= Date: Sat, 25 Oct 2025 05:41:05 +0200 Subject: [PATCH] Compute initial divisor remainders inside GPU kernel --- .../Gpu/Kernels/DivisorByDivisorKernels.cs | 4 +- ...MersenneNumberDivisorByDivisorGpuTester.cs | 43 +++---------------- 2 files changed, 8 insertions(+), 39 deletions(-) diff --git a/PerfectNumbers.Core/Gpu/Kernels/DivisorByDivisorKernels.cs b/PerfectNumbers.Core/Gpu/Kernels/DivisorByDivisorKernels.cs index accaa5f..327d25b 100644 --- a/PerfectNumbers.Core/Gpu/Kernels/DivisorByDivisorKernels.cs +++ b/PerfectNumbers.Core/Gpu/Kernels/DivisorByDivisorKernels.cs @@ -14,7 +14,6 @@ internal static class DivisorByDivisorKernels ArrayView exponentCounts, ArrayView exponents, ArrayView divisorCycles, - ArrayView firstCycleRemainders, ArrayView hits, ArrayView firstHit) { @@ -28,7 +27,6 @@ internal static class DivisorByDivisorKernels int offset = exponentOffsets[globalIndex]; GpuDivisorPartialData divisor = divisors[globalIndex]; ulong cycleLength = divisorCycles[globalIndex]; - ulong firstCycleRemainder = firstCycleRemainders[globalIndex]; var stepper = new ExponentRemainderStepperGpu(divisor); @@ -44,7 +42,7 @@ internal static class DivisorByDivisorKernels } else { - cycleRemainder = firstCycleRemainder; + cycleRemainder = firstExponent % cycleLength; firstHitValue = cycleRemainder == 0UL && firstUnity ? (byte)1 : (byte)0; } diff --git a/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs b/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs index b38f45b..f363126 100644 --- a/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs +++ b/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs @@ -23,14 +23,14 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv private ulong _divisorLimit; // private bool _isConfigured; - private readonly ConcurrentDictionary, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView>> _kernelCache = new(AcceleratorReferenceComparer.Instance); + private readonly ConcurrentDictionary, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView>> _kernelCache = new(AcceleratorReferenceComparer.Instance); private readonly ConcurrentBag _resourcePool = new(); private readonly ConcurrentBag _acceleratorPool = new(); private readonly ConcurrentBag _sessionPool = new(); - private Action, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView> GetKernel(Accelerator accelerator) => + private Action, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView> GetKernel(Accelerator accelerator) => _kernelCache.GetOrAdd(accelerator, acc => - acc.LoadAutoGroupedStreamKernel, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView>(DivisorByDivisorKernels.CheckKernel)); + acc.LoadAutoGroupedStreamKernel, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView>(DivisorByDivisorKernels.CheckKernel)); public int GpuBatchSize @@ -107,7 +107,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv resources.OffsetBuffer, resources.CountBuffer, resources.CycleBuffer, - resources.FirstRemainderBuffer, resources.ExponentBuffer, resources.HitsBuffer, resources.HitIndexBuffer, @@ -118,7 +117,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv resources.Offsets, resources.Counts, resources.Cycles, - resources.FirstRemainders, out lastProcessed, out coveredRange, out processedCount); @@ -169,12 +167,11 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv private static bool CheckDivisors( ulong prime, ulong allowedMax, - Action, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView> kernel, + Action, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView> kernel, MemoryBuffer1D divisorDataBuffer, MemoryBuffer1D offsetBuffer, MemoryBuffer1D countBuffer, MemoryBuffer1D cycleBuffer, - MemoryBuffer1D firstRemainderBuffer, MemoryBuffer1D exponentBuffer, MemoryBuffer1D hitsBuffer, MemoryBuffer1D hitIndexBuffer, @@ -185,7 +182,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv int[] offsets, int[] counts, ulong[] cycles, - ulong[] firstRemainders, out ulong lastProcessed, out bool coveredRange, out ulong processedCount) @@ -238,8 +234,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv Span offsetStorage = offsets.AsSpan(); Span countStorage = counts.AsSpan(); Span cycleStorage = cycles.AsSpan(); - Span remainderStorage = firstRemainders.AsSpan(); - while (currentK <= maxK && !composite) { int chunkCount = Math.Min(chunkCapacity, batchCapacity); @@ -312,8 +306,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv Span offsetSpan = offsetStorage; Span countSpan = countStorage; Span cycleSpan = cycleStorage; - Span remainderSpan = remainderStorage; - int admissibleCount = 0; int exponentIndex = 0; for (int i = 0; i < filteredCount; i++) @@ -332,7 +324,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv offsetSpan[admissibleCount] = exponentIndex; countSpan[admissibleCount] = 1; cycleSpan[admissibleCount] = divisorCycle; - remainderSpan[admissibleCount] = 0UL; admissibleCount++; exponentIndex++; @@ -347,7 +338,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv ArrayView1D offsetView = offsetBuffer.View.SubView(0, admissibleCount); ArrayView1D countView = countBuffer.View.SubView(0, admissibleCount); ArrayView1D cycleView = cycleBuffer.View.SubView(0, admissibleCount); - ArrayView1D remainderView = firstRemainderBuffer.View.SubView(0, admissibleCount); ArrayView1D exponentView = exponentBuffer.View.SubView(0, exponentIndex); ArrayView1D hitsView = hitsBuffer.View.SubView(0, exponentIndex); ArrayView1D hitIndexView = hitIndexBuffer.View.SubView(0, 1); @@ -356,13 +346,12 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv offsetView.CopyFromCPU(ref MemoryMarshal.GetReference(offsetSpan), admissibleCount); countView.CopyFromCPU(ref MemoryMarshal.GetReference(countSpan), admissibleCount); cycleView.CopyFromCPU(ref MemoryMarshal.GetReference(cycleSpan), admissibleCount); - remainderView.CopyFromCPU(ref MemoryMarshal.GetReference(remainderSpan), admissibleCount); exponentView.CopyFromCPU(ref MemoryMarshal.GetReference(exponentSpan), exponentIndex); int sentinel = int.MaxValue; hitIndexView.CopyFromCPU(ref sentinel, 1); - kernel(admissibleCount, divisorView, offsetView, countView, exponentView, cycleView, remainderView, hitsView, hitIndexView); + kernel(admissibleCount, divisorView, offsetView, countView, exponentView, cycleView, hitsView, hitIndexView); int firstHit = sentinel; hitIndexView.CopyToCPU(ref firstHit, 1); @@ -478,12 +467,11 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv private readonly MersenneNumberDivisorByDivisorGpuTester _owner; private readonly GpuContextPool.GpuContextLease _lease; private readonly Accelerator _accelerator; - private Action, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView> _kernel = null!; + private Action, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView> _kernel = null!; private MemoryBuffer1D _divisorBuffer = null!; private MemoryBuffer1D _offsetBuffer = null!; private MemoryBuffer1D _countBuffer = null!; private MemoryBuffer1D _cycleBuffer = null!; - private MemoryBuffer1D _firstRemainderBuffer = null!; private MemoryBuffer1D _firstHitBuffer = null!; private MemoryBuffer1D _exponentsBuffer = null!; private MemoryBuffer1D _hitBuffer = null!; @@ -517,7 +505,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv _offsetBuffer = _accelerator.Allocate1D(1); _countBuffer = _accelerator.Allocate1D(1); _cycleBuffer = _accelerator.Allocate1D(1); - _firstRemainderBuffer = _accelerator.Allocate1D(1); _firstHitBuffer = _accelerator.Allocate1D(1); } @@ -589,8 +576,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv } } - ulong firstRemainder = cycle == 0UL ? 0UL : firstPrime % cycle; - Monitor.Enter(_lease.ExecutionLock); EnsureExecutionResourcesLocked(length); @@ -599,7 +584,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv ArrayView1D offsetView = _offsetBuffer.View; ArrayView1D countView = _countBuffer.View; ArrayView1D cycleView = _cycleBuffer.View; - ArrayView1D remainderView = _firstRemainderBuffer.View; ArrayView1D firstHitView = _firstHitBuffer.View; ArrayView1D exponentView = _exponentsBuffer.View; ArrayView1D hitView = _hitBuffer.View; @@ -616,9 +600,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv ulong cycleValue = cycle; cycleView.SubView(0, 1).CopyFromCPU(ref cycleValue, 1); - ulong remainderValue = firstRemainder; - remainderView.SubView(0, 1).CopyFromCPU(ref remainderValue, 1); - Span hostSpan = _hostBuffer.AsSpan(0, length); primes.CopyTo(hostSpan); @@ -637,7 +618,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv throw new InvalidOperationException("GPU divisor kernel was not initialized."); } - kernel(1, divisorView, offsetView, countView, exponentSlice, cycleView, remainderView, hitSliceView, firstHitView); + kernel(1, divisorView, offsetView, countView, exponentSlice, cycleView, hitSliceView, firstHitView); Span hitSlice = hits.Slice(0, length); hitSliceView.CopyToCPU(ref MemoryMarshal.GetReference(hitSlice), length); @@ -709,7 +690,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv private MemoryBuffer1D? _offsetBuffer; private MemoryBuffer1D? _countBuffer; private MemoryBuffer1D? _cycleBuffer; - private MemoryBuffer1D? _firstRemainderBuffer; private MemoryBuffer1D? _exponentBuffer; private MemoryBuffer1D? _hitsBuffer; private MemoryBuffer1D? _hitIndexBuffer; @@ -730,8 +710,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv internal MemoryBuffer1D CycleBuffer => _cycleBuffer ?? throw new InvalidOperationException("Batch resources not bound to an accelerator."); - internal MemoryBuffer1D FirstRemainderBuffer => _firstRemainderBuffer ?? throw new InvalidOperationException("Batch resources not bound to an accelerator."); - internal MemoryBuffer1D ExponentBuffer => _exponentBuffer ?? throw new InvalidOperationException("Batch resources not bound to an accelerator."); internal MemoryBuffer1D HitsBuffer => _hitsBuffer ?? throw new InvalidOperationException("Batch resources not bound to an accelerator."); @@ -752,7 +730,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv internal ulong[] Cycles { get; private set; } = null!; - internal ulong[] FirstRemainders { get; private set; } = null!; internal int Capacity => _hostCapacity; @@ -805,7 +782,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv _offsetBuffer = accelerator.Allocate1D(capacity); _countBuffer = accelerator.Allocate1D(capacity); _cycleBuffer = accelerator.Allocate1D(capacity); - _firstRemainderBuffer = accelerator.Allocate1D(capacity); _exponentBuffer = accelerator.Allocate1D(capacity); _hitsBuffer = accelerator.Allocate1D(capacity); _hitIndexBuffer = accelerator.Allocate1D(1); @@ -825,7 +801,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv Offsets = intPool.Rent(capacity); Counts = intPool.Rent(capacity); Cycles = ulongPool.Rent(capacity); - FirstRemainders = ulongPool.Rent(capacity); _hostCapacity = capacity; } @@ -835,7 +810,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv _offsetBuffer?.Dispose(); _countBuffer?.Dispose(); _cycleBuffer?.Dispose(); - _firstRemainderBuffer?.Dispose(); _exponentBuffer?.Dispose(); _hitsBuffer?.Dispose(); _hitIndexBuffer?.Dispose(); @@ -843,7 +817,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv _offsetBuffer = null; _countBuffer = null; _cycleBuffer = null; - _firstRemainderBuffer = null; _exponentBuffer = null; _hitsBuffer = null; _hitIndexBuffer = null; @@ -867,7 +840,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv intPool.Return(Offsets, clearArray: false); intPool.Return(Counts, clearArray: false); ulongPool.Return(Cycles, clearArray: false); - ulongPool.Return(FirstRemainders, clearArray: false); Divisors = Array.Empty(); Exponents = Array.Empty(); FilteredDivisors = Array.Empty(); @@ -875,7 +847,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv Offsets = Array.Empty(); Counts = Array.Empty(); Cycles = Array.Empty(); - FirstRemainders = Array.Empty(); _hostCapacity = 0; }