Merge branch 'main' into codex/analyze-evenperfectbitscanner-execution-with-mersenne
This commit is contained in:
3 files changed
+8
-143
No files matched your search
@@ -16,8 +16,6 @@ internal static class Program
|
|||||||
private static ThreadLocal<MersenneNumberTester> MersenneTesters = null!;
|
private static ThreadLocal<MersenneNumberTester> MersenneTesters = null!;
|
||||||
private static ThreadLocal<ModResidueTracker> PResidue = null!; // p mod d tracker (per-thread)
|
private static ThreadLocal<ModResidueTracker> PResidue = null!; // p mod d tracker (per-thread)
|
||||||
private const ulong InitialP = PerfectNumberConstants.BiggestKnownEvenPerfectP;
|
private const ulong InitialP = PerfectNumberConstants.BiggestKnownEvenPerfectP;
|
||||||
|
|
||||||
private const int ConsoleInterval = 100_000;
|
|
||||||
private const int WriteBatchSize = 100;
|
private const int WriteBatchSize = 100;
|
||||||
private const string DefaultCyclesPath = "divisor_cycles.bin";
|
private const string DefaultCyclesPath = "divisor_cycles.bin";
|
||||||
private static string ResultsFileName = "even_perfect_bit_scan_results.csv";
|
private static string ResultsFileName = "even_perfect_bit_scan_results.csv";
|
||||||
@@ -1082,7 +1080,7 @@ internal static class Program
|
|||||||
|
|
||||||
lock (Sync)
|
lock (Sync)
|
||||||
{
|
{
|
||||||
if (_consoleCounter >= ConsoleInterval)
|
if (_consoleCounter >= PerfectNumberConstants.ConsoleInterval)
|
||||||
{
|
{
|
||||||
printToConsole = true;
|
printToConsole = true;
|
||||||
primeFlag = passedAllTests && !lastWasComposite && _primeFoundAfterInit;
|
primeFlag = passedAllTests && !lastWasComposite && _primeFoundAfterInit;
|
||||||
|
|||||||
@@ -17,14 +17,10 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
|
|||||||
private ulong _lastStatusDivisor;
|
private ulong _lastStatusDivisor;
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<Accelerator, Action<Index1D, ulong, ArrayView<ulong>, ArrayView<byte>>> _kernelCache = new();
|
private readonly ConcurrentDictionary<Accelerator, Action<Index1D, ulong, ArrayView<ulong>, ArrayView<byte>>> _kernelCache = new();
|
||||||
private readonly ConcurrentDictionary<Accelerator, Action<Index1D, ulong, ArrayView<ulong>, ArrayView<byte>>> _kernelByPrimeCache = new();
|
|
||||||
|
|
||||||
private Action<Index1D, ulong, ArrayView<ulong>, ArrayView<byte>> GetKernel(Accelerator accelerator) =>
|
private Action<Index1D, ulong, ArrayView<ulong>, ArrayView<byte>> GetKernel(Accelerator accelerator) =>
|
||||||
_kernelCache.GetOrAdd(accelerator, acc => acc.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView<ulong>, ArrayView<byte>>(CheckKernel));
|
_kernelCache.GetOrAdd(accelerator, acc => acc.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView<ulong>, ArrayView<byte>>(CheckKernel));
|
||||||
|
|
||||||
private Action<Index1D, ulong, ArrayView<ulong>, ArrayView<byte>> GetKernelByPrime(Accelerator accelerator) =>
|
|
||||||
_kernelByPrimeCache.GetOrAdd(accelerator, acc => acc.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView<ulong>, ArrayView<byte>>(CheckKernelByPrime));
|
|
||||||
|
|
||||||
public int GpuBatchSize
|
public int GpuBatchSize
|
||||||
{
|
{
|
||||||
get => _gpuBatchSize;
|
get => _gpuBatchSize;
|
||||||
@@ -41,48 +37,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong DivisorLimit
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
lock (_sync)
|
|
||||||
{
|
|
||||||
if (!_isConfigured)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("ConfigureFromMaxPrime must be called before using the tester.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return _divisorLimit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ulong GetAllowedMaxDivisor(ulong prime)
|
|
||||||
{
|
|
||||||
lock (_sync)
|
|
||||||
{
|
|
||||||
if (!_isConfigured)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("ConfigureFromMaxPrime must be called before using the tester.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ComputeAllowedMaxDivisor(prime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DivisorScanSession CreateDivisorSession()
|
|
||||||
{
|
|
||||||
lock (_sync)
|
|
||||||
{
|
|
||||||
if (!_isConfigured)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("ConfigureFromMaxPrime must be called before using the tester.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new DivisorScanSession(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsPrime(ulong prime, out bool divisorsExhausted)
|
public bool IsPrime(ulong prime, out bool divisorsExhausted)
|
||||||
{
|
{
|
||||||
lock (_sync)
|
lock (_sync)
|
||||||
@@ -101,7 +55,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
|
|||||||
|
|
||||||
bool composite = CheckDivisors(prime, allowedMax, out ulong lastProcessed, out bool coveredRange);
|
bool composite = CheckDivisors(prime, allowedMax, out ulong lastProcessed, out bool coveredRange);
|
||||||
|
|
||||||
if (!composite && lastProcessed != 0UL)
|
if (lastProcessed != 0UL)
|
||||||
{
|
{
|
||||||
ReportStatus(lastProcessed);
|
ReportStatus(lastProcessed);
|
||||||
}
|
}
|
||||||
@@ -225,88 +179,13 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
|
|||||||
return composite;
|
return composite;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class DivisorScanSession : IDisposable
|
|
||||||
{
|
|
||||||
private readonly MersenneNumberDivisorByDivisorGpuTester _owner;
|
|
||||||
private readonly GpuContextPool.GpuContextLease _lease;
|
|
||||||
private readonly Accelerator _accelerator;
|
|
||||||
private readonly Action<Index1D, ulong, ArrayView<ulong>, ArrayView<byte>> _kernel;
|
|
||||||
private readonly MemoryBuffer1D<ulong, Stride1D.Dense> _primesBuffer;
|
|
||||||
private readonly MemoryBuffer1D<byte, Stride1D.Dense> _hitsBuffer;
|
|
||||||
private readonly ulong[] _primesHost;
|
|
||||||
private readonly byte[] _hitsHost;
|
|
||||||
private bool _disposed;
|
|
||||||
|
|
||||||
internal DivisorScanSession(MersenneNumberDivisorByDivisorGpuTester owner)
|
|
||||||
{
|
|
||||||
_owner = owner;
|
|
||||||
_lease = GpuContextPool.RentPreferred(preferCpu: false);
|
|
||||||
_accelerator = _lease.Accelerator;
|
|
||||||
_kernel = owner.GetKernelByPrime(_accelerator);
|
|
||||||
_primesBuffer = _accelerator.Allocate1D<ulong>(owner._gpuBatchSize);
|
|
||||||
_hitsBuffer = _accelerator.Allocate1D<byte>(owner._gpuBatchSize);
|
|
||||||
_primesHost = ArrayPool<ulong>.Shared.Rent(owner._gpuBatchSize);
|
|
||||||
_hitsHost = ArrayPool<byte>.Shared.Rent(owner._gpuBatchSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CheckDivisor(ulong divisor, ReadOnlySpan<ulong> primes, Span<byte> hits)
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
{
|
|
||||||
throw new ObjectDisposedException(nameof(DivisorScanSession));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (primes.Length == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int offset = 0;
|
|
||||||
while (offset < primes.Length)
|
|
||||||
{
|
|
||||||
int batchSize = Math.Min(_owner._gpuBatchSize, primes.Length - offset);
|
|
||||||
Span<ulong> primeSpan = _primesHost.AsSpan(0, batchSize);
|
|
||||||
primes.Slice(offset, batchSize).CopyTo(primeSpan);
|
|
||||||
|
|
||||||
var primesView = _primesBuffer.View.SubView(0, batchSize);
|
|
||||||
var hitsView = _hitsBuffer.View.SubView(0, batchSize);
|
|
||||||
|
|
||||||
primesView.CopyFromCPU(ref MemoryMarshal.GetReference(primeSpan), batchSize);
|
|
||||||
_kernel(batchSize, divisor, primesView, hitsView);
|
|
||||||
_accelerator.Synchronize();
|
|
||||||
|
|
||||||
Span<byte> hitSpan = _hitsHost.AsSpan(0, batchSize);
|
|
||||||
hitsView.CopyToCPU(ref MemoryMarshal.GetReference(hitSpan), batchSize);
|
|
||||||
hitSpan.CopyTo(hits.Slice(offset, batchSize));
|
|
||||||
offset += batchSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_disposed = true;
|
|
||||||
ArrayPool<ulong>.Shared.Return(_primesHost, clearArray: true);
|
|
||||||
ArrayPool<byte>.Shared.Return(_hitsHost, clearArray: true);
|
|
||||||
_primesBuffer.Dispose();
|
|
||||||
_hitsBuffer.Dispose();
|
|
||||||
_lease.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ReportStatus(ulong divisor)
|
private void ReportStatus(ulong divisor)
|
||||||
{
|
{
|
||||||
if (divisor <= _lastStatusDivisor)
|
if (++_lastStatusDivisor == PerfectNumberConstants.ConsoleInterval)
|
||||||
{
|
{
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastStatusDivisor = divisor;
|
|
||||||
Console.WriteLine($"...processed by-divisor candidate = {divisor}");
|
Console.WriteLine($"...processed by-divisor candidate = {divisor}");
|
||||||
|
_lastStatusDivisor = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong ComputeDivisorLimitFromMaxPrime(ulong maxPrime)
|
private static ulong ComputeDivisorLimitFromMaxPrime(ulong maxPrime)
|
||||||
@@ -353,19 +232,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
|
|||||||
hits[index] = pow == 1UL ? (byte)1 : (byte)0;
|
hits[index] = pow == 1UL ? (byte)1 : (byte)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CheckKernelByPrime(Index1D index, ulong divisor, ArrayView<ulong> primes, ArrayView<byte> hits)
|
|
||||||
{
|
|
||||||
ulong prime = primes[index];
|
|
||||||
if (divisor <= 1UL || (divisor & 1UL) == 0UL)
|
|
||||||
{
|
|
||||||
hits[index] = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong pow = Pow2Mod(prime, divisor);
|
|
||||||
hits[index] = pow == 1UL ? (byte)1 : (byte)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ulong Pow2Mod(ulong exponent, ulong modulus)
|
private static ulong Pow2Mod(ulong exponent, ulong modulus)
|
||||||
{
|
{
|
||||||
if (modulus <= 1UL)
|
if (modulus <= 1UL)
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ namespace PerfectNumbers.Core;
|
|||||||
public static class PerfectNumberConstants
|
public static class PerfectNumberConstants
|
||||||
{
|
{
|
||||||
public const ulong BiggestKnownEvenPerfectP = 136279841UL;
|
public const ulong BiggestKnownEvenPerfectP = 136279841UL;
|
||||||
public static readonly uint PrimesLimit = 1_000_000; //(ulong)Array.MaxLength;// 1_000_000;
|
public const int ConsoleInterval = 100_000;
|
||||||
public const int MaxQForDivisorCycles = 4_000_000;
|
|
||||||
public const ulong ExtraDivisorCycleSearchLimit = 64UL;
|
public const ulong ExtraDivisorCycleSearchLimit = 64UL;
|
||||||
|
public const int MaxQForDivisorCycles = 4_000_000;
|
||||||
|
public static readonly uint PrimesLimit = 1_000_000; //(ulong)Array.MaxLength;// 1_000_000;
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user