PooledContext removal - continuation. GpuKernelLease prepared for removal.

This commit is contained in:
mlemanczyk committed 2025-11-07 14:13:11 +01:00
1 parent f4e365194d
commit 0410fd2c91
20 files changed
+192 -267

No files matched your search

+9 -99
View File
@@ -8,122 +8,32 @@ public sealed class GpuKernelLease
{
private static readonly ConcurrentQueue<GpuKernelLease> Pool = new();
public KernelContainer Kernels;
public AcceleratorStream Stream;
#pragma warning disable CS8618 // _gpu and Stream will be set by Rent method
private GpuKernelLease(KernelContainer kernels)
#pragma warning restore CS8618
{
Kernels = kernels;
}
internal static GpuKernelLease Rent(AcceleratorStream stream, KernelContainer kernels)
internal static GpuKernelLease Rent()
{
if (!Pool.TryDequeue(out var lease))
{
lease = new GpuKernelLease(kernels);
lease = new GpuKernelLease();
}
lease.Kernels = kernels;
lease.Stream = stream;
return lease;
}
public Action<AcceleratorStream, Index1D, ulong, ulong, ArrayView<GpuUInt128>, ArrayView<ulong>> OrderKernel
{
get
{
return GpuKernelPool.InitOnce(ref Kernels!.Order, () =>
{
var loaded = SharedGpuContext.Accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, ulong, ArrayView<GpuUInt128>, ArrayView<ulong>>(OrderKernels.OrderKernelScan);
var kernel = KernelUtil.GetKernel(loaded);
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, ulong, ArrayView<GpuUInt128>, ArrayView<ulong>>>();
});
}
}
public static readonly Action<AcceleratorStream, Index1D, ulong, ulong, ArrayView<GpuUInt128>, ArrayView<ulong>> OrderKernel = GpuKernelPool.Kernels.Order!;
public Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> Pow2ModKernel
{
get
{
return GpuKernelPool.InitOnce(ref Kernels!.Pow2Mod, () =>
{
var loaded = SharedGpuContext.Accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2ModKernels.Pow2ModKernelScan);
var kernel = KernelUtil.GetKernel(loaded);
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
});
}
}
public static readonly Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> Pow2ModKernel = GpuKernelPool.Kernels.Pow2Mod!;
public Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ulong, ulong, ulong, ulong, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>> IncrementalKernel
{
get
{
return GpuKernelPool.InitOnce(ref Kernels!.Incremental, () =>
{
var loaded = SharedGpuContext.Accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ulong, ulong, ulong, ulong, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>>(IncrementalKernels.IncrementalKernelScan);
var kernel = KernelUtil.GetKernel(loaded);
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ulong, ulong, ulong, ulong, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>>>();
});
}
}
public static readonly Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ulong, ulong, ulong, ulong, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>> IncrementalKernel = GpuKernelPool.Kernels.Incremental!;
public Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>> IncrementalOrderKernel
{
get
{
return GpuKernelPool.InitOnce(ref Kernels!.IncrementalOrder, () =>
{
var loaded = SharedGpuContext.Accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>(IncrementalKernels.IncrementalOrderKernelScan);
var kernel = KernelUtil.GetKernel(loaded);
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>>();
});
}
}
public static readonly Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>> IncrementalOrderKernel = GpuKernelPool.Kernels.IncrementalOrder!;
public Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>> Pow2ModOrderKernel
{
get
{
return GpuKernelPool.InitOnce(ref Kernels!.Pow2ModOrder, () =>
{
var loaded = SharedGpuContext.Accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2ModKernels.Pow2ModOrderKernelScan);
var kernel = KernelUtil.GetKernel(loaded);
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>>();
});
}
}
public static readonly Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>> Pow2ModOrderKernel = GpuKernelPool.Kernels.Pow2ModOrder!;
public Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> SpecialMaxKernel
{
get
{
return GpuKernelPool.InitOnce(ref Kernels!.SpecialMax, () =>
{
var loaded = SharedGpuContext.Accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.EvaluateSpecialMaxCandidatesKernel);
var kernel = KernelUtil.GetKernel(loaded);
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
});
}
}
public static readonly Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> SpecialMaxKernel = GpuKernelPool.Kernels.SpecialMax!;
public Action<AcceleratorStream, Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> SmallPrimeFactorKernel
{
get
{
return GpuKernelPool.InitOnce(ref Kernels!.SmallPrimeFactor, () =>
{
var loaded = SharedGpuContext.Accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(SmallPrimeFactorKernels.SmallPrimeFactorKernelScan);
var kernel = KernelUtil.GetKernel(loaded);
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
});
}
}
public static readonly Action<AcceleratorStream, Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> SmallPrimeFactorKernel = GpuKernelPool.Kernels.SmallPrimeFactor!;
public void Dispose()
{
Stream.Dispose();
Pool.Enqueue(this);
GpuPrimeWorkLimiter.Release();
}
+69 -3
View File
@@ -1,4 +1,3 @@
using System.Collections.Concurrent;
using ILGPU;
using ILGPU.Runtime;
@@ -24,6 +23,71 @@ public class GpuKernelPool
var kernels = new KernelContainer();
var stream = SharedGpuContext.Accelerator.CreateStream();
PreloadStaticTables(kernels, stream);
InitOnce(ref kernels.Order, () =>
{
var loaded = SharedGpuContext.Accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, ulong, ArrayView<GpuUInt128>, ArrayView<ulong>>(OrderKernels.OrderKernelScan);
var kernel = KernelUtil.GetKernel(loaded);
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, ulong, ArrayView<GpuUInt128>, ArrayView<ulong>>>();
});
InitOnce(ref kernels.Pow2Mod, () =>
{
var loaded = SharedGpuContext.Accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2ModKernels.Pow2ModKernelScan);
var kernel = KernelUtil.GetKernel(loaded);
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
});
InitOnce(ref kernels.Incremental, () =>
{
var loaded = SharedGpuContext.Accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ulong, ulong, ulong, ulong, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>>(IncrementalKernels.IncrementalKernelScan);
var kernel = KernelUtil.GetKernel(loaded);
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ulong, ulong, ulong, ulong, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>>>();
});
InitOnce(ref kernels.IncrementalOrder, () =>
{
var loaded = SharedGpuContext.Accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>(IncrementalKernels.IncrementalOrderKernelScan);
var kernel = KernelUtil.GetKernel(loaded);
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte,
ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>>();
});
InitOnce(ref kernels.Pow2ModOrder, () =>
{
var loaded = SharedGpuContext.Accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2ModKernels.Pow2ModOrderKernelScan);
var kernel = KernelUtil.GetKernel(loaded);
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>>();
});
InitOnce(ref kernels.SpecialMax, () =>
{
var loaded = SharedGpuContext.Accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.EvaluateSpecialMaxCandidatesKernel);
var kernel = KernelUtil.GetKernel(loaded);
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
});
InitOnce(ref kernels.SmallPrimeFactor, () =>
{
var loaded = SharedGpuContext.Accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(SmallPrimeFactorKernels.SmallPrimeFactorKernelScan);
var kernel = KernelUtil.GetKernel(loaded);
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
});
stream.Synchronize();
stream.Dispose();
return kernels;
@@ -141,7 +205,7 @@ public class GpuKernelPool
{
GpuPrimeWorkLimiter.Acquire();
var stream = SharedGpuContext.Accelerator.CreateStream();
return GpuKernelLease.Rent(stream, Kernels);
return GpuKernelLease.Rent();
}
/// <summary>
@@ -152,8 +216,10 @@ public class GpuKernelPool
{
var lease = Rent();
var accelerator = SharedGpuContext.Accelerator;
var stream = lease.Stream;
var stream = accelerator.CreateStream();
action(accelerator, stream);
stream.Synchronize();
stream.Dispose();
lease.Dispose();
}
}
@@ -7,17 +7,23 @@ public sealed class KernelContainer
{
// Serializes first-time initialization of kernels/buffers per accelerator.
public Action<AcceleratorStream, Index1D, ulong, ulong, ArrayView<GpuUInt128>, ArrayView<ulong>>? Order;
public Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong,
ulong, ulong, ulong, ulong, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>>? Incremental;
public Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong,
ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>,
ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>,
ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>? Pow2Mod;
public Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong,
ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>? IncrementalOrder;
public Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong,
ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>? Pow2ModOrder;
public Action<AcceleratorStream, Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>? SmallPrimeFactor;
public Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>? SpecialMax;
// Optional device buffer with small divisor cycles (<= 4M). Index = divisor, value = cycle length.
@@ -97,7 +97,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
var gpuLease = GpuKernelPool.Rent();
var accelerator = SharedGpuContext.Accelerator;
var stream = gpuLease.Stream;
var stream = accelerator.CreateStream();
// Monitor.Enter(gpuLease.ExecutionLock);
@@ -126,6 +126,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
out coveredRange,
out processedCount);
stream.Dispose();
ReturnBatchResources(resources);
// Monitor.Exit(gpuLease.ExecutionLock);
gpuLease.Dispose();
@@ -502,8 +503,9 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
{
_owner = owner;
_lease = GpuKernelPool.Rent();
_accelerator = SharedGpuContext.Accelerator;
_stream = _lease.Stream;
Accelerator accelerator = SharedGpuContext.Accelerator;
_accelerator = accelerator;
_stream = accelerator.CreateStream();
_capacity = Math.Max(1, owner._gpuBatchSize);
}
@@ -18,14 +18,14 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
var gpuLease = GpuKernelPool.Rent();
var accelerator = SharedGpuContext.Accelerator;
var stream = gpuLease.Stream;
var stream = accelerator.CreateStream();
int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy
UInt128 kStart = 1UL;
ulong divMul = (ulong)((((UInt128)1 << 64) - UInt128.One) / exponent) + 1UL;
byte last = lastDigit == LastDigit.Seven ? (byte)1 : (byte)0; // ILGPU kernels do not support bool parameters
var pow2Kernel = gpuLease.Pow2ModKernel;
var incKernel = gpuLease.IncrementalKernel;
var pow2Kernel = GpuKernelLease.Pow2ModKernel;
var incKernel = GpuKernelLease.IncrementalKernel;
ulong step10 = (exponent.Mod10() << 1).Mod10();
ulong step8 = ((exponent & 7UL) << 1) & 7UL;
ulong step3 = ((exponent % 3UL) << 1) % 3UL;
@@ -121,6 +121,7 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
kStart += (UInt128)currentSize;
}
stream.Dispose();
ulongPool.Return(orderArray);
orderBuffer.Dispose();
gpuLease.Dispose();
@@ -11,7 +11,7 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
{
var gpuLease = GpuKernelPool.Rent();
var accelerator = SharedGpuContext.Accelerator;
var stream = gpuLease.Stream;
var stream = accelerator.CreateStream();
int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy and avoids TDR
UInt128 kStart = UInt128.One;
ulong divMul = (ulong)((((UInt128)1 << 64) - UInt128.One) / exponent) + 1UL;
@@ -19,8 +19,8 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
var kernel = _kernelType switch
{
GpuKernelType.Pow2Mod => gpuLease.Pow2ModOrderKernel,
_ => gpuLease.IncrementalOrderKernel,
GpuKernelType.Pow2Mod => GpuKernelLease.Pow2ModOrderKernel,
_ => GpuKernelLease.IncrementalOrderKernel,
};
var foundBuffer = accelerator.Allocate1D<int>(1); // TODO: Replace this allocation with the pooled device buffer from GpuOrderKernelBenchmarks so repeated scans reuse the pinned staging memory instead of allocating per run.
@@ -60,6 +60,7 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
kStart += (UInt128)currentSize;
}
stream.Dispose();
foundBuffer.Dispose();
gpuLease.Dispose();
}
@@ -200,7 +200,7 @@ internal static partial class PrimeOrderGpuHeuristics
{
var lease = GpuKernelPool.Rent();
Accelerator accelerator = SharedGpuContext.Accelerator;
AcceleratorStream stream = lease.Stream;
AcceleratorStream stream = accelerator.CreateStream();
var kernel = GetPartialFactorKernel(accelerator);
SmallPrimeDeviceCache cache = GetSmallPrimeDeviceCache(accelerator, stream);
@@ -243,6 +243,7 @@ internal static partial class PrimeOrderGpuHeuristics
byte fullyFactoredFlag = 0;
fullyFactoredBuffer.View.CopyToCPU(stream, ref fullyFactoredFlag, 1);
stream.Synchronize();
stream.Dispose();
fullyFactored = fullyFactoredFlag != 0;
factorCount = Math.Min(factorCount, primeTargets.Length);
@@ -252,7 +253,7 @@ internal static partial class PrimeOrderGpuHeuristics
exponentBuffer.Dispose();
countBuffer.Dispose();
remainingBuffer.Dispose();
fullyFactoredBuffer.Dispose();
fullyFactoredBuffer.Dispose();
lease.Dispose();
return true;
}
@@ -367,7 +368,7 @@ internal static partial class PrimeOrderGpuHeuristics
var lease = GpuKernelPool.Rent();
Accelerator accelerator = SharedGpuContext.Accelerator;
AcceleratorStream stream = lease.Stream;
AcceleratorStream stream = accelerator.CreateStream();
var kernel = GetOrderKernel(accelerator);
SmallPrimeDeviceCache cache = GetSmallPrimeDeviceCache(accelerator, stream);
@@ -430,20 +431,29 @@ internal static partial class PrimeOrderGpuHeuristics
byte status = 0;
statusBuffer.View.CopyToCPU(stream, ref status, 1);
resultBuffer.View.CopyToCPU(stream, ref order, 1);
stream.Synchronize();
stream.Synchronize();
stream.Dispose();
phiFactorBuffer.Dispose();
phiExponentBuffer.Dispose();
workFactorBuffer.Dispose();
workExponentBuffer.Dispose();
candidateBuffer.Dispose();
stackIndexBuffer.Dispose();
stackExponentBuffer.Dispose();
stackProductBuffer.Dispose();
resultBuffer.Dispose();
statusBuffer.Dispose();
lease.Dispose();
PrimeOrderKernelStatus kernelStatus = (PrimeOrderKernelStatus)status;
if (kernelStatus == PrimeOrderKernelStatus.Fallback)
{
DisposeResources();
lease.Dispose();
return false;
}
if (kernelStatus == PrimeOrderKernelStatus.PollardOverflow)
{
DisposeResources();
lease.Dispose();
throw new InvalidOperationException("GPU Pollard Rho stack overflow; increase HeuristicStackCapacity.");
}
@@ -452,24 +462,7 @@ internal static partial class PrimeOrderGpuHeuristics
order = 0UL;
}
DisposeResources();
lease.Dispose();
return order != 0UL;
void DisposeResources()
{
phiFactorBuffer.Dispose();
phiExponentBuffer.Dispose();
workFactorBuffer.Dispose();
workExponentBuffer.Dispose();
candidateBuffer.Dispose();
stackIndexBuffer.Dispose();
stackExponentBuffer.Dispose();
stackProductBuffer.Dispose();
resultBuffer.Dispose();
statusBuffer.Dispose();
}
}
private static OrderKernelLauncher GetOrderKernel(Accelerator accelerator)
@@ -528,7 +521,7 @@ internal static partial class PrimeOrderGpuHeuristics
{
var lease = GpuKernelPool.Rent();
Accelerator accelerator = SharedGpuContext.Accelerator;
AcceleratorStream stream = lease.Stream;
AcceleratorStream? stream = accelerator.CreateStream();
var kernel = GetPow2ModKernel(accelerator);
// TODO: These buffers should be allocated once per accelerator and only reallocated when the new length exceeds capacity.
// Modify the callers to use their own pool of buffers per accelerator, so that other threads don't use the accelerators
@@ -546,6 +539,9 @@ internal static partial class PrimeOrderGpuHeuristics
kernel(stream, exponents.Length, exponentBuffer.View, divisorData, remainderBuffer.View);
remainderBuffer.View.CopyToCPU(stream, ref MemoryMarshal.GetReference(results), exponents.Length);
stream.Synchronize();
stream.Dispose();
stream = null;
exponentBuffer.Dispose();
remainderBuffer.Dispose();
lease.Dispose();
@@ -553,6 +549,7 @@ internal static partial class PrimeOrderGpuHeuristics
catch (Exception)
{
Console.WriteLine($"Exception for {prime} and exponents: {string.Join(",", exponents.ToArray())}.");
stream?.Dispose();
exponentBuffer.Dispose();
remainderBuffer.Dispose();
lease.Dispose();
@@ -587,7 +584,7 @@ internal static partial class PrimeOrderGpuHeuristics
try
{
Accelerator accelerator = SharedGpuContext.Accelerator;
AcceleratorStream stream = lease.Stream;
AcceleratorStream stream = accelerator.CreateStream();
var kernel = GetPow2ModWideKernel(accelerator);
// TODO: These buffers should be allocated once per accelerator and only reallocated when the new length exceeds capacity.
// Modify the callers to use their own pool of buffers per accelerator, so that other threads don't use the accelerators
@@ -618,6 +615,7 @@ internal static partial class PrimeOrderGpuHeuristics
remainderBuffer.View.CopyToCPU(stream, ref MemoryMarshal.GetReference(resultSpan), length);
stream.Synchronize();
stream.Dispose();
for (int i = 0; i < length; i++)
{
@@ -641,7 +639,7 @@ internal static partial class PrimeOrderGpuHeuristics
gpuUInt128Pool.Return(rentedResults!, clearArray: false);
}
lease.Dispose();
lease.Dispose();
}
}