Reduce GC pressure in divisor checking pipeline
This commit is contained in:
1 parent
571b5a9938
commit
51730bcba3
2 files changed
+55
-14
No files matched your search
@@ -1,4 +1,5 @@
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Buffers.Binary;
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
@@ -56,6 +57,9 @@ internal static partial class PrimeOrderCalculator
|
||||
[ThreadStatic]
|
||||
private static Dictionary<ulong, int>? s_partialFactorCounts;
|
||||
|
||||
[ThreadStatic]
|
||||
private static List<ulong>? s_heuristicCandidateList;
|
||||
|
||||
private static bool IsGpuHeuristicDevice => s_pow2ModeInitialized && s_deviceMode == PrimeOrderHeuristicDevice.Gpu;
|
||||
|
||||
private readonly struct Pow2ModeScope
|
||||
@@ -402,7 +406,9 @@ internal static partial class PrimeOrderCalculator
|
||||
}
|
||||
|
||||
int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecks * 4;
|
||||
List<ulong> candidates = new(capacity);
|
||||
List<ulong> candidates = AcquireHeuristicCandidateList(capacity);
|
||||
try
|
||||
{
|
||||
FactorEntry[] factorArray = orderFactors.Factors!;
|
||||
// DebugLog("Building candidates list");
|
||||
BuildCandidates(order, factorArray, orderFactors.Count, candidates, capacity);
|
||||
@@ -520,6 +526,11 @@ internal static partial class PrimeOrderCalculator
|
||||
index += batchSize;
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
candidates.Clear();
|
||||
}
|
||||
// DebugLog("No candidate confirmed");
|
||||
return false;
|
||||
}
|
||||
@@ -823,6 +834,21 @@ internal static partial class PrimeOrderCalculator
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
private static List<ulong> AcquireHeuristicCandidateList(int capacityHint)
|
||||
{
|
||||
List<ulong>? list = s_heuristicCandidateList;
|
||||
if (list is null)
|
||||
{
|
||||
list = new List<ulong>(capacityHint);
|
||||
s_heuristicCandidateList = list;
|
||||
return list;
|
||||
}
|
||||
|
||||
list.Clear();
|
||||
list.EnsureCapacity(capacityHint);
|
||||
return list;
|
||||
}
|
||||
|
||||
private static PartialFactorResult PartialFactor(ulong value, in PrimeOrderSearchConfig config)
|
||||
{
|
||||
if (value <= 1UL)
|
||||
|
||||
@@ -346,7 +346,26 @@ public static class ULongExtensions
|
||||
|
||||
ulong result = divisor.MontgomeryOne;
|
||||
ulong nPrime = divisor.NPrime;
|
||||
ulong[] oddPowers = InitializeMontgomeryOddPowersCpu(divisor, modulus, nPrime, oddPowerCount);
|
||||
|
||||
const int StackOddPowerThreshold = PerfectNumberConstants.PooledArrayThreshold;
|
||||
Span<ulong> oddPowersSpan = oddPowerCount <= StackOddPowerThreshold
|
||||
? stackalloc ulong[StackOddPowerThreshold]
|
||||
: default;
|
||||
|
||||
Span<ulong> oddPowers;
|
||||
ulong[]? oddPowersArray = null;
|
||||
|
||||
if (!oddPowersSpan.IsEmpty)
|
||||
{
|
||||
oddPowers = oddPowersSpan.Slice(0, oddPowerCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
oddPowersArray = ThreadStaticPools.UlongPool.Rent(oddPowerCount);
|
||||
oddPowers = oddPowersArray.AsSpan(0, oddPowerCount);
|
||||
}
|
||||
|
||||
InitializeMontgomeryOddPowersCpu(divisor, modulus, nPrime, oddPowers);
|
||||
|
||||
int index = bitLength - 1;
|
||||
while (index >= 0)
|
||||
@@ -384,9 +403,9 @@ public static class ULongExtensions
|
||||
index = windowStart - 1;
|
||||
}
|
||||
|
||||
if (oddPowerCount >= PerfectNumberConstants.PooledArrayThreshold)
|
||||
if (oddPowersArray is not null)
|
||||
{
|
||||
ArrayPool<ulong>.Shared.Return(oddPowers);
|
||||
ThreadStaticPools.UlongPool.Return(oddPowersArray, clearArray: false);
|
||||
}
|
||||
|
||||
if (keepMontgomery)
|
||||
@@ -533,26 +552,22 @@ public static class ULongExtensions
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong[] InitializeMontgomeryOddPowersCpu(in MontgomeryDivisorData divisor, ulong modulus, ulong nPrime, int oddPowerCount)
|
||||
private static void InitializeMontgomeryOddPowersCpu(in MontgomeryDivisorData divisor, ulong modulus, ulong nPrime, Span<ulong> oddPowers)
|
||||
{
|
||||
ulong[] oddPowers = oddPowerCount < PerfectNumberConstants.PooledArrayThreshold ? new ulong[oddPowerCount] : ArrayPool<ulong>.Shared.Rent(oddPowerCount);
|
||||
|
||||
oddPowers[0] = divisor.MontgomeryTwo;
|
||||
if (oddPowerCount == 1)
|
||||
if (oddPowers.Length == 1)
|
||||
{
|
||||
return oddPowers;
|
||||
return;
|
||||
}
|
||||
|
||||
ulong previous,
|
||||
square = divisor.MontgomeryTwoSquared;
|
||||
ulong previous;
|
||||
ulong square = divisor.MontgomeryTwoSquared;
|
||||
|
||||
for (int i = 1; i < oddPowerCount; i++)
|
||||
for (int i = 1; i < oddPowers.Length; i++)
|
||||
{
|
||||
previous = oddPowers[i - 1];
|
||||
oddPowers[i] = previous.MontgomeryMultiply(square, modulus, nPrime);
|
||||
}
|
||||
|
||||
return oddPowers;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
||||
Reference in new issue
Block a user