Divisor cycle cache will now respect --divisor-cycles-batch parameter (renamed from --divisor-cycles-batch-size)

This commit is contained in:
Marek Lemańczyk committed 2025-09-25 07:02:44 +02:00
1 parent d7f2dbbec6
commit 8b95a42f27
3 files changed
+22 -17

No files matched your search

+3 -2
View File
@@ -381,7 +381,7 @@ internal static class Program
{ {
useGpuCycles = !arg.AsSpan(arg.IndexOf('=') + 1).Equals("cpu", StringComparison.OrdinalIgnoreCase); 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))); cyclesBatchSize = Math.Max(1, int.Parse(arg.AsSpan(arg.IndexOf('=') + 1)));
} }
@@ -457,6 +457,7 @@ internal static class Program
MersenneDivisorCycles.Shared.LoadFrom(cyclesPath); MersenneDivisorCycles.Shared.LoadFrom(cyclesPath);
} }
DivisorCycleCache.SetDivisorCyclesBatchSize(cyclesBatchSize);
DivisorCycleCache.Shared.ConfigureGeneratorDevice(orderOnGpu); DivisorCycleCache.Shared.ConfigureGeneratorDevice(orderOnGpu);
DivisorCycleCache.Shared.ReloadFromCurrentSnapshot(); DivisorCycleCache.Shared.ReloadFromCurrentSnapshot();
@@ -1313,7 +1314,7 @@ internal static class Program
Console.WriteLine(" --results-prefix=<text> prefix to prepend to results filename"); Console.WriteLine(" --results-prefix=<text> prefix to prepend to results filename");
Console.WriteLine(" --divisor-cycles=<path> divisor cycles data file"); Console.WriteLine(" --divisor-cycles=<path> divisor cycles data file");
Console.WriteLine(" --divisor-cycles-device=cpu|gpu device for cycles generation (default gpu)"); Console.WriteLine(" --divisor-cycles-device=cpu|gpu device for cycles generation (default gpu)");
Console.WriteLine(" --divisor-cycles-batch-size=<value> batch size for cycles generation (default 512)"); Console.WriteLine(" --divisor-cycles-batch=<value> batch size for cycles generation (default 512)");
Console.WriteLine(" --divisor-cycles-continue continue divisor cycles generation"); Console.WriteLine(" --divisor-cycles-continue continue divisor cycles generation");
Console.WriteLine(" --divisor-cycles-limit=<value> cycle search iterations when --mersenne=divisor"); Console.WriteLine(" --divisor-cycles-limit=<value> cycle search iterations when --mersenne=divisor");
Console.WriteLine(" --use-divisor-cycles=true|false enable divisor cycle filtering in --mersenne=bydivisor (default false)"); Console.WriteLine(" --use-divisor-cycles=true|false enable divisor cycle filtering in --mersenne=bydivisor (default false)");
+15 -12
View File
@@ -24,25 +24,28 @@ public sealed class DivisorCycleCache
} }
private const int CycleGenerationBatchSize = 262_144; private const int CycleGenerationBatchSize = 262_144;
private const int GpuCycleStepsPerInvocation = 524_288 / 16;
private const byte ByteZero = 0; private const byte ByteZero = 0;
private const byte ByteOne = 1; private const byte ByteOne = 1;
private readonly object _sync = new(); private readonly object _sync = new();
private readonly ConcurrentDictionary<int, Task<CycleBlock>> _pending = new(); private readonly ConcurrentDictionary<int, Task<CycleBlock>> _pending = new();
private readonly ConcurrentDictionary<Accelerator, Action<Index1D, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>>> _gpuKernelCache = new(AcceleratorReferenceComparer.Instance); private readonly ConcurrentDictionary<Accelerator, Action<Index1D, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>>> _gpuKernelCache = new(AcceleratorReferenceComparer.Instance);
private CycleBlock _baseBlock = null!; private CycleBlock _baseBlock = null!;
private CycleBlock? _activeBlock; private CycleBlock? _activeBlock;
private CycleBlock? _prefetchedBlock; private CycleBlock? _prefetchedBlock;
private bool _useGpuGeneration = true; 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(); ulong[] snapshot = MersenneDivisorCycles.Shared.ExportSmallCyclesSnapshot();
Initialize(snapshot); Initialize(snapshot);
} }
public void ReloadFromCurrentSnapshot() public void ReloadFromCurrentSnapshot()
{ {
@@ -235,7 +238,7 @@ public sealed class DivisorCycleCache
if (_useGpuGeneration) if (_useGpuGeneration)
{ {
ComputeCyclesGpu(start, cycles); ComputeCyclesGpu(start, cycles, _divisorCyclesBatchSize);
} }
else 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 gpuLease = GpuKernelPool.GetKernel(_useGpuGeneration);
var execution = gpuLease.EnterExecutionScope(); var execution = gpuLease.EnterExecutionScope();
@@ -285,7 +288,7 @@ public sealed class DivisorCycleCache
try try
{ {
Accelerator accelerator = gpuLease.Accelerator; Accelerator accelerator = gpuLease.Accelerator;
Action<Index1D, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>> kernel = _gpuKernelCache.GetOrAdd(accelerator, LoadKernel); Action<Index1D, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>> kernel = _gpuKernelCache.GetOrAdd(accelerator, LoadKernel);
int length = destination.Length; int length = destination.Length;
int chunkCapacity = Math.Min(length, CycleGenerationBatchSize); int chunkCapacity = Math.Min(length, CycleGenerationBatchSize);
@@ -355,7 +358,7 @@ public sealed class DivisorCycleCache
while (pending > 0) while (pending > 0)
{ {
kernel(batchSize, divisorView, powView, orderView, resultView, statusView); kernel(batchSize, divisorCyclesBatchSize, divisorView, powView, orderView, resultView, statusView);
accelerator.Synchronize(); accelerator.Synchronize();
statusView.CopyToCPU(ref MemoryMarshal.GetReference(statusSpan), batchSize); statusView.CopyToCPU(ref MemoryMarshal.GetReference(statusSpan), batchSize);
@@ -390,13 +393,14 @@ public sealed class DivisorCycleCache
} }
} }
private static Action<Index1D, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>> LoadKernel(Accelerator accelerator) private static Action<Index1D, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>> LoadKernel(Accelerator accelerator)
{ {
return accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>>(GpuAdvanceDivisorCyclesKernel); return accelerator.LoadAutoGroupedStreamKernel<Index1D, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>>(GpuAdvanceDivisorCyclesKernel);
} }
private static void GpuAdvanceDivisorCyclesKernel( private static void GpuAdvanceDivisorCyclesKernel(
Index1D index, Index1D index,
int steps,
ArrayView1D<ulong, Stride1D.Dense> divisors, ArrayView1D<ulong, Stride1D.Dense> divisors,
ArrayView1D<ulong, Stride1D.Dense> pow, ArrayView1D<ulong, Stride1D.Dense> pow,
ArrayView1D<ulong, Stride1D.Dense> order, ArrayView1D<ulong, Stride1D.Dense> order,
@@ -411,7 +415,6 @@ public sealed class DivisorCycleCache
ulong divisor = divisors[index]; ulong divisor = divisors[index];
ulong currentPow = pow[index]; ulong currentPow = pow[index];
ulong currentOrder = order[index]; ulong currentOrder = order[index];
int steps = GpuCycleStepsPerInvocation;
do do
{ {
+4 -3
View File
@@ -1,7 +1,8 @@
namespace PerfectNumbers.Core.Gpu namespace PerfectNumbers.Core.Gpu
{ {
public static class GpuConstants public static class GpuConstants
{ {
public const int ScanBatchSize = 2_097_152; public const int ScanBatchSize = 2_097_152;
public const int GpuCycleStepsPerInvocation = 256;
} }
} }