Add timed test mode for prime candidate scans
This commit is contained in:
1 parent
9c474fc241
commit
03751c27be
1 file changed
+142
-1
@@ -1,5 +1,6 @@
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
@@ -45,6 +46,11 @@ internal static class Program
|
||||
private static readonly Optimized PrimeIterator = new();
|
||||
private static ulong _byDivisorStartPrime;
|
||||
|
||||
private static bool _testMode;
|
||||
private static int _testTargetPrimeCount;
|
||||
private static int _testProcessedPrimeCount;
|
||||
private const string TestTimeFileName = "even_perfect_test_time.txt";
|
||||
|
||||
[ThreadStatic]
|
||||
private static bool _lastCompositeP;
|
||||
|
||||
@@ -95,6 +101,10 @@ internal static class Program
|
||||
ulong remainder = 0UL;
|
||||
bool startPrimeProvided = false;
|
||||
|
||||
_testMode = false;
|
||||
_testTargetPrimeCount = 0;
|
||||
_testProcessedPrimeCount = 0;
|
||||
|
||||
// NTT backend selection (GPU): reference vs staged
|
||||
for (; argIndex < args.Length; argIndex++)
|
||||
{
|
||||
@@ -201,6 +211,10 @@ internal static class Program
|
||||
{
|
||||
useModuloWorkaround = true;
|
||||
}
|
||||
else if (arg.Equals("--test", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_testMode = true;
|
||||
}
|
||||
else if (arg.Equals("--use-order", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
useOrder = true;
|
||||
@@ -393,6 +407,20 @@ internal static class Program
|
||||
}
|
||||
}
|
||||
|
||||
if (_testMode)
|
||||
{
|
||||
currentP = 31UL;
|
||||
remainder = currentP % 6UL;
|
||||
useDivisor = false;
|
||||
useByDivisor = false;
|
||||
useResidue = false;
|
||||
useLucas = false;
|
||||
filterFile = string.Empty;
|
||||
maxPrimeLimit = UInt128.MaxValue;
|
||||
maxPrimeConfigured = false;
|
||||
startPrimeProvided = true;
|
||||
}
|
||||
|
||||
if (useByDivisor)
|
||||
{
|
||||
_byDivisorStartPrime = startPrimeProvided ? currentP : 0UL;
|
||||
@@ -620,7 +648,7 @@ internal static class Program
|
||||
File.WriteAllText(ResultsFileName, $"p,searchedMersenne,detailedCheck,passedAllTests{Environment.NewLine}");
|
||||
}
|
||||
|
||||
bool useFilter = !string.IsNullOrEmpty(filterFile);
|
||||
bool useFilter = !_testMode && !string.IsNullOrEmpty(filterFile);
|
||||
HashSet<ulong> filter = [];
|
||||
List<ulong> byDivisorCandidates = [];
|
||||
ulong maxP = 0UL;
|
||||
@@ -737,7 +765,19 @@ internal static class Program
|
||||
}
|
||||
}
|
||||
|
||||
if (_testMode)
|
||||
{
|
||||
_testTargetPrimeCount = Math.Max(1, threadCount) * 3;
|
||||
}
|
||||
|
||||
_state = ((long)currentP << 3) | (long)remainder;
|
||||
|
||||
Stopwatch? stopwatch = null;
|
||||
if (_testMode)
|
||||
{
|
||||
stopwatch = Stopwatch.StartNew();
|
||||
}
|
||||
|
||||
Task[] tasks = new Task[threadCount];
|
||||
|
||||
int taskIndex = 0;
|
||||
@@ -807,8 +847,23 @@ internal static class Program
|
||||
}
|
||||
|
||||
Task.WaitAll(tasks);
|
||||
|
||||
TimeSpan testElapsed = default;
|
||||
bool reportTestTime = false;
|
||||
if (stopwatch is not null)
|
||||
{
|
||||
stopwatch.Stop();
|
||||
testElapsed = stopwatch.Elapsed;
|
||||
reportTestTime = true;
|
||||
}
|
||||
|
||||
FlushBuffer();
|
||||
StringBuilderPool.Return(_outputBuilder!);
|
||||
|
||||
if (reportTestTime)
|
||||
{
|
||||
ReportTestTime(testElapsed);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<ulong> LoadByDivisorCandidates(string candidateFile, UInt128 maxPrimeLimit, bool maxPrimeConfigured, out int skippedByLimit)
|
||||
@@ -1053,6 +1108,21 @@ internal static class Program
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void OnPrimeCandidateConfirmed()
|
||||
{
|
||||
if (!_testMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int processed = Interlocked.Increment(ref _testProcessedPrimeCount);
|
||||
if (processed == _testTargetPrimeCount)
|
||||
{
|
||||
Volatile.Write(ref _limitReached, true);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool TryAcquireConsoleSlot(bool primeCandidate, out bool primeFlag)
|
||||
{
|
||||
@@ -1189,6 +1259,75 @@ internal static class Program
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReportTestTime(TimeSpan elapsed)
|
||||
{
|
||||
double elapsedSeconds = elapsed.TotalSeconds;
|
||||
double elapsedMilliseconds = elapsed.TotalMilliseconds;
|
||||
Console.WriteLine($"Test elapsed time: {elapsedSeconds:F3} s");
|
||||
|
||||
string filePath = GetTestTimeFilePath();
|
||||
bool hasPrevious = TryReadTestTime(filePath, out double previousMilliseconds);
|
||||
string elapsedText = elapsedMilliseconds.ToString("F3", CultureInfo.InvariantCulture);
|
||||
|
||||
if (!hasPrevious)
|
||||
{
|
||||
WriteTestTime(filePath, elapsedMilliseconds);
|
||||
Console.WriteLine($"FIRST TIME: {elapsedText} ms");
|
||||
return;
|
||||
}
|
||||
|
||||
string previousText = previousMilliseconds.ToString("F3", CultureInfo.InvariantCulture);
|
||||
if (elapsedMilliseconds < previousMilliseconds)
|
||||
{
|
||||
WriteTestTime(filePath, elapsedMilliseconds);
|
||||
Console.WriteLine($"BETTER TIME: {elapsedText} ms (previous {previousText} ms)");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"WORSE TIME: {elapsedText} ms (best {previousText} ms)");
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetTestTimeFilePath()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_resultsDir))
|
||||
{
|
||||
return TestTimeFileName;
|
||||
}
|
||||
|
||||
return Path.Combine(_resultsDir!, TestTimeFileName);
|
||||
}
|
||||
|
||||
private static bool TryReadTestTime(string filePath, out double milliseconds)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
milliseconds = 0.0;
|
||||
return false;
|
||||
}
|
||||
|
||||
string content = File.ReadAllText(filePath).Trim();
|
||||
if (content.Length == 0)
|
||||
{
|
||||
milliseconds = 0.0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return double.TryParse(content, NumberStyles.Float, CultureInfo.InvariantCulture, out milliseconds);
|
||||
}
|
||||
|
||||
private static void WriteTestTime(string filePath, double milliseconds)
|
||||
{
|
||||
string? directory = Path.GetDirectoryName(filePath);
|
||||
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
string formatted = milliseconds.ToString("F6", CultureInfo.InvariantCulture);
|
||||
File.WriteAllText(filePath, formatted);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static ulong CountOnes(ulong value)
|
||||
{
|
||||
@@ -1419,6 +1558,8 @@ internal static class Program
|
||||
_lastCompositeP = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
OnPrimeCandidateConfirmed();
|
||||
}
|
||||
|
||||
searchedMersenne = true;
|
||||
|
||||
Reference in new issue
Block a user