Add diagnostics for removed factorization cache

This commit is contained in:
Marek Lemańczyk committed 2025-10-20 19:22:02 +02:00
1 parent 28ff9292b8
commit 1a4818c794
3 files changed
+95 -9

No files matched your search

@@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using PerfectNumbers.Core.Gpu;
@@ -11,6 +12,12 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
private ulong _lastStatusDivisor;
private int _batchSize = 1_024;
private const int FactorCachePrimeTrackingLimit = 500_000;
private static readonly HashSet<ulong> FactorCacheTrackedPrimes = new();
private static readonly object FactorCachePrimeLock = new();
private static ulong FactorCachePrimeHitCount;
private static bool FactorCachePrimeTrackingDisabled;
[ThreadStatic]
private static GpuUInt128WorkSet _divisorScanGpuWorkSet;
@@ -115,6 +122,8 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
processedCount = 0UL;
processedAll = false;
ObserveFactorCachePrime(prime);
// The EvenPerfectBitScanner feeds primes >= 138,000,000 here, so allowedMax >= 3 in production runs.
// Keeping the guard commented out documents the reasoning for benchmarks and tests.
// if (allowedMax < 3UL)
@@ -254,6 +263,43 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
return false;
}
private static void ObserveFactorCachePrime(ulong prime)
{
bool logHit = false;
ulong hitNumber = 0UL;
bool trackingDisabledNow = false;
lock (FactorCachePrimeLock)
{
if (FactorCachePrimeTrackingDisabled)
{
return;
}
if (!FactorCacheTrackedPrimes.Add(prime))
{
FactorCachePrimeHitCount++;
hitNumber = FactorCachePrimeHitCount;
logHit = true;
}
else if (FactorCacheTrackedPrimes.Count >= FactorCachePrimeTrackingLimit)
{
FactorCachePrimeTrackingDisabled = true;
FactorCacheTrackedPrimes.Clear();
trackingDisabledNow = true;
}
}
if (logHit)
{
Console.WriteLine($"Factor cache hit for exponent {prime} ({hitNumber})");
}
else if (trackingDisabledNow)
{
Console.WriteLine("Factor cache hit tracking disabled after exceeding the tracking limit.");
}
}
private static byte CheckDivisor(ulong prime, ulong divisorCycle, in MontgomeryDivisorData divisorData)
{
ulong residue = prime.Pow2MontgomeryModWithCycleCpu(divisorCycle, divisorData);
@@ -15,6 +15,12 @@ public class MersenneDivisorCycles
private List<(ulong divisor, ulong cycleLength)> _table = [];
// Lightweight read-mostly cache for small divisors (<= 4,000,000). 0 => unknown
private ulong[]? _smallCycles;
private const int FactorCacheExponentTrackingLimit = 500_000;
private static readonly HashSet<ulong> FactorCacheTrackedExponents = new();
private static readonly object FactorCacheTrackingLock = new();
private static ulong FactorCacheHitCount;
private static bool FactorCacheTrackingDisabled;
public static MersenneDivisorCycles Shared { get; } = new MersenneDivisorCycles();
public MersenneDivisorCycles()
@@ -312,6 +318,7 @@ public class MersenneDivisorCycles
factorCounts[2UL] = twoCount;
}
ObserveFactorCacheExponent(exponent);
bool exponentAccumulated = AccumulateFactors(exponent, factorCounts);
bool factorsAccumulated = exponentAccumulated && AccumulateFactors(k, factorCounts);
@@ -326,6 +333,43 @@ public class MersenneDivisorCycles
return success;
}
private static void ObserveFactorCacheExponent(ulong exponent)
{
bool logHit = false;
ulong hitNumber = 0UL;
bool trackingDisabledNow = false;
lock (FactorCacheTrackingLock)
{
if (FactorCacheTrackingDisabled)
{
return;
}
if (!FactorCacheTrackedExponents.Add(exponent))
{
FactorCacheHitCount++;
hitNumber = FactorCacheHitCount;
logHit = true;
}
else if (FactorCacheTrackedExponents.Count >= FactorCacheExponentTrackingLimit)
{
FactorCacheTrackingDisabled = true;
FactorCacheTrackedExponents.Clear();
trackingDisabledNow = true;
}
}
if (logHit)
{
Console.WriteLine($"Factor cache hit for exponent {exponent} ({hitNumber})");
}
else if (trackingDisabledNow)
{
Console.WriteLine("Factor cache hit tracking disabled after exceeding the tracking limit.");
}
}
private static bool AccumulateFactors(
ulong value,
Dictionary<ulong, int> counts)