diff --git a/PerfectNumbers.Core/Gpu/Accelerators/LastDigitGpuTables.cs b/PerfectNumbers.Core/Gpu/Accelerators/LastDigitGpuTables.cs index 4b08a2c..d9e4a3b 100644 --- a/PerfectNumbers.Core/Gpu/Accelerators/LastDigitGpuTables.cs +++ b/PerfectNumbers.Core/Gpu/Accelerators/LastDigitGpuTables.cs @@ -4,13 +4,13 @@ using ILGPU.Runtime; namespace PerfectNumbers.Core.Gpu.Accelerators; -internal sealed class LastDigitGpuTables +internal readonly struct LastDigitGpuTables { private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators; private static readonly LastDigitGpuTables[] _sharedTables = new LastDigitGpuTables[PerfectNumberConstants.RollingAccelerators]; [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static LastDigitGpuTables EnsureStaticTables(int acceleratorIndex) => _sharedTables[acceleratorIndex]; + internal static LastDigitGpuTables GetStaticTables(int acceleratorIndex) => _sharedTables[acceleratorIndex]; [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void WarmUp(int acceleratorIndex, AcceleratorStream stream) => _sharedTables[acceleratorIndex] = new LastDigitGpuTables(_accelerators[acceleratorIndex], stream); diff --git a/PerfectNumbers.Core/Gpu/Accelerators/PrimeOrderCalculatorAccelerator.cs b/PerfectNumbers.Core/Gpu/Accelerators/PrimeOrderCalculatorAccelerator.cs index d0c8282..fe2b841 100644 --- a/PerfectNumbers.Core/Gpu/Accelerators/PrimeOrderCalculatorAccelerator.cs +++ b/PerfectNumbers.Core/Gpu/Accelerators/PrimeOrderCalculatorAccelerator.cs @@ -88,13 +88,15 @@ public sealed class PrimeOrderCalculatorAccelerator public readonly Accelerator Accelerator; public readonly int AcceleratorIndex; - public readonly MemoryBuffer1D Input; - public readonly MemoryBuffer1D OutputUlong; - public MemoryBuffer1D PrimeTestInput; + public MemoryBuffer1D Input; + public MemoryBuffer1D OutputUlong; public MemoryBuffer1D OutputByte; - public MemoryBuffer1D HeuristicFlag; + public MemoryBuffer1D OutputInt; public MemoryBuffer1D, Stride1D.Dense> Pow2ModEntriesToTestOnDevice; public Dictionary Pow2ModEntriesToTestOnHost = []; + + #region Static Tables + public readonly MemoryBuffer1D DevicePrimesLastOne; public readonly MemoryBuffer1D DevicePrimesLastSeven; public readonly MemoryBuffer1D DevicePrimesLastThree; @@ -103,30 +105,26 @@ public sealed class PrimeOrderCalculatorAccelerator public readonly MemoryBuffer1D DevicePrimesPow2LastSeven; public readonly MemoryBuffer1D DevicePrimesPow2LastThree; public readonly MemoryBuffer1D DevicePrimesPow2LastNine; + + #endregion + public readonly MemoryBuffer1D SmallPrimeFactorCountSlot; - public MemoryBuffer1D SmallPrimeFactorExponentSlots; - public MemoryBuffer1D SmallPrimeFactorPrimeSlots; - public readonly MemoryBuffer1D SmallPrimeFactorRemainingSlot; - public MemoryBuffer1D SpecialMaxCandidates; - public MemoryBuffer1D SpecialMaxFactors; public readonly MemoryBuffer1D SpecialMaxResult; public readonly HeuristicGpuCombinedDivisorTables DivisorTables; public readonly SmallPrimeFactorGpuTables SmallPrimeFactorTables; - public readonly Kernel SmallPrimeSieveKernel; public readonly Kernel CheckFactorsKernel; public readonly Kernel ConvertToStandardKernel; public readonly Kernel HeuristicCombinedTrialDivisionKernel; public readonly Kernel KeepMontgomeryKernel; public readonly Kernel PollardRhoKernel; public readonly Kernel Pow2ModWideKernel; + public readonly Kernel SharesFactorKernel; public readonly Kernel SmallPrimeFactorKernel; + public readonly Kernel SmallPrimeSieveKernel; public readonly Kernel SpecialMaxKernel; - public Kernel SharesFactorKernel; - - public void EnsureCapacity(int factorsCount, int primeTesterCapacity) { if (factorsCount > Pow2ModEntriesToTestOnDevice.Length) @@ -136,42 +134,61 @@ public sealed class PrimeOrderCalculatorAccelerator Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D>(factorsCount); } - if (primeTesterCapacity > PrimeTestInput.Length) + if (primeTesterCapacity > Input.Length) { - PrimeTestInput.Dispose(); - OutputByte.Dispose(); - HeuristicFlag.Dispose(); + Input.Dispose(); + Input = Accelerator.Allocate1D(primeTesterCapacity); + } - PrimeTestInput = Accelerator.Allocate1D(primeTesterCapacity); + if (primeTesterCapacity > OutputByte.Length) + { + OutputByte.Dispose(); OutputByte = Accelerator.Allocate1D(primeTesterCapacity); - HeuristicFlag = Accelerator.Allocate1D(primeTesterCapacity); + } + + if (primeTesterCapacity > OutputInt.Length) + { + OutputInt.Dispose(); + OutputInt = Accelerator.Allocate1D(primeTesterCapacity); } } public void EnsureSmallPrimeFactorSlotsCapacity(int newSize) { // Console.WriteLine($"Resizing GPU scratch buffer from pool ({buffer.SmallPrimeFactorPrimeSlots.Length} / {smallPrimeFactorSlotCount}), ({buffer.SpecialMaxFactors.Length}/{specialMaxFactorCapacity})"); - if (SmallPrimeFactorPrimeSlots.Length < newSize) + if (OutputUlong.Length < newSize) { - SmallPrimeFactorPrimeSlots.Dispose(); - SmallPrimeFactorExponentSlots.Dispose(); + OutputUlong.Dispose(); var accelerator = Accelerator; - SmallPrimeFactorPrimeSlots = accelerator.Allocate1D(newSize); - SmallPrimeFactorExponentSlots = accelerator.Allocate1D(newSize); + OutputUlong = accelerator.Allocate1D(newSize); + } + + if (OutputInt.Length < newSize) + { + OutputInt.Dispose(); + + var accelerator = Accelerator; + OutputInt = accelerator.Allocate1D(newSize); } } public void EnsureSpecialMaxFactorsCapacity(int newSize) { - if (SpecialMaxFactors.Length < newSize) + if (Input.Length < newSize) { - SpecialMaxFactors.Dispose(); - SpecialMaxCandidates.Dispose(); + Input.Dispose(); var accelerator = Accelerator; - SpecialMaxFactors = accelerator.Allocate1D(newSize); - SpecialMaxCandidates = accelerator.Allocate1D(newSize); + Input = accelerator.Allocate1D(newSize); + } + + if (OutputUlong.Length < newSize) + { + OutputUlong.Dispose(); + + var accelerator = Accelerator; + OutputUlong = accelerator.Allocate1D(newSize); } } @@ -180,22 +197,16 @@ public sealed class PrimeOrderCalculatorAccelerator var accelerator = _accelerators[acceleratorIndex]; Accelerator = accelerator; AcceleratorIndex = acceleratorIndex; - Input = accelerator.Allocate1D(1); - OutputUlong = accelerator.Allocate1D(1); + Input = accelerator.Allocate1D(Math.Max(specialMaxFactorCapacity, primeTesterCapacity)); + OutputUlong = accelerator.Allocate1D(Math.Max(specialMaxFactorCapacity, smallPrimeFactorSlotCount)); Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D>(factorsCount); - PrimeTestInput = Accelerator.Allocate1D(primeTesterCapacity); OutputByte = Accelerator.Allocate1D(primeTesterCapacity); - HeuristicFlag = Accelerator.Allocate1D(primeTesterCapacity); - SmallPrimeFactorPrimeSlots = accelerator.Allocate1D(smallPrimeFactorSlotCount); - SmallPrimeFactorExponentSlots = accelerator.Allocate1D(smallPrimeFactorSlotCount); + OutputInt = Accelerator.Allocate1D(Math.Max(primeTesterCapacity, smallPrimeFactorSlotCount)); SmallPrimeFactorCountSlot = accelerator.Allocate1D(1); - SmallPrimeFactorRemainingSlot = accelerator.Allocate1D(1); - SpecialMaxFactors = accelerator.Allocate1D(specialMaxFactorCapacity); - SpecialMaxCandidates = accelerator.Allocate1D(specialMaxFactorCapacity); SpecialMaxResult = accelerator.Allocate1D(1); - var lastDigitSharedTables = LastDigitGpuTables.EnsureStaticTables(acceleratorIndex); + LastDigitGpuTables lastDigitSharedTables = LastDigitGpuTables.GetStaticTables(acceleratorIndex); DevicePrimesLastOne = lastDigitSharedTables.DevicePrimesLastOne; DevicePrimesLastSeven = lastDigitSharedTables.DevicePrimesLastSeven; @@ -240,15 +251,9 @@ public sealed class PrimeOrderCalculatorAccelerator Input.Dispose(); OutputUlong.Dispose(); Pow2ModEntriesToTestOnDevice.Dispose(); - PrimeTestInput.Dispose(); OutputByte.Dispose(); - HeuristicFlag.Dispose(); - SmallPrimeFactorPrimeSlots.Dispose(); - SmallPrimeFactorExponentSlots.Dispose(); + OutputInt.Dispose(); SmallPrimeFactorCountSlot.Dispose(); - SmallPrimeFactorRemainingSlot.Dispose(); - SpecialMaxFactors.Dispose(); - SpecialMaxCandidates.Dispose(); SpecialMaxResult.Dispose(); // These resources are shared between GPU leases diff --git a/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs b/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs index e30099b..f6c83f5 100644 --- a/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs +++ b/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs @@ -238,7 +238,7 @@ public sealed class HeuristicCombinedPrimeTester var acceleratorIndex = gpu.AcceleratorIndex; var stream = AcceleratorStreamPool.Rent(acceleratorIndex); var kernel = gpu.HeuristicCombinedTrialDivisionKernel; - var flagView1D = gpu.HeuristicFlag!.View; + var flagView1D = gpu.OutputInt!.View; bool compositeDetected = false; int divisorLength = GetCombinedDivisors(nMod10).Length; diff --git a/PerfectNumbers.Core/HeuristicPrimeTester.cs b/PerfectNumbers.Core/HeuristicPrimeTester.cs index 8c19f45..4ee1288 100644 --- a/PerfectNumbers.Core/HeuristicPrimeTester.cs +++ b/PerfectNumbers.Core/HeuristicPrimeTester.cs @@ -247,7 +247,7 @@ public sealed class HeuristicPrimeTester int acceleratorIndex = gpu.AcceleratorIndex; var stream = AcceleratorStreamPool.Rent(acceleratorIndex); var kernel = gpu.HeuristicCombinedTrialDivisionKernel; - var flagView1D = gpu.HeuristicFlag!.View; + var flagView1D = gpu.OutputInt!.View; bool compositeDetected; int compositeFlag = 0; diff --git a/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs b/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs index dcff51d..d98b8e0 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); @@ -75,9 +75,9 @@ internal static partial class PrimeOrderCalculator 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 smallPrimeFactorRemainingSlotView = gpu.Input.View; + ArrayView1D smallPrimeFactorPrimeSlotsView = gpu.OutputUlong.View; + ArrayView1D smallPrimeFactorExponentSlotsView = gpu.OutputInt.View; ArrayView1D smallPrimeFactorsPrimesView = gpu.SmallPrimeFactorTables.Primes.View; ArrayView1D smallPrimeFactorsSquaresView = gpu.SmallPrimeFactorTables.Squares.View; @@ -94,7 +94,6 @@ internal static partial class PrimeOrderCalculator smallPrimeFactorCountSlotView, smallPrimeFactorRemainingSlotView); - factorCount = 0; smallPrimeFactorCountSlotView.CopyToCPU(stream, ref factorCount, 1); stream.Synchronize(); @@ -140,8 +139,8 @@ internal static partial class PrimeOrderCalculator // GpuPrimeWorkLimiter.Acquire(); var stream = AcceleratorStreamPool.Rent(acceleratorIndex); - ArrayView1D specialMaxFactorsView = gpu.SpecialMaxFactors.View; - specialMaxFactorsView.SubView(0, factorCount).CopyFromCPU(stream, ref MemoryMarshal.GetReference(factors), factorCount); + ArrayView1D specialMaxFactorsView = gpu.Input.View; + specialMaxFactorsView.SubView(0, factorCount).CopyFromCPU(stream, factors); var kernel = gpu.SpecialMaxKernel; @@ -155,7 +154,7 @@ internal static partial class PrimeOrderCalculator specialMaxFactorsView, factorCount, divisorData, - gpu.SpecialMaxCandidates.View, + gpu.OutputUlong.View, specialMaxResultView); ulong result = 0UL; diff --git a/PerfectNumbers.Core/PrimeTester.cs b/PerfectNumbers.Core/PrimeTester.cs index 574319b..e5a939b 100644 --- a/PerfectNumbers.Core/PrimeTester.cs +++ b/PerfectNumbers.Core/PrimeTester.cs @@ -96,7 +96,7 @@ public sealed class PrimeTester var gpu = PrimeOrderCalculatorAccelerator.Rent(1); int acceleratorIndex = gpu.AcceleratorIndex; - var inputView = gpu.PrimeTestInput.View; + var inputView = gpu.Input.View; var outputView = gpu.OutputByte.View; var kernel = gpu.SmallPrimeSieveKernel!; @@ -134,7 +134,7 @@ public sealed class PrimeTester public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n) { byte flag = 0; - var input = gpu.PrimeTestInput; + var input = gpu.Input; var inputView = input.View; var output = gpu.OutputByte; var outputView = output.View; @@ -203,7 +203,7 @@ public sealed class PrimeTester int totalLength = values.Length; int batchSize = GpuBatchSize; - var input = gpu.PrimeTestInput; + var input = gpu.Input; var output = gpu.OutputByte; var inputView = input.View; var outputView = output.View; @@ -281,10 +281,9 @@ public sealed class PrimeTester var gpu = PrimeOrderCalculatorAccelerator.Rent(1); int acceleratorIndex = gpu.AcceleratorIndex; - var accelerator = gpu.Accelerator; var kernel = gpu.SharesFactorKernel; gpu.EnsureCapacity(0, length); - MemoryBuffer1D? inputBuffer = gpu.PrimeTestInput; + MemoryBuffer1D? inputBuffer = gpu.Input; MemoryBuffer1D? resultBuffer = gpu.OutputByte; AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);