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

+13 -14
View File
@@ -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);
}
}
+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);
@@ -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)
+27 -28
View File
@@ -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;
+9 -11
View File
@@ -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;
}