Refine by-divisor prime test time limits

This commit is contained in:
Marek Lemańczyk committed 2025-10-11 22:28:52 +02:00
1 parent b47e758235
commit 6a1925dd47
9 files changed
+260 -71

No files matched your search

@@ -61,7 +61,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
}
}
public bool IsPrime(ulong prime, out bool divisorsExhausted)
public bool IsPrime(ulong prime, out bool divisorsExhausted, TimeSpan? timeLimit = null)
{
ulong allowedMax;
lock (_sync)
@@ -89,7 +89,8 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
allowedMax,
out lastProcessed,
out processedAll,
out processedCount);
out processedCount,
timeLimit);
if (processedCount > 0UL)
{
@@ -163,12 +164,22 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
ulong allowedMax,
out ulong lastProcessed,
out bool processedAll,
out ulong processedCount)
out ulong processedCount,
TimeSpan? timeLimit)
{
lastProcessed = 0UL;
processedCount = 0UL;
processedAll = false;
PrimeTestTimeLimit limitGuard;
if (!PrimeTestTimeLimit.TryCreate(timeLimit, out limitGuard))
{
return false;
}
bool enforceLimit = limitGuard.IsActive;
ulong iterationCounter = 0UL;
if (allowedMax < 3UL)
{
return false;
@@ -216,6 +227,13 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
while (divisor <= limit)
{
if (enforceLimit && (iterationCounter == 0UL || (iterationCounter & 63UL) == 0UL) && limitGuard.HasExpired())
{
processedAll = false;
return false;
}
iterationCounter++;
ulong candidate = (ulong)divisor;
processedCount++;
lastProcessed = candidate;
@@ -71,7 +71,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
}
}
public bool IsPrime(ulong prime, out bool divisorsExhausted)
public bool IsPrime(ulong prime, out bool divisorsExhausted, TimeSpan? timeLimit = null)
{
ulong allowedMax;
int batchCapacity;
@@ -108,6 +108,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
composite = CheckDivisors(
prime,
allowedMax,
timeLimit,
accelerator,
kernel,
resources.DivisorsBuffer,
@@ -175,6 +176,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
private static bool CheckDivisors(
ulong prime,
ulong allowedMax,
TimeSpan? timeLimit,
Accelerator accelerator,
Action<Index1D, ArrayView<MontgomeryDivisorData>, ArrayView<ulong>, ArrayView<byte>> kernel,
MemoryBuffer1D<MontgomeryDivisorData, Stride1D.Dense> divisorsBuffer,
@@ -202,6 +204,15 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
bool processedAll = false;
processedCount = 0UL;
lastProcessed = 0UL;
coveredRange = false;
PrimeTestTimeLimit limitGuard;
if (!PrimeTestTimeLimit.TryCreate(timeLimit, out limitGuard))
{
return false;
}
bool enforceLimit = limitGuard.IsActive;
Span<MontgomeryDivisorData> divisorDataSpan;
Span<ulong> divisorSpan;
@@ -277,6 +288,12 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
{
while (currentK <= maxK)
{
if (enforceLimit && limitGuard.HasExpired())
{
processedAll = false;
return false;
}
int chunkCount = Math.Min(chunkCapacity, batchCapacity);
ulong remainingK = maxK - currentK + 1UL;
if ((ulong)chunkCount > remainingK)
@@ -12,7 +12,7 @@ public interface IMersenneNumberDivisorByDivisorTester
ulong GetAllowedMaxDivisor(ulong prime);
bool IsPrime(ulong prime, out bool divisorsExhausted);
bool IsPrime(ulong prime, out bool divisorsExhausted, TimeSpan? timeLimit = null);
IDivisorScanSession CreateDivisorSession();
@@ -18,7 +18,8 @@ public static class MersenneNumberDivisorByDivisorTester
Action markComposite,
Action clearComposite,
Action<ulong, bool, bool, bool> printResult,
int threadCount)
int threadCount,
TimeSpan? primeTestLimit)
{
if (candidates.Count == 0)
{
@@ -243,7 +244,7 @@ public static class MersenneNumberDivisorByDivisorTester
void ProcessPrime(ulong prime)
{
bool isPrime = tester.IsPrime(prime, out bool divisorsExhausted);
bool isPrime = tester.IsPrime(prime, out bool divisorsExhausted, primeTestLimit);
if (!isPrime)
{
+72
View File
@@ -0,0 +1,72 @@
using System;
using System.Diagnostics;
namespace PerfectNumbers.Core;
internal readonly struct PrimeTestTimeLimit
{
private readonly long _deadlineTimestamp;
private PrimeTestTimeLimit(bool isActive, long deadlineTimestamp)
{
IsActive = isActive;
_deadlineTimestamp = deadlineTimestamp;
}
internal bool IsActive { get; }
internal static bool TryCreate(TimeSpan? timeLimit, out PrimeTestTimeLimit limit)
{
if (!timeLimit.HasValue)
{
limit = new PrimeTestTimeLimit(isActive: false, deadlineTimestamp: long.MaxValue);
return true;
}
TimeSpan limitValue = timeLimit.GetValueOrDefault();
if (limitValue <= TimeSpan.Zero)
{
limit = new PrimeTestTimeLimit(isActive: true, deadlineTimestamp: long.MinValue);
return false;
}
double seconds = limitValue.TotalSeconds;
if (double.IsInfinity(seconds))
{
limit = new PrimeTestTimeLimit(isActive: true, deadlineTimestamp: long.MaxValue);
return true;
}
double scaled = seconds * Stopwatch.Frequency;
long limitTicks = scaled >= long.MaxValue ? long.MaxValue : (long)scaled;
long startTimestamp = Stopwatch.GetTimestamp();
long deadline = startTimestamp <= long.MaxValue - limitTicks ? startTimestamp + limitTicks : long.MaxValue;
if (deadline < startTimestamp)
{
deadline = long.MaxValue;
}
limit = new PrimeTestTimeLimit(isActive: true, deadlineTimestamp: deadline);
return true;
}
internal bool HasExpired()
{
if (!IsActive)
{
return false;
}
if (_deadlineTimestamp == long.MaxValue)
{
return false;
}
if (_deadlineTimestamp == long.MinValue)
{
return true;
}
return Stopwatch.GetTimestamp() >= _deadlineTimestamp;
}
}