Performance improvements

This commit is contained in:
mlemanczyk committed 2025-11-13 00:51:32 +01:00
1 parent 5bc65464d0
commit 43863d03fb
11 files changed
+127 -86

No files matched your search

@@ -1,24 +1,26 @@
using System.Collections.Concurrent;
using ILGPU.Runtime;
using Open.Collections;
namespace PerfectNumbers.Core.Gpu.Accelerators;
public static class AcceleratorStreamPool
{
private static readonly ConcurrentDictionary<Accelerator, ConcurrentQueue<AcceleratorStream>> _streams = new(20_480, PerfectNumberConstants.RollingAccelerators);
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 SemaphoreSlim CreateLock() => new(PerfectNumberConstants.ThreadsByStream);
private static AcceleratorStream CreateStream(Accelerator accelerator) => accelerator.CreateStream();
private static readonly ConcurrentDictionary<Accelerator, SemaphoreSlim> _locks = new(AcceleratorPool.Shared.Accelerators.ToDictionary(x => x, static x => CreateLock()));
private static readonly Dictionary<Accelerator, SemaphoreSlim> _locks = new(AcceleratorPool.Shared.Accelerators.ToDictionary(x => x, static x => CreateLock()));
public static AcceleratorStream Rent(Accelerator accelerator)
{
var streamLock = _locks.GetOrAdd(accelerator, static _ => new SemaphoreSlim(PerfectNumberConstants.ThreadsByStream));
var streamLock = _locks[accelerator];
// var streamLock = _locks.GetOrAdd(accelerator, static _ => CreateLock());
streamLock.Wait();
var queue = _streams.GetOrAdd(accelerator, static _ => new());
var queue = _streams[accelerator];
return queue.TryDequeue(out var stream)
? stream
@@ -28,9 +30,23 @@ public static class AcceleratorStreamPool
public static void Return(AcceleratorStream stream)
{
Accelerator accelerator = stream.Accelerator;
var streamLock = _locks.GetOrAdd(accelerator, static _ => CreateLock());
var queue = _streams.GetOrAdd(accelerator, static _ => new());
var streamLock = _locks[accelerator];
var queue = _streams[accelerator];
queue.Enqueue(stream);
streamLock.Release();
}
public static void WarmUp(Accelerator accelerator)
{
_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();
}
}
@@ -72,6 +72,8 @@ public sealed class Pow2MontgomeryAccelerator
{
Console.WriteLine($"Preparing accelerator {i}...");
var accelerator = accelerators[i];
AcceleratorStreamPool.WarmUp(accelerator);
// AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator);
AcceleratorStream stream = accelerator.CreateStream();
LastDigitGpuTables.EnsureStaticTables(accelerator, stream);
// SharedHeuristicGpuTables.EnsureStaticTables(accelerator, stream);
@@ -80,6 +82,8 @@ public sealed class Pow2MontgomeryAccelerator
// GpuStaticTableInitializer.EnsureStaticTables(accelerator, kernels, stream);
stream.Synchronize();
stream.Dispose();
// AcceleratorStreamPool.Return(stream);
}
}
+2 -7
View File
@@ -142,14 +142,9 @@ public class GpuKernelPool
static void InitSmallPrimeFactorKernelScan(Accelerator accelerator, KernelContainer kernels)
{
InitOnce(ref kernels.SmallPrimeFactor, () =>
{
var loaded = 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 loaded = 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>>>();
});
kernels.SmallPrimeFactor = KernelUtil.GetKernel(loaded);
}
}
+42 -16
View File
@@ -1,23 +1,20 @@
using System.Collections.Concurrent;
using ILGPU;
using ILGPU.Runtime;
namespace PerfectNumbers.Core.Gpu;
public sealed class ScratchBuffer
public sealed class GpuScratchBuffer
{
public MemoryBuffer1D<ulong, Stride1D.Dense> SmallPrimeFactorPrimeSlots { get; private set; }
public MemoryBuffer1D<int, Stride1D.Dense> SmallPrimeFactorExponentSlots { get; private set; }
public MemoryBuffer1D<int, Stride1D.Dense> SmallPrimeFactorCountSlot { get; private set; }
public MemoryBuffer1D<ulong, Stride1D.Dense> SmallPrimeFactorRemainingSlot { get; private set; }
public MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxFactors { get; private set; }
public MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxCandidates { get; private set; }
public MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxResult { get; private set; }
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 ScratchBuffer(Accelerator accelerator, int smallPrimeFactorSlotCount, int specialMaxFactorCapacity)
public GpuScratchBuffer(Accelerator accelerator, int smallPrimeFactorSlotCount, int specialMaxFactorCapacity)
{
_accelerator = accelerator;
@@ -63,18 +60,29 @@ public sealed class ScratchBuffer
}
}
}
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<ScratchBuffer>>? _pools;
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 ScratchBuffer Rent(Accelerator accelerator, int smallPrimeFactorSlotCount, int specialMaxFactorCapacity)
public static GpuScratchBuffer Rent(Accelerator accelerator, int smallPrimeFactorSlotCount, int specialMaxFactorCapacity)
{
const int WarmUpCapacity = 100;
// var pool = _pools.GetOrAdd(accelerator, _ => new ConcurrentQueue<ScratchBuffer>());
@@ -107,10 +115,10 @@ public static class GpuScratchBufferPool
return buffer;
}
return new ScratchBuffer(accelerator, smallPrimeFactorSlotCount, specialMaxFactorCapacity);
return new GpuScratchBuffer(accelerator, smallPrimeFactorSlotCount, specialMaxFactorCapacity);
}
public static void Return(ScratchBuffer buffer)
public static void Return(GpuScratchBuffer buffer)
{
if (_pools!.TryGetValue(buffer._accelerator, out var pool))
{
@@ -128,4 +136,22 @@ public static class GpuScratchBufferPool
// 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;
}
}
}
+1 -1
View File
@@ -22,7 +22,7 @@ public sealed class KernelContainer
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 Kernel? SmallPrimeFactor;
public Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>? SpecialMax;
@@ -27,6 +27,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);
@@ -83,6 +84,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);