Additional checks will be skipped in bydivisor mode to speed up calculations. Console output extended.
This commit is contained in:
1 parent
562d2adc3e
commit
d117921c3a
2 files changed
+241
-231
No files matched your search
+234
-231
@@ -54,30 +54,30 @@ internal static class Program
|
|||||||
private static double _zeroFracConj = -1.0; // disabled when < 0
|
private static double _zeroFracConj = -1.0; // disabled when < 0
|
||||||
private static int _maxZeroConj = -1; // disabled when < 0
|
private static int _maxZeroConj = -1; // disabled when < 0
|
||||||
|
|
||||||
private struct ByDivisorPrimeState
|
private struct ByDivisorPrimeState
|
||||||
{
|
{
|
||||||
internal ulong Prime;
|
internal ulong Prime;
|
||||||
internal ulong AllowedMax;
|
internal ulong AllowedMax;
|
||||||
internal bool Completed;
|
internal bool Completed;
|
||||||
internal bool Composite;
|
internal bool Composite;
|
||||||
internal bool DetailedCheck;
|
internal bool DetailedCheck;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly struct PendingResult
|
private readonly struct PendingResult
|
||||||
{
|
{
|
||||||
internal PendingResult(ulong prime, bool detailedCheck, bool passedAllTests)
|
internal PendingResult(ulong prime, bool detailedCheck, bool passedAllTests)
|
||||||
{
|
{
|
||||||
Prime = prime;
|
Prime = prime;
|
||||||
DetailedCheck = detailedCheck;
|
DetailedCheck = detailedCheck;
|
||||||
PassedAllTests = passedAllTests;
|
PassedAllTests = passedAllTests;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ulong Prime { get; }
|
internal ulong Prime { get; }
|
||||||
|
|
||||||
internal bool DetailedCheck { get; }
|
internal bool DetailedCheck { get; }
|
||||||
|
|
||||||
internal bool PassedAllTests { get; }
|
internal bool PassedAllTests { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void Main(string[] args)
|
private static unsafe void Main(string[] args)
|
||||||
{
|
{
|
||||||
@@ -660,9 +660,9 @@ internal static class Program
|
|||||||
|
|
||||||
Console.WriteLine("Starting scan...");
|
Console.WriteLine("Starting scan...");
|
||||||
|
|
||||||
if (_useByDivisorMode)
|
if (_useByDivisorMode)
|
||||||
{
|
{
|
||||||
RunByDivisorMode(filterList, divisorCyclesSearchLimit, threadCount);
|
RunByDivisorMode(filterList, divisorCyclesSearchLimit, threadCount);
|
||||||
FlushBuffer();
|
FlushBuffer();
|
||||||
StringBuilderPool.Return(_outputBuilder!);
|
StringBuilderPool.Return(_outputBuilder!);
|
||||||
return;
|
return;
|
||||||
@@ -750,12 +750,12 @@ internal static class Program
|
|||||||
StringBuilderPool.Return(_outputBuilder!);
|
StringBuilderPool.Return(_outputBuilder!);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RunByDivisorMode(List<ulong> primes, ulong divisorCyclesSearchLimit, int threadCount)
|
private static void RunByDivisorMode(List<ulong> primes, ulong divisorCyclesSearchLimit, int threadCount)
|
||||||
{
|
{
|
||||||
if (primes.Count == 0)
|
if (primes.Count == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ByDivisorPrimeState> states = new(primes.Count);
|
List<ByDivisorPrimeState> states = new(primes.Count);
|
||||||
|
|
||||||
@@ -788,232 +788,232 @@ internal static class Program
|
|||||||
|
|
||||||
_byDivisorPrecheckOnly = false;
|
_byDivisorPrecheckOnly = false;
|
||||||
|
|
||||||
if (states.Count == 0)
|
if (states.Count == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
object stateLock = new();
|
object stateLock = new();
|
||||||
ulong divisorLimit = _byDivisorTester!.DivisorLimit;
|
ulong divisorLimit = _byDivisorTester!.DivisorLimit;
|
||||||
ulong nextDivisor = 3UL;
|
ulong nextDivisor = 3UL;
|
||||||
bool divisorsExhausted = false;
|
bool divisorsExhausted = false;
|
||||||
ulong finalDivisorValue = 3UL;
|
ulong finalDivisorValue = 3UL;
|
||||||
int remainingStates = states.Count;
|
int remainingStates = states.Count;
|
||||||
|
|
||||||
Task[] workers = new Task[Math.Max(1, threadCount)];
|
Task[] workers = new Task[Math.Max(1, threadCount)];
|
||||||
|
|
||||||
for (int i = 0; i < workers.Length; i++)
|
for (int i = 0; i < workers.Length; i++)
|
||||||
{
|
{
|
||||||
workers[i] = Task.Run(() =>
|
workers[i] = Task.Run(() =>
|
||||||
{
|
{
|
||||||
using var session = _byDivisorTester!.CreateDivisorSession();
|
using var session = _byDivisorTester!.CreateDivisorSession();
|
||||||
byte[] hitsBuffer = ArrayPool<byte>.Shared.Rent(states.Count);
|
byte[] hitsBuffer = ArrayPool<byte>.Shared.Rent(states.Count);
|
||||||
ulong[] primeBuffer = ArrayPool<ulong>.Shared.Rent(states.Count);
|
ulong[] primeBuffer = ArrayPool<ulong>.Shared.Rent(states.Count);
|
||||||
int[] indexBuffer = ArrayPool<int>.Shared.Rent(states.Count);
|
int[] indexBuffer = ArrayPool<int>.Shared.Rent(states.Count);
|
||||||
List<PendingResult> completions = new(states.Count);
|
List<PendingResult> completions = new(states.Count);
|
||||||
List<PendingResult> composites = new(states.Count);
|
List<PendingResult> composites = new(states.Count);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
ulong divisor;
|
ulong divisor;
|
||||||
int activeCount;
|
int activeCount;
|
||||||
bool shouldTerminate;
|
bool shouldTerminate;
|
||||||
bool hasWork;
|
bool hasWork;
|
||||||
|
|
||||||
lock (stateLock)
|
lock (stateLock)
|
||||||
{
|
{
|
||||||
hasWork = TryAcquireDivisorWork(states, divisorLimit, primeBuffer, indexBuffer, completions, ref nextDivisor, ref divisorsExhausted, ref finalDivisorValue, ref remainingStates, out divisor, out activeCount, out shouldTerminate);
|
hasWork = TryAcquireDivisorWork(states, divisorLimit, primeBuffer, indexBuffer, completions, ref nextDivisor, ref divisorsExhausted, ref finalDivisorValue, ref remainingStates, out divisor, out activeCount, out shouldTerminate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (completions.Count > 0)
|
if (completions.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (PendingResult result in completions)
|
foreach (PendingResult result in completions)
|
||||||
{
|
{
|
||||||
PrintResult(result.Prime, searchedMersenne: true, detailedCheck: result.DetailedCheck, passedAllTests: result.PassedAllTests);
|
PrintResult(result.Prime, searchedMersenne: true, detailedCheck: result.DetailedCheck, passedAllTests: result.PassedAllTests);
|
||||||
}
|
}
|
||||||
|
|
||||||
completions.Clear();
|
completions.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasWork)
|
if (!hasWork)
|
||||||
{
|
{
|
||||||
if (shouldTerminate)
|
if (shouldTerminate)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Span<byte> hitsSpan = hitsBuffer.AsSpan(0, activeCount);
|
Span<byte> hitsSpan = hitsBuffer.AsSpan(0, activeCount);
|
||||||
hitsSpan.Clear();
|
hitsSpan.Clear();
|
||||||
session.CheckDivisor(divisor, primeBuffer.AsSpan(0, activeCount), hitsSpan);
|
session.CheckDivisor(divisor, primeBuffer.AsSpan(0, activeCount), hitsSpan);
|
||||||
|
|
||||||
bool exitAfterIteration;
|
bool exitAfterIteration;
|
||||||
composites.Clear();
|
composites.Clear();
|
||||||
|
|
||||||
lock (stateLock)
|
lock (stateLock)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < activeCount; j++)
|
for (int j = 0; j < activeCount; j++)
|
||||||
{
|
{
|
||||||
if (hitsSpan[j] == 0)
|
if (hitsSpan[j] == 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = indexBuffer[j];
|
int index = indexBuffer[j];
|
||||||
var state = states[index];
|
var state = states[index];
|
||||||
if (state.Completed)
|
if (state.Completed)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.Completed = true;
|
state.Completed = true;
|
||||||
state.Composite = true;
|
state.Composite = true;
|
||||||
state.DetailedCheck = true;
|
state.DetailedCheck = true;
|
||||||
states[index] = state;
|
states[index] = state;
|
||||||
remainingStates--;
|
remainingStates--;
|
||||||
composites.Add(new PendingResult(state.Prime, state.DetailedCheck, false));
|
composites.Add(new PendingResult(state.Prime, state.DetailedCheck, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
exitAfterIteration = remainingStates == 0;
|
exitAfterIteration = remainingStates == 0;
|
||||||
if (exitAfterIteration && !divisorsExhausted)
|
if (exitAfterIteration && !divisorsExhausted)
|
||||||
{
|
{
|
||||||
divisorsExhausted = true;
|
divisorsExhausted = true;
|
||||||
finalDivisorValue = Math.Max(finalDivisorValue, nextDivisor);
|
finalDivisorValue = Math.Max(finalDivisorValue, nextDivisor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (composites.Count > 0)
|
if (composites.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (PendingResult result in composites)
|
foreach (PendingResult result in composites)
|
||||||
{
|
{
|
||||||
PrintResult(result.Prime, searchedMersenne: true, detailedCheck: result.DetailedCheck, passedAllTests: result.PassedAllTests);
|
PrintResult(result.Prime, searchedMersenne: true, detailedCheck: result.DetailedCheck, passedAllTests: result.PassedAllTests);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exitAfterIteration)
|
if (exitAfterIteration)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
ArrayPool<int>.Shared.Return(indexBuffer, clearArray: true);
|
ArrayPool<int>.Shared.Return(indexBuffer, clearArray: true);
|
||||||
ArrayPool<ulong>.Shared.Return(primeBuffer, clearArray: true);
|
ArrayPool<ulong>.Shared.Return(primeBuffer, clearArray: true);
|
||||||
ArrayPool<byte>.Shared.Return(hitsBuffer, clearArray: true);
|
ArrayPool<byte>.Shared.Return(hitsBuffer, clearArray: true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Task.WaitAll(workers);
|
Task.WaitAll(workers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TryAcquireDivisorWork(List<ByDivisorPrimeState> states, ulong divisorLimit, ulong[] primeBuffer, int[] indexBuffer, List<PendingResult> completions, ref ulong nextDivisor, ref bool divisorsExhausted, ref ulong finalDivisorValue, ref int remainingStates, out ulong divisor, out int activeCount, out bool shouldTerminate)
|
private static bool TryAcquireDivisorWork(List<ByDivisorPrimeState> states, ulong divisorLimit, ulong[] primeBuffer, int[] indexBuffer, List<PendingResult> completions, ref ulong nextDivisor, ref bool divisorsExhausted, ref ulong finalDivisorValue, ref int remainingStates, out ulong divisor, out int activeCount, out bool shouldTerminate)
|
||||||
{
|
{
|
||||||
completions.Clear();
|
completions.Clear();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (remainingStates == 0)
|
if (remainingStates == 0)
|
||||||
{
|
{
|
||||||
divisor = 0UL;
|
divisor = 0UL;
|
||||||
activeCount = 0;
|
activeCount = 0;
|
||||||
shouldTerminate = true;
|
shouldTerminate = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (divisorsExhausted || nextDivisor > divisorLimit)
|
if (divisorsExhausted || nextDivisor > divisorLimit)
|
||||||
{
|
{
|
||||||
if (!divisorsExhausted)
|
if (!divisorsExhausted)
|
||||||
{
|
{
|
||||||
divisorsExhausted = true;
|
divisorsExhausted = true;
|
||||||
finalDivisorValue = nextDivisor;
|
finalDivisorValue = nextDivisor;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong completionDivisor = finalDivisorValue;
|
ulong completionDivisor = finalDivisorValue;
|
||||||
for (int i = 0; i < states.Count; i++)
|
for (int i = 0; i < states.Count; i++)
|
||||||
{
|
{
|
||||||
var state = states[i];
|
var state = states[i];
|
||||||
if (state.Completed)
|
if (state.Completed)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.Completed = true;
|
state.Completed = true;
|
||||||
state.DetailedCheck = completionDivisor > state.AllowedMax;
|
state.DetailedCheck = completionDivisor > state.AllowedMax;
|
||||||
states[i] = state;
|
states[i] = state;
|
||||||
remainingStates--;
|
remainingStates--;
|
||||||
completions.Add(new PendingResult(state.Prime, state.DetailedCheck, true));
|
completions.Add(new PendingResult(state.Prime, state.DetailedCheck, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
divisor = 0UL;
|
divisor = 0UL;
|
||||||
activeCount = 0;
|
activeCount = 0;
|
||||||
shouldTerminate = true;
|
shouldTerminate = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong divisorValue = nextDivisor;
|
ulong divisorValue = nextDivisor;
|
||||||
ulong candidate = divisorValue + 2UL;
|
ulong candidate = divisorValue + 2UL;
|
||||||
if (candidate <= divisorValue)
|
if (candidate <= divisorValue)
|
||||||
{
|
{
|
||||||
divisorsExhausted = true;
|
divisorsExhausted = true;
|
||||||
finalDivisorValue = divisorValue;
|
finalDivisorValue = divisorValue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nextDivisor = candidate;
|
nextDivisor = candidate;
|
||||||
if (nextDivisor > divisorLimit)
|
if (nextDivisor > divisorLimit)
|
||||||
{
|
{
|
||||||
divisorsExhausted = true;
|
divisorsExhausted = true;
|
||||||
finalDivisorValue = nextDivisor;
|
finalDivisorValue = nextDivisor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
activeCount = 0;
|
activeCount = 0;
|
||||||
for (int i = 0; i < states.Count; i++)
|
for (int i = 0; i < states.Count; i++)
|
||||||
{
|
{
|
||||||
var state = states[i];
|
var state = states[i];
|
||||||
if (state.Completed)
|
if (state.Completed)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.AllowedMax < divisorValue)
|
if (state.AllowedMax < divisorValue)
|
||||||
{
|
{
|
||||||
state.Completed = true;
|
state.Completed = true;
|
||||||
state.DetailedCheck = true;
|
state.DetailedCheck = true;
|
||||||
states[i] = state;
|
states[i] = state;
|
||||||
remainingStates--;
|
remainingStates--;
|
||||||
completions.Add(new PendingResult(state.Prime, state.DetailedCheck, true));
|
completions.Add(new PendingResult(state.Prime, state.DetailedCheck, true));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
primeBuffer[activeCount] = state.Prime;
|
primeBuffer[activeCount] = state.Prime;
|
||||||
indexBuffer[activeCount] = i;
|
indexBuffer[activeCount] = i;
|
||||||
activeCount++;
|
activeCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeCount == 0)
|
if (activeCount == 0)
|
||||||
{
|
{
|
||||||
if (completions.Count == 0)
|
if (completions.Count == 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
divisor = 0UL;
|
divisor = 0UL;
|
||||||
shouldTerminate = remainingStates == 0 && (divisorsExhausted || nextDivisor > divisorLimit);
|
shouldTerminate = remainingStates == 0 && (divisorsExhausted || nextDivisor > divisorLimit);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
divisor = divisorValue;
|
divisor = divisorValue;
|
||||||
shouldTerminate = false;
|
shouldTerminate = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe void LoadResultsFile(string resultsFileName, Action<ulong, bool, bool> lineProcessorAction)
|
private static unsafe void LoadResultsFile(string resultsFileName, Action<ulong, bool, bool> lineProcessorAction)
|
||||||
{
|
{
|
||||||
@@ -1440,7 +1440,7 @@ internal static class Program
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fast residue-based composite check for p using small primes
|
// Fast residue-based composite check for p using small primes
|
||||||
if (!_useDivisor && IsCompositeByResidues(p))
|
if (!_useDivisor && !_useByDivisorMode && IsCompositeByResidues(p))
|
||||||
{
|
{
|
||||||
searchedMersenne = false;
|
searchedMersenne = false;
|
||||||
detailedCheck = false;
|
detailedCheck = false;
|
||||||
@@ -1450,13 +1450,16 @@ internal static class Program
|
|||||||
|
|
||||||
// If primes-device=gpu, route p primality through GPU-assisted sieve (optional MR later)
|
// If primes-device=gpu, route p primality through GPU-assisted sieve (optional MR later)
|
||||||
// TODO: Add deterministic Miller–Rabin rounds in GPU path for 64-bit range.
|
// TODO: Add deterministic Miller–Rabin rounds in GPU path for 64-bit range.
|
||||||
bool isPrimeP = GpuContextPool.ForceCpu
|
if (!_useByDivisorMode)
|
||||||
? PrimeTesters.Value!.IsPrime(p, CancellationToken.None)
|
|
||||||
: PrimeTesters.Value!.IsPrimeGpu(p, CancellationToken.None);
|
|
||||||
if (!isPrimeP)
|
|
||||||
{
|
{
|
||||||
_lastCompositeP = true;
|
bool isPrimeP = GpuContextPool.ForceCpu
|
||||||
return false;
|
? PrimeTesters.Value!.IsPrime(p, CancellationToken.None)
|
||||||
|
: PrimeTesters.Value!.IsPrimeGpu(p, CancellationToken.None);
|
||||||
|
if (!isPrimeP)
|
||||||
|
{
|
||||||
|
_lastCompositeP = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
searchedMersenne = true;
|
searchedMersenne = true;
|
||||||
|
|||||||
@@ -274,12 +274,19 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
|
|||||||
}
|
}
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
int consoleStatus = 0;
|
||||||
while (offset < primes.Length)
|
while (offset < primes.Length)
|
||||||
{
|
{
|
||||||
int batchSize = Math.Min(_owner._gpuBatchSize, primes.Length - offset);
|
int batchSize = Math.Min(_owner._gpuBatchSize, primes.Length - offset);
|
||||||
Span<ulong> primeSpan = _primesHost.AsSpan(0, batchSize);
|
Span<ulong> primeSpan = _primesHost.AsSpan(0, batchSize);
|
||||||
primes.Slice(offset, batchSize).CopyTo(primeSpan);
|
primes.Slice(offset, batchSize).CopyTo(primeSpan);
|
||||||
|
|
||||||
|
if (++consoleStatus == PerfectNumberConstants.ConsoleInterval)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"...processed by-divisor candidate = {primes[0]}");
|
||||||
|
consoleStatus = 0;
|
||||||
|
}
|
||||||
|
|
||||||
var primesView = _primesBuffer.View.SubView(0, batchSize);
|
var primesView = _primesBuffer.View.SubView(0, batchSize);
|
||||||
var hitsView = _hitsBuffer.View.SubView(0, batchSize);
|
var hitsView = _hitsBuffer.View.SubView(0, batchSize);
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user