Remove GPU context creation lock

This commit is contained in:
Marek Lemańczyk committed 2025-10-28 13:26:20 +01:00
1 parent c39a99a4fd
commit de7ddd8db3
10 files changed
+11 -71

No files matched your search

-2
View File
@@ -227,7 +227,6 @@ public sealed class DivisorCycleCache
{ {
int length = divisors.Length; int length = divisors.Length;
var gpuLease = GpuKernelPool.GetKernel(useGpuOrder: true); var gpuLease = GpuKernelPool.GetKernel(useGpuOrder: true);
var execution = gpuLease.EnterExecutionScope();
Accelerator accelerator = gpuLease.Accelerator; Accelerator accelerator = gpuLease.Accelerator;
var kernel = _gpuKernelCache.GetOrAdd(accelerator, LoadKernel); var kernel = _gpuKernelCache.GetOrAdd(accelerator, LoadKernel);
@@ -309,7 +308,6 @@ public sealed class DivisorCycleCache
ArrayPool<byte>.Shared.Return(rentedStatus!, clearArray: false); ArrayPool<byte>.Shared.Return(rentedStatus!, clearArray: false);
} }
execution.Dispose();
gpuLease.Dispose(); gpuLease.Dispose();
} }
+5 -15
View File
@@ -47,7 +47,6 @@ public static class GpuContextPool
private static readonly ConcurrentQueue<PooledContext> CpuPool = new(); private static readonly ConcurrentQueue<PooledContext> CpuPool = new();
private static readonly ConcurrentQueue<PooledContext> GpuPool = new(); private static readonly ConcurrentQueue<PooledContext> GpuPool = new();
private static readonly object CreationLock = new();
public static GpuContextLease Rent() public static GpuContextLease Rent()
{ {
@@ -61,20 +60,17 @@ public static class GpuContextPool
{ {
if (preferCpu && CpuPool.TryDequeue(out var cpu)) if (preferCpu && CpuPool.TryDequeue(out var cpu))
{ {
return new GpuContextLease(cpu, CreationLock); return new GpuContextLease(cpu);
} }
if (!preferCpu && GpuPool.TryDequeue(out var gpu)) if (!preferCpu && GpuPool.TryDequeue(out var gpu))
{ {
return new GpuContextLease(gpu, CreationLock); return new GpuContextLease(gpu);
} }
} }
// Serialize accelerator creation to avoid concurrent CL device/stream setup across threads. // Create a new accelerator when the pool does not have one available.
lock (CreationLock) return new GpuContextLease(new PooledContext(preferCpu));
{
return new GpuContextLease(new PooledContext(preferCpu), CreationLock);
}
} }
public static void DisposeAll() public static void DisposeAll()
@@ -113,30 +109,24 @@ public static class GpuContextPool
} }
else else
{
lock (CreationLock)
{ {
ctx.Dispose(); ctx.Dispose();
} }
} }
}
public struct GpuContextLease public struct GpuContextLease
{ {
private readonly PooledContext _ctx; private readonly PooledContext _ctx;
internal GpuContextLease(PooledContext ctx, object kernelInitLock) internal GpuContextLease(PooledContext ctx)
{ {
_ctx = ctx; _ctx = ctx;
KernelInitLock = kernelInitLock;
} }
public Context Context => _ctx.Context; public Context Context => _ctx.Context;
public Accelerator Accelerator => _ctx.Accelerator; public Accelerator Accelerator => _ctx.Accelerator;
public object KernelInitLock { get; }
public object ExecutionLock => _ctx.ExecutionLock; public object ExecutionLock => _ctx.ExecutionLock;
+6 -33
View File
@@ -14,7 +14,6 @@ public sealed class GpuKernelLease
private GpuContextLease? _gpu; private GpuContextLease? _gpu;
private KernelContainer? _kernels; private KernelContainer? _kernels;
private AcceleratorStream? _stream; private AcceleratorStream? _stream;
private object? _executionLock;
private GpuKernelLease() private GpuKernelLease()
{ {
@@ -31,7 +30,6 @@ public sealed class GpuKernelLease
lease._gpu = gpu; lease._gpu = gpu;
lease._kernels = kernels; lease._kernels = kernels;
lease._stream = null; lease._stream = null;
lease._executionLock = gpu.ExecutionLock;
return lease; return lease;
} }
@@ -53,14 +51,12 @@ public sealed class GpuKernelLease
} }
} }
public ExecutionScope EnterExecutionScope() => new ExecutionScope(_executionLock);
public Action<AcceleratorStream, Index1D, ulong, ulong, ArrayView<GpuUInt128>, ArrayView<ulong>> OrderKernel public Action<AcceleratorStream, Index1D, ulong, ulong, ArrayView<GpuUInt128>, ArrayView<ulong>> OrderKernel
{ {
get get
{ {
var accel = Accelerator; // avoid capturing 'this' in lambda var accel = Accelerator; // avoid capturing 'this' in lambda
lock (_gpu!.Value.KernelInitLock) lock (_gpu!.Value.ExecutionLock)
{ {
return KernelContainer.InitOnce(ref _kernels!.Order, () => return KernelContainer.InitOnce(ref _kernels!.Order, () =>
{ {
@@ -77,7 +73,7 @@ public sealed class GpuKernelLease
get get
{ {
var accel = Accelerator; var accel = Accelerator;
lock (_gpu!.Value.KernelInitLock) lock (_gpu!.Value.ExecutionLock)
{ {
return KernelContainer.InitOnce(ref _kernels!.Pow2Mod, () => return KernelContainer.InitOnce(ref _kernels!.Pow2Mod, () =>
{ {
@@ -94,7 +90,7 @@ public sealed class GpuKernelLease
get get
{ {
var accel = Accelerator; var accel = Accelerator;
lock (_gpu!.Value.KernelInitLock) lock (_gpu!.Value.ExecutionLock)
{ {
return KernelContainer.InitOnce(ref _kernels!.Incremental, () => return KernelContainer.InitOnce(ref _kernels!.Incremental, () =>
{ {
@@ -111,7 +107,7 @@ public sealed class GpuKernelLease
get get
{ {
var accel = Accelerator; var accel = Accelerator;
lock (_gpu!.Value.KernelInitLock) lock (_gpu!.Value.ExecutionLock)
{ {
return KernelContainer.InitOnce(ref _kernels!.IncrementalOrder, () => return KernelContainer.InitOnce(ref _kernels!.IncrementalOrder, () =>
{ {
@@ -128,7 +124,7 @@ public sealed class GpuKernelLease
get get
{ {
var accel = Accelerator; var accel = Accelerator;
lock (_gpu!.Value.KernelInitLock) lock (_gpu!.Value.ExecutionLock)
{ {
return KernelContainer.InitOnce(ref _kernels!.Pow2ModOrder, () => return KernelContainer.InitOnce(ref _kernels!.Pow2ModOrder, () =>
{ {
@@ -145,7 +141,7 @@ public sealed class GpuKernelLease
get get
{ {
var accel = Accelerator; var accel = Accelerator;
lock (_gpu!.Value.KernelInitLock) lock (_gpu!.Value.ExecutionLock)
{ {
return KernelContainer.InitOnce(ref _kernels!.SmallPrimeFactor, () => return KernelContainer.InitOnce(ref _kernels!.SmallPrimeFactor, () =>
{ {
@@ -165,8 +161,6 @@ public sealed class GpuKernelLease
_gpu?.Dispose(); _gpu?.Dispose();
_gpu = null; _gpu = null;
_executionLock = null;
_releaseLimiter?.Invoke(); _releaseLimiter?.Invoke();
_releaseLimiter = null; _releaseLimiter = null;
@@ -174,25 +168,4 @@ public sealed class GpuKernelLease
Pool.Enqueue(this); Pool.Enqueue(this);
} }
public readonly struct ExecutionScope
{
private readonly object? _lock;
public ExecutionScope(object? sync)
{
_lock = sync;
if (_lock is not null)
{
Monitor.Enter(_lock);
}
}
public void Dispose()
{
if (_lock is not null)
{
Monitor.Exit(_lock);
}
}
}
} }
-2
View File
@@ -293,12 +293,10 @@ public class GpuKernelPool
public static void Run(Action<Accelerator, AcceleratorStream> action) public static void Run(Action<Accelerator, AcceleratorStream> action)
{ {
var lease = GetKernel(useGpuOrder: true); var lease = GetKernel(useGpuOrder: true);
var execution = lease.EnterExecutionScope();
var accelerator = lease.Accelerator; var accelerator = lease.Accelerator;
var stream = accelerator.CreateStream(); var stream = accelerator.CreateStream();
action(accelerator, stream); action(accelerator, stream);
stream.Dispose(); stream.Dispose();
execution.Dispose();
lease.Dispose(); lease.Dispose();
} }
@@ -17,7 +17,6 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
throw new NotImplementedException($"GPU incremental scanning requires the device cycle heuristics implementation (kernel: {_kernelType}, GPU order: {_useGpuOrder})."); throw new NotImplementedException($"GPU incremental scanning requires the device cycle heuristics implementation (kernel: {_kernelType}, GPU order: {_useGpuOrder}).");
var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder); var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder);
var execution = gpuLease.EnterExecutionScope();
var accelerator = gpuLease.Accelerator; var accelerator = gpuLease.Accelerator;
var stream = gpuLease.Stream; var stream = gpuLease.Stream;
int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy
@@ -123,7 +122,6 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
ArrayPool<ulong>.Shared.Return(orderArray); ArrayPool<ulong>.Shared.Return(orderArray);
orderBuffer.Dispose(); orderBuffer.Dispose();
execution.Dispose();
gpuLease.Dispose(); gpuLease.Dispose();
} }
} }
@@ -10,7 +10,6 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime) public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
{ {
var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder); var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder);
var execution = gpuLease.EnterExecutionScope();
var accelerator = gpuLease.Accelerator; var accelerator = gpuLease.Accelerator;
var stream = gpuLease.Stream; var stream = gpuLease.Stream;
int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy and avoids TDR int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy and avoids TDR
@@ -61,7 +60,6 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
} }
foundBuffer.Dispose(); foundBuffer.Dispose();
execution.Dispose();
gpuLease.Dispose(); gpuLease.Dispose();
} }
} }
@@ -194,7 +194,6 @@ internal static partial class PrimeOrderGpuHeuristics
try try
{ {
var lease = GpuKernelPool.GetKernel(useGpuOrder: true); var lease = GpuKernelPool.GetKernel(useGpuOrder: true);
var execution = lease.EnterExecutionScope();
Accelerator accelerator = lease.Accelerator; Accelerator accelerator = lease.Accelerator;
AcceleratorStream stream = lease.Stream; AcceleratorStream stream = lease.Stream;
@@ -248,7 +247,6 @@ internal static partial class PrimeOrderGpuHeuristics
countBuffer.Dispose(); countBuffer.Dispose();
remainingBuffer.Dispose(); remainingBuffer.Dispose();
fullyFactoredBuffer.Dispose(); fullyFactoredBuffer.Dispose();
execution.Dispose();
lease.Dispose(); lease.Dispose();
return true; return true;
} }
@@ -362,7 +360,6 @@ internal static partial class PrimeOrderGpuHeuristics
order = 0UL; order = 0UL;
var lease = GpuKernelPool.GetKernel(useGpuOrder: true); var lease = GpuKernelPool.GetKernel(useGpuOrder: true);
var execution = lease.EnterExecutionScope();
Accelerator accelerator = lease.Accelerator; Accelerator accelerator = lease.Accelerator;
AcceleratorStream stream = lease.Stream; AcceleratorStream stream = lease.Stream;
@@ -467,7 +464,6 @@ internal static partial class PrimeOrderGpuHeuristics
stackProductBuffer.Dispose(); stackProductBuffer.Dispose();
resultBuffer.Dispose(); resultBuffer.Dispose();
statusBuffer.Dispose(); statusBuffer.Dispose();
execution.Dispose();
} }
} }
@@ -526,7 +522,6 @@ internal static partial class PrimeOrderGpuHeuristics
private static bool TryComputeOnGpu(ReadOnlySpan<ulong> exponents, ulong prime, in MontgomeryDivisorData divisorData, Span<ulong> results) private static bool TryComputeOnGpu(ReadOnlySpan<ulong> exponents, ulong prime, in MontgomeryDivisorData divisorData, Span<ulong> results)
{ {
var lease = GpuKernelPool.GetKernel(useGpuOrder: true); var lease = GpuKernelPool.GetKernel(useGpuOrder: true);
var execution = lease.EnterExecutionScope();
Accelerator accelerator = lease.Accelerator; Accelerator accelerator = lease.Accelerator;
AcceleratorStream stream = lease.Stream; AcceleratorStream stream = lease.Stream;
var kernel = GetPow2ModKernel(accelerator); var kernel = GetPow2ModKernel(accelerator);
@@ -551,7 +546,6 @@ internal static partial class PrimeOrderGpuHeuristics
Console.WriteLine($"Exception for {prime} and exponents: {string.Join(",", exponents.ToArray())}."); Console.WriteLine($"Exception for {prime} and exponents: {string.Join(",", exponents.ToArray())}.");
exponentBuffer.Dispose(); exponentBuffer.Dispose();
remainderBuffer.Dispose(); remainderBuffer.Dispose();
execution.Dispose();
lease.Dispose(); lease.Dispose();
throw; throw;
} }
@@ -559,7 +553,6 @@ internal static partial class PrimeOrderGpuHeuristics
remainderBuffer.View.CopyToCPU(ref MemoryMarshal.GetReference(results), exponents.Length); remainderBuffer.View.CopyToCPU(ref MemoryMarshal.GetReference(results), exponents.Length);
exponentBuffer.Dispose(); exponentBuffer.Dispose();
remainderBuffer.Dispose(); remainderBuffer.Dispose();
execution.Dispose();
lease.Dispose(); lease.Dispose();
return true; return true;
} }
@@ -587,7 +580,6 @@ internal static partial class PrimeOrderGpuHeuristics
try try
{ {
var execution = lease.EnterExecutionScope();
Accelerator accelerator = lease.Accelerator; Accelerator accelerator = lease.Accelerator;
AcceleratorStream stream = lease.Stream; AcceleratorStream stream = lease.Stream;
var kernel = GetPow2ModWideKernel(accelerator); var kernel = GetPow2ModWideKernel(accelerator);
@@ -628,7 +620,6 @@ internal static partial class PrimeOrderGpuHeuristics
exponentBuffer.Dispose(); exponentBuffer.Dispose();
remainderBuffer.Dispose(); remainderBuffer.Dispose();
execution.Dispose();
return true; return true;
} }
catch (Exception) catch (Exception)
@@ -147,7 +147,6 @@ public sealed class MersenneNumberTester(
UInt128[] qs = qsBuffer; UInt128[] qs = qsBuffer;
var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder); var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder);
var execution = gpuLease.EnterExecutionScope();
var accelerator = gpuLease.Accelerator; var accelerator = gpuLease.Accelerator;
var stream = gpuLease.Stream; var stream = gpuLease.Stream;
var orderKernel = gpuLease.OrderKernel!; var orderKernel = gpuLease.OrderKernel!;
@@ -194,7 +193,6 @@ public sealed class MersenneNumberTester(
qBuffer.Dispose(); qBuffer.Dispose();
} }
execution.Dispose();
gpuLease.Dispose(); gpuLease.Dispose();
ArrayPool<UInt128>.Shared.Return(qs); ArrayPool<UInt128>.Shared.Return(qs);
} }
@@ -22,7 +22,6 @@ internal static partial class PrimeOrderCalculator
remaining = value; remaining = value;
var lease = GpuKernelPool.GetKernel(useGpuOrder: true); var lease = GpuKernelPool.GetKernel(useGpuOrder: true);
var execution = lease.EnterExecutionScope();
Accelerator accelerator = lease.Accelerator; Accelerator accelerator = lease.Accelerator;
AcceleratorStream stream = lease.Stream; AcceleratorStream stream = lease.Stream;
@@ -64,7 +63,6 @@ internal static partial class PrimeOrderCalculator
counts.Add(primeValue, exponent); counts.Add(primeValue, exponent);
} }
execution.Dispose();
lease.Dispose(); lease.Dispose();
ThreadStaticPools.UlongPool.Return(primeBufferArray); ThreadStaticPools.UlongPool.Return(primeBufferArray);
ThreadStaticPools.IntPool.Return(exponentBufferArray); ThreadStaticPools.IntPool.Return(exponentBufferArray);
@@ -417,7 +417,6 @@ public static partial class ULongExtensions
ulong result = 0UL; ulong result = 0UL;
GpuKernelLease lease = GpuKernelPool.GetKernel(useGpuOrder: true); GpuKernelLease lease = GpuKernelPool.GetKernel(useGpuOrder: true);
var execution = lease.EnterExecutionScope();
Accelerator accelerator = lease.Accelerator; Accelerator accelerator = lease.Accelerator;
// Keep this commented out. It should never happen in production code. // Keep this commented out. It should never happen in production code.
@@ -444,7 +443,6 @@ public static partial class ULongExtensions
resultBuffer.Dispose(); resultBuffer.Dispose();
exponentBuffer.Dispose(); exponentBuffer.Dispose();
execution.Dispose();
lease.Dispose(); lease.Dispose();
// Keep this commented. We don't want to catch any exceptions. All should crash the scanner. // Keep this commented. We don't want to catch any exceptions. All should crash the scanner.
// catch (AcceleratorException) // catch (AcceleratorException)