Performance improvements
This commit is contained in:
1 parent
5bc65464d0
commit
43863d03fb
11 files changed
+127
-86
No files matched your search
@@ -7,6 +7,7 @@ using ILGPU;
|
||||
using ILGPU.Algorithms;
|
||||
using ILGPU.Runtime;
|
||||
using PerfectNumbers.Core.Gpu;
|
||||
using PerfectNumbers.Core.Gpu.Accelerators;
|
||||
|
||||
namespace PerfectNumbers.Core;
|
||||
|
||||
@@ -273,11 +274,7 @@ public sealed class DivisorCycleCache
|
||||
private void ComputeCyclesGpuCore(ReadOnlySpan<ulong> divisors, Span<ulong> destination)
|
||||
{
|
||||
int length = divisors.Length;
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
|
||||
Accelerator accelerator = _accelerator;
|
||||
var stream = accelerator.CreateStream();
|
||||
var kernel = _gpuKernel;
|
||||
EnsureCapacity(length);
|
||||
|
||||
ulong[]? rentedPow = null;
|
||||
@@ -300,9 +297,6 @@ public sealed class DivisorCycleCache
|
||||
? stackalloc byte[length]
|
||||
: new Span<byte>(rentedStatus = ThreadStaticPools.BytePool.Rent(length), 0, length);
|
||||
|
||||
ref ulong divisorRef = ref MemoryMarshal.GetReference(divisors);
|
||||
divisorBuffer!.View.CopyFromCPU(stream, ref divisorRef, length);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
ulong divisor = divisors[i];
|
||||
@@ -318,17 +312,22 @@ public sealed class DivisorCycleCache
|
||||
statusSpan[i] = ByteZero;
|
||||
}
|
||||
|
||||
powBuffer!.View.CopyFromCPU(stream, ref MemoryMarshal.GetReference(powSpan), length);
|
||||
orderBuffer!.View.CopyFromCPU(stream, ref MemoryMarshal.GetReference(orderSpan), length);
|
||||
resultBuffer!.View.CopyFromCPU(stream, ref MemoryMarshal.GetReference(resultSpan), length);
|
||||
statusBuffer!.View.CopyFromCPU(stream, ref MemoryMarshal.GetReference(statusSpan), length);
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
var stream = AcceleratorStreamPool.Rent(_accelerator);// accelerator.CreateStream();
|
||||
|
||||
divisorBuffer!.View.CopyFromCPU(stream, divisors);
|
||||
powBuffer!.View.CopyFromCPU(stream, powSpan);
|
||||
orderBuffer!.View.CopyFromCPU(stream, orderSpan);
|
||||
resultBuffer!.View.CopyFromCPU(stream, resultSpan);
|
||||
statusBuffer!.View.CopyFromCPU(stream, statusSpan);
|
||||
|
||||
int pending;
|
||||
var kernel = _gpuKernel;
|
||||
do
|
||||
{
|
||||
kernel(stream, length, _divisorCyclesBatchSize, divisorBuffer.View, powBuffer.View, orderBuffer.View, resultBuffer.View, statusBuffer.View);
|
||||
|
||||
statusBuffer.View.CopyToCPU(stream, ref MemoryMarshal.GetReference(statusSpan), length);
|
||||
statusBuffer.View.CopyToCPU(stream, statusSpan);
|
||||
stream.Synchronize();
|
||||
|
||||
pending = 0;
|
||||
@@ -342,9 +341,9 @@ public sealed class DivisorCycleCache
|
||||
}
|
||||
while (pending > 0);
|
||||
|
||||
resultBuffer.View.CopyToCPU(stream, ref MemoryMarshal.GetReference(resultSpan), length);
|
||||
resultBuffer.View.CopyToCPU(stream,resultSpan);
|
||||
stream.Synchronize();
|
||||
stream.Dispose();
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
|
||||
resultSpan.CopyTo(destination);
|
||||
if (rentedPow is not null)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Threading.Tasks;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using PerfectNumbers.Core.Gpu.Accelerators;
|
||||
using PerfectNumbers.Core.Gpu;
|
||||
|
||||
namespace PerfectNumbers.Core;
|
||||
|
||||
@@ -304,6 +305,7 @@ public static class MersenneNumberDivisorByDivisorTester
|
||||
|
||||
Console.WriteLine($"Task finished for range {rangeStart}");
|
||||
Pow2MontgomeryAccelerator.DisposeAll();
|
||||
GpuScratchBufferPool.DisposeAll();
|
||||
},
|
||||
CancellationToken.None,
|
||||
TaskCreationOptions.DenyChildAttach,
|
||||
|
||||
@@ -86,7 +86,7 @@ internal static partial class PrimeOrderCalculator
|
||||
ulong phi,
|
||||
PartialFactorResult phiFactors)
|
||||
{
|
||||
if (phiFactors.FullyFactored && TrySpecialMaxCpu(phi, prime, phiFactors, divisorData))
|
||||
if (phiFactors.FullyFactored && TrySpecialMaxCpu(gpu, phi, prime, phiFactors, divisorData))
|
||||
{
|
||||
return phi;
|
||||
}
|
||||
@@ -119,7 +119,7 @@ internal static partial class PrimeOrderCalculator
|
||||
}
|
||||
|
||||
// private static ulong specialMaxHits;
|
||||
private static bool TrySpecialMaxCpu(ulong phi, ulong prime, PartialFactorResult factors, in MontgomeryDivisorData divisorData)
|
||||
private static bool TrySpecialMaxCpu(Pow2MontgomeryAccelerator gpu, ulong phi, ulong prime, PartialFactorResult factors, in MontgomeryDivisorData divisorData)
|
||||
{
|
||||
int length = factors.Count;
|
||||
// The phi factorization on the scanner path always yields at least one entry for phi >= 2,
|
||||
@@ -140,7 +140,7 @@ internal static partial class PrimeOrderCalculator
|
||||
|
||||
// Atomic.Add(ref specialMaxHits, 1);
|
||||
// Console.WriteLine($"Special max GPU hit {specialMaxHits} ({length})");
|
||||
return EvaluateSpecialMaxCandidatesGpu(stackBuffer, factorSpan, phi, prime, divisorData);
|
||||
return EvaluateSpecialMaxCandidatesGpu(gpu, stackBuffer, factorSpan, phi, prime, divisorData);
|
||||
}
|
||||
|
||||
private static bool EvaluateSpecialMaxCandidates(Span<ulong> buffer, ReadOnlySpan<FactorEntry> factors, ulong phi, ulong prime, in MontgomeryDivisorData divisorData)
|
||||
|
||||
@@ -39,18 +39,18 @@ internal static partial class PrimeOrderCalculator
|
||||
|
||||
entries.Sort(entries, static (a, b) => a.Key.CompareTo(b.Key));
|
||||
|
||||
// AcceleratorStream stream = gpu.Stream!;
|
||||
ulong order = phi;
|
||||
var kernel = gpu.CheckFactorsKernel;
|
||||
gpu.EnsureCapacity(entryCount, 1);
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
||||
gpu.Pow2ModEntriesToTestOnDevice.View.CopyFromCPU(stream, entries);
|
||||
|
||||
ulong order = phi;
|
||||
var kernel = gpu.CheckFactorsKernel;
|
||||
stream.Synchronize();
|
||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||
|
||||
kernelLauncher(stream, entryCount, phi, gpu.Pow2ModEntriesToTestOnDevice.View, divisorData, gpu.OutputUlong.View);
|
||||
|
||||
kernel.Launch(stream, 1, entryCount, phi, gpu.Pow2ModEntriesToTestOnDevice.View, divisorData, gpu.OutputUlong.View);
|
||||
gpu.OutputUlong.View.CopyToCPU(stream, ref order, 1);
|
||||
stream.Synchronize();
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
@@ -67,19 +67,16 @@ internal static partial class PrimeOrderCalculator
|
||||
Span<int> exponentBuffer = exponentBufferArray.AsSpan(0, GpuSmallPrimeFactorSlots);
|
||||
remaining = value;
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
Accelerator accelerator = AcceleratorPool.Shared.Rent();
|
||||
var stream = accelerator.CreateStream();
|
||||
GpuScratchBuffer scratch = GpuScratchBufferPool.Rent(accelerator, GpuSmallPrimeFactorSlots, 0);
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
var stream = AcceleratorStreamPool.Rent(accelerator);
|
||||
KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.SmallPrimeFactorKernelScan);
|
||||
|
||||
ScratchBuffer scratch = GpuScratchBufferPool.Rent(accelerator, GpuSmallPrimeFactorSlots, 0);
|
||||
|
||||
SmallPrimeFactorViews tables = GpuKernelPool.GetSmallPrimeFactorTables(kernels);
|
||||
|
||||
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");
|
||||
|
||||
var kernel = kernels.SmallPrimeFactor!;
|
||||
var kernelLauncher = 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>>>();
|
||||
|
||||
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorCountSlotView = scratch.SmallPrimeFactorCountSlot.View;
|
||||
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorRemainingSlotView = scratch.SmallPrimeFactorRemainingSlot.View;
|
||||
@@ -87,7 +84,7 @@ internal static partial class PrimeOrderCalculator
|
||||
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorExponentSlotsView = scratch.SmallPrimeFactorExponentSlots.View;
|
||||
ArrayView1D<uint, Stride1D.Dense> smallPrimeFactorsPrimesView = kernels.SmallPrimeFactorsPrimes!.View;
|
||||
|
||||
kernel(
|
||||
kernelLauncher(
|
||||
stream,
|
||||
1,
|
||||
value,
|
||||
@@ -101,26 +98,27 @@ internal static partial class PrimeOrderCalculator
|
||||
smallPrimeFactorRemainingSlotView);
|
||||
|
||||
|
||||
// Span<int> factorCountTemp = stackalloc int[1];
|
||||
factorCount = 0;
|
||||
smallPrimeFactorCountSlotView.CopyToCPU(stream, ref factorCount, 1);
|
||||
stream.Synchronize();
|
||||
// factorCount = factorCountTemp[0];
|
||||
|
||||
factorCount = Math.Min(factorCount, GpuSmallPrimeFactorSlots);
|
||||
|
||||
if (factorCount > 0)
|
||||
{
|
||||
smallPrimeFactorPrimeSlotsView.CopyToCPU(stream, ref MemoryMarshal.GetReference(primeBuffer), factorCount);
|
||||
primeBuffer = primeBuffer[..factorCount];
|
||||
smallPrimeFactorPrimeSlotsView.CopyToCPU(stream, primeBuffer);
|
||||
|
||||
smallPrimeFactorExponentSlotsView.CopyToCPU(stream, ref MemoryMarshal.GetReference(exponentBuffer), factorCount);
|
||||
exponentBuffer = exponentBuffer[..factorCount];
|
||||
smallPrimeFactorExponentSlotsView.CopyToCPU(stream, exponentBuffer);
|
||||
}
|
||||
|
||||
// Span<ulong> remainingTemp = stackalloc ulong[1];
|
||||
|
||||
smallPrimeFactorRemainingSlotView.CopyToCPU(stream, ref remaining, 1);
|
||||
// remaining = remainingTemp[0];
|
||||
stream.Synchronize();
|
||||
stream.Dispose();
|
||||
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
GpuScratchBufferPool.Return(scratch);
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
|
||||
for (int i = 0; i < factorCount; i++)
|
||||
{
|
||||
@@ -129,12 +127,11 @@ internal static partial class PrimeOrderCalculator
|
||||
counts.Add(primeValue, exponent);
|
||||
}
|
||||
|
||||
GpuScratchBufferPool.Return(scratch);
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool EvaluateSpecialMaxCandidatesGpu(
|
||||
Pow2MontgomeryAccelerator gpu,
|
||||
Span<ulong> buffer,
|
||||
ReadOnlySpan<FactorEntry> factors,
|
||||
ulong phi,
|
||||
@@ -154,11 +151,11 @@ internal static partial class PrimeOrderCalculator
|
||||
}
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
Accelerator accelerator = AcceleratorPool.Shared.Rent();
|
||||
var stream = accelerator.CreateStream();
|
||||
Accelerator accelerator = gpu.Accelerator; //AcceleratorPool.Shared.Rent();
|
||||
var stream = AcceleratorStreamPool.Rent(accelerator);// accelerator.CreateStream();
|
||||
var kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.EvaluateSpecialMaxCandidatesKernel);
|
||||
|
||||
ScratchBuffer scratch = GpuScratchBufferPool.Rent(accelerator, 0, factorCount);
|
||||
GpuScratchBuffer scratch = GpuScratchBufferPool.Rent(accelerator, 0, factorCount);
|
||||
|
||||
ArrayView1D<ulong, Stride1D.Dense> specialMaxFactorsView = scratch.SpecialMaxFactors.View;
|
||||
specialMaxFactorsView.SubView(0, factorCount).CopyFromCPU(stream, ref MemoryMarshal.GetReference(factorSpan), factorCount);
|
||||
@@ -182,7 +179,9 @@ internal static partial class PrimeOrderCalculator
|
||||
// specialMaxResultView.CopyToCPU(stream, ref result, 1);
|
||||
specialMaxResultView.CopyToCPU(stream, ref result, 1);
|
||||
stream.Synchronize();
|
||||
stream.Dispose();
|
||||
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
// stream.Dispose();
|
||||
|
||||
// stream.Synchronize();
|
||||
// return result != 0;
|
||||
|
||||
@@ -94,20 +94,22 @@ public sealed class PrimeTester
|
||||
public static bool IsPrimeGpu(ulong n)
|
||||
{
|
||||
var gpu = Pow2MontgomeryAccelerator.Rent(1);
|
||||
var kernel = gpu.SmallPrimeSieveKernel!;
|
||||
|
||||
// Span<byte> flag = stackalloc byte[1];
|
||||
|
||||
|
||||
var inputView = gpu.PrimeTestInput.View;
|
||||
var outputView = gpu.OutputByte.View;
|
||||
var kernel = gpu.SmallPrimeSieveKernel!;
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
||||
// var stream = gpu.Stream!;
|
||||
inputView.CopyFromCPU(stream, ref n, 1);
|
||||
|
||||
var outputView = gpu.OutputByte.View;
|
||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>>();
|
||||
|
||||
kernel.Launch(
|
||||
kernelLauncher(
|
||||
stream,
|
||||
1,
|
||||
inputView,
|
||||
@@ -136,18 +138,15 @@ public sealed class PrimeTester
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsPrimeGpu(Pow2MontgomeryAccelerator gpu, ulong n)
|
||||
{
|
||||
// var stream = gpu.Stream!;
|
||||
var input = gpu.PrimeTestInput;
|
||||
var inputView = input.View;
|
||||
var output = gpu.OutputByte;
|
||||
var outputView = output.View;
|
||||
Kernel kernel = gpu.SmallPrimeSieveKernel!;
|
||||
|
||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
||||
inputView.CopyFromCPU(stream, ref n, 1);
|
||||
|
||||
// Span<byte> flag = stackalloc byte[1];
|
||||
var output = gpu.OutputByte;
|
||||
var outputView = output.View;
|
||||
|
||||
Kernel kernel = gpu.SmallPrimeSieveKernel!;
|
||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>>();
|
||||
|
||||
kernelLauncher(
|
||||
@@ -238,8 +237,7 @@ public sealed class PrimeTester
|
||||
outputView);
|
||||
|
||||
var resultSlice = results.Slice(pos, count);
|
||||
ref byte resultRef = ref MemoryMarshal.GetReference(resultSlice);
|
||||
outputView.CopyToCPU(stream, ref resultRef, count);
|
||||
outputView.CopyToCPU(stream, resultSlice);
|
||||
|
||||
pos += count;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user