SemaphoreSlim replaced with PollingSemaphore.
This commit is contained in:
1 parent
471f9ac6cf
commit
15bcde1776
4 files changed
+57
-51
No files matched your search
@@ -6,10 +6,10 @@ namespace PerfectNumbers.Core.Gpu.Accelerators;
|
||||
public static class AcceleratorStreamPool
|
||||
{
|
||||
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||
private static readonly SemaphoreSlim[] _locks = new SemaphoreSlim[PerfectNumberConstants.RollingAccelerators];
|
||||
private static readonly PollingSemaphore[] _locks = new PollingSemaphore[PerfectNumberConstants.RollingAccelerators];
|
||||
private static readonly ConcurrentFixedCapacityStack<AcceleratorStream>[] _streams = new ConcurrentFixedCapacityStack<AcceleratorStream>[PerfectNumberConstants.RollingAccelerators];
|
||||
|
||||
private static SemaphoreSlim CreateLock() => new(PerfectNumberConstants.ThreadsByAccelerator);
|
||||
private static PollingSemaphore CreateLock() => new(PerfectNumberConstants.ThreadsByAccelerator, TimeSpan.FromMilliseconds(1000), 1);
|
||||
|
||||
|
||||
// private static int _rented;
|
||||
|
||||
@@ -1,58 +1,59 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace PerfectNumbers.Core.Gpu;
|
||||
|
||||
public static class GpuWorkLimiter
|
||||
{
|
||||
private static SemaphoreSlim _semaphore = new(1, int.MaxValue);
|
||||
private static readonly object _lock = new();
|
||||
private static int _currentLimit = 1;
|
||||
private static readonly TimeSpan _pauseBetweenChecks = TimeSpan.FromSeconds(30);
|
||||
private static PollingSemaphore _semaphore = new(int.MaxValue, _pauseBetweenChecks, 1);
|
||||
private static readonly object _lock = new();
|
||||
private static int _currentLimit = 1;
|
||||
|
||||
public static Lease Acquire()
|
||||
{
|
||||
// TODO: Replace the per-call Lease allocation with the pooled struct-based guard from the
|
||||
// GpuLimiterThroughputBenchmarks so limiter acquisition does not allocate when we enter the
|
||||
// GPU scanning hot path.
|
||||
var sem = _semaphore;
|
||||
sem.Wait();
|
||||
return new Lease(sem);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static Lease Acquire()
|
||||
{
|
||||
// TODO: Replace the per-call Lease allocation with the pooled struct-based guard from the
|
||||
// GpuLimiterThroughputBenchmarks so limiter acquisition does not allocate when we enter the
|
||||
// GPU scanning hot path.
|
||||
var sem = _semaphore;
|
||||
sem.Wait();
|
||||
return new Lease(sem);
|
||||
}
|
||||
|
||||
public static void SetLimit(int value)
|
||||
{
|
||||
if (value < 1)
|
||||
{
|
||||
value = 1;
|
||||
}
|
||||
public static void SetLimit(int value)
|
||||
{
|
||||
if (value < 1)
|
||||
{
|
||||
value = 1;
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (value == _currentLimit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (_lock)
|
||||
{
|
||||
if (value == _currentLimit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Swap to a new semaphore for the new limit. We intentionally
|
||||
// do not dispose the old semaphore to avoid releasing handles
|
||||
// that may still be in use by existing Lease instances.
|
||||
// TODO: Consolidate with GpuPrimeWorkLimiter so both limiters share a pooled SemaphoreSlim and avoid rebuilding the
|
||||
// limiter state whenever limits are adjusted from the CLI.
|
||||
_semaphore = new SemaphoreSlim(value, value);
|
||||
_currentLimit = value;
|
||||
}
|
||||
}
|
||||
// Swap to a new semaphore for the new limit. We intentionally
|
||||
// do not dispose the old semaphore to avoid releasing handles
|
||||
// that may still be in use by existing Lease instances.
|
||||
// TODO: Consolidate with GpuPrimeWorkLimiter so both limiters share a pooled SemaphoreSlim and avoid rebuilding the
|
||||
// limiter state whenever limits are adjusted from the CLI.
|
||||
_semaphore = new PollingSemaphore(value, _pauseBetweenChecks, 1);
|
||||
_currentLimit = value;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Lease
|
||||
{
|
||||
private readonly SemaphoreSlim _sem;
|
||||
[method: MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public readonly struct Lease(PollingSemaphore sem)
|
||||
{
|
||||
private readonly PollingSemaphore _sem = sem;
|
||||
|
||||
internal Lease(SemaphoreSlim sem)
|
||||
{
|
||||
_sem = sem;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_sem.Release();
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public void Dispose()
|
||||
{
|
||||
_sem.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user