Cache divisor cycle suppression scopes
This commit is contained in:
1 parent
e1be80048f
commit
3c926e4909
1 file changed
+120
-29
@@ -61,6 +61,18 @@ internal static partial class PrimeOrderCalculator
|
|||||||
[ThreadStatic]
|
[ThreadStatic]
|
||||||
private static Dictionary<ulong, int>? s_partialFactorCounts;
|
private static Dictionary<ulong, int>? s_partialFactorCounts;
|
||||||
|
|
||||||
|
[ThreadStatic]
|
||||||
|
private static ulong s_cachedDivisorCycleModulus;
|
||||||
|
|
||||||
|
[ThreadStatic]
|
||||||
|
private static ulong s_cachedDivisorCycleLength;
|
||||||
|
|
||||||
|
[ThreadStatic]
|
||||||
|
private static bool s_hasCachedDivisorCycle;
|
||||||
|
|
||||||
|
[ThreadStatic]
|
||||||
|
private static int s_divisorCycleSuppressionDepth;
|
||||||
|
|
||||||
private static bool IsGpuHeuristicDevice => s_pow2ModeInitialized && s_deviceMode == PrimeOrderHeuristicDevice.Gpu;
|
private static bool IsGpuHeuristicDevice => s_pow2ModeInitialized && s_deviceMode == PrimeOrderHeuristicDevice.Gpu;
|
||||||
|
|
||||||
private readonly struct Pow2ModeScope
|
private readonly struct Pow2ModeScope
|
||||||
@@ -110,10 +122,45 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsDivisorCycleSuppressed => s_divisorCycleSuppressionDepth > 0;
|
||||||
|
|
||||||
|
private readonly struct DivisorCycleSuppressionScope
|
||||||
|
{
|
||||||
|
private readonly bool _suppress;
|
||||||
|
|
||||||
|
private DivisorCycleSuppressionScope(bool suppress)
|
||||||
|
{
|
||||||
|
_suppress = suppress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly DivisorCycleSuppressionScope Suppressed = new(true);
|
||||||
|
|
||||||
|
public static readonly DivisorCycleSuppressionScope Unsuppressed = new(false);
|
||||||
|
|
||||||
|
public void Enter()
|
||||||
|
{
|
||||||
|
if (_suppress)
|
||||||
|
{
|
||||||
|
s_divisorCycleSuppressionDepth++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Exit()
|
||||||
|
{
|
||||||
|
if (_suppress)
|
||||||
|
{
|
||||||
|
s_divisorCycleSuppressionDepth--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static Pow2ModeScope UsePow2Mode(PrimeOrderHeuristicDevice device) => new(device);
|
private static Pow2ModeScope UsePow2Mode(PrimeOrderHeuristicDevice device) => new(device);
|
||||||
|
|
||||||
private static DebugLoggingScope UseDebugLogging(bool enabled) => new(enabled);
|
private static DebugLoggingScope UseDebugLogging(bool enabled) => new(enabled);
|
||||||
|
|
||||||
|
private static DivisorCycleSuppressionScope SuppressDivisorCycleUsage(bool suppress) =>
|
||||||
|
suppress ? DivisorCycleSuppressionScope.Suppressed : DivisorCycleSuppressionScope.Unsuppressed;
|
||||||
|
|
||||||
[Conditional("DEBUG")]
|
[Conditional("DEBUG")]
|
||||||
private static void DebugLog(string message)
|
private static void DebugLog(string message)
|
||||||
{
|
{
|
||||||
@@ -187,43 +234,52 @@ internal static partial class PrimeOrderCalculator
|
|||||||
ulong phi,
|
ulong phi,
|
||||||
PartialFactorResult phiFactors)
|
PartialFactorResult phiFactors)
|
||||||
{
|
{
|
||||||
if (phiFactors.FullyFactored && TrySpecialMaxCpu(phi, prime, phiFactors, divisorData))
|
var cycleScope = SuppressDivisorCycleUsage(config.Mode == PrimeOrderMode.Heuristic && !IsGpuHeuristicDevice);
|
||||||
|
cycleScope.Enter();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
return phi;
|
if (phiFactors.FullyFactored && TrySpecialMaxCpu(phi, prime, phiFactors, divisorData))
|
||||||
}
|
{
|
||||||
|
return phi;
|
||||||
|
}
|
||||||
|
|
||||||
ulong candidateOrder = InitializeStartingOrderCpu(prime, phi, divisorData);
|
ulong candidateOrder = InitializeStartingOrderCpu(prime, phi, divisorData);
|
||||||
candidateOrder = ExponentLoweringCpu(candidateOrder, prime, phiFactors, divisorData);
|
candidateOrder = ExponentLoweringCpu(candidateOrder, prime, phiFactors, divisorData);
|
||||||
|
|
||||||
|
PartialFactorResult orderFactors = PartialFactor(candidateOrder, config);
|
||||||
|
if (orderFactors.Factors is null)
|
||||||
|
{
|
||||||
|
orderFactors.Dispose();
|
||||||
|
return candidateOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reuse the computed factorization for both the confirmation check and the heuristic pass
|
||||||
|
// to avoid factoring the same order twice on the by-divisor CPU pipeline.
|
||||||
|
if (TryConfirmOrderCpu(prime, candidateOrder, divisorData, ref orderFactors))
|
||||||
|
{
|
||||||
|
orderFactors.Dispose();
|
||||||
|
return candidateOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.Mode == PrimeOrderMode.Strict)
|
||||||
|
{
|
||||||
|
orderFactors.Dispose();
|
||||||
|
return CalculateByFactorizationCpu(prime, divisorData, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TryHeuristicFinishCpu(prime, candidateOrder, previousOrder, divisorData, config, ref orderFactors, phiFactors, out ulong order))
|
||||||
|
{
|
||||||
|
orderFactors.Dispose();
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
PartialFactorResult orderFactors = PartialFactor(candidateOrder, config);
|
|
||||||
if (orderFactors.Factors is null)
|
|
||||||
{
|
|
||||||
orderFactors.Dispose();
|
orderFactors.Dispose();
|
||||||
return candidateOrder;
|
return candidateOrder;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
// Reuse the computed factorization for both the confirmation check and the heuristic pass
|
|
||||||
// to avoid factoring the same order twice on the by-divisor CPU pipeline.
|
|
||||||
if (TryConfirmOrderCpu(prime, candidateOrder, divisorData, ref orderFactors))
|
|
||||||
{
|
{
|
||||||
orderFactors.Dispose();
|
cycleScope.Exit();
|
||||||
return candidateOrder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.Mode == PrimeOrderMode.Strict)
|
|
||||||
{
|
|
||||||
orderFactors.Dispose();
|
|
||||||
return CalculateByFactorizationCpu(prime, divisorData, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TryHeuristicFinishCpu(prime, candidateOrder, previousOrder, divisorData, config, ref orderFactors, phiFactors, out ulong order))
|
|
||||||
{
|
|
||||||
orderFactors.Dispose();
|
|
||||||
return order;
|
|
||||||
}
|
|
||||||
|
|
||||||
orderFactors.Dispose();
|
|
||||||
return candidateOrder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TrySpecialMaxCpu(ulong phi, ulong prime, PartialFactorResult factors, in MontgomeryDivisorData divisorData)
|
private static bool TrySpecialMaxCpu(ulong phi, ulong prime, PartialFactorResult factors, in MontgomeryDivisorData divisorData)
|
||||||
@@ -787,6 +843,36 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool TryGetDivisorCycle(ulong prime, in MontgomeryDivisorData divisorData, out ulong cycleLength)
|
||||||
|
{
|
||||||
|
if (prime <= 1UL || IsDivisorCycleSuppressed)
|
||||||
|
{
|
||||||
|
cycleLength = 0UL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_hasCachedDivisorCycle && s_cachedDivisorCycleModulus == prime)
|
||||||
|
{
|
||||||
|
cycleLength = s_cachedDivisorCycleLength;
|
||||||
|
return cycleLength != 0UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
var suppression = SuppressDivisorCycleUsage(true);
|
||||||
|
suppression.Enter();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
cycleLength = MersenneDivisorCycles.CalculateCycleLength(prime, divisorData);
|
||||||
|
s_cachedDivisorCycleModulus = prime;
|
||||||
|
s_cachedDivisorCycleLength = cycleLength;
|
||||||
|
s_hasCachedDivisorCycle = true;
|
||||||
|
return cycleLength != 0UL;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
suppression.Exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static bool Pow2EqualsOneCpu(ulong exponent, ulong prime, in MontgomeryDivisorData divisorData)
|
private static bool Pow2EqualsOneCpu(ulong exponent, ulong prime, in MontgomeryDivisorData divisorData)
|
||||||
{
|
{
|
||||||
if (IsGpuPow2Allowed)
|
if (IsGpuPow2Allowed)
|
||||||
@@ -798,6 +884,11 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TryGetDivisorCycle(prime, divisorData, out ulong cycleLength) && cycleLength != 0UL)
|
||||||
|
{
|
||||||
|
return exponent.Pow2MontgomeryModWithCycleCpu(cycleLength, divisorData) == 1UL;
|
||||||
|
}
|
||||||
|
|
||||||
return exponent.Pow2MontgomeryModWindowedCpu(divisorData, keepMontgomery: false) == 1UL;
|
return exponent.Pow2MontgomeryModWindowedCpu(divisorData, keepMontgomery: false) == 1UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user