diff --git a/PerfectNumbers.Core/Gpu/GpuContextPool.cs b/PerfectNumbers.Core/Gpu/GpuContextPool.cs index c71f7d9..5e9f0a5 100644 --- a/PerfectNumbers.Core/Gpu/GpuContextPool.cs +++ b/PerfectNumbers.Core/Gpu/GpuContextPool.cs @@ -12,13 +12,17 @@ public static class GpuContextPool // Default device preference for generic GPU kernels (prime scans, NTT, etc.) internal sealed class PooledContext { - public Context Context { get; } - public Accelerator Accelerator { get; } + public readonly Context Context; + public readonly Accelerator Accelerator; + + private static readonly Context _sharedContext = Context.CreateDefault(); + private static readonly Device _sharedDevice = _sharedContext.GetPreferredDevice(false); + private static readonly Accelerator _sharedAccelerator = _sharedDevice.CreateAccelerator(_sharedContext); public PooledContext() { - Context = Context.CreateDefault(); - Accelerator = Context.GetPreferredDevice(false).CreateAccelerator(Context); + Context = _sharedContext; + Accelerator = _sharedAccelerator; // NOTE: Avoid loading/compiling any kernel here to prevent implicit // CL stream/queue creation during accelerator construction. // Some OpenCL drivers are fragile when a queue is created immediately @@ -34,8 +38,9 @@ public static class GpuContextPool // after the accelerator is destroyed. PrimeTester.ClearGpuCaches(Accelerator); - Accelerator.Dispose(); - Context.Dispose(); + // These resources are shared between GPU leases + // Accelerator.Dispose(); + // Context.Dispose(); } } @@ -62,15 +67,15 @@ public static class GpuContextPool } int toCreate = threadCount - WarmedGpuContextCount; + Console.WriteLine($"Warming up GPU context pool to {toCreate} contexts..."); var contexts = new PooledContext[toCreate]; + var pool = GpuPool; + PooledContext context; for (int i = 0; i < toCreate; i++) { - contexts[i] = new PooledContext(); - } - - for (int i = 0; i < toCreate; i++) - { - GpuPool.Enqueue(contexts[i]); + context = new PooledContext(); + contexts[i] = context; + pool.Enqueue(context); } WarmedGpuContextCount = threadCount; diff --git a/PerfectNumbers.Core/PrimeTester.cs b/PerfectNumbers.Core/PrimeTester.cs index 9a8fc90..36187f9 100644 --- a/PerfectNumbers.Core/PrimeTester.cs +++ b/PerfectNumbers.Core/PrimeTester.cs @@ -99,7 +99,7 @@ public sealed class PrimeTester // if (belowGpuRange) // { - return IsPrime(n); + return IsPrime(n); // } // var limiter = GpuPrimeWorkLimiter.Acquire(); @@ -378,12 +378,16 @@ public sealed class PrimeTester public HeuristicGpuDivisorTables HeuristicGpuTables => _heuristicDivisorTables; + private static readonly Context _sharedContext = Context.CreateDefault(); + private static readonly Device _sharedDevice = _sharedContext.GetPreferredDevice(false); + private static readonly Accelerator _sharedAccelerator = _sharedDevice.CreateAccelerator(_sharedContext); + internal PrimeTesterGpuContextLease(int minBufferCapacity) { - AcceleratorContext = Context.CreateDefault(); - Accelerator = AcceleratorContext.GetPreferredDevice(false).CreateAccelerator(AcceleratorContext); + AcceleratorContext = _sharedContext;// Context.CreateDefault(); + Accelerator = _sharedAccelerator; //AcceleratorContext.GetPreferredDevice(false).CreateAccelerator(AcceleratorContext); Kernel = Accelerator.LoadAutoGroupedStreamKernel, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView>(PrimeTesterKernels.SmallPrimeSieveKernel); - HeuristicTrialDivisionKernel = Accelerator.LoadAutoGroupedStreamKernel, ulong, ulong, HeuristicGpuDivisorTableKind, HeuristicGpuDivisorTables>(PrimeTesterKernels.HeuristicTrialDivisionKernel); + HeuristicTrialDivisionKernel = Accelerator.LoadAutoGroupedStreamKernel, ulong, ulong, HeuristicGpuDivisorTableKind, HeuristicGpuDivisorTables>(PrimeTesterKernels.HeuristicTrialDivisionKernel); _sharedTables = RentSharedTables(Accelerator); @@ -439,7 +443,7 @@ public sealed class PrimeTester } _returned = true; - PrimeTesterGpuContextPool.Return(this); + Return(this); } internal void DisposeResources() @@ -448,8 +452,9 @@ public sealed class PrimeTester Output?.Dispose(); HeuristicFlag?.Dispose(); ReleaseSharedTables(_sharedTables); - Accelerator.Dispose(); - AcceleratorContext.Dispose(); + // These resources are shared between GPU leases + // Accelerator.Dispose(); + // AcceleratorContext.Dispose(); } }