From 342eff2726d71d1e57e901e34d7aee695282218f Mon Sep 17 00:00:00 2001 From: mlemanczyk Date: Mon, 17 Nov 2025 23:33:59 +0100 Subject: [PATCH] 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. --- .../Gpu/GpuKernelCompilationTests.cs | 2 +- ...MersenneNumberDivisorByDivisorCpuTester.cs | 2 - .../PrimeOrderCalculatorAccelerator.cs | 10 +++ PerfectNumbers.Core/Gpu/GpuKernelPool.cs | 66 ---------------- PerfectNumbers.Core/Gpu/KernelType.cs | 4 +- ...MersenneNumberDivisorByDivisorGpuTester.cs | 2 - .../Gpu/PrimeOrderGpuHeuristics.cs | 45 +---------- .../Gpu/SmallPrimeFactorGpuTables.cs | 34 ++++++++ .../Gpu/SmallPrimeFactorViews.cs | 32 -------- PerfectNumbers.Core/PartialFactorResult.cs | 79 ++++++++++++++----- .../PrimeOrderCalculator.Cpu.cs | 14 +--- .../PrimeOrderCalculator.Gpu.cs | 18 ++--- 12 files changed, 119 insertions(+), 189 deletions(-) create mode 100644 PerfectNumbers.Core/Gpu/SmallPrimeFactorGpuTables.cs delete mode 100644 PerfectNumbers.Core/Gpu/SmallPrimeFactorViews.cs diff --git a/PerfectNumbers.Core.Tests/Gpu/GpuKernelCompilationTests.cs b/PerfectNumbers.Core.Tests/Gpu/GpuKernelCompilationTests.cs index b40333b..0bef11d 100644 --- a/PerfectNumbers.Core.Tests/Gpu/GpuKernelCompilationTests.cs +++ b/PerfectNumbers.Core.Tests/Gpu/GpuKernelCompilationTests.cs @@ -344,7 +344,7 @@ public class GpuKernelCompilationTests _ = 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) { diff --git a/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs b/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs index 3fc4d28..f8cea9e 100644 --- a/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs +++ b/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs @@ -100,8 +100,6 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv ulong allowedMax, out bool processedAll) { - processedAll = false; - // 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) diff --git a/PerfectNumbers.Core/Gpu/Accelerators/PrimeOrderCalculatorAccelerator.cs b/PerfectNumbers.Core/Gpu/Accelerators/PrimeOrderCalculatorAccelerator.cs index cc9da8f..d0c8282 100644 --- a/PerfectNumbers.Core/Gpu/Accelerators/PrimeOrderCalculatorAccelerator.cs +++ b/PerfectNumbers.Core/Gpu/Accelerators/PrimeOrderCalculatorAccelerator.cs @@ -67,8 +67,10 @@ public sealed class PrimeOrderCalculatorAccelerator 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. AcceleratorStream stream = accelerator.CreateStream(); + // TODO: Review which tables are needed when final execution path is defined. LastDigitGpuTables.WarmUp(i, stream); HeuristicGpuCombinedTables.WarmUp(i, stream); + // SmallPrimeFactorGpuTables.WarmUp(i, stream); // SharedHeuristicGpuTables.EnsureStaticTables(accelerator, stream); // _ = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.None); // KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream); @@ -110,6 +112,7 @@ public sealed class PrimeOrderCalculatorAccelerator public readonly MemoryBuffer1D SpecialMaxResult; public readonly HeuristicGpuCombinedDivisorTables DivisorTables; + public readonly SmallPrimeFactorGpuTables SmallPrimeFactorTables; public readonly Kernel SmallPrimeSieveKernel; public readonly Kernel CheckFactorsKernel; @@ -118,6 +121,8 @@ public sealed class PrimeOrderCalculatorAccelerator public readonly Kernel KeepMontgomeryKernel; public readonly Kernel PollardRhoKernel; public readonly Kernel Pow2ModWideKernel; + public readonly Kernel SmallPrimeFactorKernel; + public readonly Kernel SpecialMaxKernel; public Kernel SharesFactorKernel; @@ -203,6 +208,7 @@ public sealed class PrimeOrderCalculatorAccelerator var heuristicSharedTables = HeuristicGpuCombinedTables.GetStaticTables(acceleratorIndex); DivisorTables = heuristicSharedTables.CreateHeuristicDivisorTables(); + SmallPrimeFactorTables = SmallPrimeFactorGpuTables.GetStaticTables(acceleratorIndex); var checkFactorsKernel = accelerator.LoadStreamKernel, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D>(PrimeOrderGpuHeuristics.CheckFactorsKernel); CheckFactorsKernel = KernelUtil.GetKernel(checkFactorsKernel); @@ -223,6 +229,10 @@ public sealed class PrimeOrderCalculatorAccelerator accelerator.LoadAutoGroupedStreamKernel, GpuUInt128, ArrayView1D>(PrimeOrderGpuHeuristics.Pow2ModKernelWide)); SharesFactorKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel, ArrayView>(PrimeTesterKernels.SharesFactorKernel)); + + SpecialMaxKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel, int, MontgomeryDivisorData, ArrayView1D, ArrayView1D>(PrimeOrderGpuHeuristics.EvaluateSpecialMaxCandidatesKernel)); + + SmallPrimeFactorKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel, ArrayView1D, int, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D>(SmallPrimeFactorKernels.SmallPrimeFactorKernelScan)); } public void Dispose() diff --git a/PerfectNumbers.Core/Gpu/GpuKernelPool.cs b/PerfectNumbers.Core/Gpu/GpuKernelPool.cs index fae25c4..5a97c63 100644 --- a/PerfectNumbers.Core/Gpu/GpuKernelPool.cs +++ b/PerfectNumbers.Core/Gpu/GpuKernelPool.cs @@ -57,16 +57,6 @@ public class GpuKernelPool InitPow2ModOrderKernelScan(accelerator, kernels); } - if (kernelType.HasFlag(KernelType.EvaluateSpecialMaxCandidatesKernel)) - { - InitEvaluateSpecialMaxCandidatesKernel(accelerator, kernels); - } - - if (kernelType.HasFlag(KernelType.SmallPrimeFactorKernelScan)) - { - InitSmallPrimeFactorKernelScan(accelerator, kernels); - } - PreloadStaticTables(accelerator, kernels, stream, kernelType); pool[acceleratorIndex] = kernels; @@ -132,25 +122,6 @@ public class GpuKernelPool return kernel.CreateLauncherDelegate, ArrayView1D>>(); }); } - - static void InitEvaluateSpecialMaxCandidatesKernel(Accelerator accelerator, KernelContainer kernels) - { - InitOnce(ref kernels.SpecialMax, () => - { - var loaded = accelerator.LoadAutoGroupedStreamKernel, int, MontgomeryDivisorData, ArrayView1D, ArrayView1D>(PrimeOrderGpuHeuristics.EvaluateSpecialMaxCandidatesKernel); - - var kernel = KernelUtil.GetKernel(loaded); - - return kernel.CreateLauncherDelegate, int, MontgomeryDivisorData, ArrayView1D, ArrayView1D>>(); - }); - } - - static void InitSmallPrimeFactorKernelScan(Accelerator accelerator, KernelContainer kernels) - { - var loaded = accelerator.LoadAutoGroupedStreamKernel, ArrayView1D, int, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D>(SmallPrimeFactorKernels.SmallPrimeFactorKernelScan); - - kernels.SmallPrimeFactor = KernelUtil.GetKernel(loaded); - } } internal static void PreloadStaticTables(Accelerator accelerator, KernelContainer kernels, AcceleratorStream stream, KernelType kernelType) @@ -164,11 +135,6 @@ public class GpuKernelPool { EnsureSmallPrimesOnDevice(accelerator, kernels, stream); } - - if (kernelType.HasFlag(KernelType.SmallPrimeFactorKernelScan)) - { - EnsureSmallPrimeFactorTables(accelerator, kernels, stream); - } } public static ArrayView1D GetSmallCyclesOnDevice(KernelContainer kernels) => kernels.SmallCycles!; @@ -247,38 +213,6 @@ public class GpuKernelPool 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? devicePrimes; - MemoryBuffer1D? deviceSquares; - - // lock (accelerator) - { - devicePrimes = accelerator.Allocate1D(length); - deviceSquares = accelerator.Allocate1D(length); - } - - devicePrimes.View.CopyFromCPU(stream, hostPrimes); - deviceSquares.View.CopyFromCPU(stream, hostSquares); - - kernels.SmallPrimeFactorsPrimes = devicePrimes; - kernels.SmallPrimeFactorsSquares = deviceSquares; - } - /// /// Runs a GPU action with an acquired accelerator and stream. /// diff --git a/PerfectNumbers.Core/Gpu/KernelType.cs b/PerfectNumbers.Core/Gpu/KernelType.cs index 683530f..654808d 100644 --- a/PerfectNumbers.Core/Gpu/KernelType.cs +++ b/PerfectNumbers.Core/Gpu/KernelType.cs @@ -10,7 +10,5 @@ public enum KernelType OrderKernelScan, IncrementalKernelScan, IncrementalOrderKernelScan, - Pow2ModOrderKernelScan, - EvaluateSpecialMaxCandidatesKernel, - SmallPrimeFactorKernelScan + Pow2ModOrderKernelScan } diff --git a/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs b/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs index 2237fb6..146f131 100644 --- a/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs +++ b/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs @@ -502,8 +502,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv public sealed class DivisorScanSession : IMersenneNumberDivisorByDivisorTester.IDivisorScanSession { - private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators; - private readonly MersenneNumberDivisorByDivisorGpuTester _owner; private readonly PrimeOrderCalculatorAccelerator _primeTesterAccelerator; private readonly Accelerator _accelerator; diff --git a/PerfectNumbers.Core/Gpu/PrimeOrderGpuHeuristics.cs b/PerfectNumbers.Core/Gpu/PrimeOrderGpuHeuristics.cs index 671d3cf..3c4f55e 100644 --- a/PerfectNumbers.Core/Gpu/PrimeOrderGpuHeuristics.cs +++ b/PerfectNumbers.Core/Gpu/PrimeOrderGpuHeuristics.cs @@ -33,9 +33,6 @@ internal static partial class PrimeOrderGpuHeuristics [ThreadStatic] 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 ulong PreviousOrder = previousOrder; @@ -69,13 +66,6 @@ internal static partial class PrimeOrderGpuHeuristics public readonly ArrayView1D Status = status; } - private sealed class SmallPrimeDeviceCache - { - public MemoryBuffer1D? Primes; - public MemoryBuffer1D? Squares; - public int Count; - } - private const int WideStackThreshold = 12; private static PrimeOrderGpuCapability s_capability = PrimeOrderGpuCapability.Default; @@ -100,36 +90,6 @@ internal static partial class PrimeOrderGpuHeuristics 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? primeBuffer; - MemoryBuffer1D? squareBuffer; - - var accelerator = _accelerators[acceleratorIndex]; - primeBuffer = accelerator.Allocate1D(primes.Length); - squareBuffer = accelerator.Allocate1D(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) { var pool = _partialFactorKernel ??= []; @@ -212,7 +172,7 @@ internal static partial class PrimeOrderGpuHeuristics Accelerator accelerator = _accelerators[acceleratorIndex]; 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. MemoryBuffer1D? factorBuffer = accelerator.Allocate1D(primeTargets.Length); @@ -363,6 +323,7 @@ internal static partial class PrimeOrderGpuHeuristics } internal static bool TryCalculateOrder( + PrimeOrderCalculatorAccelerator gpu, ulong prime, ulong? previousOrder, PrimeOrderCalculator.PrimeOrderSearchConfig config, @@ -375,7 +336,7 @@ internal static partial class PrimeOrderGpuHeuristics int acceleratorIndex = AcceleratorPool.Shared.Rent(); Accelerator accelerator = _accelerators[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 // thread static cache to prevent other threads from using taking accelerators with pre-allocated buffers if they don't diff --git a/PerfectNumbers.Core/Gpu/SmallPrimeFactorGpuTables.cs b/PerfectNumbers.Core/Gpu/SmallPrimeFactorGpuTables.cs new file mode 100644 index 0000000..50ffa17 --- /dev/null +++ b/PerfectNumbers.Core/Gpu/SmallPrimeFactorGpuTables.cs @@ -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 Primes; + public readonly MemoryBuffer1D Squares; + public readonly int Count; + + public SmallPrimeFactorGpuTables(Accelerator accelerator, AcceleratorStream stream) + { + var hostPrimes = PrimesGenerator.SmallPrimes; + var hostSquares = PrimesGenerator.SmallPrimesPow2; + + MemoryBuffer1D? devicePrimes = accelerator.Allocate1D(stream, hostPrimes); + MemoryBuffer1D? deviceSquares = accelerator.Allocate1D(stream, hostSquares); + + Primes = devicePrimes; + Squares = deviceSquares; + Count = hostPrimes.Length; + } +} diff --git a/PerfectNumbers.Core/Gpu/SmallPrimeFactorViews.cs b/PerfectNumbers.Core/Gpu/SmallPrimeFactorViews.cs deleted file mode 100644 index 7fb62ba..0000000 --- a/PerfectNumbers.Core/Gpu/SmallPrimeFactorViews.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Runtime.CompilerServices; -using ILGPU; -using ILGPU.Runtime; - -namespace PerfectNumbers.Core.Gpu; - -public readonly struct SmallPrimeFactorViews( - MemoryBuffer1D primes, - MemoryBuffer1D squares) -{ - public readonly MemoryBuffer1D Primes = primes; - public readonly MemoryBuffer1D Squares = squares; - public readonly int Count = (int)primes.Length; - - public ArrayView1D PrimesView - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return Primes.View; - } - } - - public ArrayView1D SquaresView - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return Squares.View; - } - } -} diff --git a/PerfectNumbers.Core/PartialFactorResult.cs b/PerfectNumbers.Core/PartialFactorResult.cs index 712ae44..f0800f3 100644 --- a/PerfectNumbers.Core/PartialFactorResult.cs +++ b/PerfectNumbers.Core/PartialFactorResult.cs @@ -67,36 +67,73 @@ namespace PerfectNumbers.Core FullyFactored = true }; - public PartialFactorResult WithAdditionalPrime(ulong prime) + public void WithAdditionalPrime(ulong prime) { - ulong[]? source = Factors; + ulong[]? sourceFactors = Factors; int sourceCount = Count; - int[] exponents; - if (source is null || sourceCount == 0) + if (sourceFactors is null || sourceCount == 0) { - source = ThreadStaticPools.UlongPool.Rent(1); - exponents = ThreadStaticPools.IntPool.Rent(1); - // source = new ulong[1]; - // exponents = new int[1]; - source[0] = prime; - exponents[0] = 1; + InitializeWithPrime(prime); + return; + } - return Rent(source, exponents, 1UL, true, 1, false); - } + int newSize = sourceCount + 1; + int[] extendedExponents; - ulong[] extended = ThreadStaticPools.UlongPool.Rent(sourceCount + 1); - Array.Copy(source, 0, extended, 0, sourceCount); - extended[sourceCount] = prime; + ulong[] extendedFactors = sourceFactors.Length >= newSize + ? sourceFactors + : ResizeFactors(sourceFactors, sourceCount, newSize); - exponents = ThreadStaticPools.IntPool.Rent(sourceCount + 1); - Array.Copy(Exponents!, 0, exponents, 0, sourceCount); - exponents[sourceCount] = 1; - Array.Sort(extended, exponents, 0, sourceCount + 1); + int[] sourceExponents = Exponents!; + extendedExponents = sourceExponents.Length >= newSize + ? sourceExponents + : 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) { diff --git a/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs b/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs index bf1b6a7..d0a352a 100644 --- a/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs +++ b/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs @@ -55,7 +55,7 @@ internal static partial class PrimeOrderCalculator ulong phi = prime - 1UL; 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); return gpuOrder; @@ -374,9 +374,7 @@ internal static partial class PrimeOrderCalculator return false; } - PartialFactorResult extended = factorization.WithAdditionalPrime(factorization.Cofactor); - factorization.Dispose(); - factorization = extended; + factorization.WithAdditionalPrime(factorization.Cofactor); } if (!ValidateOrderAgainstFactors(prime, order, divisorData, factorization)) @@ -541,9 +539,7 @@ internal static partial class PrimeOrderCalculator return false; } - PartialFactorResult extended = orderFactors.WithAdditionalPrime(orderFactors.Cofactor); - orderFactors.Dispose(); - orderFactors = extended; + orderFactors.WithAdditionalPrime(orderFactors.Cofactor); } int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecks << 2; @@ -907,9 +903,7 @@ internal static partial class PrimeOrderCalculator return false; } - PartialFactorResult extended = factorization.WithAdditionalPrime(factorization.Cofactor); - factorization.Dispose(); - factorization = extended; + factorization.WithAdditionalPrime(factorization.Cofactor); } // ReadOnlySpan span = factorization.Factors; diff --git a/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs b/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs index b8bce1e..dcff51d 100644 --- a/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs +++ b/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs @@ -55,7 +55,7 @@ internal static partial class PrimeOrderCalculator // GpuPrimeWorkLimiter.Release(); return order; } - + private static bool TryPopulateSmallPrimeFactorsGpu(PrimeOrderCalculatorAccelerator gpu, ulong value, uint limit, Dictionary counts, out int factorCount, out ulong remaining) { var primeBufferArray = ThreadStaticPools.UlongPool.Rent(GpuSmallPrimeFactorSlots); @@ -70,17 +70,16 @@ internal static partial class PrimeOrderCalculator // GpuPrimeWorkLimiter.Acquire(); 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, ArrayView1D, int, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D>>(); ArrayView1D smallPrimeFactorCountSlotView = gpu.SmallPrimeFactorCountSlot.View; ArrayView1D smallPrimeFactorRemainingSlotView = gpu.SmallPrimeFactorRemainingSlot.View; ArrayView1D smallPrimeFactorPrimeSlotsView = gpu.SmallPrimeFactorPrimeSlots.View; ArrayView1D smallPrimeFactorExponentSlotsView = gpu.SmallPrimeFactorExponentSlots.View; - ArrayView1D smallPrimeFactorsPrimesView = kernels.SmallPrimeFactorsPrimes!.View; + ArrayView1D smallPrimeFactorsPrimesView = gpu.SmallPrimeFactorTables.Primes.View; + ArrayView1D smallPrimeFactorsSquaresView = gpu.SmallPrimeFactorTables.Squares.View; kernelLauncher( stream, @@ -88,7 +87,7 @@ internal static partial class PrimeOrderCalculator value, limit, smallPrimeFactorsPrimesView, - kernels.SmallPrimeFactorsSquares!.View, + smallPrimeFactorsSquaresView, (int)smallPrimeFactorsPrimesView.Length, smallPrimeFactorPrimeSlotsView, smallPrimeFactorExponentSlotsView, @@ -138,21 +137,20 @@ internal static partial class PrimeOrderCalculator gpu.EnsureSpecialMaxFactorsCapacity(factorCount); int acceleratorIndex = gpu.AcceleratorIndex; - Accelerator accelerator = gpu.Accelerator; // GpuPrimeWorkLimiter.Acquire(); var stream = AcceleratorStreamPool.Rent(acceleratorIndex); - var kernels = GpuKernelPool.GetOrAddKernels(acceleratorIndex, stream, KernelType.EvaluateSpecialMaxCandidatesKernel); ArrayView1D specialMaxFactorsView = gpu.SpecialMaxFactors.View; specialMaxFactorsView.SubView(0, factorCount).CopyFromCPU(stream, ref MemoryMarshal.GetReference(factors), factorCount); - var kernel = kernels.SpecialMax!; + var kernel = gpu.SpecialMaxKernel; ArrayView1D specialMaxResultView = gpu.SpecialMaxResult.View; - kernel( + kernel.Launch( stream, 1, + 1, phi, specialMaxFactorsView, factorCount,