Performance improvements
This commit is contained in:
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user