Recycle small prime stepper arrays
This commit is contained in:
1 parent
06b08708d9
commit
ca0f498d0d
5 files changed
+1744
-1642
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using PerfectNumbers.Core.Gpu;
|
||||
|
||||
namespace PerfectNumbers.Core;
|
||||
|
||||
internal static partial class PrimeOrderCalculator
|
||||
{
|
||||
private static bool IsGpuPow2Allowed => s_pow2ModeInitialized && s_allowGpuPow2;
|
||||
|
||||
private const int GpuSmallPrimeFactorSlots = 64;
|
||||
|
||||
private static bool TryPopulateSmallPrimeFactorsGpu(ulong value, uint limit, Dictionary<ulong, int> counts, out ulong remaining)
|
||||
{
|
||||
ulong[] primeBufferArray = ThreadStaticPools.UlongPool.Rent(GpuSmallPrimeFactorSlots);
|
||||
int[] exponentBufferArray = ThreadStaticPools.IntPool.Rent(GpuSmallPrimeFactorSlots);
|
||||
Span<ulong> primeBuffer = primeBufferArray.AsSpan(0, GpuSmallPrimeFactorSlots);
|
||||
Span<int> exponentBuffer = exponentBufferArray.AsSpan(0, GpuSmallPrimeFactorSlots);
|
||||
primeBuffer.Clear();
|
||||
exponentBuffer.Clear();
|
||||
|
||||
if (!PrimeOrderGpuHeuristics.TryPartialFactor(value, limit, primeBuffer, exponentBuffer, out int factorCount, out ulong gpuRemaining, out _))
|
||||
{
|
||||
remaining = value;
|
||||
ThreadStaticPools.UlongPool.Return(primeBufferArray);
|
||||
ThreadStaticPools.IntPool.Return(exponentBufferArray);
|
||||
return false;
|
||||
}
|
||||
|
||||
remaining = gpuRemaining;
|
||||
for (int i = 0; i < factorCount; i++)
|
||||
{
|
||||
ulong primeValue = primeBuffer[i];
|
||||
int exponent = exponentBuffer[i];
|
||||
if (primeValue == 0UL || exponent == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
counts[primeValue] = exponent;
|
||||
}
|
||||
|
||||
ThreadStaticPools.UlongPool.Return(primeBufferArray);
|
||||
ThreadStaticPools.IntPool.Return(exponentBufferArray);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+72
-36
@@ -1,54 +1,90 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using PerfectNumbers.Core.Gpu;
|
||||
|
||||
namespace PerfectNumbers.Core;
|
||||
|
||||
internal static partial class PrimeOrderCalculator
|
||||
{
|
||||
public static UInt128 Calculate(
|
||||
in UInt128 prime,
|
||||
in UInt128? previousOrder,
|
||||
in PrimeOrderSearchConfig config,
|
||||
in PrimeOrderHeuristicDevice device)
|
||||
{
|
||||
var scope = UsePow2Mode(device);
|
||||
MontgomeryDivisorData divisorData;
|
||||
UInt128 result;
|
||||
if (prime <= ulong.MaxValue)
|
||||
{
|
||||
ulong? previous = null;
|
||||
if (previousOrder.HasValue)
|
||||
{
|
||||
UInt128 previousValue = previousOrder.Value;
|
||||
if (previousValue <= ulong.MaxValue)
|
||||
{
|
||||
previous = (ulong)previousValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
previous = ulong.MaxValue;
|
||||
}
|
||||
}
|
||||
[ThreadStatic]
|
||||
private static bool s_pow2ModeInitialized;
|
||||
|
||||
ulong prime64 = (ulong)prime;
|
||||
divisorData = MontgomeryDivisorData.FromModulus(prime64);
|
||||
ulong order64 = Calculate(prime64, previous, divisorData, config, device);
|
||||
result = order64 == 0UL ? UInt128.Zero : (UInt128)order64;
|
||||
}
|
||||
else
|
||||
[ThreadStatic]
|
||||
private static bool s_allowGpuPow2;
|
||||
|
||||
[ThreadStatic]
|
||||
private static PrimeOrderHeuristicDevice s_deviceMode;
|
||||
|
||||
[ThreadStatic]
|
||||
private static bool s_debugLoggingEnabled;
|
||||
|
||||
private static bool IsGpuHeuristicDevice => s_pow2ModeInitialized && s_deviceMode == PrimeOrderHeuristicDevice.Gpu;
|
||||
|
||||
private readonly struct Pow2ModeScope
|
||||
{
|
||||
divisorData = default;
|
||||
result = CalculateWideInternal(prime, previousOrder, divisorData, config);
|
||||
private readonly bool _previousInitialized;
|
||||
private readonly bool _previousAllow;
|
||||
private readonly PrimeOrderHeuristicDevice _previousDevice;
|
||||
|
||||
public Pow2ModeScope(PrimeOrderHeuristicDevice device)
|
||||
{
|
||||
_previousInitialized = s_pow2ModeInitialized;
|
||||
_previousAllow = s_allowGpuPow2;
|
||||
_previousDevice = s_deviceMode;
|
||||
s_pow2ModeInitialized = true;
|
||||
s_allowGpuPow2 = device == PrimeOrderHeuristicDevice.Gpu;
|
||||
s_deviceMode = device;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
s_allowGpuPow2 = _previousAllow;
|
||||
s_pow2ModeInitialized = _previousInitialized;
|
||||
s_deviceMode = _previousDevice;
|
||||
}
|
||||
}
|
||||
|
||||
scope.Dispose();
|
||||
return result;
|
||||
}
|
||||
private readonly struct DebugLoggingScope
|
||||
{
|
||||
private readonly bool _previous;
|
||||
|
||||
public DebugLoggingScope(bool enabled)
|
||||
{
|
||||
_previous = s_debugLoggingEnabled;
|
||||
s_debugLoggingEnabled = enabled;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
s_debugLoggingEnabled = _previous;
|
||||
}
|
||||
}
|
||||
|
||||
private static Pow2ModeScope UsePow2Mode(PrimeOrderHeuristicDevice device) => new(device);
|
||||
|
||||
private static DebugLoggingScope UseDebugLogging(bool enabled) => new(enabled);
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
private static void DebugLog(string message)
|
||||
{
|
||||
if (s_debugLoggingEnabled)
|
||||
{
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
private static void DebugLog(Func<string> messageFactory)
|
||||
{
|
||||
if (s_debugLoggingEnabled)
|
||||
{
|
||||
Console.WriteLine(messageFactory());
|
||||
}
|
||||
}
|
||||
private static UInt128 CalculateWideInternal(in UInt128 prime, in UInt128? previousOrder, in MontgomeryDivisorData divisorData, in PrimeOrderSearchConfig config)
|
||||
{
|
||||
if (prime <= UInt128.One)
|
||||
File diff suppressed because it is too large.
Load diff
@@ -11,6 +11,18 @@ namespace PerfectNumbers.Core
|
||||
[ThreadStatic]
|
||||
private static ArrayPool<FactorEntry>? _factorEntryPool;
|
||||
|
||||
[ThreadStatic]
|
||||
private static ArrayPool<CycleRemainderStepper>? _cycleRemainderStepperPool;
|
||||
|
||||
public static ArrayPool<CycleRemainderStepper> CycleRemainderStepperPool
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return _cycleRemainderStepperPool ??= ArrayPool<CycleRemainderStepper>.Create();
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayPool<FactorEntry> FactorEntryPool
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -70,6 +82,18 @@ namespace PerfectNumbers.Core
|
||||
[ThreadStatic]
|
||||
private static ArrayPool<ulong>? _ulongPool;
|
||||
|
||||
[ThreadStatic]
|
||||
private static ArrayPool<bool>? _boolPool;
|
||||
|
||||
public static ArrayPool<bool> BoolPool
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return _boolPool ??= ArrayPool<bool>.Create();
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayPool<ulong> UlongPool
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
||||
Reference in new issue
Block a user