diff --git a/PerfectNumbers.Core/DivisorCycleCache.cs b/PerfectNumbers.Core/DivisorCycleCache.cs index 0077181..b9c93b9 100644 --- a/PerfectNumbers.Core/DivisorCycleCache.cs +++ b/PerfectNumbers.Core/DivisorCycleCache.cs @@ -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 divisors, Span 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(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) diff --git a/PerfectNumbers.Core/Gpu/Accelerators/AcceleratorStreamPool.cs b/PerfectNumbers.Core/Gpu/Accelerators/AcceleratorStreamPool.cs index f1cb530..6282cca 100644 --- a/PerfectNumbers.Core/Gpu/Accelerators/AcceleratorStreamPool.cs +++ b/PerfectNumbers.Core/Gpu/Accelerators/AcceleratorStreamPool.cs @@ -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> _streams = new(20_480, PerfectNumberConstants.RollingAccelerators); + private static readonly Dictionary> _streams = new(PerfectNumberConstants .RollingAccelerators); // private static readonly ConcurrentDictionary _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 _locks = new(AcceleratorPool.Shared.Accelerators.ToDictionary(x => x, static x => CreateLock())); + private static readonly Dictionary _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 streamQueue = new(); + // var stream = accelerator.CreateStream(); + // // var stream = accelerator.CreateStream(); + // streamQueue.Enqueue(stream); + // _streams[accelerator] = streamQueue; + // _locks[accelerator] = CreateLock(); + // stream.Synchronize(); + } } diff --git a/PerfectNumbers.Core/Gpu/Accelerators/Pow2MontgomeryAccelerator.cs b/PerfectNumbers.Core/Gpu/Accelerators/Pow2MontgomeryAccelerator.cs index 13a913a..7160552 100644 --- a/PerfectNumbers.Core/Gpu/Accelerators/Pow2MontgomeryAccelerator.cs +++ b/PerfectNumbers.Core/Gpu/Accelerators/Pow2MontgomeryAccelerator.cs @@ -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); } } diff --git a/PerfectNumbers.Core/Gpu/GpuKernelPool.cs b/PerfectNumbers.Core/Gpu/GpuKernelPool.cs index 3b5a533..bfaa5b7 100644 --- a/PerfectNumbers.Core/Gpu/GpuKernelPool.cs +++ b/PerfectNumbers.Core/Gpu/GpuKernelPool.cs @@ -142,14 +142,9 @@ public class GpuKernelPool static void InitSmallPrimeFactorKernelScan(Accelerator accelerator, KernelContainer kernels) { - InitOnce(ref kernels.SmallPrimeFactor, () => - { - var loaded = accelerator.LoadAutoGroupedStreamKernel, ArrayView1D, int, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D>(SmallPrimeFactorKernels.SmallPrimeFactorKernelScan); + var loaded = accelerator.LoadAutoGroupedStreamKernel, ArrayView1D, int, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D>(SmallPrimeFactorKernels.SmallPrimeFactorKernelScan); - var kernel = KernelUtil.GetKernel(loaded); - - return kernel.CreateLauncherDelegate, ArrayView1D, int, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D>>(); - }); + kernels.SmallPrimeFactor = KernelUtil.GetKernel(loaded); } } diff --git a/PerfectNumbers.Core/Gpu/GpuScratchBufferPool.cs b/PerfectNumbers.Core/Gpu/GpuScratchBufferPool.cs index dad48c0..e05a7af 100644 --- a/PerfectNumbers.Core/Gpu/GpuScratchBufferPool.cs +++ b/PerfectNumbers.Core/Gpu/GpuScratchBufferPool.cs @@ -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 SmallPrimeFactorPrimeSlots { get; private set; } - public MemoryBuffer1D SmallPrimeFactorExponentSlots { get; private set; } - public MemoryBuffer1D SmallPrimeFactorCountSlot { get; private set; } - public MemoryBuffer1D SmallPrimeFactorRemainingSlot { get; private set; } - - public MemoryBuffer1D SpecialMaxFactors { get; private set; } - public MemoryBuffer1D SpecialMaxCandidates { get; private set; } - public MemoryBuffer1D SpecialMaxResult { get; private set; } - internal readonly Accelerator _accelerator; + public readonly MemoryBuffer1D SmallPrimeFactorCountSlot; + public MemoryBuffer1D SmallPrimeFactorExponentSlots; + public MemoryBuffer1D SmallPrimeFactorPrimeSlots; + public readonly MemoryBuffer1D SmallPrimeFactorRemainingSlot; + public MemoryBuffer1D SpecialMaxCandidates; + public MemoryBuffer1D SpecialMaxFactors; + public readonly MemoryBuffer1D 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>? _pools; + private static Dictionary>? _pools; // private static readonly ConcurrentDictionary> _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()); @@ -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; + } + } } \ No newline at end of file diff --git a/PerfectNumbers.Core/Gpu/KernelContainer.cs b/PerfectNumbers.Core/Gpu/KernelContainer.cs index 12f8c60..65c4594 100644 --- a/PerfectNumbers.Core/Gpu/KernelContainer.cs +++ b/PerfectNumbers.Core/Gpu/KernelContainer.cs @@ -22,7 +22,7 @@ public sealed class KernelContainer public Action, ArrayView1D>? Pow2ModOrder; - public Action, ArrayView1D, int, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D>? SmallPrimeFactor; + public Kernel? SmallPrimeFactor; public Action, int, MontgomeryDivisorData, ArrayView1D, ArrayView1D>? SpecialMax; diff --git a/PerfectNumbers.Core/Gpu/Pow2MontgomeryGpuCalculator.cs b/PerfectNumbers.Core/Gpu/Pow2MontgomeryGpuCalculator.cs index 7463757..1efe5c9 100644 --- a/PerfectNumbers.Core/Gpu/Pow2MontgomeryGpuCalculator.cs +++ b/PerfectNumbers.Core/Gpu/Pow2MontgomeryGpuCalculator.cs @@ -27,6 +27,7 @@ public static class Pow2MontgomeryGpuCalculator var kernelLauncher = kernel.CreateLauncherDelegate, MontgomeryDivisorData, ArrayView1D>>(); 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, MontgomeryDivisorData, ArrayView1D>>(); 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); diff --git a/PerfectNumbers.Core/MersenneNumberDivisorByDivisorTester.cs b/PerfectNumbers.Core/MersenneNumberDivisorByDivisorTester.cs index c28859a..7f4eace 100644 --- a/PerfectNumbers.Core/MersenneNumberDivisorByDivisorTester.cs +++ b/PerfectNumbers.Core/MersenneNumberDivisorByDivisorTester.cs @@ -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, diff --git a/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs b/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs index 5c16d14..62cd3db 100644 --- a/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs +++ b/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs @@ -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 buffer, ReadOnlySpan factors, ulong phi, ulong prime, in MontgomeryDivisorData divisorData) diff --git a/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs b/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs index 89a49e0..d11d9b6 100644 --- a/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs +++ b/PerfectNumbers.Core/PrimeOrderCalculator.Gpu.cs @@ -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, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D>>(); + + 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 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, ArrayView1D, int, ArrayView1D, ArrayView1D, ArrayView1D, ArrayView1D>>(); ArrayView1D smallPrimeFactorCountSlotView = scratch.SmallPrimeFactorCountSlot.View; ArrayView1D smallPrimeFactorRemainingSlotView = scratch.SmallPrimeFactorRemainingSlot.View; @@ -87,7 +84,7 @@ internal static partial class PrimeOrderCalculator ArrayView1D smallPrimeFactorExponentSlotsView = scratch.SmallPrimeFactorExponentSlots.View; ArrayView1D smallPrimeFactorsPrimesView = kernels.SmallPrimeFactorsPrimes!.View; - kernel( + kernelLauncher( stream, 1, value, @@ -101,26 +98,27 @@ internal static partial class PrimeOrderCalculator smallPrimeFactorRemainingSlotView); - // Span 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 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 buffer, ReadOnlySpan 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 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; diff --git a/PerfectNumbers.Core/PrimeTester.cs b/PerfectNumbers.Core/PrimeTester.cs index 4dd3ff5..475a5a7 100644 --- a/PerfectNumbers.Core/PrimeTester.cs +++ b/PerfectNumbers.Core/PrimeTester.cs @@ -94,20 +94,22 @@ public sealed class PrimeTester public static bool IsPrimeGpu(ulong n) { var gpu = Pow2MontgomeryAccelerator.Rent(1); - var kernel = gpu.SmallPrimeSieveKernel!; // Span 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, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView>>(); - 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 flag = stackalloc byte[1]; - var output = gpu.OutputByte; - var outputView = output.View; - - Kernel kernel = gpu.SmallPrimeSieveKernel!; var kernelLauncher = kernel.CreateLauncherDelegate, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView>>(); 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; }