diff --git a/PerfectNumbers.Core.Tests/Gpu/GpuKernelCompilationTests.cs b/PerfectNumbers.Core.Tests/Gpu/GpuKernelCompilationTests.cs index 1627fd6..d6c38f2 100644 --- a/PerfectNumbers.Core.Tests/Gpu/GpuKernelCompilationTests.cs +++ b/PerfectNumbers.Core.Tests/Gpu/GpuKernelCompilationTests.cs @@ -365,7 +365,7 @@ public class GpuKernelCompilationTests { stream.Synchronize(); stream.Dispose(); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); } stream = accelerator.CreateStream(); @@ -383,7 +383,7 @@ public class GpuKernelCompilationTests { stream.Synchronize(); stream.Dispose(); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); } } } diff --git a/PerfectNumbers.Core/DivisorCycleCache.cs b/PerfectNumbers.Core/DivisorCycleCache.cs index b9c93b9..f9fab73 100644 --- a/PerfectNumbers.Core/DivisorCycleCache.cs +++ b/PerfectNumbers.Core/DivisorCycleCache.cs @@ -41,8 +41,9 @@ public sealed class DivisorCycleCache private DivisorCycleCache(int divisorCyclesBatchSize) { _divisorCyclesBatchSize = Math.Max(1, divisorCyclesBatchSize); - _accelerator = SharedGpuContext.Device.CreateAccelerator(SharedGpuContext.Context); - _gpuKernel = LoadKernel(_accelerator); + var accelerator = AcceleratorPool.Shared.Rent(); + _accelerator = accelerator; + _gpuKernel = LoadKernel(accelerator); _snapshot = MersenneDivisorCycles.Shared.ExportSmallCyclesSnapshot(); } @@ -83,7 +84,6 @@ public sealed class DivisorCycleCache throw new InvalidDataException($"Divisor cycle is missing for {divisor}"); } - // ObserveCycleCacheDivisor(divisor); return cached; } @@ -118,7 +118,6 @@ public sealed class DivisorCycleCache throw new InvalidDataException($"Divisor cycle is missing for {divisor}"); } - // ObserveCycleCacheDivisor(divisor); cycles[i] = cached; } else @@ -257,18 +256,15 @@ public sealed class DivisorCycleCache powBuffer!.Dispose(); orderBuffer!.Dispose(); resultBuffer!.Dispose(); - statusBuffer!.Dispose(); + statusBuffer!.Dispose(); } Accelerator accelerator = _accelerator; - // lock(accelerator) - { - divisorBuffer = accelerator.Allocate1D(requiredCapacity); - powBuffer = accelerator.Allocate1D(requiredCapacity); - orderBuffer = accelerator.Allocate1D(requiredCapacity); - resultBuffer = accelerator.Allocate1D(requiredCapacity); - statusBuffer = accelerator.Allocate1D(requiredCapacity); - } + divisorBuffer = accelerator.Allocate1D(requiredCapacity); + powBuffer = accelerator.Allocate1D(requiredCapacity); + orderBuffer = accelerator.Allocate1D(requiredCapacity); + resultBuffer = accelerator.Allocate1D(requiredCapacity); + statusBuffer = accelerator.Allocate1D(requiredCapacity); } private void ComputeCyclesGpuCore(ReadOnlySpan divisors, Span destination) @@ -312,8 +308,10 @@ public sealed class DivisorCycleCache statusSpan[i] = ByteZero; } - GpuPrimeWorkLimiter.Acquire(); - var stream = AcceleratorStreamPool.Rent(_accelerator);// accelerator.CreateStream(); + // GpuPrimeWorkLimiter.Acquire(); + int pending; + var kernel = _gpuKernel; + var stream = AcceleratorStreamPool.Rent(_accelerator); divisorBuffer!.View.CopyFromCPU(stream, divisors); powBuffer!.View.CopyFromCPU(stream, powSpan); @@ -321,8 +319,6 @@ public sealed class DivisorCycleCache resultBuffer!.View.CopyFromCPU(stream, resultSpan); statusBuffer!.View.CopyFromCPU(stream, statusSpan); - int pending; - var kernel = _gpuKernel; do { kernel(stream, length, _divisorCyclesBatchSize, divisorBuffer.View, powBuffer.View, orderBuffer.View, resultBuffer.View, statusBuffer.View); @@ -341,7 +337,7 @@ public sealed class DivisorCycleCache } while (pending > 0); - resultBuffer.View.CopyToCPU(stream,resultSpan); + resultBuffer.View.CopyToCPU(stream, resultSpan); stream.Synchronize(); AcceleratorStreamPool.Return(stream); @@ -354,7 +350,7 @@ public sealed class DivisorCycleCache ThreadStaticPools.BytePool.Return(rentedStatus!, clearArray: false); } - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); } private static Action, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D> LoadKernel(Accelerator accelerator) diff --git a/PerfectNumbers.Core/Gpu/GpuKernelPool.cs b/PerfectNumbers.Core/Gpu/GpuKernelPool.cs index bfaa5b7..323be20 100644 --- a/PerfectNumbers.Core/Gpu/GpuKernelPool.cs +++ b/PerfectNumbers.Core/Gpu/GpuKernelPool.cs @@ -280,13 +280,13 @@ public class GpuKernelPool /// Action to run with (Accelerator, Stream). public static void Run(Action action) { - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); var accelerator = SharedGpuContext.CreateAccelerator(); var stream = accelerator.CreateStream(); action(accelerator, stream); stream.Synchronize(); stream.Dispose(); accelerator.Dispose(); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); } } diff --git a/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs b/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs index 6137b29..44ba292 100644 --- a/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs +++ b/PerfectNumbers.Core/Gpu/MersenneNumberDivisorByDivisorGpuTester.cs @@ -103,7 +103,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv ulong processedCount; ulong lastProcessed; - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter(); var accelerator = AcceleratorPool.Shared.Rent(); var stream = accelerator.CreateStream(); @@ -137,7 +137,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv stream.Dispose(); ReturnBatchResources(resources); // Monitor.Exit(gpuLease.ExecutionLock); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); if (composite) { @@ -509,7 +509,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv internal DivisorScanSession(MersenneNumberDivisorByDivisorGpuTester owner) { _owner = owner; - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); Accelerator accelerator = AcceleratorPool.Shared.Rent(); _accelerator = accelerator; _stream = accelerator.CreateStream(); diff --git a/PerfectNumbers.Core/Gpu/MersenneNumberIncrementalGpuTester.cs b/PerfectNumbers.Core/Gpu/MersenneNumberIncrementalGpuTester.cs index 4a1e401..c856f13 100644 --- a/PerfectNumbers.Core/Gpu/MersenneNumberIncrementalGpuTester.cs +++ b/PerfectNumbers.Core/Gpu/MersenneNumberIncrementalGpuTester.cs @@ -16,7 +16,7 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u { throw new NotImplementedException($"GPU incremental scanning requires the device cycle heuristics implementation (kernel: {_kernelType}, GPU order: {_useGpuOrder})."); - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); var accelerator = AcceleratorPool.Shared.Rent(); var stream = accelerator.CreateStream(); int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy @@ -125,6 +125,6 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u stream.Dispose(); ulongPool.Return(orderArray); orderBuffer.Dispose(); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); } } diff --git a/PerfectNumbers.Core/Gpu/MersenneNumberLucasLehmerGpuTester.cs b/PerfectNumbers.Core/Gpu/MersenneNumberLucasLehmerGpuTester.cs index e86e30b..a072f56 100644 --- a/PerfectNumbers.Core/Gpu/MersenneNumberLucasLehmerGpuTester.cs +++ b/PerfectNumbers.Core/Gpu/MersenneNumberLucasLehmerGpuTester.cs @@ -159,7 +159,7 @@ public class MersenneNumberLucasLehmerGpuTester } else { - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); var accelerator = AcceleratorPool.Shared.Rent(); var stream = accelerator.CreateStream(); var modulus = new GpuUInt128(((UInt128)1 << (int)exponent) - 1UL); // TODO: Cache these Mersenne moduli per exponent so LL GPU runs skip rebuilding them every launch. @@ -173,7 +173,7 @@ public class MersenneNumberLucasLehmerGpuTester stream.Dispose(); } - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); return result; } diff --git a/PerfectNumbers.Core/Gpu/MersenneNumberOrderGpuTester.cs b/PerfectNumbers.Core/Gpu/MersenneNumberOrderGpuTester.cs index 4631fa1..e385ff6 100644 --- a/PerfectNumbers.Core/Gpu/MersenneNumberOrderGpuTester.cs +++ b/PerfectNumbers.Core/Gpu/MersenneNumberOrderGpuTester.cs @@ -9,7 +9,7 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime) { - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); // var accelerator = SharedGpuContext.Accelerator; var accelerator = AcceleratorPool.Shared.Rent(); var stream = accelerator.CreateStream(); @@ -71,6 +71,6 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO stream.Dispose(); foundBuffer.Dispose(); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); } } diff --git a/PerfectNumbers.Core/Gpu/MersenneNumberResidueGpuTester.cs b/PerfectNumbers.Core/Gpu/MersenneNumberResidueGpuTester.cs index fc02b90..1f6a8ad 100644 --- a/PerfectNumbers.Core/Gpu/MersenneNumberResidueGpuTester.cs +++ b/PerfectNumbers.Core/Gpu/MersenneNumberResidueGpuTester.cs @@ -25,7 +25,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder) // GPU residue variant: check 2^p % q == 1 for q = 2*p*k + 1. public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime) { - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); var accelerator = AcceleratorPool.Shared.Rent(); // Monitor.Enter(gpuLease.ExecutionLock); @@ -110,7 +110,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder) stream.Dispose(); // Monitor.Exit(gpuLease.ExecutionLock); gpuKernels.Dispose(); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); } private static Action, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D> GetPow2ModKernel(Accelerator accelerator) diff --git a/PerfectNumbers.Core/Gpu/Pow2MontgomeryGpuCalculator.cs b/PerfectNumbers.Core/Gpu/Pow2MontgomeryGpuCalculator.cs index f723748..a11c74a 100644 --- a/PerfectNumbers.Core/Gpu/Pow2MontgomeryGpuCalculator.cs +++ b/PerfectNumbers.Core/Gpu/Pow2MontgomeryGpuCalculator.cs @@ -10,28 +10,29 @@ public static class Pow2MontgomeryGpuCalculator [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong CalculateKeep(ulong exponent, in MontgomeryDivisorData divisor) { - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); + ulong result = 0UL; var gpu = PrimeOrderCalculatorAccelerator.Rent(1); Accelerator? accelerator = gpu.Accelerator; - AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator); MemoryBuffer1D exponentBuffer = gpu.Input; + MemoryBuffer1D resultBuffer = gpu.OutputUlong; + var kernel = gpu.KeepMontgomeryKernel; + + AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator); exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1); // We don't need to worry about any left-overs here. // resultBuffer.MemSetToZero(stream); - MemoryBuffer1D resultBuffer = gpu.OutputUlong; - var kernel = gpu.KeepMontgomeryKernel; var kernelLauncher = kernel.CreateLauncherDelegate, MontgomeryDivisorData, ArrayView1D>>(); kernelLauncher(stream, 1, exponentBuffer.View, divisor, resultBuffer.View); - ulong result = 0UL; resultBuffer.View.CopyToCPU(stream, ref result, 1); stream.Synchronize(); AcceleratorStreamPool.Return(stream); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); PrimeOrderCalculatorAccelerator.Return(gpu); return result; @@ -40,50 +41,48 @@ public static class Pow2MontgomeryGpuCalculator [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong CalculateConvert(ulong exponent, in MontgomeryDivisorData divisor) { - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); + ulong result = 0UL; var gpu = PrimeOrderCalculatorAccelerator.Rent(1); - AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator); MemoryBuffer1D exponentBuffer = gpu.Input; + MemoryBuffer1D resultBuffer = gpu.OutputUlong; + AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator); exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1); // We don't need to worry about any left-overs here. // resultBuffer.MemSetToZero(stream); - MemoryBuffer1D resultBuffer = gpu.OutputUlong; var kernel = gpu.ConvertToStandardKernel; - kernel.Launch(stream, 1, 1, exponentBuffer.View, divisor, resultBuffer.View); - - ulong result = 0UL; resultBuffer.View.CopyToCPU(stream, ref result, 1); stream.Synchronize(); - AcceleratorStreamPool.Return(stream); - GpuPrimeWorkLimiter.Release(); + AcceleratorStreamPool.Return(stream); + // GpuPrimeWorkLimiter.Release(); PrimeOrderCalculatorAccelerator.Return(gpu); + return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong CalculateConvert(PrimeOrderCalculatorAccelerator gpu, ulong exponent, in MontgomeryDivisorData divisor) { - AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator); + ulong result = 0UL; MemoryBuffer1D exponentBuffer = gpu.Input; + MemoryBuffer1D resultBuffer = gpu.OutputUlong; + var kernel = gpu.ConvertToStandardKernel; + AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator); exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1); // We don't need to worry about any left-overs here. // resultBuffer.MemSetToZero(stream); - MemoryBuffer1D resultBuffer = gpu.OutputUlong; - var kernel = gpu.ConvertToStandardKernel; var kernelLauncher = kernel.CreateLauncherDelegate, MontgomeryDivisorData, ArrayView1D>>(); - kernelLauncher(stream, 1,exponentBuffer.View, divisor, resultBuffer.View); - - ulong result = 0UL; resultBuffer.View.CopyToCPU(stream, ref result, 1); stream.Synchronize(); + AcceleratorStreamPool.Return(stream); return result; diff --git a/PerfectNumbers.Core/Gpu/PrimeOrderGpuHeuristics.cs b/PerfectNumbers.Core/Gpu/PrimeOrderGpuHeuristics.cs index 18e3837..101396e 100644 --- a/PerfectNumbers.Core/Gpu/PrimeOrderGpuHeuristics.cs +++ b/PerfectNumbers.Core/Gpu/PrimeOrderGpuHeuristics.cs @@ -225,7 +225,7 @@ internal static partial class PrimeOrderGpuHeuristics try { - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); Accelerator accelerator = AcceleratorPool.Shared.Rent(); AcceleratorStream stream = accelerator.CreateStream(); @@ -290,7 +290,7 @@ internal static partial class PrimeOrderGpuHeuristics countBuffer.Dispose(); remainingBuffer.Dispose(); fullyFactoredBuffer.Dispose(); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); return true; } catch (CLException ex) @@ -402,7 +402,7 @@ internal static partial class PrimeOrderGpuHeuristics { order = 0UL; - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); Accelerator accelerator = AcceleratorPool.Shared.Rent(); AcceleratorStream stream = accelerator.CreateStream(); @@ -494,7 +494,7 @@ internal static partial class PrimeOrderGpuHeuristics stackProductBuffer.Dispose(); resultBuffer.Dispose(); statusBuffer.Dispose(); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); PrimeOrderKernelStatus kernelStatus = (PrimeOrderKernelStatus)status; if (kernelStatus == PrimeOrderKernelStatus.Fallback) @@ -574,7 +574,7 @@ internal static partial class PrimeOrderGpuHeuristics private static bool TryComputeOnGpu(ReadOnlySpan exponents, ulong prime, in MontgomeryDivisorData divisorData, Span results) { - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); Accelerator accelerator = AcceleratorPool.Shared.Rent(); AcceleratorStream? stream = accelerator.CreateStream(); // TODO: These buffers should be allocated once per accelerator and only reallocated when the new length exceeds capacity. @@ -604,7 +604,7 @@ internal static partial class PrimeOrderGpuHeuristics stream = null; exponentBuffer.Dispose(); remainderBuffer.Dispose(); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); } catch (Exception) { @@ -612,7 +612,7 @@ internal static partial class PrimeOrderGpuHeuristics stream?.Dispose(); exponentBuffer.Dispose(); remainderBuffer.Dispose(); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); throw; } @@ -638,7 +638,7 @@ internal static partial class PrimeOrderGpuHeuristics GpuUInt128[]? rentedExponents = null; GpuUInt128[]? rentedResults = null; - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); ArrayPool gpuUInt128Pool = ThreadStaticPools.GpuUInt128Pool; try @@ -704,7 +704,7 @@ internal static partial class PrimeOrderGpuHeuristics gpuUInt128Pool.Return(rentedResults!, clearArray: false); } - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); } } diff --git a/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs b/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs index 481f22e..727eaa1 100644 --- a/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs +++ b/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs @@ -224,11 +224,11 @@ public sealed class HeuristicCombinedPrimeTester private static bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10) { - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); var gpu = HeuristicPrimeTesterAccelerator.Rent(1); var accelerator = gpu.Accelerator; var stream = gpu.Stream; - var kernel = HeuristicPrimeTesterAccelerator.GetHeuristicTrialDivisionKernel(accelerator); + var kernel = HeuristicPrimeTesterAccelerator.HeuristicTrialDivisionKernel; var flagView1D = gpu.HeuristicFlag.View; var flagView = flagView1D.AsContiguous(); @@ -251,7 +251,7 @@ public sealed class HeuristicCombinedPrimeTester flagView1D.CopyToCPU(stream, ref compositeFlag, 1); stream.Synchronize(); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); compositeDetected = compositeFlag != 0; HeuristicPrimeTesterAccelerator.Return(gpu); diff --git a/PerfectNumbers.Core/HeuristicPrimeTester.cs b/PerfectNumbers.Core/HeuristicPrimeTester.cs index 1d9a6dc..29d14f3 100644 --- a/PerfectNumbers.Core/HeuristicPrimeTester.cs +++ b/PerfectNumbers.Core/HeuristicPrimeTester.cs @@ -241,7 +241,7 @@ public sealed class HeuristicPrimeTester private bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10) { - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); var gpu = HeuristicPrimeTesterAccelerator.Rent(1); var accelerator = gpu.Accelerator; var stream = gpu.Stream; @@ -307,7 +307,7 @@ public sealed class HeuristicPrimeTester } gpu.Dispose(); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); return compositeDetected; } diff --git a/PerfectNumbers.Core/MersenneDivisorCycles.cs b/PerfectNumbers.Core/MersenneDivisorCycles.cs index 3467868..7594897 100644 --- a/PerfectNumbers.Core/MersenneDivisorCycles.cs +++ b/PerfectNumbers.Core/MersenneDivisorCycles.cs @@ -804,7 +804,7 @@ public class MersenneDivisorCycles divisors = pool.Rent(count); outCycles = pool.Rent(count); - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); var accelerator = AcceleratorPool.Shared.Rent(); var stream = accelerator.CreateStream(); @@ -897,7 +897,7 @@ public class MersenneDivisorCycles pool.Return(divisors, clearArray: false); pool.Return(outCycles, clearArray: false); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); } private static Action, ArrayView1D> GetDivisorCycleKernel(Accelerator accelerator) diff --git a/PerfectNumbers.Core/MersenneNumberTester.cs b/PerfectNumbers.Core/MersenneNumberTester.cs index 554f780..eab4264 100644 --- a/PerfectNumbers.Core/MersenneNumberTester.cs +++ b/PerfectNumbers.Core/MersenneNumberTester.cs @@ -147,7 +147,7 @@ public sealed class MersenneNumberTester( UInt128[] qs = qsBuffer; - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); var accelerator = AcceleratorPool.Shared.Rent(); var stream = accelerator.CreateStream(); var orderKernel = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.OrderKernelScan).Order!; @@ -164,11 +164,8 @@ public sealed class MersenneNumberTester( while (offset < idx) { int count = Math.Min(batchSize, idx - offset); - // lock (accelerator) - { - qBuffer = accelerator.Allocate1D(count); - orderBuffer = accelerator.Allocate1D(count); - } + qBuffer = accelerator.Allocate1D(count); + orderBuffer = accelerator.Allocate1D(count); // Convert to device-friendly GpuUInt128 on the fly var tmp = gpuUInt128Pool.Rent(count); @@ -204,7 +201,7 @@ public sealed class MersenneNumberTester( } stream.Dispose(); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); uInt128Pool.Return(qs); } diff --git a/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs b/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs index 3ca3c2e..2b4aea0 100644 --- a/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs +++ b/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs @@ -91,30 +91,30 @@ internal static partial class PrimeOrderCalculator return phi; } - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); ulong candidateOrder = InitializeStartingOrderCpu(gpu, prime, phi, divisorData); candidateOrder = ExponentLoweringCpu(candidateOrder, prime, phiFactors, divisorData); if (TryConfirmOrderCpu(gpu, prime, candidateOrder, divisorData, config, out PartialFactorResult? orderFactors)) { - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); return candidateOrder; } if (config.Mode == PrimeOrderMode.Strict) { orderFactors?.Dispose(); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); return CalculateByFactorizationGpu(gpu, prime, divisorData); } if (TryHeuristicFinishCpu(gpu, prime, candidateOrder, previousOrder, divisorData, config, phiFactors, orderFactors, out ulong order)) { - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); return order; } - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); return candidateOrder; } @@ -1148,7 +1148,7 @@ internal static partial class PrimeOrderCalculator bool pollardRhoDeadlineReached = Stopwatch.GetTimestamp() > deadlineTimestamp; if (!pollardRhoDeadlineReached) { - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); while (compositeStack.Count > 0) { @@ -1200,7 +1200,7 @@ internal static partial class PrimeOrderCalculator pollardRhoDeadlineReached = Stopwatch.GetTimestamp() > deadlineTimestamp; } - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); } if (pollardRhoDeadlineReached) @@ -1216,7 +1216,7 @@ internal static partial class PrimeOrderCalculator bool cofactorContainsComposite = false; int pendingCount = pending.Count; int index = 0; - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); for (; index < pendingCount; index++) { PendingEntry entry = pending[index]; @@ -1280,7 +1280,7 @@ internal static partial class PrimeOrderCalculator // cofactorIsPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(cofactor); } - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); // ArrayPool pool = ThreadStaticPools.FactorEntryPool; bool temp; @@ -1331,19 +1331,14 @@ internal static partial class PrimeOrderCalculator // continue; // } - // factorsArray[arrayIndex] = new FactorEntry(primeValue, exponentValue, true); factorsArray[arrayIndex] = primeValue; exponentsArray[arrayIndex] = exponentValue; - // cofactorIsPrimesArray[arrayIndex] = true; arrayIndex++; } - // Span arraySpan = factorsArray.AsSpan(0, arrayIndex); - // Span arraySpan = factorsArray.AsSpan(0, arrayIndex); - // arraySpan.Sort(static (a, b) => a.CompareTo(b)); Array.Sort(factorsArray, exponentsArray, 0, arrayIndex); temp = cofactor == 1UL; - // result = PartialFactorResult.Rent(factorsArray, exponentsArray, cofactorIsPrimesArray, cofactor, temp, arrayIndex, cofactorIsPrime); + result = PartialFactorResult.Rent(factorsArray, exponentsArray, cofactor, temp, arrayIndex, cofactorIsPrime); ReturnResult: @@ -1716,7 +1711,7 @@ internal static partial class PrimeOrderCalculator ulong order = phi; int entryCount = entries.Length; - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); for (int i = 0; i < entryCount; i++) { ulong primeFactor = entries[i].Key; @@ -1744,7 +1739,7 @@ internal static partial class PrimeOrderCalculator } } - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); return order; } diff --git a/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs b/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs index b258337..b09f935 100644 --- a/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs +++ b/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs @@ -39,7 +39,7 @@ internal static partial class PrimeOrderCalculator var kernel = gpu.CheckFactorsKernel; gpu.EnsureCapacity(entryCount, 1); - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator); gpu.Pow2ModEntriesToTestOnDevice.View.CopyFromCPU(stream, entries); @@ -51,7 +51,7 @@ internal static partial class PrimeOrderCalculator stream.Synchronize(); AcceleratorStreamPool.Return(stream); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); return order; } @@ -66,7 +66,7 @@ internal static partial class PrimeOrderCalculator gpu.EnsureSmallPrimeFactorSlotsCapacity(GpuSmallPrimeFactorSlots); var accelerator = gpu.Accelerator; - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); var stream = AcceleratorStreamPool.Rent(accelerator); KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.SmallPrimeFactorKernelScan); SmallPrimeFactorViews tables = GpuKernelPool.GetSmallPrimeFactorTables(kernels); @@ -113,7 +113,7 @@ internal static partial class PrimeOrderCalculator stream.Synchronize(); AcceleratorStreamPool.Return(stream); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); for (int i = 0; i < factorCount; i++) { @@ -136,7 +136,7 @@ internal static partial class PrimeOrderCalculator gpu.EnsureSpecialMaxFactorsCapacity(factorCount); Accelerator accelerator = gpu.Accelerator; - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); var stream = AcceleratorStreamPool.Rent(accelerator); var kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.EvaluateSpecialMaxCandidatesKernel); @@ -162,7 +162,7 @@ internal static partial class PrimeOrderCalculator stream.Synchronize(); AcceleratorStreamPool.Return(stream); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); return result != 0; } @@ -171,11 +171,12 @@ internal static partial class PrimeOrderCalculator Span randomStateSpan = stackalloc ulong[1]; randomStateSpan[0] = ThreadStaticDeterministicRandomGpu.Exclusive.State; + Span factoredSpan = stackalloc byte[1]; + Span factorSpan = stackalloc ulong[1]; + AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator); gpu.Input.View.CopyFromCPU(stream, randomStateSpan); - Span factoredSpan = stackalloc byte[1]; - Span factorSpan = stackalloc ulong[1]; var kernelLauncher = gpu.PollardRhoKernel.CreateLauncherDelegate, ArrayView1D, ArrayView1D>>(); kernelLauncher(stream, n, 1, gpu.Input.View, gpu.OutputByte.View, gpu.OutputUlong.View); diff --git a/PerfectNumbers.Core/PrimeTester.cs b/PerfectNumbers.Core/PrimeTester.cs index 58e2750..0aeabe2 100644 --- a/PerfectNumbers.Core/PrimeTester.cs +++ b/PerfectNumbers.Core/PrimeTester.cs @@ -1,7 +1,6 @@ using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using ILGPU; using ILGPU.Runtime; using PerfectNumbers.Core.Gpu; @@ -93,15 +92,15 @@ public sealed class PrimeTester [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsPrimeGpu(ulong n) { - var gpu = PrimeOrderCalculatorAccelerator.Rent(1); + byte flag = 0; + var gpu = PrimeOrderCalculatorAccelerator.Rent(1); var inputView = gpu.PrimeTestInput.View; var outputView = gpu.OutputByte.View; var kernel = gpu.SmallPrimeSieveKernel!; - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator); - // var stream = gpu.Stream!; inputView.CopyFromCPU(stream, ref n, 1); var kernelLauncher = kernel.CreateLauncherDelegate, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView>>(); @@ -120,13 +119,12 @@ public sealed class PrimeTester gpu.DevicePrimesPow2LastNine.View, outputView); - byte flag = 0; outputView.CopyToCPU(stream, ref flag, 1); stream.Synchronize(); AcceleratorStreamPool.Return(stream); PrimeOrderCalculatorAccelerator.Return(gpu); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); return flag != 0; } @@ -134,6 +132,7 @@ public sealed class PrimeTester [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n) { + byte flag = 0; var input = gpu.PrimeTestInput; var inputView = input.View; var output = gpu.OutputByte; @@ -159,7 +158,6 @@ public sealed class PrimeTester gpu.DevicePrimesPow2LastNine.View, outputView); - byte flag = 0; outputView.CopyToCPU(stream, ref flag, 1); stream.Synchronize(); AcceleratorStreamPool.Return(stream); @@ -195,7 +193,7 @@ public sealed class PrimeTester [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void IsPrimeBatchGpu(ReadOnlySpan values, Span results) { - GpuPrimeWorkLimiter.Acquire(); + // GpuPrimeWorkLimiter.Acquire(); var gpu = PrimeOrderCalculatorAccelerator.Rent(GpuBatchSize); var accelerator = gpu.Accelerator; var kernel = gpu.SmallPrimeSieveKernel!; @@ -240,7 +238,7 @@ public sealed class PrimeTester stream.Synchronize(); AcceleratorStreamPool.Return(stream); PrimeOrderCalculatorAccelerator.Return(gpu); - GpuPrimeWorkLimiter.Release(); + // GpuPrimeWorkLimiter.Release(); } // Expose cache clearing for accelerator disposal coordination @@ -276,31 +274,27 @@ public sealed class PrimeTester // TODO: Route this batch helper through the shared GPU kernel pool from // GpuUInt128BinaryGcdBenchmarks so we reuse cached kernels, pinned host buffers, // and divisor-cycle staging instead of allocating new device buffers per call. - var gpu = PrimeOrderCalculatorAccelerator.Rent(1); - var accelerator = gpu.Accelerator; + // Check in benchmarks, which implementation was the fastest, is compatible with GPU, + // and implement it. int length = values.Length; ArrayPool pool = ThreadStaticPools.UlongPool; - ulong[] temp = pool.Rent(length); - values.CopyTo(temp); - MemoryBuffer1D? inputBuffer; - MemoryBuffer1D? resultBuffer; - - inputBuffer = accelerator.Allocate1D(length); - resultBuffer = accelerator.Allocate1D(length); + var gpu = PrimeOrderCalculatorAccelerator.Rent(1); + var accelerator = gpu.Accelerator; + gpu.EnsureCapacity(0, length); + MemoryBuffer1D? inputBuffer = gpu.PrimeTestInput; + MemoryBuffer1D? resultBuffer = gpu.OutputByte; AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator); - inputBuffer.View.CopyFromCPU(stream, ref temp[0], length); + inputBuffer.View.CopyFromCPU(stream, values); + var kernel = GetSharesFactorKernel(accelerator); kernel(stream, length, inputBuffer.View, resultBuffer.View); resultBuffer.View.CopyToCPU(stream, in results); stream.Synchronize(); AcceleratorStreamPool.Return(stream); - pool.Return(temp, clearArray: false); - resultBuffer.Dispose(); - inputBuffer.Dispose(); PrimeOrderCalculatorAccelerator.Return(gpu); } @@ -323,6 +317,8 @@ public sealed class PrimeTester // TODO: Swap this handwritten binary GCD for the optimized helper measured in // GpuUInt128BinaryGcdBenchmarks so CPU callers share the faster subtract-less // ladder once the common implementation is promoted into PerfectNumbers.Core. + // You have an example in the benchmarks and you already implemented it in + // GpuUInt128, iirc. if (u == 0UL) { return v;