Use GpuPrimeWorkLimiter for GPU lease limiting
This commit is contained in:
1 parent
00d4e9bde2
commit
1cbe7bf869
5 files changed
+42
-93
No files matched your search
@@ -48,27 +48,18 @@ public static class GpuContextPool
|
||||
private static int WarmedGpuContextCount;
|
||||
|
||||
// Allows callers to choose CPU/GPU per use-case, decoupled from ForceCpu.
|
||||
public static GpuContextLease Rent()
|
||||
public static GpuContextLease Rent()
|
||||
{
|
||||
GpuPrimeLeaseLimiter.Enter();
|
||||
|
||||
try
|
||||
if (GpuPool.TryDequeue(out var gpu))
|
||||
{
|
||||
if (GpuPool.TryDequeue(out var gpu))
|
||||
{
|
||||
return new GpuContextLease(gpu);
|
||||
}
|
||||
return new GpuContextLease(gpu);
|
||||
}
|
||||
|
||||
// Create a new accelerator when the pool does not have one available.
|
||||
return new GpuContextLease(new PooledContext());
|
||||
}
|
||||
catch
|
||||
{
|
||||
GpuPrimeLeaseLimiter.Exit();
|
||||
throw;
|
||||
}
|
||||
// Create a new accelerator when the pool does not have one available.
|
||||
return new GpuContextLease(new PooledContext());
|
||||
}
|
||||
|
||||
|
||||
public static void WarmUpPool(int threadCount)
|
||||
{
|
||||
if (threadCount <= WarmedGpuContextCount)
|
||||
@@ -106,7 +97,6 @@ public static class GpuContextPool
|
||||
{
|
||||
ctx.Accelerator.Synchronize();
|
||||
GpuPool.Enqueue(ctx);
|
||||
GpuPrimeLeaseLimiter.Exit();
|
||||
}
|
||||
|
||||
public struct GpuContextLease
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
using System.Threading;
|
||||
|
||||
namespace PerfectNumbers.Core.Gpu;
|
||||
|
||||
public static class GpuPrimeLeaseLimiter
|
||||
{
|
||||
private static SemaphoreSlim _semaphore = new(int.MaxValue, int.MaxValue);
|
||||
private static int _currentLimit = int.MaxValue;
|
||||
|
||||
public static void Initialize(int limit)
|
||||
{
|
||||
if (limit <= 0)
|
||||
{
|
||||
limit = 1;
|
||||
}
|
||||
|
||||
if (limit == _currentLimit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var previous = _semaphore;
|
||||
_semaphore = new SemaphoreSlim(limit, limit);
|
||||
_currentLimit = limit;
|
||||
previous.Dispose();
|
||||
}
|
||||
|
||||
public static void Enter()
|
||||
{
|
||||
_semaphore.Wait();
|
||||
}
|
||||
|
||||
public static void Exit()
|
||||
{
|
||||
_semaphore.Release();
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace PerfectNumbers.Core.Gpu;
|
||||
|
||||
public static class GpuPrimeWorkLimiter
|
||||
@@ -10,24 +13,31 @@ public static class GpuPrimeWorkLimiter
|
||||
// TODO: Inline the pooled limiter guard from the GpuLimiterThroughputBenchmarks so prime-sieve
|
||||
// GPU jobs stop allocating Lease instances on every acquisition.
|
||||
var sem = _semaphore;
|
||||
// sem.Wait();
|
||||
sem.Wait();
|
||||
return new Lease(sem);
|
||||
}
|
||||
|
||||
public static void SetLimit(int value)
|
||||
{
|
||||
if (value == _currentLimit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (value <= 0)
|
||||
{
|
||||
value = 1;
|
||||
}
|
||||
|
||||
// TODO: Switch to a shared limiter implementation with GpuWorkLimiter so we can coordinate CPU/GPU prime work using
|
||||
// the same semaphore pool without reallocating per adjustment.
|
||||
_semaphore = new SemaphoreSlim(value, value);
|
||||
_currentLimit = value;
|
||||
if (value == _currentLimit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Switch to a shared limiter implementation with GpuWorkLimiter so we can coordinate CPU/GPU prime work using
|
||||
// the same semaphore pool without reallocating per adjustment.
|
||||
var previous = _semaphore;
|
||||
_semaphore = new SemaphoreSlim(value, value);
|
||||
_currentLimit = value;
|
||||
previous.Dispose();
|
||||
}
|
||||
|
||||
public sealed class Lease
|
||||
public sealed class Lease : IDisposable
|
||||
{
|
||||
private readonly SemaphoreSlim _sem;
|
||||
|
||||
@@ -38,8 +48,7 @@ public static class GpuPrimeWorkLimiter
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// _sem.Release();
|
||||
_sem.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,36 +282,26 @@ public sealed class PrimeTester
|
||||
}
|
||||
}
|
||||
|
||||
internal static PrimeTesterGpuContextLease Rent(int minBufferCapacity = 1)
|
||||
{
|
||||
GpuPrimeLeaseLimiter.Enter();
|
||||
internal static PrimeTesterGpuContextLease Rent(int minBufferCapacity = 1)
|
||||
{
|
||||
if (!Pool.TryDequeue(out var lease))
|
||||
{
|
||||
lease = new PrimeTesterGpuContextLease(minBufferCapacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
lease.EnsureCapacity(minBufferCapacity);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!Pool.TryDequeue(out var lease))
|
||||
{
|
||||
lease = new PrimeTesterGpuContextLease(minBufferCapacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
lease.EnsureCapacity(minBufferCapacity);
|
||||
}
|
||||
lease.ResetReturnFlag();
|
||||
return lease;
|
||||
}
|
||||
|
||||
lease.ResetReturnFlag();
|
||||
return lease;
|
||||
}
|
||||
catch
|
||||
{
|
||||
GpuPrimeLeaseLimiter.Exit();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Return(PrimeTesterGpuContextLease lease)
|
||||
{
|
||||
lease.Accelerator.Synchronize();
|
||||
Pool.Enqueue(lease);
|
||||
GpuPrimeLeaseLimiter.Exit();
|
||||
}
|
||||
|
||||
internal static void DisposeAll()
|
||||
|
||||
Reference in new issue
Block a user