Use GpuPrimeWorkLimiter for GPU lease limiting
This commit is contained in:
1 parent
00d4e9bde2
commit
1cbe7bf869
5 files changed
+16
-67
No files matched your search
@@ -61,7 +61,7 @@ internal static class Program
|
|||||||
int gpuPrimeThreads = Math.Max(1, _cliArguments.GpuPrimeThreads);
|
int gpuPrimeThreads = Math.Max(1, _cliArguments.GpuPrimeThreads);
|
||||||
UnboundedTaskScheduler.ConfigureThreadCount(threadCount);
|
UnboundedTaskScheduler.ConfigureThreadCount(threadCount);
|
||||||
PrimeTester.GpuBatchSize = gpuPrimeBatch;
|
PrimeTester.GpuBatchSize = gpuPrimeBatch;
|
||||||
GpuPrimeLeaseLimiter.Initialize(gpuPrimeThreads);
|
GpuPrimeWorkLimiter.SetLimit(gpuPrimeThreads);
|
||||||
GpuContextPool.WarmUpPool(threadCount);
|
GpuContextPool.WarmUpPool(threadCount);
|
||||||
PrimeTester.WarmUpGpuKernels(gpuPrimeThreads);
|
PrimeTester.WarmUpGpuKernels(gpuPrimeThreads);
|
||||||
Console.WriteLine("Starting up threads...");
|
Console.WriteLine("Starting up threads...");
|
||||||
@@ -118,9 +118,6 @@ internal static class Program
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply GPU prime sieve runtime configuration
|
|
||||||
GpuPrimeWorkLimiter.SetLimit(gpuPrimeThreads);
|
|
||||||
PrimeTester.GpuBatchSize = gpuPrimeBatch;
|
|
||||||
|
|
||||||
MersenneDivisorCycles mersenneDivisorCycles = new();
|
MersenneDivisorCycles mersenneDivisorCycles = new();
|
||||||
if (!File.Exists(cyclesPath) || continueCyclesGeneration)
|
if (!File.Exists(cyclesPath) || continueCyclesGeneration)
|
||||||
|
|||||||
@@ -49,10 +49,6 @@ public static class GpuContextPool
|
|||||||
|
|
||||||
// Allows callers to choose CPU/GPU per use-case, decoupled from ForceCpu.
|
// 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))
|
||||||
{
|
{
|
||||||
@@ -62,12 +58,7 @@ public static class GpuContextPool
|
|||||||
// Create a new accelerator when the pool does not have one available.
|
// Create a new accelerator when the pool does not have one available.
|
||||||
return new GpuContextLease(new PooledContext());
|
return new GpuContextLease(new PooledContext());
|
||||||
}
|
}
|
||||||
catch
|
|
||||||
{
|
|
||||||
GpuPrimeLeaseLimiter.Exit();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void WarmUpPool(int threadCount)
|
public static void WarmUpPool(int threadCount)
|
||||||
{
|
{
|
||||||
@@ -106,7 +97,6 @@ public static class GpuContextPool
|
|||||||
{
|
{
|
||||||
ctx.Accelerator.Synchronize();
|
ctx.Accelerator.Synchronize();
|
||||||
GpuPool.Enqueue(ctx);
|
GpuPool.Enqueue(ctx);
|
||||||
GpuPrimeLeaseLimiter.Exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct GpuContextLease
|
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;
|
namespace PerfectNumbers.Core.Gpu;
|
||||||
|
|
||||||
public static class GpuPrimeWorkLimiter
|
public static class GpuPrimeWorkLimiter
|
||||||
@@ -10,12 +13,17 @@ public static class GpuPrimeWorkLimiter
|
|||||||
// TODO: Inline the pooled limiter guard from the GpuLimiterThroughputBenchmarks so prime-sieve
|
// TODO: Inline the pooled limiter guard from the GpuLimiterThroughputBenchmarks so prime-sieve
|
||||||
// GPU jobs stop allocating Lease instances on every acquisition.
|
// GPU jobs stop allocating Lease instances on every acquisition.
|
||||||
var sem = _semaphore;
|
var sem = _semaphore;
|
||||||
// sem.Wait();
|
sem.Wait();
|
||||||
return new Lease(sem);
|
return new Lease(sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetLimit(int value)
|
public static void SetLimit(int value)
|
||||||
{
|
{
|
||||||
|
if (value <= 0)
|
||||||
|
{
|
||||||
|
value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (value == _currentLimit)
|
if (value == _currentLimit)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -23,11 +31,13 @@ public static class GpuPrimeWorkLimiter
|
|||||||
|
|
||||||
// TODO: Switch to a shared limiter implementation with GpuWorkLimiter so we can coordinate CPU/GPU prime work using
|
// 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.
|
// the same semaphore pool without reallocating per adjustment.
|
||||||
|
var previous = _semaphore;
|
||||||
_semaphore = new SemaphoreSlim(value, value);
|
_semaphore = new SemaphoreSlim(value, value);
|
||||||
_currentLimit = value;
|
_currentLimit = value;
|
||||||
|
previous.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class Lease
|
public sealed class Lease : IDisposable
|
||||||
{
|
{
|
||||||
private readonly SemaphoreSlim _sem;
|
private readonly SemaphoreSlim _sem;
|
||||||
|
|
||||||
@@ -38,8 +48,7 @@ public static class GpuPrimeWorkLimiter
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
// _sem.Release();
|
_sem.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,10 +283,6 @@ public sealed class PrimeTester
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal static PrimeTesterGpuContextLease Rent(int minBufferCapacity = 1)
|
internal static PrimeTesterGpuContextLease Rent(int minBufferCapacity = 1)
|
||||||
{
|
|
||||||
GpuPrimeLeaseLimiter.Enter();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (!Pool.TryDequeue(out var lease))
|
if (!Pool.TryDequeue(out var lease))
|
||||||
{
|
{
|
||||||
@@ -300,18 +296,12 @@ public sealed class PrimeTester
|
|||||||
lease.ResetReturnFlag();
|
lease.ResetReturnFlag();
|
||||||
return lease;
|
return lease;
|
||||||
}
|
}
|
||||||
catch
|
|
||||||
{
|
|
||||||
GpuPrimeLeaseLimiter.Exit();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void Return(PrimeTesterGpuContextLease lease)
|
internal static void Return(PrimeTesterGpuContextLease lease)
|
||||||
{
|
{
|
||||||
lease.Accelerator.Synchronize();
|
lease.Accelerator.Synchronize();
|
||||||
Pool.Enqueue(lease);
|
Pool.Enqueue(lease);
|
||||||
GpuPrimeLeaseLimiter.Exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void DisposeAll()
|
internal static void DisposeAll()
|
||||||
|
|||||||
Reference in new issue
Block a user