GpuContextPool removed, because we share context and accelerator between threads, using streams to separate.
This commit is contained in:
1 parent
7c035239b4
commit
f4e365194d
19 files changed
+92
-232
No files matched your search
@@ -269,7 +269,7 @@ public sealed class DivisorCycleCache
|
||||
int length = divisors.Length;
|
||||
var gpuLease = GpuKernelPool.Rent();
|
||||
|
||||
Accelerator accelerator = gpuLease.Accelerator;
|
||||
Accelerator accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = gpuLease.Stream;
|
||||
var kernel = _gpuKernel;
|
||||
EnsureCapacity(length);
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
using System.Collections.Concurrent;
|
||||
using ILGPU;
|
||||
using ILGPU.Runtime;
|
||||
|
||||
namespace PerfectNumbers.Core.Gpu;
|
||||
|
||||
public sealed class GpuContextLease
|
||||
{
|
||||
private GpuContextPool.PooledContext? _ctx;
|
||||
|
||||
internal GpuContextLease(GpuContextPool.PooledContext ctx)
|
||||
{
|
||||
_ctx = ctx;
|
||||
}
|
||||
|
||||
public Context Context => _ctx!.Context;
|
||||
public Accelerator Accelerator => _ctx!.Accelerator;
|
||||
|
||||
public void Dispose() => GpuContextPool.Return(_ctx!);
|
||||
}
|
||||
|
||||
public static class GpuContextPool
|
||||
{
|
||||
// The pool intentionally skips pre-loading ProcessEightBitWindows kernels so accelerator initialization
|
||||
// stays stable; GpuKernelPool JIT-compiles them on first use alongside the small-cycle uploads.
|
||||
// Default device preference for generic GPU kernels (prime scans, NTT, etc.)
|
||||
internal sealed class PooledContext
|
||||
{
|
||||
public readonly Context Context;
|
||||
public readonly Accelerator Accelerator;
|
||||
|
||||
public PooledContext()
|
||||
{
|
||||
Context = SharedGpuContext.Context;
|
||||
Accelerator = SharedGpuContext.Accelerator;
|
||||
// NOTE: Avoid loading/compiling any kernel here to prevent implicit
|
||||
// CL stream/queue creation during accelerator construction.
|
||||
// Some OpenCL drivers are fragile when a queue is created immediately
|
||||
// after device init. Real kernels will be JIT-loaded at first use.
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Ensure all cached GPU buffers for this accelerator are released.
|
||||
// Release PrimeTester GPU state for this accelerator (kernel/device primes)
|
||||
// Clear any per-accelerator cached resources to avoid releasing
|
||||
// after the accelerator is destroyed.
|
||||
|
||||
// These resources are shared between GPU leases
|
||||
// Accelerator.Dispose();
|
||||
// Context.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly ConcurrentQueue<PooledContext> GpuPool = new();
|
||||
private static int WarmedGpuContextCount;
|
||||
|
||||
// Allows callers to choose CPU/GPU per use-case, decoupled from ForceCpu.
|
||||
public static GpuContextLease Rent()
|
||||
{
|
||||
if (GpuPool.TryDequeue(out var gpu))
|
||||
{
|
||||
return new GpuContextLease(gpu);
|
||||
}
|
||||
|
||||
// Create a new accelerator when the pool does not have one available.
|
||||
return new GpuContextLease(new PooledContext());
|
||||
}
|
||||
|
||||
|
||||
public static void WarmUpPool(int threadCount)
|
||||
{
|
||||
if (threadCount <= WarmedGpuContextCount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int toCreate = threadCount - WarmedGpuContextCount;
|
||||
Console.WriteLine($"Warming up GPU context pool to {toCreate} contexts...");
|
||||
var contexts = new PooledContext[toCreate];
|
||||
var pool = GpuPool;
|
||||
PooledContext context;
|
||||
for (int i = 0; i < toCreate; i++)
|
||||
{
|
||||
context = new PooledContext();
|
||||
contexts[i] = context;
|
||||
pool.Enqueue(context);
|
||||
}
|
||||
|
||||
WarmedGpuContextCount = threadCount;
|
||||
}
|
||||
|
||||
public static void DisposeAll()
|
||||
{
|
||||
while (GpuPool.TryDequeue(out var gpu))
|
||||
{
|
||||
gpu.Dispose();
|
||||
}
|
||||
|
||||
WarmedGpuContextCount = 0;
|
||||
}
|
||||
|
||||
internal static void Return(PooledContext ctx)
|
||||
{
|
||||
GpuPool.Enqueue(ctx);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Concurrent;
|
||||
using ILGPU;
|
||||
using ILGPU.Algorithms;
|
||||
using ILGPU.Runtime;
|
||||
|
||||
namespace PerfectNumbers.Core.Gpu;
|
||||
@@ -9,7 +8,6 @@ public sealed class GpuKernelLease
|
||||
{
|
||||
private static readonly ConcurrentQueue<GpuKernelLease> Pool = new();
|
||||
|
||||
private GpuContextLease _gpu;
|
||||
public KernelContainer Kernels;
|
||||
public AcceleratorStream Stream;
|
||||
|
||||
@@ -20,29 +18,25 @@ public sealed class GpuKernelLease
|
||||
Kernels = kernels;
|
||||
}
|
||||
|
||||
internal static GpuKernelLease Rent(GpuContextLease gpu, AcceleratorStream stream, KernelContainer kernels)
|
||||
internal static GpuKernelLease Rent(AcceleratorStream stream, KernelContainer kernels)
|
||||
{
|
||||
if (!Pool.TryDequeue(out var lease))
|
||||
{
|
||||
lease = new GpuKernelLease(kernels);
|
||||
}
|
||||
|
||||
lease._gpu = gpu;
|
||||
lease.Kernels = kernels;
|
||||
lease.Stream = stream;
|
||||
return lease;
|
||||
}
|
||||
|
||||
public Accelerator Accelerator => _gpu?.Accelerator ?? throw new NullReferenceException("GPU context is already released");
|
||||
|
||||
public Action<AcceleratorStream, Index1D, ulong, ulong, ArrayView<GpuUInt128>, ArrayView<ulong>> OrderKernel
|
||||
{
|
||||
get
|
||||
{
|
||||
var accel = Accelerator; // avoid capturing 'this' in lambda
|
||||
return GpuKernelPool.InitOnce(ref Kernels!.Order, () =>
|
||||
{
|
||||
var loaded = accel.LoadAutoGroupedStreamKernel<Index1D, ulong, ulong, ArrayView<GpuUInt128>, ArrayView<ulong>>(OrderKernels.OrderKernelScan);
|
||||
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>>>();
|
||||
});
|
||||
@@ -53,10 +47,9 @@ public sealed class GpuKernelLease
|
||||
{
|
||||
get
|
||||
{
|
||||
var accel = Accelerator;
|
||||
return GpuKernelPool.InitOnce(ref Kernels!.Pow2Mod, () =>
|
||||
{
|
||||
var loaded = accel.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 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>>>();
|
||||
});
|
||||
@@ -67,10 +60,9 @@ public sealed class GpuKernelLease
|
||||
{
|
||||
get
|
||||
{
|
||||
var accel = Accelerator; // avoid capturing 'this' in lambda
|
||||
return GpuKernelPool.InitOnce(ref Kernels!.Incremental, () =>
|
||||
{
|
||||
var loaded = accel.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ulong, ulong, ulong, ulong, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>>(IncrementalKernels.IncrementalKernelScan);
|
||||
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>>>();
|
||||
});
|
||||
@@ -81,10 +73,9 @@ public sealed class GpuKernelLease
|
||||
{
|
||||
get
|
||||
{
|
||||
var accel = Accelerator;
|
||||
return GpuKernelPool.InitOnce(ref Kernels!.IncrementalOrder, () =>
|
||||
{
|
||||
var loaded = accel.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>(IncrementalKernels.IncrementalOrderKernelScan);
|
||||
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>>>();
|
||||
});
|
||||
@@ -95,10 +86,9 @@ public sealed class GpuKernelLease
|
||||
{
|
||||
get
|
||||
{
|
||||
var accel = Accelerator;
|
||||
return GpuKernelPool.InitOnce(ref Kernels!.Pow2ModOrder, () =>
|
||||
{
|
||||
var loaded = accel.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2ModKernels.Pow2ModOrderKernelScan);
|
||||
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>>>();
|
||||
});
|
||||
@@ -109,10 +99,9 @@ public sealed class GpuKernelLease
|
||||
{
|
||||
get
|
||||
{
|
||||
var accel = Accelerator;
|
||||
return GpuKernelPool.InitOnce(ref Kernels!.SpecialMax, () =>
|
||||
{
|
||||
var loaded = accel.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.EvaluateSpecialMaxCandidatesKernel);
|
||||
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>>>();
|
||||
});
|
||||
@@ -123,10 +112,9 @@ public sealed class GpuKernelLease
|
||||
{
|
||||
get
|
||||
{
|
||||
var accel = Accelerator;
|
||||
return GpuKernelPool.InitOnce(ref Kernels!.SmallPrimeFactor, () =>
|
||||
{
|
||||
var loaded = accel.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 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>>>();
|
||||
});
|
||||
@@ -136,9 +124,7 @@ public sealed class GpuKernelLease
|
||||
public void Dispose()
|
||||
{
|
||||
Stream.Dispose();
|
||||
_gpu.Dispose();
|
||||
Pool.Enqueue(this);
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
using System.Collections.Concurrent;
|
||||
using ILGPU;
|
||||
using ILGPU.Runtime;
|
||||
using static PerfectNumbers.Core.Gpu.GpuContextPool;
|
||||
|
||||
namespace PerfectNumbers.Core.Gpu;
|
||||
|
||||
public class GpuKernelPool
|
||||
{
|
||||
private static readonly ConcurrentDictionary<Accelerator, KernelContainer> _kernels = new();
|
||||
public static readonly KernelContainer Kernels = CreateKernels();
|
||||
|
||||
public static T InitOnce<T>(ref T? target, Func<T> valueFactory) where T : class
|
||||
{
|
||||
@@ -20,26 +19,35 @@ public class GpuKernelPool
|
||||
return Interlocked.CompareExchange(ref target, newValue, null) ?? newValue;
|
||||
}
|
||||
|
||||
internal static KernelContainer GetKernels(Accelerator accelerator, AcceleratorStream stream)
|
||||
{
|
||||
return _kernels.GetOrAdd(accelerator, (accelerator) =>
|
||||
private static KernelContainer CreateKernels()
|
||||
{
|
||||
var kernels = new KernelContainer();
|
||||
PreloadStaticTables(kernels, accelerator, stream);
|
||||
var stream = SharedGpuContext.Accelerator.CreateStream();
|
||||
PreloadStaticTables(kernels, stream);
|
||||
stream.Synchronize();
|
||||
stream.Dispose();
|
||||
return kernels;
|
||||
});
|
||||
}
|
||||
|
||||
internal static void PreloadStaticTables(KernelContainer kernels, Accelerator accelerator, AcceleratorStream stream)
|
||||
private static KernelContainer CreateKernels(AcceleratorStream stream)
|
||||
{
|
||||
EnsureSmallCyclesOnDevice(kernels, accelerator, stream);
|
||||
EnsureSmallPrimesOnDevice(kernels, accelerator, stream);
|
||||
EnsureSmallPrimeFactorTables(kernels, accelerator, stream);
|
||||
KernelContainer kernels = new();
|
||||
PreloadStaticTables(kernels, stream);
|
||||
return Kernels;
|
||||
}
|
||||
|
||||
internal static void PreloadStaticTables(KernelContainer kernels, AcceleratorStream stream)
|
||||
{
|
||||
_ = EnsureSmallCyclesOnDevice(kernels, stream);
|
||||
_ = EnsureSmallPrimesOnDevice(kernels, stream);
|
||||
_ = EnsureSmallPrimeFactorTables(kernels, stream);
|
||||
}
|
||||
|
||||
public static ArrayView1D<ulong, Stride1D.Dense> GetSmallCyclesOnDevice() => Kernels.SmallCycles!;
|
||||
|
||||
// Ensures the small cycles table is uploaded to the device for the given accelerator.
|
||||
// Returns the ArrayView to pass into kernels (when kernels are extended to accept it).
|
||||
public static ArrayView1D<ulong, Stride1D.Dense> EnsureSmallCyclesOnDevice(KernelContainer kernels, Accelerator accelerator, AcceleratorStream stream)
|
||||
private static ArrayView1D<ulong, Stride1D.Dense> EnsureSmallCyclesOnDevice(KernelContainer kernels, AcceleratorStream stream)
|
||||
{
|
||||
if (kernels.SmallCycles is { } buffer)
|
||||
{
|
||||
@@ -47,13 +55,20 @@ public class GpuKernelPool
|
||||
}
|
||||
|
||||
var host = MersenneDivisorCycles.Shared.ExportSmallCyclesSnapshot(); // TODO: Preload this device buffer during startup and keep it immutable so we can delete the lock above in favor of the preloaded snapshot.
|
||||
var device = accelerator.Allocate1D<ulong>(host.Length);
|
||||
var device = SharedGpuContext.Accelerator.Allocate1D<ulong>(host.Length);
|
||||
device.View.CopyFromCPU(stream, host);
|
||||
kernels.SmallCycles = device;
|
||||
return device.View;
|
||||
}
|
||||
|
||||
public static ResiduePrimeViews EnsureSmallPrimesOnDevice(KernelContainer kernels, Accelerator accelerator, AcceleratorStream stream)
|
||||
public static ResiduePrimeViews GetSmallPrimesOnDevice() => new(
|
||||
Kernels.SmallPrimesLastOne!,
|
||||
Kernels.SmallPrimesLastSeven!,
|
||||
Kernels.SmallPrimesPow2LastOne!,
|
||||
Kernels.SmallPrimesPow2LastSeven!
|
||||
);
|
||||
|
||||
private static ResiduePrimeViews EnsureSmallPrimesOnDevice(KernelContainer kernels, AcceleratorStream stream)
|
||||
{
|
||||
if (kernels.SmallPrimesLastOne is { } lastOne &&
|
||||
kernels.SmallPrimesLastSeven is { } lastSeven &&
|
||||
@@ -71,6 +86,7 @@ public class GpuKernelPool
|
||||
return new ResiduePrimeViews(existingLastOne.View, existingLastSeven.View, existingLastOnePow2.View, existingLastSevenPow2.View);
|
||||
}
|
||||
|
||||
Accelerator accelerator = SharedGpuContext.Accelerator;
|
||||
var hostLastOne = PrimesGenerator.SmallPrimesLastOne;
|
||||
var hostLastSeven = PrimesGenerator.SmallPrimesLastSeven;
|
||||
var hostLastOnePow2 = PrimesGenerator.SmallPrimesPow2LastOne;
|
||||
@@ -93,34 +109,39 @@ public class GpuKernelPool
|
||||
return new ResiduePrimeViews(deviceLastOne.View, deviceLastSeven.View, deviceLastOnePow2.View, deviceLastSevenPow2.View);
|
||||
}
|
||||
|
||||
public static SmallPrimeFactorViews EnsureSmallPrimeFactorTables(KernelContainer kernels, Accelerator accelerator, AcceleratorStream stream)
|
||||
public static SmallPrimeFactorViews GetSmallPrimeFactorTables() => new(
|
||||
Kernels.SmallPrimeFactorsPrimes!,
|
||||
Kernels.SmallPrimeFactorsSquares!
|
||||
);
|
||||
|
||||
private static SmallPrimeFactorViews EnsureSmallPrimeFactorTables(KernelContainer kernels, AcceleratorStream stream)
|
||||
{
|
||||
if (kernels.SmallPrimeFactorsPrimes is { } primeBuffer && kernels.SmallPrimeFactorsSquares is { } squareBuffer)
|
||||
{
|
||||
return new SmallPrimeFactorViews(primeBuffer, squareBuffer, (int)primeBuffer.Length);
|
||||
return new SmallPrimeFactorViews(primeBuffer, squareBuffer);
|
||||
}
|
||||
|
||||
Accelerator accelerator = SharedGpuContext.Accelerator;
|
||||
var hostPrimes = PrimesGenerator.SmallPrimes;
|
||||
var hostSquares = PrimesGenerator.SmallPrimesPow2;
|
||||
|
||||
var devicePrimes = accelerator.Allocate1D<uint>(hostPrimes.Length);
|
||||
int length = hostPrimes.Length;
|
||||
var devicePrimes = accelerator.Allocate1D<uint>(length);
|
||||
devicePrimes.View.CopyFromCPU(stream, hostPrimes);
|
||||
var deviceSquares = accelerator.Allocate1D<ulong>(hostSquares.Length);
|
||||
var deviceSquares = accelerator.Allocate1D<ulong>(length);
|
||||
deviceSquares.View.CopyFromCPU(stream, hostSquares);
|
||||
|
||||
kernels.SmallPrimeFactorsPrimes = devicePrimes;
|
||||
kernels.SmallPrimeFactorsSquares = deviceSquares;
|
||||
|
||||
return new SmallPrimeFactorViews(devicePrimes, deviceSquares, hostPrimes.Length);
|
||||
return new SmallPrimeFactorViews(devicePrimes, deviceSquares);
|
||||
}
|
||||
|
||||
public static GpuKernelLease Rent()
|
||||
{
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
var gpu = GpuContextPool.Rent();
|
||||
var stream = gpu.Accelerator.CreateStream();
|
||||
var kernels = GetKernels(gpu.Accelerator, stream);
|
||||
return GpuKernelLease.Rent(gpu, stream, kernels);
|
||||
var stream = SharedGpuContext.Accelerator.CreateStream();
|
||||
return GpuKernelLease.Rent(stream, Kernels);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -130,7 +151,7 @@ public class GpuKernelPool
|
||||
public static void Run(Action<Accelerator, AcceleratorStream> action)
|
||||
{
|
||||
var lease = Rent();
|
||||
var accelerator = lease.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = lease.Stream;
|
||||
action(accelerator, stream);
|
||||
lease.Dispose();
|
||||
|
||||
@@ -16,7 +16,7 @@ internal static class GpuStaticTableInitializer
|
||||
Initialized.GetOrAdd(accelerator, acc =>
|
||||
{
|
||||
PrimeTester.PrimeTesterGpuContextPool.EnsureStaticTables(kernels, acc, stream);
|
||||
GpuKernelPool.PreloadStaticTables(kernels, acc, stream);
|
||||
GpuKernelPool.PreloadStaticTables(kernels, stream);
|
||||
PrimeOrderGpuHeuristics.PreloadStaticTables( acc, stream);
|
||||
return 0;
|
||||
});
|
||||
|
||||
@@ -96,7 +96,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
||||
ulong lastProcessed;
|
||||
|
||||
var gpuLease = GpuKernelPool.Rent();
|
||||
var accelerator = gpuLease.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = gpuLease.Stream;
|
||||
|
||||
// Monitor.Enter(gpuLease.ExecutionLock);
|
||||
@@ -502,7 +502,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
||||
{
|
||||
_owner = owner;
|
||||
_lease = GpuKernelPool.Rent();
|
||||
_accelerator = _lease.Accelerator;
|
||||
_accelerator = SharedGpuContext.Accelerator;
|
||||
_stream = _lease.Stream;
|
||||
_capacity = Math.Max(1, owner._gpuBatchSize);
|
||||
}
|
||||
|
||||
@@ -43,8 +43,7 @@ public sealed class MersenneNumberDivisorGpuTester
|
||||
|
||||
public bool IsDivisible(ulong exponent, in ReadOnlyGpuUInt128 divisor)
|
||||
{
|
||||
var gpu = GpuContextPool.Rent();
|
||||
var accelerator = gpu.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = accelerator.CreateStream();
|
||||
var kernel = GetKernel(accelerator);
|
||||
var resultBuffer = _resultBuffers.GetOrAdd(accelerator, acc => acc.Allocate1D<byte>(1));
|
||||
@@ -56,11 +55,10 @@ public sealed class MersenneNumberDivisorGpuTester
|
||||
stream.Synchronize();
|
||||
bool divisible = result[0] != 0;
|
||||
stream.Dispose();
|
||||
gpu.Dispose();
|
||||
return divisible;
|
||||
}
|
||||
|
||||
private static (ulong divisor, uint cycle)[]? _divisorCandidates = Array.Empty<(ulong divisor, uint cycle)>();
|
||||
private static (ulong divisor, uint cycle)[]? _divisorCandidates = [];
|
||||
|
||||
public bool IsPrime(ulong p, UInt128 d, ulong divisorCyclesSearchLimit, out bool divisorsExhausted)
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
|
||||
throw new NotImplementedException($"GPU incremental scanning requires the device cycle heuristics implementation (kernel: {_kernelType}, GPU order: {_useGpuOrder}).");
|
||||
|
||||
var gpuLease = GpuKernelPool.Rent();
|
||||
var accelerator = gpuLease.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = gpuLease.Stream;
|
||||
int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy
|
||||
UInt128 kStart = 1UL;
|
||||
@@ -31,11 +31,11 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
|
||||
ulong step3 = ((exponent % 3UL) << 1) % 3UL;
|
||||
ulong step5 = ((exponent % 5UL) << 1) % 5UL;
|
||||
GpuUInt128 twoPGpu = (GpuUInt128)twoP;
|
||||
var smallCyclesView = GpuKernelPool.EnsureSmallCyclesOnDevice(gpuLease.Kernels, accelerator, stream);
|
||||
var smallCyclesView = GpuKernelPool.GetSmallCyclesOnDevice();
|
||||
ResiduePrimeViews primeViews = default;
|
||||
if (_kernelType == GpuKernelType.Pow2Mod)
|
||||
{
|
||||
primeViews = GpuKernelPool.EnsureSmallPrimesOnDevice(gpuLease.Kernels, accelerator, stream);
|
||||
primeViews = GpuKernelPool.GetSmallPrimesOnDevice();
|
||||
}
|
||||
|
||||
var orderBuffer = accelerator.Allocate1D<ulong>(batchSize);
|
||||
|
||||
@@ -97,8 +97,7 @@ public class MersenneNumberLucasLehmerGpuTester
|
||||
}
|
||||
else
|
||||
{
|
||||
var gpu = GpuContextPool.Rent();
|
||||
var accelerator = gpu.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = accelerator.CreateStream();
|
||||
var kernel = GetKernel(accelerator);
|
||||
var modulus = new GpuUInt128(((UInt128)1 << (int)exponent) - 1UL); // TODO: Cache these Mersenne moduli per exponent so LL GPU runs skip rebuilding them every launch.
|
||||
@@ -109,7 +108,6 @@ public class MersenneNumberLucasLehmerGpuTester
|
||||
result = buffer.GetAsArray1D()[0].IsZero;
|
||||
buffer.Dispose();
|
||||
stream.Dispose();
|
||||
gpu.Dispose();
|
||||
}
|
||||
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
@@ -132,8 +130,7 @@ public class MersenneNumberLucasLehmerGpuTester
|
||||
}
|
||||
}
|
||||
|
||||
var gpu = GpuContextPool.Rent();
|
||||
var accelerator = gpu.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = accelerator.CreateStream();
|
||||
var kernel = GetBatchKernel(accelerator);
|
||||
|
||||
@@ -166,7 +163,6 @@ public class MersenneNumberLucasLehmerGpuTester
|
||||
gpuUInt128Pool.Return(modulusArray);
|
||||
ulongPool.Return(expArray);
|
||||
stream.Dispose();
|
||||
gpu.Dispose();
|
||||
}
|
||||
|
||||
public void IsMersennePrimeBatch(ReadOnlySpan<ulong> exponents, Span<bool> results)
|
||||
@@ -189,9 +185,9 @@ public class MersenneNumberLucasLehmerGpuTester
|
||||
|
||||
private bool IsMersennePrimeNtt(ulong exponent, GpuUInt128 nttMod, GpuUInt128 primitiveRoot, bool runOnGpu)
|
||||
{
|
||||
var gpu = GpuContextPool.Rent();
|
||||
var accelerator = gpu.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = accelerator.CreateStream();
|
||||
|
||||
var addKernel = GetAddSmallKernel(accelerator);
|
||||
var subKernel = GetSubSmallKernel(accelerator);
|
||||
var reduceKernel = GetReduceKernel(accelerator);
|
||||
@@ -240,7 +236,6 @@ public class MersenneNumberLucasLehmerGpuTester
|
||||
resultBuffer.Dispose();
|
||||
stateBuffer.Dispose();
|
||||
stream.Dispose();
|
||||
gpu.Dispose();
|
||||
return isPrime;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
|
||||
public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
|
||||
{
|
||||
var gpuLease = GpuKernelPool.Rent();
|
||||
var accelerator = gpuLease.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = gpuLease.Stream;
|
||||
int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy and avoids TDR
|
||||
UInt128 kStart = UInt128.One;
|
||||
@@ -30,7 +30,7 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
|
||||
int currentSize;
|
||||
int found = 0;
|
||||
|
||||
var smallCyclesView = GpuKernelPool.EnsureSmallCyclesOnDevice(gpuLease.Kernels, accelerator, stream);
|
||||
var smallCyclesView = GpuKernelPool.GetSmallCyclesOnDevice();
|
||||
while (kStart <= maxK && Volatile.Read(ref isPrime))
|
||||
{
|
||||
remaining = maxK - kStart + 1UL;
|
||||
|
||||
@@ -14,7 +14,6 @@ namespace PerfectNumbers.Core.Gpu;
|
||||
public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
||||
{
|
||||
private readonly bool _useGpuOrder = useGpuOrder;
|
||||
private readonly ConcurrentBag<GpuContextLease> _acceleratorPool = new();
|
||||
private readonly ConcurrentDictionary<Accelerator, 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>>> _pow2ModKernelCache = new(AcceleratorReferenceComparer.Instance);
|
||||
private readonly ConcurrentDictionary<Accelerator, ConcurrentBag<ResidueResources>> _resourcePools = new(AcceleratorReferenceComparer.Instance);
|
||||
|
||||
@@ -28,15 +27,14 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
||||
public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
|
||||
{
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
var gpuLease = RentAccelerator();
|
||||
var accelerator = gpuLease.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
|
||||
// Monitor.Enter(gpuLease.ExecutionLock);
|
||||
|
||||
var stream = accelerator.CreateStream();
|
||||
var kernel = GetPow2ModKernel(accelerator);
|
||||
var resources = RentResources(accelerator, GpuConstants.ScanBatchSize);
|
||||
var gpuKernels = GpuKernelPool.GetKernels(accelerator, stream);
|
||||
var gpuKernels = GpuKernelPool.Kernels;
|
||||
|
||||
var orderBuffer = resources.OrderBuffer;
|
||||
ulong[] orderArray = resources.OrderArray;
|
||||
@@ -44,8 +42,8 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
||||
|
||||
// Ensure device has small cycles and primes tables for in-kernel lookup
|
||||
// TODO: Pass-in the stream down the path
|
||||
var smallCyclesView = GpuKernelPool.EnsureSmallCyclesOnDevice(gpuKernels, accelerator, stream);
|
||||
ResiduePrimeViews primeViews = GpuKernelPool.EnsureSmallPrimesOnDevice(gpuKernels, accelerator, stream);
|
||||
var smallCyclesView = GpuKernelPool.GetSmallCyclesOnDevice();
|
||||
ResiduePrimeViews primeViews = GpuKernelPool.GetSmallPrimesOnDevice();
|
||||
|
||||
UInt128 kStart = 1UL;
|
||||
UInt128 limit = maxK + UInt128.One;
|
||||
@@ -114,7 +112,6 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
||||
stream.Dispose();
|
||||
// Monitor.Exit(gpuLease.ExecutionLock);
|
||||
gpuKernels.Dispose();
|
||||
ReturnAccelerator(gpuLease);
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
}
|
||||
|
||||
@@ -130,18 +127,6 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
||||
loaded.Method);
|
||||
});
|
||||
|
||||
private GpuContextLease RentAccelerator()
|
||||
{
|
||||
if (_acceleratorPool.TryTake(out var lease))
|
||||
{
|
||||
return lease;
|
||||
}
|
||||
|
||||
return GpuContextPool.Rent();
|
||||
}
|
||||
|
||||
private void ReturnAccelerator(GpuContextLease lease) => _acceleratorPool.Add(lease);
|
||||
|
||||
private ResidueResources RentResources(Accelerator accelerator, int capacity)
|
||||
{
|
||||
var bag = _resourcePools.GetOrAdd(accelerator, static _ => []);
|
||||
|
||||
@@ -504,8 +504,7 @@ public static class NttGpuMath
|
||||
{
|
||||
int n = values.Length;
|
||||
int bits = (int)Math.Log2(n);
|
||||
var gpu = GpuContextPool.Rent();
|
||||
var accelerator = gpu.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var kernel = GetBitReverseKernel(accelerator);
|
||||
var pool = ThreadStaticPools.GpuUInt128Pool;
|
||||
var array = pool.Rent(n);
|
||||
@@ -520,7 +519,6 @@ public static class NttGpuMath
|
||||
pool.Return(array, clearArray: true);
|
||||
buffer.Dispose();
|
||||
stream.Dispose();
|
||||
gpu.Dispose();
|
||||
|
||||
}
|
||||
|
||||
@@ -568,8 +566,7 @@ public static class NttGpuMath
|
||||
private static void ForwardGpuReference(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
|
||||
{
|
||||
int n = (int)values.Length;
|
||||
var gpu = GpuContextPool.Rent();
|
||||
var accelerator = gpu.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = accelerator.CreateStream();
|
||||
var kernel = GetForwardKernel(accelerator);
|
||||
var pool = ThreadStaticPools.GpuUInt128Pool;
|
||||
@@ -592,8 +589,6 @@ public static class NttGpuMath
|
||||
outputBuffer.Dispose();
|
||||
inputBuffer.Dispose();
|
||||
stream.Dispose();
|
||||
gpu.Dispose();
|
||||
|
||||
}
|
||||
|
||||
public static void Inverse(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
|
||||
@@ -667,8 +662,7 @@ public static class NttGpuMath
|
||||
private static void InverseGpuReference(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
|
||||
{
|
||||
int n = values.Length;
|
||||
var gpu = GpuContextPool.Rent();
|
||||
var accelerator = gpu.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = accelerator.CreateStream();
|
||||
var kernel = GetInverseKernel(accelerator);
|
||||
var pool = ThreadStaticPools.GpuUInt128Pool;
|
||||
@@ -710,15 +704,12 @@ public static class NttGpuMath
|
||||
outputBuffer.Dispose();
|
||||
inputBuffer.Dispose();
|
||||
stream.Dispose();
|
||||
gpu.Dispose();
|
||||
|
||||
}
|
||||
|
||||
private static void ForwardGpuStaged(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
|
||||
{
|
||||
int n = values.Length;
|
||||
var gpu = GpuContextPool.Rent();
|
||||
var accelerator = gpu.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = accelerator.CreateStream();
|
||||
var buffer = accelerator.Allocate1D<GpuUInt128>(n);
|
||||
buffer.View.CopyFromCPU(stream, ref values[0], n);
|
||||
@@ -728,15 +719,12 @@ public static class NttGpuMath
|
||||
stream.Synchronize();
|
||||
stream.Dispose();
|
||||
buffer.Dispose();
|
||||
gpu.Dispose();
|
||||
|
||||
}
|
||||
|
||||
private static void InverseGpuStaged(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
|
||||
{
|
||||
int n = values.Length;
|
||||
var gpu = GpuContextPool.Rent();
|
||||
var accelerator = gpu.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = accelerator.CreateStream();
|
||||
var buffer = accelerator.Allocate1D<GpuUInt128>(n);
|
||||
buffer.View.CopyFromCPU(stream, ref values[0], n);
|
||||
@@ -746,8 +734,6 @@ public static class NttGpuMath
|
||||
stream.Synchronize();
|
||||
stream.Dispose();
|
||||
buffer.Dispose();
|
||||
gpu.Dispose();
|
||||
|
||||
}
|
||||
|
||||
private static void ForwardDevice(Accelerator accelerator, AcceleratorStream stream, ArrayView<GpuUInt128> data, int length, GpuUInt128 modulus, SquareCacheEntry cache)
|
||||
@@ -939,8 +925,7 @@ public static class NttGpuMath
|
||||
|
||||
public static void PointwiseMultiply(Span<GpuUInt128> left, Span<GpuUInt128> right, GpuUInt128 modulus)
|
||||
{
|
||||
var gpu = GpuContextPool.Rent();
|
||||
var accelerator = gpu.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = accelerator.CreateStream();
|
||||
var kernel = GetMulKernel(accelerator);
|
||||
var pool = ThreadStaticPools.GpuUInt128Pool;
|
||||
@@ -963,8 +948,6 @@ public static class NttGpuMath
|
||||
rightBuffer.Dispose();
|
||||
leftBuffer.Dispose();
|
||||
stream.Dispose();
|
||||
gpu.Dispose();
|
||||
|
||||
}
|
||||
|
||||
private static ulong[] GenerateSmallPrimes(int limit)
|
||||
|
||||
@@ -199,7 +199,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
||||
try
|
||||
{
|
||||
var lease = GpuKernelPool.Rent();
|
||||
Accelerator accelerator = lease.Accelerator;
|
||||
Accelerator accelerator = SharedGpuContext.Accelerator;
|
||||
AcceleratorStream stream = lease.Stream;
|
||||
|
||||
var kernel = GetPartialFactorKernel(accelerator);
|
||||
@@ -366,7 +366,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
||||
order = 0UL;
|
||||
|
||||
var lease = GpuKernelPool.Rent();
|
||||
Accelerator accelerator = lease.Accelerator;
|
||||
Accelerator accelerator = SharedGpuContext.Accelerator;
|
||||
AcceleratorStream stream = lease.Stream;
|
||||
|
||||
var kernel = GetOrderKernel(accelerator);
|
||||
@@ -527,7 +527,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
||||
private static bool TryComputeOnGpu(ReadOnlySpan<ulong> exponents, ulong prime, in MontgomeryDivisorData divisorData, Span<ulong> results)
|
||||
{
|
||||
var lease = GpuKernelPool.Rent();
|
||||
Accelerator accelerator = lease.Accelerator;
|
||||
Accelerator accelerator = SharedGpuContext.Accelerator;
|
||||
AcceleratorStream stream = lease.Stream;
|
||||
var kernel = GetPow2ModKernel(accelerator);
|
||||
// TODO: These buffers should be allocated once per accelerator and only reallocated when the new length exceeds capacity.
|
||||
@@ -586,7 +586,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
||||
|
||||
try
|
||||
{
|
||||
Accelerator accelerator = lease.Accelerator;
|
||||
Accelerator accelerator = SharedGpuContext.Accelerator;
|
||||
AcceleratorStream stream = lease.Stream;
|
||||
var kernel = GetPow2ModWideKernel(accelerator);
|
||||
// TODO: These buffers should be allocated once per accelerator and only reallocated when the new length exceeds capacity.
|
||||
|
||||
@@ -6,12 +6,11 @@ namespace PerfectNumbers.Core.Gpu;
|
||||
|
||||
public readonly struct SmallPrimeFactorViews(
|
||||
MemoryBuffer1D<uint, Stride1D.Dense> primes,
|
||||
MemoryBuffer1D<ulong, Stride1D.Dense> squares,
|
||||
int count)
|
||||
MemoryBuffer1D<ulong, Stride1D.Dense> squares)
|
||||
{
|
||||
public readonly MemoryBuffer1D<uint, Stride1D.Dense> Primes = primes;
|
||||
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> Squares = squares;
|
||||
public readonly int Count = count;
|
||||
public readonly int Count = (int)primes.Length;
|
||||
|
||||
public ArrayView1D<uint, Stride1D.Dense> PrimesView
|
||||
{
|
||||
|
||||
@@ -805,7 +805,7 @@ public class MersenneDivisorCycles
|
||||
divisors = pool.Rent(count);
|
||||
outCycles = pool.Rent(count);
|
||||
var lease = GpuKernelPool.Rent();
|
||||
var accelerator = lease.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = lease.Stream;
|
||||
var loaded = accelerator.LoadAutoGroupedStreamKernel<
|
||||
Index1D,
|
||||
|
||||
@@ -148,7 +148,7 @@ public sealed class MersenneNumberTester(
|
||||
UInt128[] qs = qsBuffer;
|
||||
|
||||
var gpuLease = GpuKernelPool.Rent();
|
||||
var accelerator = gpuLease.Accelerator;
|
||||
var accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = gpuLease.Stream;
|
||||
var orderKernel = gpuLease.OrderKernel!;
|
||||
|
||||
|
||||
@@ -20,13 +20,13 @@ internal static partial class PrimeOrderCalculator
|
||||
remaining = value;
|
||||
|
||||
var lease = GpuKernelPool.Rent();
|
||||
Accelerator accelerator = lease.Accelerator;
|
||||
Accelerator accelerator = SharedGpuContext.Accelerator;
|
||||
var stream = lease.Stream;
|
||||
KernelContainer kernels = lease.Kernels;
|
||||
|
||||
ScratchBuffer scratch = GpuScratchBufferPool.Rent(accelerator, GpuSmallPrimeFactorSlots, 0);
|
||||
|
||||
SmallPrimeFactorViews tables = GpuKernelPool.EnsureSmallPrimeFactorTables(kernels, accelerator, stream);
|
||||
SmallPrimeFactorViews tables = GpuKernelPool.GetSmallPrimeFactorTables();
|
||||
|
||||
if (kernels.SmallPrimeFactorsPrimes is null) throw new NullReferenceException($"{nameof(kernels.SmallPrimeFactorsPrimes)} is null");
|
||||
if (kernels.SmallPrimeFactorsSquares is null) throw new NullReferenceException($"{nameof(kernels.SmallPrimeFactorsSquares)} is null");
|
||||
@@ -101,7 +101,7 @@ internal static partial class PrimeOrderCalculator
|
||||
}
|
||||
|
||||
GpuKernelLease lease = GpuKernelPool.Rent();
|
||||
Accelerator accelerator = lease.Accelerator;
|
||||
Accelerator accelerator = SharedGpuContext.Accelerator;
|
||||
|
||||
var stream = lease.Stream;
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ public sealed class PrimeTester
|
||||
|
||||
Accelerator accelerator = SharedGpuContext.Accelerator;
|
||||
AcceleratorStream stream = accelerator.CreateStream();
|
||||
KernelContainer kernels = GpuKernelPool.GetKernels(accelerator, stream);
|
||||
KernelContainer kernels = GpuKernelPool.Kernels;
|
||||
|
||||
GpuStaticTableInitializer.EnsureStaticTables(kernels, accelerator, stream);
|
||||
|
||||
@@ -433,7 +433,7 @@ public sealed class PrimeTester
|
||||
AcceleratorContext = SharedGpuContext.Context;
|
||||
Accelerator = SharedGpuContext.Accelerator;
|
||||
AcceleratorStream stream = SharedGpuContext.Accelerator.CreateStream();
|
||||
var kernels = GpuKernelPool.GetKernels(Accelerator, stream);
|
||||
var kernels = GpuKernelPool.Kernels;
|
||||
GpuStaticTableInitializer.EnsureStaticTables(kernels, Accelerator, stream);
|
||||
|
||||
_sharedTables = RentSharedTables(Accelerator, stream);
|
||||
|
||||
@@ -463,7 +463,7 @@ public static partial class ULongExtensions
|
||||
|
||||
GpuKernelLease lease = GpuKernelPool.Rent();
|
||||
|
||||
Accelerator accelerator = lease.Accelerator;
|
||||
Accelerator accelerator = SharedGpuContext.Accelerator;
|
||||
AcceleratorStream stream = lease.Stream;
|
||||
var kernelGroup = Kernel;
|
||||
|
||||
|
||||
Reference in new issue
Block a user