From 5ce67fa1c59aaeacdf3a05f3961a80328b5b4449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Lema=C5=84czyk?= Date: Tue, 23 Sep 2025 23:28:32 +0200 Subject: [PATCH] Reduce span slicing in GPU divisor checks --- ...MersenneNumberDivisorByDivisorGpuTester.cs | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs b/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs index 0d6175c..d5a0c28 100644 --- a/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs +++ b/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs @@ -322,11 +322,23 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester MersenneDivisorCycles? divisorCycles = useCycles ? MersenneDivisorCycles.Shared : null; ulong cycle = useCycles ? divisorCycles!.GetCycle(divisor) : 0UL; MontgomeryDivisorData divisorData = CreateMontgomeryDivisorData(divisor); - while (offset < primes.Length) - { - int batchSize = Math.Min(_owner._gpuBatchSize, primes.Length - offset); - Span primeSpan = _primesHost.AsSpan(0, batchSize); - primes.Slice(offset, batchSize).CopyTo(primeSpan); + Span primeSpan = _primesHost.AsSpan(0, _owner._gpuBatchSize); + Span indexSpan = _indexHost.AsSpan(0, _owner._gpuBatchSize); + Span hitSpan = _hitsHost.AsSpan(0, _owner._gpuBatchSize); + int currentSpanSize = _owner._gpuBatchSize; + + while (offset < primes.Length) + { + int batchSize = Math.Min(_owner._gpuBatchSize, primes.Length - offset); + if (batchSize != currentSpanSize) + { + primeSpan = _primesHost.AsSpan(0, batchSize); + indexSpan = _indexHost.AsSpan(0, batchSize); + hitSpan = _hitsHost.AsSpan(0, batchSize); + currentSpanSize = batchSize; + } + + primes.Slice(offset, batchSize).CopyTo(primeSpan); if (++consoleStatus == PerfectNumberConstants.ConsoleInterval) { @@ -334,13 +346,11 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester consoleStatus = 0; } - Span indexSpan = _indexHost.AsSpan(0, batchSize); - Span hitSpan = _hitsHost.AsSpan(0, batchSize); - Span hitsSlice = hits.Slice(offset, batchSize); - int gpuCount = 0; + Span hitsSlice = hits.Slice(offset, batchSize); + int gpuCount = 0; - if (useCycles) - { + if (useCycles) + { for (int i = 0; i < batchSize; i++) { ulong primeValue = primeSpan[i]; @@ -357,19 +367,19 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester if (gpuCount > 0) { - var primesView = _primesBuffer.View.SubView(0, gpuCount); - var hitsView = _hitsBuffer.View.SubView(0, gpuCount); + var primesView = _primesBuffer.View.SubView(0, gpuCount); + var hitsView = _hitsBuffer.View.SubView(0, gpuCount); - primesView.CopyFromCPU(ref MemoryMarshal.GetReference(primeSpan.Slice(0, gpuCount)), gpuCount); - _kernel(gpuCount, divisorData, primesView, hitsView); - _accelerator.Synchronize(); + primesView.CopyFromCPU(ref MemoryMarshal.GetReference(primeSpan), gpuCount); + _kernel(gpuCount, divisorData, primesView, hitsView); + _accelerator.Synchronize(); - hitsView.CopyToCPU(ref MemoryMarshal.GetReference(hitSpan.Slice(0, gpuCount)), gpuCount); - for (int i = 0; i < gpuCount; i++) - { - hitsSlice[indexSpan[i]] = hitSpan[i]; - } - } + hitsView.CopyToCPU(ref MemoryMarshal.GetReference(hitSpan), gpuCount); + for (int i = 0; i < gpuCount; i++) + { + hitsSlice[indexSpan[i]] = hitSpan[i]; + } + } } else {