GpuScratchBuffer / -Pool naively integrated with PriemOrderCalculatorAccelerator (formerly Pow2MontgomeryAccelerator). FactorEntry replaced with 2 arrays - unused field removed. Small cleanup.

This commit is contained in:
mlemanczyk committed 2025-11-13 14:41:27 +01:00
1 parent 43863d03fb
commit c53aa517f7
14 files changed
+295 -420

No files matched your search

@@ -6,21 +6,20 @@ namespace PerfectNumbers.Core.Gpu.Accelerators;
public static class AcceleratorStreamPool
{
private static readonly Dictionary<Accelerator, ConcurrentQueue<AcceleratorStream>> _streams = new(PerfectNumberConstants .RollingAccelerators);
// private static readonly ConcurrentDictionary<Accelerator, AcceleratorStream> _streams = new(AcceleratorPool.Shared.Accelerators.ToDictionary(static x => x, CreateStream));
private static readonly Dictionary<Accelerator, ConcurrentQueue<AcceleratorStream>> _streams = new(PerfectNumberConstants .RollingAccelerators << 1);
private static SemaphoreSlim CreateLock() => new(PerfectNumberConstants.ThreadsByStream);
private static AcceleratorStream CreateStream(Accelerator accelerator) => accelerator.CreateStream();
private static readonly Dictionary<Accelerator, SemaphoreSlim> _locks = new(AcceleratorPool.Shared.Accelerators.ToDictionary(x => x, static x => CreateLock()));
private static readonly Dictionary<Accelerator, SemaphoreSlim> _locks = new(PerfectNumberConstants.RollingAccelerators << 1);
// private static int _rented;
public static AcceleratorStream Rent(Accelerator accelerator)
{
var streamLock = _locks[accelerator];
// var streamLock = _locks.GetOrAdd(accelerator, static _ => CreateLock());
var queue = _streams[accelerator];
streamLock.Wait();
var queue = _streams[accelerator];
return queue.TryDequeue(out var stream)
? stream
@@ -40,13 +39,5 @@ public static class AcceleratorStreamPool
{
_streams.Add(accelerator, new());
_ = _locks.TryAdd(accelerator, CreateLock());
// ConcurrentQueue<AcceleratorStream> streamQueue = new();
// var stream = accelerator.CreateStream();
// // var stream = accelerator.CreateStream();
// streamQueue.Enqueue(stream);
// _streams[accelerator] = streamQueue;
// _locks[accelerator] = CreateLock();
// stream.Synchronize();
}
}
@@ -1,4 +1,4 @@
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using ILGPU;
using ILGPU.Runtime;
@@ -6,10 +6,13 @@ namespace PerfectNumbers.Core.Gpu.Accelerators;
internal sealed class LastDigitGpuTables
{
private static readonly ConcurrentDictionary<Accelerator, LastDigitGpuTables> _sharedTables = new(20_480, PerfectNumberConstants.RollingAccelerators * 2);
private static readonly Dictionary<Accelerator, LastDigitGpuTables> _sharedTables = new(PerfectNumberConstants.RollingAccelerators);
internal static LastDigitGpuTables EnsureStaticTables(Accelerator accelerator, AcceleratorStream stream)
=> _sharedTables.GetOrAdd(accelerator, _ => new LastDigitGpuTables(accelerator, stream));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static LastDigitGpuTables EnsureStaticTables(Accelerator accelerator) => _sharedTables[accelerator];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void WarmUp(Accelerator accelerator, AcceleratorStream stream) => _sharedTables[accelerator] = new LastDigitGpuTables(accelerator, stream);
internal LastDigitGpuTables(Accelerator accelerator, AcceleratorStream stream)
{
@@ -21,18 +24,14 @@ internal sealed class LastDigitGpuTables
var primesPow2LastSeven = DivisorGenerator.SmallPrimesPow2LastSeven;
var primesPow2LastThree = DivisorGenerator.SmallPrimesPow2LastThree;
var primesPow2LastNine = DivisorGenerator.SmallPrimesPow2LastNine;
// lock (accelerator)
{
DevicePrimesLastOne = accelerator.Allocate1D(stream, primesLastOne);
DevicePrimesLastSeven = accelerator.Allocate1D(stream, primesLastSeven);
DevicePrimesLastThree = accelerator.Allocate1D(stream, primesLastThree);
DevicePrimesLastNine = accelerator.Allocate1D(stream, primesLastNine);
DevicePrimesPow2LastOne = accelerator.Allocate1D(stream, primesPow2LastOne);
DevicePrimesPow2LastSeven = accelerator.Allocate1D(stream, primesPow2LastSeven);
DevicePrimesPow2LastThree = accelerator.Allocate1D(stream, primesPow2LastThree);
DevicePrimesPow2LastNine = accelerator.Allocate1D(stream, primesPow2LastNine);
}
DevicePrimesLastOne = accelerator.Allocate1D(stream, primesLastOne);
DevicePrimesLastSeven = accelerator.Allocate1D(stream, primesLastSeven);
DevicePrimesLastThree = accelerator.Allocate1D(stream, primesLastThree);
DevicePrimesLastNine = accelerator.Allocate1D(stream, primesLastNine);
DevicePrimesPow2LastOne = accelerator.Allocate1D(stream, primesPow2LastOne);
DevicePrimesPow2LastSeven = accelerator.Allocate1D(stream, primesPow2LastSeven);
DevicePrimesPow2LastThree = accelerator.Allocate1D(stream, primesPow2LastThree);
DevicePrimesPow2LastNine = accelerator.Allocate1D(stream, primesPow2LastNine);
}
internal readonly MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastOne;
@@ -5,27 +5,26 @@ using PerfectNumbers.Core.Gpu.Kernels;
namespace PerfectNumbers.Core.Gpu.Accelerators;
public sealed class Pow2MontgomeryAccelerator
public sealed class PrimeOrderCalculatorAccelerator
{
#region Pool
[ThreadStatic]
private static Queue<Pow2MontgomeryAccelerator>? _pool;
private static Queue<PrimeOrderCalculatorAccelerator>? _pool;
private static AcceleratorPool _accelerators = new(PerfectNumberConstants.RollingAccelerators);
private static readonly AcceleratorPool _accelerators = new(PerfectNumberConstants.RollingAccelerators);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Pow2MontgomeryAccelerator Rent(int primeTesterCapacity)
public static PrimeOrderCalculatorAccelerator Rent(int primeTesterCapacity)
{
var pool = _pool ??= [];
if (!pool.TryDequeue(out var gpu))
{
Accelerator accelerator = _accelerators.Rent();
gpu = new(accelerator, PerfectNumberConstants.DefaultFactorsBuffer, primeTesterCapacity);
gpu = new(accelerator, PerfectNumberConstants.DefaultFactorsBuffer, primeTesterCapacity, PerfectNumberConstants.DefaultSmallPrimeFactorSlotCount, PerfectNumberConstants.DefaultSpecialMaxFactorCapacity);
}
else
{
// gpu.Stream = gpu.Accelerator.CreateStream();
gpu.EnsureCapacity(PerfectNumberConstants.DefaultFactorsBuffer, primeTesterCapacity);
}
@@ -33,33 +32,28 @@ public sealed class Pow2MontgomeryAccelerator
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Return(Pow2MontgomeryAccelerator gpu)
{
// gpu.Stream!.Dispose();
// gpu.Stream = null;
_pool!.Enqueue(gpu);
}
public static void Return(PrimeOrderCalculatorAccelerator gpu) => _pool!.Enqueue(gpu);
internal static void Clear()
{
Queue<Pow2MontgomeryAccelerator>? pool = _pool;
Queue<PrimeOrderCalculatorAccelerator>? pool = _pool;
if (pool != null)
{
while (pool.TryDequeue(out var lease))
while (pool.TryDequeue(out var gpu))
{
lease.Dispose();
gpu.Dispose();
}
}
}
internal static void DisposeAll()
{
Queue<Pow2MontgomeryAccelerator>? pool = _pool;
Queue<PrimeOrderCalculatorAccelerator>? pool = _pool;
if (pool != null)
{
while (pool.TryDequeue(out var lease))
while (pool.TryDequeue(out var gpu))
{
lease.Dispose();
gpu.Dispose();
}
}
}
@@ -73,17 +67,15 @@ public sealed class Pow2MontgomeryAccelerator
Console.WriteLine($"Preparing accelerator {i}...");
var accelerator = accelerators[i];
AcceleratorStreamPool.WarmUp(accelerator);
// AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator);
// Don't take this from the pool as quick uploads of data to the accelerator consumes much of GPU's memory and throws.
AcceleratorStream stream = accelerator.CreateStream();
LastDigitGpuTables.EnsureStaticTables(accelerator, stream);
LastDigitGpuTables.WarmUp(accelerator, stream);
// SharedHeuristicGpuTables.EnsureStaticTables(accelerator, stream);
// _ = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.None);
// KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream);
// GpuStaticTableInitializer.EnsureStaticTables(accelerator, kernels, stream);
stream.Synchronize();
stream.Dispose();
// AcceleratorStreamPool.Return(stream);
}
}
@@ -105,31 +97,20 @@ public sealed class Pow2MontgomeryAccelerator
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastSeven;
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastThree;
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastNine;
public readonly MemoryBuffer1D<int, Stride1D.Dense> SmallPrimeFactorCountSlot;
public MemoryBuffer1D<int, Stride1D.Dense> SmallPrimeFactorExponentSlots;
public MemoryBuffer1D<ulong, Stride1D.Dense> SmallPrimeFactorPrimeSlots;
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> SmallPrimeFactorRemainingSlot;
public MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxCandidates;
public MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxFactors;
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxResult;
public readonly Kernel SmallPrimeSieveKernel;
// public AcceleratorStream? Stream;
public readonly Kernel CheckFactorsKernel;
public readonly Kernel ConvertToStandardKernel;
public readonly Kernel KeepMontgomeryKernel;
public readonly Kernel PollardRhoKernel;
[ThreadStatic]
private static Dictionary<Accelerator, Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>>? SmallPrimeSieveKernelPool;
internal static Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>> GetSmallPrimeSieveKernel(Accelerator accelerator)
{
var pool = SmallPrimeSieveKernelPool ??= [];
if (pool.TryGetValue(accelerator, out var cached))
{
return cached;
}
cached = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SmallPrimeSieveKernel)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>>();
pool[accelerator] = cached;
return cached;
}
public void EnsureCapacity(int factorsCount, int primeTesterCapacity)
{
if (factorsCount > Pow2ModEntriesToTestOnDevice.Length)
@@ -141,35 +122,62 @@ public sealed class Pow2MontgomeryAccelerator
if (primeTesterCapacity > PrimeTestInput.Length)
{
PrimeTestInput?.Dispose();
OutputByte?.Dispose();
HeuristicFlag?.Dispose();
PrimeTestInput.Dispose();
OutputByte.Dispose();
HeuristicFlag.Dispose();
// lock (Accelerator)
{
PrimeTestInput = Accelerator.Allocate1D<ulong>(primeTesterCapacity);
OutputByte = Accelerator.Allocate1D<byte>(primeTesterCapacity);
HeuristicFlag = Accelerator.Allocate1D<int>(primeTesterCapacity);
}
PrimeTestInput = Accelerator.Allocate1D<ulong>(primeTesterCapacity);
OutputByte = Accelerator.Allocate1D<byte>(primeTesterCapacity);
HeuristicFlag = Accelerator.Allocate1D<int>(primeTesterCapacity);
}
}
public Pow2MontgomeryAccelerator(Accelerator accelerator, int factorsCount, int primeTesterCapacity)
public void EnsureSmallPrimeFactorSlotsCapacity(int newSize)
{
// Console.WriteLine($"Resizing GPU scratch buffer from pool ({buffer.SmallPrimeFactorPrimeSlots.Length} / {smallPrimeFactorSlotCount}), ({buffer.SpecialMaxFactors.Length}/{specialMaxFactorCapacity})");
if (SmallPrimeFactorPrimeSlots.Length < newSize)
{
SmallPrimeFactorPrimeSlots.Dispose();
SmallPrimeFactorExponentSlots.Dispose();
var accelerator = Accelerator;
SmallPrimeFactorPrimeSlots = accelerator.Allocate1D<ulong>(newSize);
SmallPrimeFactorExponentSlots = accelerator.Allocate1D<int>(newSize);
}
}
public void EnsureSpecialMaxFactorsCapacity(int newSize)
{
if (SpecialMaxFactors.Length < newSize)
{
SpecialMaxFactors.Dispose();
SpecialMaxCandidates.Dispose();
var accelerator = Accelerator;
SpecialMaxFactors = accelerator.Allocate1D<ulong>(newSize);
SpecialMaxCandidates = accelerator.Allocate1D<ulong>(newSize);
}
}
public PrimeOrderCalculatorAccelerator(Accelerator accelerator, int factorsCount, int primeTesterCapacity, int smallPrimeFactorSlotCount, int specialMaxFactorCapacity)
{
Accelerator = accelerator;
AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator);
// AcceleratorStream stream = accelerator.DefaultStream;
// AcceleratorStream stream = accelerator.CreateStream();
// Stream = stream;
Input = accelerator.Allocate1D<ulong>(1);
OutputUlong = accelerator.Allocate1D<ulong>(1);
Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount);
PrimeTestInput = Accelerator.Allocate1D<ulong>(primeTesterCapacity);
OutputByte = Accelerator.Allocate1D<byte>(primeTesterCapacity);
HeuristicFlag = Accelerator.Allocate1D<int>(primeTesterCapacity);
SmallPrimeFactorPrimeSlots = accelerator.Allocate1D<ulong>(smallPrimeFactorSlotCount);
SmallPrimeFactorExponentSlots = accelerator.Allocate1D<int>(smallPrimeFactorSlotCount);
SmallPrimeFactorCountSlot = accelerator.Allocate1D<int>(1);
SmallPrimeFactorRemainingSlot = accelerator.Allocate1D<ulong>(1);
var sharedTables = LastDigitGpuTables.EnsureStaticTables(accelerator, stream);
SpecialMaxFactors = accelerator.Allocate1D<ulong>(specialMaxFactorCapacity);
SpecialMaxCandidates = accelerator.Allocate1D<ulong>(specialMaxFactorCapacity);
SpecialMaxResult = accelerator.Allocate1D<ulong>(1);
var sharedTables = LastDigitGpuTables.EnsureStaticTables(accelerator);
DevicePrimesLastOne = sharedTables.DevicePrimesLastOne;
DevicePrimesLastSeven = sharedTables.DevicePrimesLastSeven;
DevicePrimesLastThree = sharedTables.DevicePrimesLastThree;
@@ -191,27 +199,27 @@ public sealed class Pow2MontgomeryAccelerator
SmallPrimeSieveKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SmallPrimeSieveKernel));
PollardRhoKernel = KernelUtil.GetKernel(accelerator.LoadStreamKernel<ulong, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.TryPollardRhoKernel));
AcceleratorStreamPool.Return(stream);
}
public void Dispose()
{
Input.Dispose();
OutputUlong.Dispose();
// Stream?.Dispose();
Pow2ModEntriesToTestOnDevice.Dispose();
PrimeTestInput?.Dispose();
OutputByte?.Dispose();
HeuristicFlag?.Dispose();
// Stream is disposed upon return to the queue, so we don't need to dispose it here.
// Stream.Dispose();
PrimeTestInput.Dispose();
OutputByte.Dispose();
HeuristicFlag.Dispose();
SmallPrimeFactorPrimeSlots.Dispose();
SmallPrimeFactorExponentSlots.Dispose();
SmallPrimeFactorCountSlot.Dispose();
SmallPrimeFactorRemainingSlot.Dispose();
SpecialMaxFactors.Dispose();
SpecialMaxCandidates.Dispose();
SpecialMaxResult.Dispose();
// These resources are shared between GPU leases
// ReleaseSharedTables(_sharedTables);
// Stream.Dispose();
// Accelerator.Dispose();
// Context.Dispose();
// Accelerator.Dispose();
}
}
@@ -5,11 +5,11 @@ namespace PerfectNumbers.Core.Gpu;
public static class GpuPrimeWorkLimiter
{
private static SemaphoreSlim _semaphore = new(1, int.MaxValue);
private static int _currentLimit = 1;
private static SemaphoreSlim _semaphore = new(1, int.MaxValue);
private static int _currentLimit = 1;
public static void Acquire() => _semaphore.Wait();
public static void Release() => _semaphore.Release();
public static void Acquire() { } // => _semaphore.Wait();
public static void Release() { }// => _semaphore.Release();
public static void SetLimit(int value)
{
@@ -1,157 +0,0 @@
using ILGPU;
using ILGPU.Runtime;
namespace PerfectNumbers.Core.Gpu;
public sealed class GpuScratchBuffer
{
internal readonly Accelerator _accelerator;
public readonly MemoryBuffer1D<int, Stride1D.Dense> SmallPrimeFactorCountSlot;
public MemoryBuffer1D<int, Stride1D.Dense> SmallPrimeFactorExponentSlots;
public MemoryBuffer1D<ulong, Stride1D.Dense> SmallPrimeFactorPrimeSlots;
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> SmallPrimeFactorRemainingSlot;
public MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxCandidates;
public MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxFactors;
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxResult;
public GpuScratchBuffer(Accelerator accelerator, int smallPrimeFactorSlotCount, int specialMaxFactorCapacity)
{
_accelerator = accelerator;
// lock (accelerator)
{
SmallPrimeFactorPrimeSlots = accelerator.Allocate1D<ulong>(smallPrimeFactorSlotCount);
SmallPrimeFactorExponentSlots = accelerator.Allocate1D<int>(smallPrimeFactorSlotCount);
SmallPrimeFactorCountSlot = accelerator.Allocate1D<int>(1);
SmallPrimeFactorRemainingSlot = accelerator.Allocate1D<ulong>(1);
SpecialMaxFactors = accelerator.Allocate1D<ulong>(specialMaxFactorCapacity);
SpecialMaxCandidates = accelerator.Allocate1D<ulong>(specialMaxFactorCapacity);
SpecialMaxResult = accelerator.Allocate1D<ulong>(1);
}
}
public void ResizeSmallPrimeFactorSlots(int newSize)
{
if (SmallPrimeFactorPrimeSlots.Length < newSize)
{
SmallPrimeFactorPrimeSlots.Dispose();
SmallPrimeFactorExponentSlots.Dispose();
// lock(_accelerator)
{
SmallPrimeFactorPrimeSlots = _accelerator.Allocate1D<ulong>(newSize);
SmallPrimeFactorExponentSlots = _accelerator.Allocate1D<int>(newSize);
}
}
}
public void ResizeSpecialMaxFactors(int newSize)
{
if (SpecialMaxFactors.Length < newSize)
{
SpecialMaxFactors.Dispose();
SpecialMaxCandidates.Dispose();
// lock(_accelerator)
{
SpecialMaxFactors = _accelerator.Allocate1D<ulong>(newSize);
SpecialMaxCandidates = _accelerator.Allocate1D<ulong>(newSize);
}
}
}
internal void Dispose()
{
SmallPrimeFactorPrimeSlots.Dispose();
SmallPrimeFactorExponentSlots.Dispose();
SmallPrimeFactorCountSlot.Dispose();
SmallPrimeFactorRemainingSlot.Dispose();
SpecialMaxFactors.Dispose();
SpecialMaxCandidates.Dispose();
SpecialMaxResult.Dispose();
}
}
public static class GpuScratchBufferPool
{
[ThreadStatic]
private static Dictionary<Accelerator, Queue<GpuScratchBuffer>>? _pools;
// private static readonly ConcurrentDictionary<Accelerator, ConcurrentQueue<ScratchBuffer>> _pools = new();
private const int DefaultSmallPrimeFactorSlotCount = 64; // From PrimeOrderCalculator.Gpu.cs
private const int DefaultSpecialMaxFactorCapacity = 1024; // A reasonable default, will be resized if needed
public static GpuScratchBuffer Rent(Accelerator accelerator, int smallPrimeFactorSlotCount, int specialMaxFactorCapacity)
{
const int WarmUpCapacity = 100;
// var pool = _pools.GetOrAdd(accelerator, _ => new ConcurrentQueue<ScratchBuffer>());
if (_pools is not { })
{
_pools = new(WarmUpCapacity);
WarmUp(WarmUpCapacity, DefaultSmallPrimeFactorSlotCount, DefaultSpecialMaxFactorCapacity);
}
var pools = _pools;
if (!pools.TryGetValue(accelerator, out var pool))
{
pool = new();
pools[accelerator] = pool;
}
// var pool = _pools.GetOrAdd(accelerator, _ => new ConcurrentQueue<ScratchBuffer>());
if (pool.TryDequeue(out var buffer))
{
if (buffer.SmallPrimeFactorPrimeSlots.Length < smallPrimeFactorSlotCount || buffer.SpecialMaxFactors.Length < specialMaxFactorCapacity)
{
// throw new InvalidOperationException();
// lock (accelerator)
{
// Console.WriteLine($"Resizing GPU scratch buffer from pool ({buffer.SmallPrimeFactorPrimeSlots.Length} / {smallPrimeFactorSlotCount}), ({buffer.SpecialMaxFactors.Length}/{specialMaxFactorCapacity})");
buffer.ResizeSmallPrimeFactorSlots(smallPrimeFactorSlotCount);
buffer.ResizeSpecialMaxFactors(specialMaxFactorCapacity);
}
}
return buffer;
}
return new GpuScratchBuffer(accelerator, smallPrimeFactorSlotCount, specialMaxFactorCapacity);
}
public static void Return(GpuScratchBuffer buffer)
{
if (_pools!.TryGetValue(buffer._accelerator, out var pool))
{
pool.Enqueue(buffer);
}
}
public static void WarmUp(int count, int smallPrimeFactorSlots, int specialMaxFactorCapacity)
{
// Accelerator accelerator = SharedGpuContext.Accelerator;
// for (int i = 0; i < count; i++)
// {
// var buffer = Rent(accelerator, smallPrimeFactorSlots, specialMaxFactorCapacity);
// Return(buffer);
// }
}
public static void DisposeAll()
{
var pool = _pools;
if (pool is not null)
{
foreach (var queue in pool.Values)
{
while (queue.TryDequeue(out var buffer))
{
buffer.Dispose();
}
}
pool.Clear();
_pools = null;
}
}
}
@@ -12,10 +12,9 @@ public static class Pow2MontgomeryGpuCalculator
{
GpuPrimeWorkLimiter.Acquire();
var gpu = Pow2MontgomeryAccelerator.Rent(1);
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
Accelerator? accelerator = gpu.Accelerator;
AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator);
// AcceleratorStream stream = gpu.Stream!;
MemoryBuffer1D<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
@@ -27,7 +26,6 @@ public static class Pow2MontgomeryGpuCalculator
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
kernelLauncher(stream, 1, exponentBuffer.View, divisor, resultBuffer.View);
// kernel.Launch(stream, 1, 1, exponentBuffer.View, divisor, resultBuffer.View);
ulong result = 0UL;
resultBuffer.View.CopyToCPU(stream, ref result, 1);
@@ -35,7 +33,7 @@ public static class Pow2MontgomeryGpuCalculator
AcceleratorStreamPool.Return(stream);
GpuPrimeWorkLimiter.Release();
Pow2MontgomeryAccelerator.Return(gpu);
PrimeOrderCalculatorAccelerator.Return(gpu);
return result;
}
@@ -44,9 +42,8 @@ public static class Pow2MontgomeryGpuCalculator
{
GpuPrimeWorkLimiter.Acquire();
var gpu = Pow2MontgomeryAccelerator.Rent(1);
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
// AcceleratorStream stream = gpu.Stream!;
MemoryBuffer1D<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
@@ -64,15 +61,14 @@ public static class Pow2MontgomeryGpuCalculator
AcceleratorStreamPool.Return(stream);
GpuPrimeWorkLimiter.Release();
Pow2MontgomeryAccelerator.Return(gpu);
PrimeOrderCalculatorAccelerator.Return(gpu);
return result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong CalculateConvert(Pow2MontgomeryAccelerator gpu, ulong exponent, in MontgomeryDivisorData divisor)
public static ulong CalculateConvert(PrimeOrderCalculatorAccelerator gpu, ulong exponent, in MontgomeryDivisorData divisor)
{
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
// AcceleratorStream stream = gpu.Stream!;
MemoryBuffer1D<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
@@ -84,8 +80,7 @@ public static class Pow2MontgomeryGpuCalculator
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
kernelLauncher(stream, 1,exponentBuffer.View, divisor, resultBuffer.View);
// kernel.Launch(stream, 1, 1,exponentBuffer.View, divisor, resultBuffer.View);
ulong result = 0UL;
resultBuffer.View.CopyToCPU(stream, ref result, 1);
stream.Synchronize();