Avoid using declarations for GPU resources

This commit is contained in:
Marek Lemańczyk committed 2025-09-10 00:19:48 +02:00
1 parent 2be49020a9
commit 117ea94b50
9 files changed
+105 -44

No files matched your search

+5 -2
View File
@@ -542,9 +542,12 @@ public class GpuKernelPool
/// <param name="action">Action to run with (Accelerator, Stream).</param> /// <param name="action">Action to run with (Accelerator, Stream).</param>
public static void Run(Action<Accelerator, AcceleratorStream> action) public static void Run(Action<Accelerator, AcceleratorStream> action)
{ {
using var lease = GetKernel(useGpuOrder: true); var lease = GetKernel(useGpuOrder: true);
var accelerator = lease.Accelerator; var accelerator = lease.Accelerator;
using var stream = accelerator.CreateStream(); var stream = accelerator.CreateStream();
action(accelerator, stream); action(accelerator, stream);
stream.Dispose();
lease.Dispose();
} }
} }
@@ -11,7 +11,7 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
public void Scan(ulong exponent, UInt128 twoP, bool lastIsSeven, UInt128 maxK, ref bool isPrime) public void Scan(ulong exponent, UInt128 twoP, bool lastIsSeven, UInt128 maxK, ref bool isPrime)
{ {
using var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder); var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder);
var accelerator = gpuLease.Accelerator; var accelerator = gpuLease.Accelerator;
int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy
UInt128 kStart = 1UL; UInt128 kStart = 1UL;
@@ -22,7 +22,7 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
? gpuLease.Pow2ModKernel ? gpuLease.Pow2ModKernel
: gpuLease.IncrementalKernel; : gpuLease.IncrementalKernel;
using var orderBuffer = accelerator.Allocate1D<ulong>(batchSize); var orderBuffer = accelerator.Allocate1D<ulong>(batchSize);
// Avoid giant stack allocations that can trigger StackOverflow when batchSize is large. // Avoid giant stack allocations that can trigger StackOverflow when batchSize is large.
// Rent a reusable array from the shared pool instead. // Rent a reusable array from the shared pool instead.
ulong[] orderArray = ArrayPool<ulong>.Shared.Rent(batchSize); ulong[] orderArray = ArrayPool<ulong>.Shared.Rent(batchSize);
@@ -73,5 +73,9 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
{ {
ArrayPool<ulong>.Shared.Return(orderArray); ArrayPool<ulong>.Shared.Return(orderArray);
} }
orderBuffer.Dispose();
gpuLease.Dispose();
} }
} }
@@ -55,30 +55,39 @@ public class MersenneNumberLucasLehmerGpuTester
return false; return false;
} }
using var limiter = GpuPrimeWorkLimiter.Acquire(); var limiter = GpuPrimeWorkLimiter.Acquire();
bool result;
if (exponent >= 128UL) if (exponent >= 128UL)
{ {
if (!TryGetNttParameters(exponent, out var nttMod, out var primitiveRoot)) if (!TryGetNttParameters(exponent, out var nttMod, out var primitiveRoot))
{ {
limiter.Dispose();
throw new NotSupportedException("NTT parameters for the given exponent are not available."); throw new NotSupportedException("NTT parameters for the given exponent are not available.");
} }
return IsMersennePrimeNtt(exponent, nttMod, primitiveRoot, runOnGpu); result = IsMersennePrimeNtt(exponent, nttMod, primitiveRoot, runOnGpu);
} }
else
using var gpu = GpuContextPool.RentPreferred(preferCpu: !runOnGpu); {
var gpu = GpuContextPool.RentPreferred(preferCpu: !runOnGpu);
var accelerator = gpu.Accelerator; var accelerator = gpu.Accelerator;
var kernel = GetKernel(accelerator); var kernel = GetKernel(accelerator);
var modulus = new GpuUInt128(((UInt128)1 << (int)exponent) - 1UL); var modulus = new GpuUInt128(((UInt128)1 << (int)exponent) - 1UL);
using var buffer = accelerator.Allocate1D<GpuUInt128>(1); var buffer = accelerator.Allocate1D<GpuUInt128>(1);
kernel(1, exponent, modulus, buffer.View); kernel(1, exponent, modulus, buffer.View);
accelerator.Synchronize(); accelerator.Synchronize();
return buffer.GetAsArray1D()[0].IsZero; result = buffer.GetAsArray1D()[0].IsZero;
buffer.Dispose();
gpu.Dispose();
}
limiter.Dispose();
return result;
} }
private bool IsMersennePrimeNtt(ulong exponent, GpuUInt128 nttMod, GpuUInt128 primitiveRoot, bool runOnGpu) private bool IsMersennePrimeNtt(ulong exponent, GpuUInt128 nttMod, GpuUInt128 primitiveRoot, bool runOnGpu)
{ {
using var gpu = GpuContextPool.RentPreferred(preferCpu: !runOnGpu); var gpu = GpuContextPool.RentPreferred(preferCpu: !runOnGpu);
var accelerator = gpu.Accelerator; var accelerator = gpu.Accelerator;
var addKernel = GetAddSmallKernel(accelerator); var addKernel = GetAddSmallKernel(accelerator);
var subKernel = GetSubSmallKernel(accelerator); var subKernel = GetSubSmallKernel(accelerator);
@@ -92,7 +101,7 @@ public class MersenneNumberLucasLehmerGpuTester
{ {
transformLength <<= 1; transformLength <<= 1;
} }
using var stateBuffer = accelerator.Allocate1D<GpuUInt128>(transformLength); var stateBuffer = accelerator.Allocate1D<GpuUInt128>(transformLength);
stateBuffer.MemSetToZero(); stateBuffer.MemSetToZero();
addKernel(1, 4UL, stateBuffer.View); addKernel(1, 4UL, stateBuffer.View);
@@ -121,12 +130,16 @@ public class MersenneNumberLucasLehmerGpuTester
reduceKernel(1, exponent, stateBuffer.View); reduceKernel(1, exponent, stateBuffer.View);
using var resultBuffer = accelerator.Allocate1D<byte>(1); var resultBuffer = accelerator.Allocate1D<byte>(1);
zeroKernel(1, stateBuffer.View, resultBuffer.View); zeroKernel(1, stateBuffer.View, resultBuffer.View);
accelerator.Synchronize(); accelerator.Synchronize();
byte[] result = new byte[1]; byte[] result = new byte[1];
resultBuffer.View.CopyToCPU(result); resultBuffer.View.CopyToCPU(result);
return result[0] != 0; bool isPrime = result[0] != 0;
resultBuffer.Dispose();
stateBuffer.Dispose();
gpu.Dispose();
return isPrime;
} }
private static readonly ConcurrentDictionary<int, (GpuUInt128 Modulus, GpuUInt128 PrimitiveRoot)> NttParameterCache = new() private static readonly ConcurrentDictionary<int, (GpuUInt128 Modulus, GpuUInt128 PrimitiveRoot)> NttParameterCache = new()
@@ -9,7 +9,7 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
public void Scan(ulong exponent, UInt128 twoP, bool lastIsSeven, UInt128 maxK, ref bool isPrime) public void Scan(ulong exponent, UInt128 twoP, bool lastIsSeven, UInt128 maxK, ref bool isPrime)
{ {
using var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder); var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder);
var accelerator = gpuLease.Accelerator; var accelerator = gpuLease.Accelerator;
int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy and avoids TDR int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy and avoids TDR
UInt128 kStart = UInt128.One; UInt128 kStart = UInt128.One;
@@ -22,7 +22,7 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
_ => gpuLease.IncrementalOrderKernel, _ => gpuLease.IncrementalOrderKernel,
}; };
using var foundBuffer = accelerator.Allocate1D<int>(1); var foundBuffer = accelerator.Allocate1D<int>(1);
UInt128 remaining; UInt128 remaining;
int currentSize; int currentSize;
int found = 0; int found = 0;
@@ -59,5 +59,9 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
kStart += (UInt128)currentSize; kStart += (UInt128)currentSize;
} }
foundBuffer.Dispose();
gpuLease.Dispose();
} }
} }
@@ -14,7 +14,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
// GPU residue variant: check 2^p % q == 1 for q = 2*p*k + 1. // GPU residue variant: check 2^p % q == 1 for q = 2*p*k + 1.
public void Scan(ulong exponent, UInt128 twoP, bool lastIsSeven, UInt128 maxK, ref bool isPrime) public void Scan(ulong exponent, UInt128 twoP, bool lastIsSeven, UInt128 maxK, ref bool isPrime)
{ {
using var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder); var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder);
var accelerator = gpuLease.Accelerator; var accelerator = gpuLease.Accelerator;
// Ensure device has small cycles table for in-kernel lookup // Ensure device has small cycles table for in-kernel lookup
var smallCyclesView = GpuKernelPool.EnsureSmallCyclesOnDevice(accelerator); var smallCyclesView = GpuKernelPool.EnsureSmallCyclesOnDevice(accelerator);
@@ -23,7 +23,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
byte last = lastIsSeven ? (byte)1 : (byte)0; byte last = lastIsSeven ? (byte)1 : (byte)0;
var kernel = gpuLease.Pow2ModKernel; var kernel = gpuLease.Pow2ModKernel;
using var orderBuffer = accelerator.Allocate1D<ulong>(batchSize); var orderBuffer = accelerator.Allocate1D<ulong>(batchSize);
ulong[] orderArray = ArrayPool<ulong>.Shared.Rent(batchSize); ulong[] orderArray = ArrayPool<ulong>.Shared.Rent(batchSize);
UInt128 remaining; UInt128 remaining;
int currentSize; int currentSize;
@@ -60,7 +60,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
orderBuffer.View.CopyToCPU(ref MemoryMarshal.GetReference(orders), currentSize); orderBuffer.View.CopyToCPU(ref MemoryMarshal.GetReference(orders), currentSize);
if (!Volatile.Read(ref isPrime)) if (!Volatile.Read(ref isPrime))
{ {
return; break;
} }
for (i = 0; i < currentSize; i++, q += twoP) for (i = 0; i < currentSize; i++, q += twoP)
@@ -79,5 +79,9 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
{ {
ArrayPool<ulong>.Shared.Return(orderArray); ArrayPool<ulong>.Shared.Return(orderArray);
} }
orderBuffer.Dispose();
gpuLease.Dispose();
} }
} }
+36 -15
View File
@@ -804,19 +804,22 @@ public static class NttGpuMath
{ {
int n = values.Length; int n = values.Length;
int bits = (int)Math.Log2(n); int bits = (int)Math.Log2(n);
using var gpu = GpuContextPool.Rent(); var gpu = GpuContextPool.Rent();
var accelerator = gpu.Accelerator; var accelerator = gpu.Accelerator;
var kernel = GetBitReverseKernel(accelerator); var kernel = GetBitReverseKernel(accelerator);
var pool = ArrayPool<GpuUInt128>.Shared; var pool = ArrayPool<GpuUInt128>.Shared;
var array = pool.Rent(n); var array = pool.Rent(n);
values.CopyTo(array); values.CopyTo(array);
using var buffer = accelerator.Allocate1D<GpuUInt128>(n); var buffer = accelerator.Allocate1D<GpuUInt128>(n);
buffer.View.CopyFromCPU(ref array[0], n); buffer.View.CopyFromCPU(ref array[0], n);
kernel(n, buffer.View, bits); kernel(n, buffer.View, bits);
accelerator.Synchronize(); accelerator.Synchronize();
buffer.View.CopyToCPU(ref array[0], n); buffer.View.CopyToCPU(ref array[0], n);
array.AsSpan(0, n).CopyTo(values); array.AsSpan(0, n).CopyTo(values);
pool.Return(array, clearArray: true); pool.Return(array, clearArray: true);
buffer.Dispose();
gpu.Dispose();
} }
public static void Forward(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot) public static void Forward(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
@@ -863,15 +866,15 @@ public static class NttGpuMath
private static void ForwardGpuReference(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot) private static void ForwardGpuReference(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
{ {
int n = (int)values.Length; int n = (int)values.Length;
using var gpu = GpuContextPool.Rent(); var gpu = GpuContextPool.Rent();
var accelerator = gpu.Accelerator; var accelerator = gpu.Accelerator;
var kernel = GetForwardKernel(accelerator); var kernel = GetForwardKernel(accelerator);
var pool = ArrayPool<GpuUInt128>.Shared; var pool = ArrayPool<GpuUInt128>.Shared;
var inputArray = pool.Rent(n); var inputArray = pool.Rent(n);
var outputArray = pool.Rent(n); var outputArray = pool.Rent(n);
values.CopyTo(inputArray); values.CopyTo(inputArray);
using var inputBuffer = accelerator.Allocate1D<GpuUInt128>(n); var inputBuffer = accelerator.Allocate1D<GpuUInt128>(n);
using var outputBuffer = accelerator.Allocate1D<GpuUInt128>(n); var outputBuffer = accelerator.Allocate1D<GpuUInt128>(n);
inputBuffer.View.CopyFromCPU(ref inputArray[0], n); inputBuffer.View.CopyFromCPU(ref inputArray[0], n);
UInt128 modValue = modulus; UInt128 modValue = modulus;
UInt128 expBase = (modValue - 1UL) / (ulong)n; UInt128 expBase = (modValue - 1UL) / (ulong)n;
@@ -883,6 +886,10 @@ public static class NttGpuMath
outputArray.AsSpan(0, n).CopyTo(values); outputArray.AsSpan(0, n).CopyTo(values);
pool.Return(inputArray, clearArray: true); pool.Return(inputArray, clearArray: true);
pool.Return(outputArray, clearArray: true); pool.Return(outputArray, clearArray: true);
outputBuffer.Dispose();
inputBuffer.Dispose();
gpu.Dispose();
} }
public static void Inverse(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot) public static void Inverse(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
@@ -954,15 +961,15 @@ public static class NttGpuMath
private static void InverseGpuReference(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot) private static void InverseGpuReference(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
{ {
int n = values.Length; int n = values.Length;
using var gpu = GpuContextPool.Rent(); var gpu = GpuContextPool.Rent();
var accelerator = gpu.Accelerator; var accelerator = gpu.Accelerator;
var kernel = GetInverseKernel(accelerator); var kernel = GetInverseKernel(accelerator);
var pool = ArrayPool<GpuUInt128>.Shared; var pool = ArrayPool<GpuUInt128>.Shared;
var inputArray = pool.Rent(n); var inputArray = pool.Rent(n);
var outputArray = pool.Rent(n); var outputArray = pool.Rent(n);
values.CopyTo(inputArray); values.CopyTo(inputArray);
using var inputBuffer = accelerator.Allocate1D<GpuUInt128>(n); var inputBuffer = accelerator.Allocate1D<GpuUInt128>(n);
using var outputBuffer = accelerator.Allocate1D<GpuUInt128>(n); var outputBuffer = accelerator.Allocate1D<GpuUInt128>(n);
inputBuffer.View.CopyFromCPU(ref inputArray[0], n); inputBuffer.View.CopyFromCPU(ref inputArray[0], n);
UInt128 modValue = modulus; UInt128 modValue = modulus;
UInt128 expBase = (modValue - 1UL) / (ulong)n; UInt128 expBase = (modValue - 1UL) / (ulong)n;
@@ -993,30 +1000,40 @@ public static class NttGpuMath
outputArray.AsSpan(0, n).CopyTo(values); outputArray.AsSpan(0, n).CopyTo(values);
pool.Return(inputArray, clearArray: true); pool.Return(inputArray, clearArray: true);
pool.Return(outputArray, clearArray: true); pool.Return(outputArray, clearArray: true);
outputBuffer.Dispose();
inputBuffer.Dispose();
gpu.Dispose();
} }
private static void ForwardGpuStaged(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot) private static void ForwardGpuStaged(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
{ {
int n = values.Length; int n = values.Length;
using var gpu = GpuContextPool.Rent(); var gpu = GpuContextPool.Rent();
var accelerator = gpu.Accelerator; var accelerator = gpu.Accelerator;
using var buffer = accelerator.Allocate1D<GpuUInt128>(n); var buffer = accelerator.Allocate1D<GpuUInt128>(n);
buffer.View.CopyFromCPU(ref values[0], n); buffer.View.CopyFromCPU(ref values[0], n);
var cache = GetSquareCache(accelerator, n, modulus, primitiveRoot); var cache = GetSquareCache(accelerator, n, modulus, primitiveRoot);
ForwardDevice(accelerator, buffer.View, n, modulus, cache); ForwardDevice(accelerator, buffer.View, n, modulus, cache);
buffer.View.CopyToCPU(ref values[0], n); buffer.View.CopyToCPU(ref values[0], n);
buffer.Dispose();
gpu.Dispose();
} }
private static void InverseGpuStaged(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot) private static void InverseGpuStaged(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
{ {
int n = values.Length; int n = values.Length;
using var gpu = GpuContextPool.Rent(); var gpu = GpuContextPool.Rent();
var accelerator = gpu.Accelerator; var accelerator = gpu.Accelerator;
using var buffer = accelerator.Allocate1D<GpuUInt128>(n); var buffer = accelerator.Allocate1D<GpuUInt128>(n);
buffer.View.CopyFromCPU(ref values[0], n); buffer.View.CopyFromCPU(ref values[0], n);
var cache = GetSquareCache(accelerator, n, modulus, primitiveRoot); var cache = GetSquareCache(accelerator, n, modulus, primitiveRoot);
InverseDevice(accelerator, buffer.View, n, modulus, cache); InverseDevice(accelerator, buffer.View, n, modulus, cache);
buffer.View.CopyToCPU(ref values[0], n); buffer.View.CopyToCPU(ref values[0], n);
buffer.Dispose();
gpu.Dispose();
} }
private static void ForwardDevice(Accelerator accelerator, ArrayView<GpuUInt128> data, int length, GpuUInt128 modulus, SquareCacheEntry cache) private static void ForwardDevice(Accelerator accelerator, ArrayView<GpuUInt128> data, int length, GpuUInt128 modulus, SquareCacheEntry cache)
@@ -1221,7 +1238,7 @@ public static class NttGpuMath
public static void PointwiseMultiply(Span<GpuUInt128> left, Span<GpuUInt128> right, GpuUInt128 modulus) public static void PointwiseMultiply(Span<GpuUInt128> left, Span<GpuUInt128> right, GpuUInt128 modulus)
{ {
using var gpu = GpuContextPool.Rent(); var gpu = GpuContextPool.Rent();
var accelerator = gpu.Accelerator; var accelerator = gpu.Accelerator;
var kernel = GetMulKernel(accelerator); var kernel = GetMulKernel(accelerator);
var pool = ArrayPool<GpuUInt128>.Shared; var pool = ArrayPool<GpuUInt128>.Shared;
@@ -1229,8 +1246,8 @@ public static class NttGpuMath
var rightArray = pool.Rent(right.Length); var rightArray = pool.Rent(right.Length);
left.CopyTo(leftArray); left.CopyTo(leftArray);
right.CopyTo(rightArray); right.CopyTo(rightArray);
using var leftBuffer = accelerator.Allocate1D<GpuUInt128>(left.Length); var leftBuffer = accelerator.Allocate1D<GpuUInt128>(left.Length);
using var rightBuffer = accelerator.Allocate1D<GpuUInt128>(right.Length); var rightBuffer = accelerator.Allocate1D<GpuUInt128>(right.Length);
leftBuffer.View.CopyFromCPU(ref leftArray[0], left.Length); leftBuffer.View.CopyFromCPU(ref leftArray[0], left.Length);
rightBuffer.View.CopyFromCPU(ref rightArray[0], right.Length); rightBuffer.View.CopyFromCPU(ref rightArray[0], right.Length);
kernel(left.Length, leftBuffer.View, rightBuffer.View, modulus); kernel(left.Length, leftBuffer.View, rightBuffer.View, modulus);
@@ -1241,6 +1258,10 @@ public static class NttGpuMath
rightArray.AsSpan(0, right.Length).CopyTo(right); rightArray.AsSpan(0, right.Length).CopyTo(right);
pool.Return(leftArray, clearArray: true); pool.Return(leftArray, clearArray: true);
pool.Return(rightArray, clearArray: true); pool.Return(rightArray, clearArray: true);
rightBuffer.Dispose();
leftBuffer.Dispose();
gpu.Dispose();
} }
private static ulong[] GenerateSmallPrimes(int limit) private static ulong[] GenerateSmallPrimes(int limit)
+6 -2
View File
@@ -225,9 +225,9 @@ public class MersenneDivisorCycles
divisors = pool.Rent(count); divisors = pool.Rent(count);
outCycles = pool.Rent(count); outCycles = pool.Rent(count);
using var lease = GpuKernelPool.GetKernel(useGpuOrder: true); var lease = GpuKernelPool.GetKernel(useGpuOrder: true);
var accelerator = lease.Accelerator; var accelerator = lease.Accelerator;
using var stream = accelerator.CreateStream(); var stream = accelerator.CreateStream();
var kernel = accelerator.LoadAutoGroupedStreamKernel< var kernel = accelerator.LoadAutoGroupedStreamKernel<
Index1D, Index1D,
ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>,
@@ -314,6 +314,10 @@ public class MersenneDivisorCycles
pool.Return(divisors, clearArray: false); pool.Return(divisors, clearArray: false);
pool.Return(outCycles, clearArray: false); pool.Return(outCycles, clearArray: false);
} }
stream.Dispose();
lease.Dispose();
} }
const byte ByteZero = 0; const byte ByteZero = 0;
+6 -3
View File
@@ -141,7 +141,7 @@ public sealed class MersenneNumberTester(
UInt128[] qs = qsBuffer; UInt128[] qs = qsBuffer;
using var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder); var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder);
var accelerator = gpuLease.Accelerator; var accelerator = gpuLease.Accelerator;
var orderKernel = gpuLease.OrderKernel!; var orderKernel = gpuLease.OrderKernel!;
@@ -153,8 +153,8 @@ public sealed class MersenneNumberTester(
while (offset < idx) while (offset < idx)
{ {
int count = Math.Min(batchSize, idx - offset); int count = Math.Min(batchSize, idx - offset);
using var qBuffer = accelerator.Allocate1D<PerfectNumbers.Core.Gpu.GpuUInt128>(count); var qBuffer = accelerator.Allocate1D<PerfectNumbers.Core.Gpu.GpuUInt128>(count);
using var orderBuffer = accelerator.Allocate1D<ulong>(count); var orderBuffer = accelerator.Allocate1D<ulong>(count);
// Convert to device-friendly GpuUInt128 on the fly // Convert to device-friendly GpuUInt128 on the fly
var tmp = System.Buffers.ArrayPool<PerfectNumbers.Core.Gpu.GpuUInt128>.Shared.Rent(count); var tmp = System.Buffers.ArrayPool<PerfectNumbers.Core.Gpu.GpuUInt128>.Shared.Rent(count);
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
@@ -183,8 +183,11 @@ public sealed class MersenneNumberTester(
} }
offset += count; offset += count;
orderBuffer.Dispose();
qBuffer.Dispose();
} }
gpuLease.Dispose();
ArrayPool<UInt128>.Shared.Return(qs); ArrayPool<UInt128>.Shared.Return(qs);
} }
+10 -5
View File
@@ -81,8 +81,8 @@ public sealed class PrimeTester(bool useInternal = false)
public static void IsPrimeBatchGpu(ReadOnlySpan<ulong> values, Span<byte> results) public static void IsPrimeBatchGpu(ReadOnlySpan<ulong> values, Span<byte> results)
{ {
// Limit concurrency and declare variables outside loops for performance and reuse // Limit concurrency and declare variables outside loops for performance and reuse
using var limiter = GpuPrimeWorkLimiter.Acquire(); var limiter = GpuPrimeWorkLimiter.Acquire();
using var gpu = GpuContextPool.Rent(); var gpu = GpuContextPool.Rent();
var accelerator = gpu.Accelerator; var accelerator = gpu.Accelerator;
// Get per-accelerator cached kernel and device primes buffer. // Get per-accelerator cached kernel and device primes buffer.
@@ -123,6 +123,8 @@ public sealed class PrimeTester(bool useInternal = false)
ArrayPool<ulong>.Shared.Return(temp); ArrayPool<ulong>.Shared.Return(temp);
state.ReturnScratch(scratch); state.ReturnScratch(scratch);
gpu.Dispose();
limiter.Dispose();
} }
// Per-accelerator GPU state for prime sieve (kernel + uploaded primes). // Per-accelerator GPU state for prime sieve (kernel + uploaded primes).
@@ -283,13 +285,13 @@ public sealed class PrimeTester(bool useInternal = false)
internal static void SharesFactorWithMaxExponentBatch(ReadOnlySpan<ulong> values, Span<byte> results) internal static void SharesFactorWithMaxExponentBatch(ReadOnlySpan<ulong> values, Span<byte> results)
{ {
using var gpu = GpuContextPool.Rent(); var gpu = GpuContextPool.Rent();
var accelerator = gpu.Accelerator; var accelerator = gpu.Accelerator;
var kernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<byte>>(SharesFactorKernel); var kernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<byte>>(SharesFactorKernel);
int length = values.Length; int length = values.Length;
using var inputBuffer = accelerator.Allocate1D<ulong>(length); var inputBuffer = accelerator.Allocate1D<ulong>(length);
using var resultBuffer = accelerator.Allocate1D<byte>(length); var resultBuffer = accelerator.Allocate1D<byte>(length);
ulong[] temp = ArrayPool<ulong>.Shared.Rent(length); ulong[] temp = ArrayPool<ulong>.Shared.Rent(length);
values.CopyTo(temp); values.CopyTo(temp);
@@ -298,6 +300,9 @@ public sealed class PrimeTester(bool useInternal = false)
accelerator.Synchronize(); accelerator.Synchronize();
resultBuffer.View.CopyToCPU(ref results[0], length); resultBuffer.View.CopyToCPU(ref results[0], length);
ArrayPool<ulong>.Shared.Return(temp); ArrayPool<ulong>.Shared.Return(temp);
resultBuffer.Dispose();
inputBuffer.Dispose();
gpu.Dispose();
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]