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
+23 -18

No files matched your search

+4 -3
View File
@@ -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=<text> prefix to prepend to results filename");
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-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-limit=<value> cycle search iterations when --mersenne=divisor");
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 GpuCycleStepsPerInvocation = 524_288 / 16;
private const byte ByteZero = 0;
private const byte ByteOne = 1;
private readonly object _sync = 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? _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<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 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<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(
Index1D index,
int steps,
ArrayView1D<ulong, Stride1D.Dense> divisors,
ArrayView1D<ulong, Stride1D.Dense> pow,
ArrayView1D<ulong, Stride1D.Dense> 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
{
+4 -3
View File
@@ -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;
}
}