GpuPrimeWorkLimiter.Acquire() / .Release() removed to save time on the hot-path with billions of calls. We'll rely on AcceleratorStreamPool limits and synchronization.

This commit is contained in:
mlemanczyk committed 2025-11-13 17:52:13 +01:00
1 parent 1552e10ff0
commit 0d2a88c45f
17 files changed
+108 -124

No files matched your search

+2 -2
View File
@@ -280,13 +280,13 @@ public class GpuKernelPool
/// <param name="action">Action to run with (Accelerator, Stream).</param>
public static void Run(Action<Accelerator, AcceleratorStream> 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();
}
}
@@ -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();
@@ -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();
}
}
@@ -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;
}
@@ -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();
}
}
@@ -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<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> GetPow2ModKernel(Accelerator accelerator)
@@ -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<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
MemoryBuffer1D<ulong, Stride1D.Dense> 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<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
var kernel = gpu.KeepMontgomeryKernel;
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
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<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
MemoryBuffer1D<ulong, Stride1D.Dense> 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<ulong, Stride1D.Dense> 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<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
MemoryBuffer1D<ulong, Stride1D.Dense> 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<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
var kernel = gpu.ConvertToStandardKernel;
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
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;
@@ -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<ulong> exponents, ulong prime, in MontgomeryDivisorData divisorData, Span<ulong> 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<GpuUInt128> gpuUInt128Pool = ThreadStaticPools.GpuUInt128Pool;
try
@@ -704,7 +704,7 @@ internal static partial class PrimeOrderGpuHeuristics
gpuUInt128Pool.Return(rentedResults!, clearArray: false);
}
GpuPrimeWorkLimiter.Release();
// GpuPrimeWorkLimiter.Release();
}
}