GpuKernelPool.GetOrAddKernels removed in --mersenne=bydivisor mode. PartialFactorResult.WithAdditionalPrime will now modify the current instance instead of creating new copy for better performance. SmallPrimeFactorViews renamed to SmallPrimeFactorGpuTables for consistency with other static tables.
This commit is contained in:
1 parent
2fc74cf98d
commit
342eff2726
12 files changed
+118
-188
No files matched your search
@@ -344,7 +344,7 @@ public class GpuKernelCompilationTests
|
|||||||
_ = kernel;
|
_ = kernel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static KernelType _kernelType = KernelType.Pow2ModKernelScan | KernelType.OrderKernelScan | KernelType.IncrementalKernelScan | KernelType.IncrementalOrderKernelScan | KernelType.Pow2ModOrderKernelScan | KernelType.EvaluateSpecialMaxCandidatesKernel | KernelType.SmallPrimeFactorKernelScan;
|
private static KernelType _kernelType = KernelType.Pow2ModKernelScan | KernelType.OrderKernelScan | KernelType.IncrementalKernelScan | KernelType.IncrementalOrderKernelScan | KernelType.Pow2ModOrderKernelScan;
|
||||||
private static void CompileGpuKernelPoolKernels(Accelerator accelerator)
|
private static void CompileGpuKernelPoolKernels(Accelerator accelerator)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -100,8 +100,6 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
ulong allowedMax,
|
ulong allowedMax,
|
||||||
out bool processedAll)
|
out bool processedAll)
|
||||||
{
|
{
|
||||||
processedAll = false;
|
|
||||||
|
|
||||||
// The EvenPerfectBitScanner feeds primes >= 138,000,000 here, so allowedMax >= 3 in production runs.
|
// 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.
|
// Keeping the guard commented out documents the reasoning for benchmarks and tests.
|
||||||
// if (allowedMax < 3UL)
|
// if (allowedMax < 3UL)
|
||||||
|
|||||||
@@ -67,8 +67,10 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
AcceleratorStreamPool.WarmUp(i);
|
AcceleratorStreamPool.WarmUp(i);
|
||||||
// Don't take this from the pool as quick uploads of data to the accelerator consumes much of GPU's memory and throws.
|
// Don't take this from the pool as quick uploads of data to the accelerator consumes much of GPU's memory and throws.
|
||||||
AcceleratorStream stream = accelerator.CreateStream();
|
AcceleratorStream stream = accelerator.CreateStream();
|
||||||
|
// TODO: Review which tables are needed when final execution path is defined.
|
||||||
LastDigitGpuTables.WarmUp(i, stream);
|
LastDigitGpuTables.WarmUp(i, stream);
|
||||||
HeuristicGpuCombinedTables.WarmUp(i, stream);
|
HeuristicGpuCombinedTables.WarmUp(i, stream);
|
||||||
|
// SmallPrimeFactorGpuTables.WarmUp(i, stream);
|
||||||
// SharedHeuristicGpuTables.EnsureStaticTables(accelerator, stream);
|
// SharedHeuristicGpuTables.EnsureStaticTables(accelerator, stream);
|
||||||
// _ = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.None);
|
// _ = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.None);
|
||||||
// KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream);
|
// KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream);
|
||||||
@@ -110,6 +112,7 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxResult;
|
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxResult;
|
||||||
|
|
||||||
public readonly HeuristicGpuCombinedDivisorTables DivisorTables;
|
public readonly HeuristicGpuCombinedDivisorTables DivisorTables;
|
||||||
|
public readonly SmallPrimeFactorGpuTables SmallPrimeFactorTables;
|
||||||
|
|
||||||
public readonly Kernel SmallPrimeSieveKernel;
|
public readonly Kernel SmallPrimeSieveKernel;
|
||||||
public readonly Kernel CheckFactorsKernel;
|
public readonly Kernel CheckFactorsKernel;
|
||||||
@@ -118,6 +121,8 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
public readonly Kernel KeepMontgomeryKernel;
|
public readonly Kernel KeepMontgomeryKernel;
|
||||||
public readonly Kernel PollardRhoKernel;
|
public readonly Kernel PollardRhoKernel;
|
||||||
public readonly Kernel Pow2ModWideKernel;
|
public readonly Kernel Pow2ModWideKernel;
|
||||||
|
public readonly Kernel SmallPrimeFactorKernel;
|
||||||
|
public readonly Kernel SpecialMaxKernel;
|
||||||
|
|
||||||
public Kernel SharesFactorKernel;
|
public Kernel SharesFactorKernel;
|
||||||
|
|
||||||
@@ -203,6 +208,7 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
|
|
||||||
var heuristicSharedTables = HeuristicGpuCombinedTables.GetStaticTables(acceleratorIndex);
|
var heuristicSharedTables = HeuristicGpuCombinedTables.GetStaticTables(acceleratorIndex);
|
||||||
DivisorTables = heuristicSharedTables.CreateHeuristicDivisorTables();
|
DivisorTables = heuristicSharedTables.CreateHeuristicDivisorTables();
|
||||||
|
SmallPrimeFactorTables = SmallPrimeFactorGpuTables.GetStaticTables(acceleratorIndex);
|
||||||
|
|
||||||
var checkFactorsKernel = accelerator.LoadStreamKernel<int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.CheckFactorsKernel);
|
var checkFactorsKernel = accelerator.LoadStreamKernel<int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.CheckFactorsKernel);
|
||||||
CheckFactorsKernel = KernelUtil.GetKernel(checkFactorsKernel);
|
CheckFactorsKernel = KernelUtil.GetKernel(checkFactorsKernel);
|
||||||
@@ -223,6 +229,10 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>(PrimeOrderGpuHeuristics.Pow2ModKernelWide));
|
accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>(PrimeOrderGpuHeuristics.Pow2ModKernelWide));
|
||||||
|
|
||||||
SharesFactorKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SharesFactorKernel));
|
SharesFactorKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SharesFactorKernel));
|
||||||
|
|
||||||
|
SpecialMaxKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.EvaluateSpecialMaxCandidatesKernel));
|
||||||
|
|
||||||
|
SmallPrimeFactorKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(SmallPrimeFactorKernels.SmallPrimeFactorKernelScan));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
@@ -57,16 +57,6 @@ public class GpuKernelPool
|
|||||||
InitPow2ModOrderKernelScan(accelerator, kernels);
|
InitPow2ModOrderKernelScan(accelerator, kernels);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kernelType.HasFlag(KernelType.EvaluateSpecialMaxCandidatesKernel))
|
|
||||||
{
|
|
||||||
InitEvaluateSpecialMaxCandidatesKernel(accelerator, kernels);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kernelType.HasFlag(KernelType.SmallPrimeFactorKernelScan))
|
|
||||||
{
|
|
||||||
InitSmallPrimeFactorKernelScan(accelerator, kernels);
|
|
||||||
}
|
|
||||||
|
|
||||||
PreloadStaticTables(accelerator, kernels, stream, kernelType);
|
PreloadStaticTables(accelerator, kernels, stream, kernelType);
|
||||||
|
|
||||||
pool[acceleratorIndex] = kernels;
|
pool[acceleratorIndex] = kernels;
|
||||||
@@ -132,25 +122,6 @@ public class GpuKernelPool
|
|||||||
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InitEvaluateSpecialMaxCandidatesKernel(Accelerator accelerator, KernelContainer kernels)
|
|
||||||
{
|
|
||||||
InitOnce(ref kernels.SpecialMax, () =>
|
|
||||||
{
|
|
||||||
var loaded = accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.EvaluateSpecialMaxCandidatesKernel);
|
|
||||||
|
|
||||||
var kernel = KernelUtil.GetKernel(loaded);
|
|
||||||
|
|
||||||
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static void InitSmallPrimeFactorKernelScan(Accelerator accelerator, KernelContainer kernels)
|
|
||||||
{
|
|
||||||
var loaded = accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(SmallPrimeFactorKernels.SmallPrimeFactorKernelScan);
|
|
||||||
|
|
||||||
kernels.SmallPrimeFactor = KernelUtil.GetKernel(loaded);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void PreloadStaticTables(Accelerator accelerator, KernelContainer kernels, AcceleratorStream stream, KernelType kernelType)
|
internal static void PreloadStaticTables(Accelerator accelerator, KernelContainer kernels, AcceleratorStream stream, KernelType kernelType)
|
||||||
@@ -164,11 +135,6 @@ public class GpuKernelPool
|
|||||||
{
|
{
|
||||||
EnsureSmallPrimesOnDevice(accelerator, kernels, stream);
|
EnsureSmallPrimesOnDevice(accelerator, kernels, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kernelType.HasFlag(KernelType.SmallPrimeFactorKernelScan))
|
|
||||||
{
|
|
||||||
EnsureSmallPrimeFactorTables(accelerator, kernels, stream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayView1D<ulong, Stride1D.Dense> GetSmallCyclesOnDevice(KernelContainer kernels) => kernels.SmallCycles!;
|
public static ArrayView1D<ulong, Stride1D.Dense> GetSmallCyclesOnDevice(KernelContainer kernels) => kernels.SmallCycles!;
|
||||||
@@ -247,38 +213,6 @@ public class GpuKernelPool
|
|||||||
kernels.SmallPrimesPow2LastSeven = deviceLastSevenPow2;
|
kernels.SmallPrimesPow2LastSeven = deviceLastSevenPow2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SmallPrimeFactorViews GetSmallPrimeFactorTables(KernelContainer kernels) => new(
|
|
||||||
kernels.SmallPrimeFactorsPrimes!,
|
|
||||||
kernels.SmallPrimeFactorsSquares!
|
|
||||||
);
|
|
||||||
|
|
||||||
private static void EnsureSmallPrimeFactorTables(Accelerator accelerator, KernelContainer kernels, AcceleratorStream stream)
|
|
||||||
{
|
|
||||||
if (kernels.SmallPrimeFactorsPrimes is { } && kernels.SmallPrimeFactorsSquares is { })
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var hostPrimes = PrimesGenerator.SmallPrimes;
|
|
||||||
var hostSquares = PrimesGenerator.SmallPrimesPow2;
|
|
||||||
|
|
||||||
int length = hostPrimes.Length;
|
|
||||||
MemoryBuffer1D<uint, Stride1D.Dense>? devicePrimes;
|
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense>? deviceSquares;
|
|
||||||
|
|
||||||
// lock (accelerator)
|
|
||||||
{
|
|
||||||
devicePrimes = accelerator.Allocate1D<uint>(length);
|
|
||||||
deviceSquares = accelerator.Allocate1D<ulong>(length);
|
|
||||||
}
|
|
||||||
|
|
||||||
devicePrimes.View.CopyFromCPU(stream, hostPrimes);
|
|
||||||
deviceSquares.View.CopyFromCPU(stream, hostSquares);
|
|
||||||
|
|
||||||
kernels.SmallPrimeFactorsPrimes = devicePrimes;
|
|
||||||
kernels.SmallPrimeFactorsSquares = deviceSquares;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Runs a GPU action with an acquired accelerator and stream.
|
/// Runs a GPU action with an acquired accelerator and stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -10,7 +10,5 @@ public enum KernelType
|
|||||||
OrderKernelScan,
|
OrderKernelScan,
|
||||||
IncrementalKernelScan,
|
IncrementalKernelScan,
|
||||||
IncrementalOrderKernelScan,
|
IncrementalOrderKernelScan,
|
||||||
Pow2ModOrderKernelScan,
|
Pow2ModOrderKernelScan
|
||||||
EvaluateSpecialMaxCandidatesKernel,
|
|
||||||
SmallPrimeFactorKernelScan
|
|
||||||
}
|
}
|
||||||
@@ -502,8 +502,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
|
|
||||||
public sealed class DivisorScanSession : IMersenneNumberDivisorByDivisorTester.IDivisorScanSession
|
public sealed class DivisorScanSession : IMersenneNumberDivisorByDivisorTester.IDivisorScanSession
|
||||||
{
|
{
|
||||||
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
|
||||||
|
|
||||||
private readonly MersenneNumberDivisorByDivisorGpuTester _owner;
|
private readonly MersenneNumberDivisorByDivisorGpuTester _owner;
|
||||||
private readonly PrimeOrderCalculatorAccelerator _primeTesterAccelerator;
|
private readonly PrimeOrderCalculatorAccelerator _primeTesterAccelerator;
|
||||||
private readonly Accelerator _accelerator;
|
private readonly Accelerator _accelerator;
|
||||||
|
|||||||
@@ -33,9 +33,6 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
[ThreadStatic]
|
[ThreadStatic]
|
||||||
private static Kernel[]? _orderKernel;
|
private static Kernel[]? _orderKernel;
|
||||||
|
|
||||||
[ThreadStatic]
|
|
||||||
private static SmallPrimeDeviceCache[]? _smallPrimeDeviceCache;
|
|
||||||
|
|
||||||
public readonly struct OrderKernelConfig(ulong previousOrder, byte hasPreviousOrder, uint smallFactorLimit, int maxPowChecks, int mode)
|
public readonly struct OrderKernelConfig(ulong previousOrder, byte hasPreviousOrder, uint smallFactorLimit, int maxPowChecks, int mode)
|
||||||
{
|
{
|
||||||
public readonly ulong PreviousOrder = previousOrder;
|
public readonly ulong PreviousOrder = previousOrder;
|
||||||
@@ -69,13 +66,6 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
public readonly ArrayView1D<byte, Stride1D.Dense> Status = status;
|
public readonly ArrayView1D<byte, Stride1D.Dense> Status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class SmallPrimeDeviceCache
|
|
||||||
{
|
|
||||||
public MemoryBuffer1D<uint, Stride1D.Dense>? Primes;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense>? Squares;
|
|
||||||
public int Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
private const int WideStackThreshold = 12;
|
private const int WideStackThreshold = 12;
|
||||||
private static PrimeOrderGpuCapability s_capability = PrimeOrderGpuCapability.Default;
|
private static PrimeOrderGpuCapability s_capability = PrimeOrderGpuCapability.Default;
|
||||||
|
|
||||||
@@ -100,36 +90,6 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
s_capability = PrimeOrderGpuCapability.Default;
|
s_capability = PrimeOrderGpuCapability.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SmallPrimeDeviceCache GetSmallPrimeDeviceCache(int acceleratorIndex, AcceleratorStream stream)
|
|
||||||
{
|
|
||||||
var pool = _smallPrimeDeviceCache ??= [];
|
|
||||||
if (pool[acceleratorIndex] is {} cached)
|
|
||||||
{
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint[] primes = PrimesGenerator.SmallPrimes;
|
|
||||||
ulong[] squares = PrimesGenerator.SmallPrimesPow2;
|
|
||||||
MemoryBuffer1D<uint, Stride1D.Dense>? primeBuffer;
|
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense>? squareBuffer;
|
|
||||||
|
|
||||||
var accelerator = _accelerators[acceleratorIndex];
|
|
||||||
primeBuffer = accelerator.Allocate1D<uint>(primes.Length);
|
|
||||||
squareBuffer = accelerator.Allocate1D<ulong>(squares.Length);
|
|
||||||
|
|
||||||
primeBuffer.View.CopyFromCPU(stream, primes);
|
|
||||||
squareBuffer.View.CopyFromCPU(stream, squares);
|
|
||||||
cached = new SmallPrimeDeviceCache
|
|
||||||
{
|
|
||||||
Primes = primeBuffer,
|
|
||||||
Squares = squareBuffer,
|
|
||||||
Count = primes.Length,
|
|
||||||
};
|
|
||||||
|
|
||||||
pool[acceleratorIndex] = cached;
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Kernel GetPartialFactorKernel(int acceleratorIndex)
|
private static Kernel GetPartialFactorKernel(int acceleratorIndex)
|
||||||
{
|
{
|
||||||
var pool = _partialFactorKernel ??= [];
|
var pool = _partialFactorKernel ??= [];
|
||||||
@@ -212,7 +172,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
Accelerator accelerator = _accelerators[acceleratorIndex];
|
Accelerator accelerator = _accelerators[acceleratorIndex];
|
||||||
AcceleratorStream stream = accelerator.CreateStream();
|
AcceleratorStream stream = accelerator.CreateStream();
|
||||||
|
|
||||||
SmallPrimeDeviceCache cache = GetSmallPrimeDeviceCache(acceleratorIndex, stream);
|
SmallPrimeFactorGpuTables cache = gpu.SmallPrimeFactorTables;
|
||||||
|
|
||||||
// TODO: We should create / reallocate these buffer only once or if the new required length is bigger than capacity.
|
// TODO: We should create / reallocate these buffer only once or if the new required length is bigger than capacity.
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense>? factorBuffer = accelerator.Allocate1D<ulong>(primeTargets.Length);
|
MemoryBuffer1D<ulong, Stride1D.Dense>? factorBuffer = accelerator.Allocate1D<ulong>(primeTargets.Length);
|
||||||
@@ -363,6 +323,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal static bool TryCalculateOrder(
|
internal static bool TryCalculateOrder(
|
||||||
|
PrimeOrderCalculatorAccelerator gpu,
|
||||||
ulong prime,
|
ulong prime,
|
||||||
ulong? previousOrder,
|
ulong? previousOrder,
|
||||||
PrimeOrderCalculator.PrimeOrderSearchConfig config,
|
PrimeOrderCalculator.PrimeOrderSearchConfig config,
|
||||||
@@ -375,7 +336,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
int acceleratorIndex = AcceleratorPool.Shared.Rent();
|
int acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
Accelerator accelerator = _accelerators[acceleratorIndex];
|
Accelerator accelerator = _accelerators[acceleratorIndex];
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
SmallPrimeDeviceCache cache = GetSmallPrimeDeviceCache(acceleratorIndex, stream);
|
SmallPrimeFactorGpuTables cache = gpu.SmallPrimeFactorTables;
|
||||||
|
|
||||||
// TODO: These buffers should be created reallocated once and assigned to an accelerator. Callers should use their own
|
// TODO: These buffers should be created reallocated once and assigned to an accelerator. Callers should use their own
|
||||||
// thread static cache to prevent other threads from using taking accelerators with pre-allocated buffers if they don't
|
// thread static cache to prevent other threads from using taking accelerators with pre-allocated buffers if they don't
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using ILGPU;
|
||||||
|
using ILGPU.Runtime;
|
||||||
|
|
||||||
|
namespace PerfectNumbers.Core.Gpu;
|
||||||
|
|
||||||
|
public readonly struct SmallPrimeFactorGpuTables
|
||||||
|
{
|
||||||
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
private static readonly SmallPrimeFactorGpuTables[] _sharedTables = new SmallPrimeFactorGpuTables[PerfectNumberConstants.RollingAccelerators];
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal static SmallPrimeFactorGpuTables GetStaticTables(int acceleratorIndex) => _sharedTables[acceleratorIndex];
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal static void WarmUp(int acceleratorIndex, AcceleratorStream stream) => _sharedTables[acceleratorIndex] = new SmallPrimeFactorGpuTables(_accelerators[acceleratorIndex], stream);
|
||||||
|
|
||||||
|
public readonly MemoryBuffer1D<uint, Stride1D.Dense> Primes;
|
||||||
|
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> Squares;
|
||||||
|
public readonly int Count;
|
||||||
|
|
||||||
|
public SmallPrimeFactorGpuTables(Accelerator accelerator, AcceleratorStream stream)
|
||||||
|
{
|
||||||
|
var hostPrimes = PrimesGenerator.SmallPrimes;
|
||||||
|
var hostSquares = PrimesGenerator.SmallPrimesPow2;
|
||||||
|
|
||||||
|
MemoryBuffer1D<uint, Stride1D.Dense>? devicePrimes = accelerator.Allocate1D(stream, hostPrimes);
|
||||||
|
MemoryBuffer1D<ulong, Stride1D.Dense>? deviceSquares = accelerator.Allocate1D(stream, hostSquares);
|
||||||
|
|
||||||
|
Primes = devicePrimes;
|
||||||
|
Squares = deviceSquares;
|
||||||
|
Count = hostPrimes.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
using System.Runtime.CompilerServices;
|
|
||||||
using ILGPU;
|
|
||||||
using ILGPU.Runtime;
|
|
||||||
|
|
||||||
namespace PerfectNumbers.Core.Gpu;
|
|
||||||
|
|
||||||
public readonly struct SmallPrimeFactorViews(
|
|
||||||
MemoryBuffer1D<uint, Stride1D.Dense> primes,
|
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> squares)
|
|
||||||
{
|
|
||||||
public readonly MemoryBuffer1D<uint, Stride1D.Dense> Primes = primes;
|
|
||||||
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> Squares = squares;
|
|
||||||
public readonly int Count = (int)primes.Length;
|
|
||||||
|
|
||||||
public ArrayView1D<uint, Stride1D.Dense> PrimesView
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Primes.View;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayView1D<ulong, Stride1D.Dense> SquaresView
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Squares.View;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -67,36 +67,73 @@ namespace PerfectNumbers.Core
|
|||||||
FullyFactored = true
|
FullyFactored = true
|
||||||
};
|
};
|
||||||
|
|
||||||
public PartialFactorResult WithAdditionalPrime(ulong prime)
|
public void WithAdditionalPrime(ulong prime)
|
||||||
{
|
{
|
||||||
ulong[]? source = Factors;
|
ulong[]? sourceFactors = Factors;
|
||||||
int sourceCount = Count;
|
int sourceCount = Count;
|
||||||
int[] exponents;
|
if (sourceFactors is null || sourceCount == 0)
|
||||||
if (source is null || sourceCount == 0)
|
|
||||||
{
|
{
|
||||||
source = ThreadStaticPools.UlongPool.Rent(1);
|
InitializeWithPrime(prime);
|
||||||
exponents = ThreadStaticPools.IntPool.Rent(1);
|
return;
|
||||||
// source = new ulong[1];
|
}
|
||||||
// exponents = new int[1];
|
|
||||||
source[0] = prime;
|
|
||||||
exponents[0] = 1;
|
|
||||||
|
|
||||||
return Rent(source, exponents, 1UL, true, 1, false);
|
int newSize = sourceCount + 1;
|
||||||
}
|
int[] extendedExponents;
|
||||||
|
|
||||||
ulong[] extended = ThreadStaticPools.UlongPool.Rent(sourceCount + 1);
|
ulong[] extendedFactors = sourceFactors.Length >= newSize
|
||||||
Array.Copy(source, 0, extended, 0, sourceCount);
|
? sourceFactors
|
||||||
extended[sourceCount] = prime;
|
: ResizeFactors(sourceFactors, sourceCount, newSize);
|
||||||
|
|
||||||
exponents = ThreadStaticPools.IntPool.Rent(sourceCount + 1);
|
int[] sourceExponents = Exponents!;
|
||||||
Array.Copy(Exponents!, 0, exponents, 0, sourceCount);
|
extendedExponents = sourceExponents.Length >= newSize
|
||||||
exponents[sourceCount] = 1;
|
? sourceExponents
|
||||||
Array.Sort(extended, exponents, 0, sourceCount + 1);
|
: ResizeExponents(sourceCount, newSize, sourceExponents);
|
||||||
|
|
||||||
return Rent(extended, exponents, 1UL, true, sourceCount + 1, false);
|
extendedFactors[sourceCount] = prime;
|
||||||
|
extendedExponents[sourceCount] = 1;
|
||||||
|
Array.Sort(extendedFactors, extendedExponents, 0, newSize);
|
||||||
|
|
||||||
|
Factors = extendedFactors;
|
||||||
|
Exponents = extendedExponents;
|
||||||
|
Cofactor = 1UL;
|
||||||
|
FullyFactored = true;
|
||||||
|
Count = newSize;
|
||||||
|
CofactorIsPrime = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
private static int[] ResizeExponents(int sourceCount, int newSize, int[] sourceExponents)
|
||||||
|
{
|
||||||
|
int[] extendedExponents = ThreadStaticPools.IntPool.Rent(newSize);
|
||||||
|
Array.Copy(sourceExponents, 0, extendedExponents, 0, sourceCount);
|
||||||
|
ThreadStaticPools.IntPool.Return(sourceExponents, clearArray: false);
|
||||||
|
return extendedExponents;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ulong[] ResizeFactors(ulong[] sourceFactors, int sourceCount, int newSize)
|
||||||
|
{
|
||||||
|
ulong[] extendedFactors = ThreadStaticPools.UlongPool.Rent(newSize);
|
||||||
|
Array.Copy(sourceFactors, 0, extendedFactors, 0, sourceCount);
|
||||||
|
ThreadStaticPools.UlongPool.Return(sourceFactors, clearArray: false);
|
||||||
|
return extendedFactors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeWithPrime(ulong prime)
|
||||||
|
{
|
||||||
|
ulong[] source = ThreadStaticPools.UlongPool.Rent(1);
|
||||||
|
int[] exponents = ThreadStaticPools.IntPool.Rent(1);
|
||||||
|
// source = new ulong[1];
|
||||||
|
// exponents = new int[1];
|
||||||
|
source[0] = prime;
|
||||||
|
exponents[0] = 1;
|
||||||
|
Factors = source;
|
||||||
|
Exponents = exponents;
|
||||||
|
Cofactor = 1UL;
|
||||||
|
FullyFactored = true;
|
||||||
|
Count = 1;
|
||||||
|
CofactorIsPrime = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (this != Empty)
|
if (this != Empty)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
ulong phi = prime - 1UL;
|
ulong phi = prime - 1UL;
|
||||||
|
|
||||||
PrimeOrderCalculatorAccelerator gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
PrimeOrderCalculatorAccelerator gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
if (IsGpuHeuristicDevice && PrimeOrderGpuHeuristics.TryCalculateOrder(prime, previousOrder, config, divisorData, out ulong gpuOrder))
|
if (IsGpuHeuristicDevice && PrimeOrderGpuHeuristics.TryCalculateOrder(gpu, prime, previousOrder, config, divisorData, out ulong gpuOrder))
|
||||||
{
|
{
|
||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
return gpuOrder;
|
return gpuOrder;
|
||||||
@@ -374,9 +374,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PartialFactorResult extended = factorization.WithAdditionalPrime(factorization.Cofactor);
|
factorization.WithAdditionalPrime(factorization.Cofactor);
|
||||||
factorization.Dispose();
|
|
||||||
factorization = extended;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ValidateOrderAgainstFactors(prime, order, divisorData, factorization))
|
if (!ValidateOrderAgainstFactors(prime, order, divisorData, factorization))
|
||||||
@@ -541,9 +539,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PartialFactorResult extended = orderFactors.WithAdditionalPrime(orderFactors.Cofactor);
|
orderFactors.WithAdditionalPrime(orderFactors.Cofactor);
|
||||||
orderFactors.Dispose();
|
|
||||||
orderFactors = extended;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecks << 2;
|
int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecks << 2;
|
||||||
@@ -907,9 +903,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PartialFactorResult extended = factorization.WithAdditionalPrime(factorization.Cofactor);
|
factorization.WithAdditionalPrime(factorization.Cofactor);
|
||||||
factorization.Dispose();
|
|
||||||
factorization = extended;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadOnlySpan<FactorEntry> span = factorization.Factors;
|
// ReadOnlySpan<FactorEntry> span = factorization.Factors;
|
||||||
|
|||||||
@@ -70,17 +70,16 @@ internal static partial class PrimeOrderCalculator
|
|||||||
|
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
KernelContainer kernels = GpuKernelPool.GetOrAddKernels(acceleratorIndex, stream, KernelType.SmallPrimeFactorKernelScan);
|
|
||||||
SmallPrimeFactorViews tables = GpuKernelPool.GetSmallPrimeFactorTables(kernels);
|
|
||||||
|
|
||||||
var kernel = kernels.SmallPrimeFactor!;
|
var kernel = gpu.SmallPrimeFactorKernel;
|
||||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
|
|
||||||
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorCountSlotView = gpu.SmallPrimeFactorCountSlot.View;
|
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorCountSlotView = gpu.SmallPrimeFactorCountSlot.View;
|
||||||
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorRemainingSlotView = gpu.SmallPrimeFactorRemainingSlot.View;
|
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorRemainingSlotView = gpu.SmallPrimeFactorRemainingSlot.View;
|
||||||
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorPrimeSlotsView = gpu.SmallPrimeFactorPrimeSlots.View;
|
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorPrimeSlotsView = gpu.SmallPrimeFactorPrimeSlots.View;
|
||||||
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorExponentSlotsView = gpu.SmallPrimeFactorExponentSlots.View;
|
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorExponentSlotsView = gpu.SmallPrimeFactorExponentSlots.View;
|
||||||
ArrayView1D<uint, Stride1D.Dense> smallPrimeFactorsPrimesView = kernels.SmallPrimeFactorsPrimes!.View;
|
ArrayView1D<uint, Stride1D.Dense> smallPrimeFactorsPrimesView = gpu.SmallPrimeFactorTables.Primes.View;
|
||||||
|
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorsSquaresView = gpu.SmallPrimeFactorTables.Squares.View;
|
||||||
|
|
||||||
kernelLauncher(
|
kernelLauncher(
|
||||||
stream,
|
stream,
|
||||||
@@ -88,7 +87,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
value,
|
value,
|
||||||
limit,
|
limit,
|
||||||
smallPrimeFactorsPrimesView,
|
smallPrimeFactorsPrimesView,
|
||||||
kernels.SmallPrimeFactorsSquares!.View,
|
smallPrimeFactorsSquaresView,
|
||||||
(int)smallPrimeFactorsPrimesView.Length,
|
(int)smallPrimeFactorsPrimesView.Length,
|
||||||
smallPrimeFactorPrimeSlotsView,
|
smallPrimeFactorPrimeSlotsView,
|
||||||
smallPrimeFactorExponentSlotsView,
|
smallPrimeFactorExponentSlotsView,
|
||||||
@@ -138,21 +137,20 @@ internal static partial class PrimeOrderCalculator
|
|||||||
gpu.EnsureSpecialMaxFactorsCapacity(factorCount);
|
gpu.EnsureSpecialMaxFactorsCapacity(factorCount);
|
||||||
|
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
Accelerator accelerator = gpu.Accelerator;
|
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
var kernels = GpuKernelPool.GetOrAddKernels(acceleratorIndex, stream, KernelType.EvaluateSpecialMaxCandidatesKernel);
|
|
||||||
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> specialMaxFactorsView = gpu.SpecialMaxFactors.View;
|
ArrayView1D<ulong, Stride1D.Dense> specialMaxFactorsView = gpu.SpecialMaxFactors.View;
|
||||||
specialMaxFactorsView.SubView(0, factorCount).CopyFromCPU(stream, ref MemoryMarshal.GetReference(factors), factorCount);
|
specialMaxFactorsView.SubView(0, factorCount).CopyFromCPU(stream, ref MemoryMarshal.GetReference(factors), factorCount);
|
||||||
|
|
||||||
var kernel = kernels.SpecialMax!;
|
var kernel = gpu.SpecialMaxKernel;
|
||||||
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> specialMaxResultView = gpu.SpecialMaxResult.View;
|
ArrayView1D<ulong, Stride1D.Dense> specialMaxResultView = gpu.SpecialMaxResult.View;
|
||||||
|
|
||||||
kernel(
|
kernel.Launch(
|
||||||
stream,
|
stream,
|
||||||
1,
|
1,
|
||||||
|
1,
|
||||||
phi,
|
phi,
|
||||||
specialMaxFactorsView,
|
specialMaxFactorsView,
|
||||||
factorCount,
|
factorCount,
|
||||||
|
|||||||
Reference in new issue
Block a user