Scope GPU prime tester buffers to leases

This commit is contained in:
Marek Lemańczyk committed 2025-10-29 17:05:17 +01:00
1 parent ca53ddc798
commit 83a6c6c558
1 file changed
+27 -51
+27 -51
View File
@@ -1,3 +1,4 @@
using System;
using System.Buffers; using System.Buffers;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Numerics; using System.Numerics;
@@ -217,8 +218,6 @@ public sealed class PrimeTester
private static readonly ConcurrentQueue<PooledContext> Pool = new(); private static readonly ConcurrentQueue<PooledContext> Pool = new();
private static readonly ConcurrentQueue<(Accelerator Accelerator, MemoryBuffer1D<ulong, Stride1D.Dense> Input, MemoryBuffer1D<byte, Stride1D.Dense> Output, int Capacity)> BufferPool = new();
internal static PrimeTesterGpuContextLease Rent(int minBufferCapacity = 0) internal static PrimeTesterGpuContextLease Rent(int minBufferCapacity = 0)
{ {
if (Pool.TryDequeue(out var ctx)) if (Pool.TryDequeue(out var ctx))
@@ -235,47 +234,6 @@ public sealed class PrimeTester
{ {
ctx.Dispose(); ctx.Dispose();
} }
while (BufferPool.TryDequeue(out var entry))
{
entry.Output.Dispose();
entry.Input.Dispose();
}
}
private static void AcquireBuffers(Accelerator accelerator, int minCapacity, out MemoryBuffer1D<ulong, Stride1D.Dense> input, out MemoryBuffer1D<byte, Stride1D.Dense> output, out int capacity)
{
int required = Math.Max(1, minCapacity);
while (BufferPool.TryDequeue(out var entry))
{
if (entry.Accelerator != accelerator)
{
entry.Output.Dispose();
entry.Input.Dispose();
continue;
}
if (entry.Capacity >= required)
{
input = entry.Input;
output = entry.Output;
capacity = entry.Capacity;
return;
}
entry.Output.Dispose();
entry.Input.Dispose();
}
capacity = required;
input = accelerator.Allocate1D<ulong>(capacity);
output = accelerator.Allocate1D<byte>(capacity);
}
private static void ReturnBuffers(Accelerator accelerator, MemoryBuffer1D<ulong, Stride1D.Dense> input, MemoryBuffer1D<byte, Stride1D.Dense> output, int capacity)
{
BufferPool.Enqueue((accelerator, input, output, capacity));
} }
private static void Return(PooledContext ctx) private static void Return(PooledContext ctx)
@@ -284,31 +242,49 @@ public sealed class PrimeTester
Pool.Enqueue(ctx); Pool.Enqueue(ctx);
} }
internal readonly struct PrimeTesterGpuContextLease internal sealed class PrimeTesterGpuContextLease : IDisposable
{ {
private readonly PooledContext _ctx; private readonly PooledContext _ctx;
public readonly Accelerator Accelerator; public Accelerator Accelerator { get; }
public readonly KernelState State; public KernelState State { get; }
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> Input; public MemoryBuffer1D<ulong, Stride1D.Dense> Input { get; private set; }
public readonly MemoryBuffer1D<byte, Stride1D.Dense> Output; public MemoryBuffer1D<byte, Stride1D.Dense> Output { get; private set; }
public readonly int BufferCapacity; public int BufferCapacity { get; private set; }
internal PrimeTesterGpuContextLease(PooledContext ctx, int minBufferCapacity) internal PrimeTesterGpuContextLease(PooledContext ctx, int minBufferCapacity)
{ {
_ctx = ctx; _ctx = ctx;
Accelerator = ctx.Accelerator; Accelerator = ctx.Accelerator;
State = ctx.KernelState; State = ctx.KernelState;
AcquireBuffers(Accelerator, minBufferCapacity, out Input, out Output, out BufferCapacity); BufferCapacity = Math.Max(1, minBufferCapacity);
Input = Accelerator.Allocate1D<ulong>(BufferCapacity);
Output = Accelerator.Allocate1D<byte>(BufferCapacity);
}
public void EnsureCapacity(int minCapacity)
{
if (minCapacity <= BufferCapacity)
{
return;
}
Input.Dispose();
Output.Dispose();
BufferCapacity = Math.Max(1, minCapacity);
Input = Accelerator.Allocate1D<ulong>(BufferCapacity);
Output = Accelerator.Allocate1D<byte>(BufferCapacity);
} }
public void Dispose() public void Dispose()
{ {
ReturnBuffers(Accelerator, Input, Output, BufferCapacity); Input.Dispose();
Output.Dispose();
Return(_ctx); Return(_ctx);
} }
} }