From 8b95a42f2748ff3dd9f6e0b0baf1f7510d77ced5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Lema=C5=84czyk?= Date: Thu, 25 Sep 2025 07:02:44 +0200 Subject: [PATCH] Divisor cycle cache will now respect --divisor-cycles-batch parameter (renamed from --divisor-cycles-batch-size) --- EvenPerfectBitScanner/Program.cs | 7 +++--- PerfectNumbers.Core/DivisorCycleCache.cs | 27 +++++++++++++----------- PerfectNumbers.Core/Gpu/GpuConstants.cs | 7 +++--- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/EvenPerfectBitScanner/Program.cs b/EvenPerfectBitScanner/Program.cs index c888631..192b03f 100644 --- a/EvenPerfectBitScanner/Program.cs +++ b/EvenPerfectBitScanner/Program.cs @@ -381,7 +381,7 @@ internal static class Program { useGpuCycles = !arg.AsSpan(arg.IndexOf('=') + 1).Equals("cpu", StringComparison.OrdinalIgnoreCase); } - else if (arg.StartsWith("--divisor-cycles-batch-size=", StringComparison.OrdinalIgnoreCase)) + else if (arg.StartsWith("--divisor-cycles-batch=", StringComparison.OrdinalIgnoreCase)) { cyclesBatchSize = Math.Max(1, int.Parse(arg.AsSpan(arg.IndexOf('=') + 1))); } @@ -457,6 +457,7 @@ internal static class Program MersenneDivisorCycles.Shared.LoadFrom(cyclesPath); } + DivisorCycleCache.SetDivisorCyclesBatchSize(cyclesBatchSize); DivisorCycleCache.Shared.ConfigureGeneratorDevice(orderOnGpu); DivisorCycleCache.Shared.ReloadFromCurrentSnapshot(); @@ -521,7 +522,7 @@ internal static class Program _divisorTester = new MersenneNumberDivisorGpuTester(); } else if (useByDivisor) - { + { _byDivisorTester = mersenneOnGpu ? new MersenneNumberDivisorByDivisorGpuTester() : new MersenneNumberDivisorByDivisorCpuTester(); @@ -1313,7 +1314,7 @@ internal static class Program Console.WriteLine(" --results-prefix= prefix to prepend to results filename"); Console.WriteLine(" --divisor-cycles= divisor cycles data file"); Console.WriteLine(" --divisor-cycles-device=cpu|gpu device for cycles generation (default gpu)"); - Console.WriteLine(" --divisor-cycles-batch-size= batch size for cycles generation (default 512)"); + Console.WriteLine(" --divisor-cycles-batch= batch size for cycles generation (default 512)"); Console.WriteLine(" --divisor-cycles-continue continue divisor cycles generation"); Console.WriteLine(" --divisor-cycles-limit= cycle search iterations when --mersenne=divisor"); Console.WriteLine(" --use-divisor-cycles=true|false enable divisor cycle filtering in --mersenne=bydivisor (default false)"); diff --git a/PerfectNumbers.Core/DivisorCycleCache.cs b/PerfectNumbers.Core/DivisorCycleCache.cs index dd14fd5..d825534 100644 --- a/PerfectNumbers.Core/DivisorCycleCache.cs +++ b/PerfectNumbers.Core/DivisorCycleCache.cs @@ -24,25 +24,28 @@ public sealed class DivisorCycleCache } private const int CycleGenerationBatchSize = 262_144; - private const int GpuCycleStepsPerInvocation = 524_288 / 16; private const byte ByteZero = 0; private const byte ByteOne = 1; private readonly object _sync = new(); private readonly ConcurrentDictionary> _pending = new(); - private readonly ConcurrentDictionary, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D>> _gpuKernelCache = new(AcceleratorReferenceComparer.Instance); + private readonly ConcurrentDictionary, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D>> _gpuKernelCache = new(AcceleratorReferenceComparer.Instance); private CycleBlock _baseBlock = null!; private CycleBlock? _activeBlock; private CycleBlock? _prefetchedBlock; private bool _useGpuGeneration = true; + private readonly int _divisorCyclesBatchSize; + private static int _sharedDivisorCyclesBatchSize = GpuConstants.GpuCycleStepsPerInvocation; - public static DivisorCycleCache Shared { get; } = new DivisorCycleCache(); + public static void SetDivisorCyclesBatchSize(int divisorCyclesBatchSize) => _sharedDivisorCyclesBatchSize = divisorCyclesBatchSize; + public static DivisorCycleCache Shared { get; } = new DivisorCycleCache(_sharedDivisorCyclesBatchSize); - private DivisorCycleCache() + private DivisorCycleCache(int divisorCyclesBatchSize) { + _divisorCyclesBatchSize = divisorCyclesBatchSize; ulong[] snapshot = MersenneDivisorCycles.Shared.ExportSmallCyclesSnapshot(); Initialize(snapshot); - } + } public void ReloadFromCurrentSnapshot() { @@ -235,7 +238,7 @@ public sealed class DivisorCycleCache if (_useGpuGeneration) { - ComputeCyclesGpu(start, cycles); + ComputeCyclesGpu(start, cycles, _divisorCyclesBatchSize); } else { @@ -277,7 +280,7 @@ public sealed class DivisorCycleCache } } - private void ComputeCyclesGpu(ulong start, ulong[] destination) + private void ComputeCyclesGpu(ulong start, ulong[] destination, int divisorCyclesBatchSize) { var gpuLease = GpuKernelPool.GetKernel(_useGpuGeneration); var execution = gpuLease.EnterExecutionScope(); @@ -285,7 +288,7 @@ public sealed class DivisorCycleCache try { Accelerator accelerator = gpuLease.Accelerator; - Action, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D> kernel = _gpuKernelCache.GetOrAdd(accelerator, LoadKernel); + Action, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D> kernel = _gpuKernelCache.GetOrAdd(accelerator, LoadKernel); int length = destination.Length; int chunkCapacity = Math.Min(length, CycleGenerationBatchSize); @@ -355,7 +358,7 @@ public sealed class DivisorCycleCache while (pending > 0) { - kernel(batchSize, divisorView, powView, orderView, resultView, statusView); + kernel(batchSize, divisorCyclesBatchSize, divisorView, powView, orderView, resultView, statusView); accelerator.Synchronize(); statusView.CopyToCPU(ref MemoryMarshal.GetReference(statusSpan), batchSize); @@ -390,13 +393,14 @@ public sealed class DivisorCycleCache } } - private static Action, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D> LoadKernel(Accelerator accelerator) + private static Action, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D> LoadKernel(Accelerator accelerator) { - return accelerator.LoadAutoGroupedStreamKernel, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D>(GpuAdvanceDivisorCyclesKernel); + return accelerator.LoadAutoGroupedStreamKernel, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D>(GpuAdvanceDivisorCyclesKernel); } private static void GpuAdvanceDivisorCyclesKernel( Index1D index, + int steps, ArrayView1D divisors, ArrayView1D pow, ArrayView1D order, @@ -411,7 +415,6 @@ public sealed class DivisorCycleCache ulong divisor = divisors[index]; ulong currentPow = pow[index]; ulong currentOrder = order[index]; - int steps = GpuCycleStepsPerInvocation; do { diff --git a/PerfectNumbers.Core/Gpu/GpuConstants.cs b/PerfectNumbers.Core/Gpu/GpuConstants.cs index 976de4d..f48d4c6 100644 --- a/PerfectNumbers.Core/Gpu/GpuConstants.cs +++ b/PerfectNumbers.Core/Gpu/GpuConstants.cs @@ -1,7 +1,8 @@ namespace PerfectNumbers.Core.Gpu { - public static class GpuConstants - { - public const int ScanBatchSize = 2_097_152; + public static class GpuConstants + { + public const int ScanBatchSize = 2_097_152; + public const int GpuCycleStepsPerInvocation = 256; } } \ No newline at end of file