Accelerator index added for dictionary-less use-cases
This commit is contained in:
1 parent
6cb63b6e73
commit
0540411cad
21 files changed
+849
-772
No files matched your search
@@ -17,6 +17,7 @@ public sealed class DivisorCycleCache
|
|||||||
private const byte ByteOne = 1;
|
private const byte ByteOne = 1;
|
||||||
private const int StackBufferThreshold = 128;
|
private const int StackBufferThreshold = 128;
|
||||||
private readonly Accelerator _accelerator;
|
private readonly Accelerator _accelerator;
|
||||||
|
private readonly int _acceleratorIndex;
|
||||||
private readonly Action<AcceleratorStream, Index1D, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>> _gpuKernel;
|
private readonly Action<AcceleratorStream, Index1D, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>> _gpuKernel;
|
||||||
private volatile ulong[] _snapshot;
|
private volatile ulong[] _snapshot;
|
||||||
private volatile bool _useGpuGeneration = true;
|
private volatile bool _useGpuGeneration = true;
|
||||||
@@ -38,10 +39,14 @@ public sealed class DivisorCycleCache
|
|||||||
|
|
||||||
public int PreferredBatchSize => _divisorCyclesBatchSize;
|
public int PreferredBatchSize => _divisorCyclesBatchSize;
|
||||||
|
|
||||||
|
// private static readonly Accelerator[] _accelerators;
|
||||||
|
|
||||||
private DivisorCycleCache(int divisorCyclesBatchSize)
|
private DivisorCycleCache(int divisorCyclesBatchSize)
|
||||||
{
|
{
|
||||||
_divisorCyclesBatchSize = Math.Max(1, divisorCyclesBatchSize);
|
_divisorCyclesBatchSize = Math.Max(1, divisorCyclesBatchSize);
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
_acceleratorIndex = acceleratorIndex;
|
||||||
|
Accelerator accelerator = AcceleratorPool.Shared.Accelerators[acceleratorIndex];
|
||||||
_accelerator = accelerator;
|
_accelerator = accelerator;
|
||||||
_gpuKernel = LoadKernel(accelerator);
|
_gpuKernel = LoadKernel(accelerator);
|
||||||
_snapshot = MersenneDivisorCycles.Shared.ExportSmallCyclesSnapshot();
|
_snapshot = MersenneDivisorCycles.Shared.ExportSmallCyclesSnapshot();
|
||||||
@@ -311,7 +316,8 @@ public sealed class DivisorCycleCache
|
|||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
int pending;
|
int pending;
|
||||||
var kernel = _gpuKernel;
|
var kernel = _gpuKernel;
|
||||||
var stream = AcceleratorStreamPool.Rent(_accelerator);
|
var acceleratorIndex = _acceleratorIndex;
|
||||||
|
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
|
|
||||||
divisorBuffer!.View.CopyFromCPU(stream, divisors);
|
divisorBuffer!.View.CopyFromCPU(stream, divisors);
|
||||||
powBuffer!.View.CopyFromCPU(stream, powSpan);
|
powBuffer!.View.CopyFromCPU(stream, powSpan);
|
||||||
@@ -339,7 +345,7 @@ public sealed class DivisorCycleCache
|
|||||||
|
|
||||||
resultBuffer.View.CopyToCPU(stream, resultSpan);
|
resultBuffer.View.CopyToCPU(stream, resultSpan);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
AcceleratorStreamPool.Return(stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
|
|
||||||
resultSpan.CopyTo(destination);
|
resultSpan.CopyTo(destination);
|
||||||
if (rentedPow is not null)
|
if (rentedPow is not null)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace PerfectNumbers.Core.Gpu
|
|||||||
|
|
||||||
private int _index;
|
private int _index;
|
||||||
|
|
||||||
public Accelerator Rent()
|
public int Rent()
|
||||||
{
|
{
|
||||||
Atomic.CompareExchange(ref _index, Capacity, 0);
|
Atomic.CompareExchange(ref _index, Capacity, 0);
|
||||||
var index = Atomic.Add(ref _index, 1);
|
var index = Atomic.Add(ref _index, 1);
|
||||||
@@ -20,27 +20,31 @@ namespace PerfectNumbers.Core.Gpu
|
|||||||
index -= Capacity;
|
index -= Capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Accelerators[index];
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Return(Accelerator accelerator)
|
public void Return(int acceleratorIndex)
|
||||||
{
|
{
|
||||||
// Intentionally left empty - there's nothing to do here. We're not really renting anything.
|
// Intentionally left empty - there's nothing to do here. We're not really renting anything.
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly AcceleratorPool Shared = new(PerfectNumberConstants.RollingAccelerators);
|
public static readonly AcceleratorPool Shared = new(PerfectNumberConstants.RollingAccelerators);
|
||||||
|
|
||||||
private readonly int Capacity;
|
private readonly int Capacity;
|
||||||
|
|
||||||
public AcceleratorPool(int capacity)
|
public AcceleratorPool(int capacity)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine("Creating accelerators");
|
||||||
Capacity = capacity;
|
Capacity = capacity;
|
||||||
var context = Context.CreateDefault();
|
var context = Context.CreateDefault();
|
||||||
var device = context.GetPreferredDevice(false);
|
var device = context.GetPreferredDevice(false);
|
||||||
Context = context;
|
Context = context;
|
||||||
Device = device;
|
Device = device;
|
||||||
int acceleratorsInContext = 0;
|
int acceleratorsInContext = 0;
|
||||||
|
int acceleratorIndex = 0;
|
||||||
Accelerators = [.. Enumerable.Range(0, capacity).Select(_ =>
|
Accelerators = [.. Enumerable.Range(0, capacity).Select(_ =>
|
||||||
{
|
{
|
||||||
|
Console.WriteLine($"Preparing accelerator {acceleratorIndex++}");
|
||||||
Accelerator accelerator = device.CreateAccelerator(context);
|
Accelerator accelerator = device.CreateAccelerator(context);
|
||||||
acceleratorsInContext++;
|
acceleratorsInContext++;
|
||||||
if (acceleratorsInContext >= 128)
|
if (acceleratorsInContext >= 128)
|
||||||
|
|||||||
@@ -5,38 +5,38 @@ namespace PerfectNumbers.Core.Gpu.Accelerators;
|
|||||||
|
|
||||||
public static class AcceleratorStreamPool
|
public static class AcceleratorStreamPool
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<Accelerator, ConcurrentQueue<AcceleratorStream>> _streams = new(PerfectNumberConstants .RollingAccelerators << 1);
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
private static readonly SemaphoreSlim[] _locks = new SemaphoreSlim[PerfectNumberConstants.RollingAccelerators];
|
||||||
|
private static readonly ConcurrentQueue<AcceleratorStream>[] _streams = new ConcurrentQueue<AcceleratorStream> [PerfectNumberConstants.RollingAccelerators];
|
||||||
|
|
||||||
private static SemaphoreSlim CreateLock() => new(PerfectNumberConstants.ThreadsByStream);
|
private static SemaphoreSlim CreateLock() => new(PerfectNumberConstants.ThreadsByAccelerator);
|
||||||
|
|
||||||
private static readonly Dictionary<Accelerator, SemaphoreSlim> _locks = new(PerfectNumberConstants.RollingAccelerators << 1);
|
|
||||||
|
|
||||||
// private static int _rented;
|
// private static int _rented;
|
||||||
|
|
||||||
public static AcceleratorStream Rent(Accelerator accelerator)
|
public static AcceleratorStream Rent(int acceleratorIndex)
|
||||||
{
|
{
|
||||||
var streamLock = _locks[accelerator];
|
var streamLock = _locks[acceleratorIndex];
|
||||||
var queue = _streams[accelerator];
|
var queue = _streams[acceleratorIndex];
|
||||||
|
|
||||||
streamLock.Wait();
|
streamLock.Wait();
|
||||||
|
|
||||||
return queue.TryDequeue(out var stream)
|
return queue.TryDequeue(out var stream)
|
||||||
? stream
|
? stream
|
||||||
: accelerator.CreateStream();
|
: _accelerators[acceleratorIndex].CreateStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Return(AcceleratorStream stream)
|
public static void Return(int acceleratorIndex, AcceleratorStream stream)
|
||||||
{
|
{
|
||||||
Accelerator accelerator = stream.Accelerator;
|
var streamLock = _locks[acceleratorIndex];
|
||||||
var streamLock = _locks[accelerator];
|
var queue = _streams[acceleratorIndex];
|
||||||
var queue = _streams[accelerator];
|
|
||||||
queue.Enqueue(stream);
|
queue.Enqueue(stream);
|
||||||
streamLock.Release();
|
streamLock.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void WarmUp(Accelerator accelerator)
|
public static void WarmUp(int acceleratorIndex)
|
||||||
{
|
{
|
||||||
_streams.Add(accelerator, new());
|
_streams[acceleratorIndex] = new();
|
||||||
_ = _locks.TryAdd(accelerator, CreateLock());
|
_locks[acceleratorIndex] = CreateLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,9 +131,12 @@ internal sealed class HeuristicPrimeTesterAccelerator
|
|||||||
|
|
||||||
public HeuristicGpuDivisorTables HeuristicGpuTables => _heuristicDivisorTables;
|
public HeuristicGpuDivisorTables HeuristicGpuTables => _heuristicDivisorTables;
|
||||||
|
|
||||||
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
|
||||||
internal HeuristicPrimeTesterAccelerator(int minBufferCapacity)
|
internal HeuristicPrimeTesterAccelerator(int minBufferCapacity)
|
||||||
{
|
{
|
||||||
Accelerator accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
Accelerator accelerator = _accelerators[acceleratorIndex];
|
||||||
Context = accelerator.Context;
|
Context = accelerator.Context;
|
||||||
|
|
||||||
Accelerator = accelerator;
|
Accelerator = accelerator;
|
||||||
@@ -141,7 +144,7 @@ internal sealed class HeuristicPrimeTesterAccelerator
|
|||||||
|
|
||||||
HeuristicTrialDivisionKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<int>, ulong, ulong, HeuristicGpuDivisorTableKind, HeuristicGpuDivisorTables>(PrimeTesterKernels.HeuristicTrialDivisionKernel));
|
HeuristicTrialDivisionKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<int>, ulong, ulong, HeuristicGpuDivisorTableKind, HeuristicGpuDivisorTables>(PrimeTesterKernels.HeuristicTrialDivisionKernel));
|
||||||
|
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
|
|
||||||
// GpuStaticTableInitializer.EnsureStaticTables(accelerator, kernels, stream);
|
// GpuStaticTableInitializer.EnsureStaticTables(accelerator, kernels, stream);
|
||||||
|
|
||||||
@@ -149,7 +152,7 @@ internal sealed class HeuristicPrimeTesterAccelerator
|
|||||||
_heuristicDivisorTables = _sharedTables.CreateHeuristicDivisorTables();
|
_heuristicDivisorTables = _sharedTables.CreateHeuristicDivisorTables();
|
||||||
|
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
AcceleratorStreamPool.Return(stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnsureCapacity(int minCapacity)
|
public void EnsureCapacity(int minCapacity)
|
||||||
|
|||||||
@@ -6,13 +6,14 @@ namespace PerfectNumbers.Core.Gpu.Accelerators;
|
|||||||
|
|
||||||
internal sealed class LastDigitGpuTables
|
internal sealed class LastDigitGpuTables
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<Accelerator, LastDigitGpuTables> _sharedTables = new(PerfectNumberConstants.RollingAccelerators);
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
private static readonly LastDigitGpuTables[] _sharedTables = new LastDigitGpuTables[PerfectNumberConstants.RollingAccelerators];
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static LastDigitGpuTables EnsureStaticTables(Accelerator accelerator) => _sharedTables[accelerator];
|
internal static LastDigitGpuTables EnsureStaticTables(int acceleratorIndex) => _sharedTables[acceleratorIndex];
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static void WarmUp(Accelerator accelerator, AcceleratorStream stream) => _sharedTables[accelerator] = new LastDigitGpuTables(accelerator, stream);
|
internal static void WarmUp(int acceleratorIndex, AcceleratorStream stream) => _sharedTables[acceleratorIndex] = new LastDigitGpuTables(_accelerators[acceleratorIndex], stream);
|
||||||
|
|
||||||
internal LastDigitGpuTables(Accelerator accelerator, AcceleratorStream stream)
|
internal LastDigitGpuTables(Accelerator accelerator, AcceleratorStream stream)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using ILGPU;
|
using ILGPU;
|
||||||
using ILGPU.Runtime;
|
using ILGPU.Runtime;
|
||||||
using PerfectNumbers.Core.Gpu;
|
|
||||||
using PerfectNumbers.Core.Gpu.Kernels;
|
using PerfectNumbers.Core.Gpu.Kernels;
|
||||||
|
|
||||||
namespace PerfectNumbers.Core.Gpu.Accelerators;
|
namespace PerfectNumbers.Core.Gpu.Accelerators;
|
||||||
@@ -19,8 +18,8 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
var pool = _pool ??= [];
|
var pool = _pool ??= [];
|
||||||
if (!pool.TryDequeue(out var gpu))
|
if (!pool.TryDequeue(out var gpu))
|
||||||
{
|
{
|
||||||
Accelerator accelerator = AcceleratorPool.Shared.Rent();
|
int acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
gpu = new(accelerator, PerfectNumberConstants.DefaultFactorsBuffer, primeTesterCapacity, PerfectNumberConstants.DefaultSmallPrimeFactorSlotCount, PerfectNumberConstants.DefaultSpecialMaxFactorCapacity);
|
gpu = new(acceleratorIndex, PerfectNumberConstants.DefaultFactorsBuffer, primeTesterCapacity, PerfectNumberConstants.DefaultSmallPrimeFactorSlotCount, PerfectNumberConstants.DefaultSpecialMaxFactorCapacity);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -65,22 +64,26 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
{
|
{
|
||||||
Console.WriteLine($"Preparing accelerator {i}...");
|
Console.WriteLine($"Preparing accelerator {i}...");
|
||||||
var accelerator = accelerators[i];
|
var accelerator = accelerators[i];
|
||||||
AcceleratorStreamPool.WarmUp(accelerator);
|
AcceleratorStreamPool.WarmUp(i);
|
||||||
// Don't take this from the pool as quick uploads of data to the accelerator consumes much of GPU's memory and throws.
|
// Don't take this from the pool as quick uploads of data to the accelerator consumes much of GPU's memory and throws.
|
||||||
AcceleratorStream stream = accelerator.CreateStream();
|
AcceleratorStream stream = accelerator.CreateStream();
|
||||||
LastDigitGpuTables.WarmUp(accelerator, stream);
|
LastDigitGpuTables.WarmUp(i, stream);
|
||||||
// SharedHeuristicGpuTables.EnsureStaticTables(accelerator, stream);
|
// SharedHeuristicGpuTables.EnsureStaticTables(accelerator, stream);
|
||||||
// _ = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.None);
|
// _ = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.None);
|
||||||
// KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream);
|
// KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream);
|
||||||
// GpuStaticTableInitializer.EnsureStaticTables(accelerator, kernels, stream);
|
// GpuStaticTableInitializer.EnsureStaticTables(accelerator, kernels, stream);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
stream.Dispose();
|
stream.Dispose();
|
||||||
|
accelerator.Synchronize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
|
||||||
public readonly Accelerator Accelerator;
|
public readonly Accelerator Accelerator;
|
||||||
|
public readonly int AcceleratorIndex;
|
||||||
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> Input;
|
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> Input;
|
||||||
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> OutputUlong;
|
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> OutputUlong;
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> PrimeTestInput;
|
public MemoryBuffer1D<ulong, Stride1D.Dense> PrimeTestInput;
|
||||||
@@ -161,9 +164,11 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PrimeOrderCalculatorAccelerator(Accelerator accelerator, int factorsCount, int primeTesterCapacity, int smallPrimeFactorSlotCount, int specialMaxFactorCapacity)
|
public PrimeOrderCalculatorAccelerator(int acceleratorIndex, int factorsCount, int primeTesterCapacity, int smallPrimeFactorSlotCount, int specialMaxFactorCapacity)
|
||||||
{
|
{
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
Accelerator = accelerator;
|
Accelerator = accelerator;
|
||||||
|
AcceleratorIndex = acceleratorIndex;
|
||||||
Input = accelerator.Allocate1D<ulong>(1);
|
Input = accelerator.Allocate1D<ulong>(1);
|
||||||
OutputUlong = accelerator.Allocate1D<ulong>(1);
|
OutputUlong = accelerator.Allocate1D<ulong>(1);
|
||||||
Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount);
|
Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount);
|
||||||
@@ -179,7 +184,7 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
SpecialMaxCandidates = accelerator.Allocate1D<ulong>(specialMaxFactorCapacity);
|
SpecialMaxCandidates = accelerator.Allocate1D<ulong>(specialMaxFactorCapacity);
|
||||||
SpecialMaxResult = accelerator.Allocate1D<ulong>(1);
|
SpecialMaxResult = accelerator.Allocate1D<ulong>(1);
|
||||||
|
|
||||||
var sharedTables = LastDigitGpuTables.EnsureStaticTables(accelerator);
|
var sharedTables = LastDigitGpuTables.EnsureStaticTables(acceleratorIndex);
|
||||||
|
|
||||||
DevicePrimesLastOne = sharedTables.DevicePrimesLastOne;
|
DevicePrimesLastOne = sharedTables.DevicePrimesLastOne;
|
||||||
DevicePrimesLastSeven = sharedTables.DevicePrimesLastSeven;
|
DevicePrimesLastSeven = sharedTables.DevicePrimesLastSeven;
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -54,10 +54,13 @@ public sealed class MersenneNumberDivisorGpuTester
|
|||||||
_divisorCandidates = count == 0 ? [] : list[..count];
|
_divisorCandidates = count == 0 ? [] : list[..count];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
|
||||||
public bool IsDivisible(ulong exponent, in ReadOnlyGpuUInt128 divisor)
|
public bool IsDivisible(ulong exponent, in ReadOnlyGpuUInt128 divisor)
|
||||||
{
|
{
|
||||||
// var accelerator = SharedGpuContext.CreateAccelerator();
|
// var accelerator = SharedGpuContext.CreateAccelerator();
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
var stream = accelerator.CreateStream();
|
var stream = accelerator.CreateStream();
|
||||||
Queue<MemoryBuffer1D<byte, Stride1D.Dense>> resultBuffers = GetQueue(accelerator);
|
Queue<MemoryBuffer1D<byte, Stride1D.Dense>> resultBuffers = GetQueue(accelerator);
|
||||||
if (!resultBuffers.TryDequeue(out var resultBuffer))
|
if (!resultBuffers.TryDequeue(out var resultBuffer))
|
||||||
|
|||||||
@@ -12,12 +12,15 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
|
|||||||
private readonly GpuKernelType _kernelType = kernelType;
|
private readonly GpuKernelType _kernelType = kernelType;
|
||||||
private readonly bool _useGpuOrder = useGpuOrder;
|
private readonly bool _useGpuOrder = useGpuOrder;
|
||||||
|
|
||||||
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
|
||||||
public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
|
public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException($"GPU incremental scanning requires the device cycle heuristics implementation (kernel: {_kernelType}, GPU order: {_useGpuOrder}).");
|
throw new NotImplementedException($"GPU incremental scanning requires the device cycle heuristics implementation (kernel: {_kernelType}, GPU order: {_useGpuOrder}).");
|
||||||
|
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
var stream = accelerator.CreateStream();
|
var stream = accelerator.CreateStream();
|
||||||
int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy
|
int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy
|
||||||
UInt128 kStart = 1UL;
|
UInt128 kStart = 1UL;
|
||||||
|
|||||||
@@ -160,7 +160,8 @@ public class MersenneNumberLucasLehmerGpuTester
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
var stream = accelerator.CreateStream();
|
var stream = accelerator.CreateStream();
|
||||||
var modulus = new GpuUInt128(((UInt128)1 << (int)exponent) - 1UL); // TODO: Cache these Mersenne moduli per exponent so LL GPU runs skip rebuilding them every launch.
|
var modulus = new GpuUInt128(((UInt128)1 << (int)exponent) - 1UL); // TODO: Cache these Mersenne moduli per exponent so LL GPU runs skip rebuilding them every launch.
|
||||||
var buffer = accelerator.Allocate1D<GpuUInt128>(1);
|
var buffer = accelerator.Allocate1D<GpuUInt128>(1);
|
||||||
@@ -193,7 +194,8 @@ public class MersenneNumberLucasLehmerGpuTester
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
var stream = accelerator.CreateStream();
|
var stream = accelerator.CreateStream();
|
||||||
|
|
||||||
var expBuffer = accelerator.Allocate1D<ulong>(count);
|
var expBuffer = accelerator.Allocate1D<ulong>(count);
|
||||||
@@ -246,9 +248,12 @@ public class MersenneNumberLucasLehmerGpuTester
|
|||||||
gpuUInt128Pool.Return(buffer);
|
gpuUInt128Pool.Return(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
|
||||||
private bool IsMersennePrimeNtt(ulong exponent, GpuUInt128 nttMod, GpuUInt128 primitiveRoot, bool runOnGpu)
|
private bool IsMersennePrimeNtt(ulong exponent, GpuUInt128 nttMod, GpuUInt128 primitiveRoot, bool runOnGpu)
|
||||||
{
|
{
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
var stream = accelerator.CreateStream();
|
var stream = accelerator.CreateStream();
|
||||||
|
|
||||||
var subKernel = GetSubSmallKernel(accelerator);
|
var subKernel = GetSubSmallKernel(accelerator);
|
||||||
|
|||||||
@@ -7,11 +7,14 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
|
|||||||
private readonly GpuKernelType _kernelType = kernelType;
|
private readonly GpuKernelType _kernelType = kernelType;
|
||||||
private readonly bool _useGpuOrder = useGpuOrder;
|
private readonly bool _useGpuOrder = useGpuOrder;
|
||||||
|
|
||||||
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
|
||||||
public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
|
public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
|
||||||
{
|
{
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
// var accelerator = SharedGpuContext.Accelerator;
|
// var accelerator = SharedGpuContext.Accelerator;
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
var stream = accelerator.CreateStream();
|
var stream = accelerator.CreateStream();
|
||||||
int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy and avoids TDR
|
int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy and avoids TDR
|
||||||
UInt128 kStart = UInt128.One;
|
UInt128 kStart = UInt128.One;
|
||||||
|
|||||||
@@ -22,11 +22,14 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
|||||||
// TODO: When cycles are missing for larger q values, compute only the single required cycle on the device
|
// TODO: When cycles are missing for larger q values, compute only the single required cycle on the device
|
||||||
// requested by the caller, skip queuing additional block generation, and keep the snapshot cache untouched.
|
// requested by the caller, skip queuing additional block generation, and keep the snapshot cache untouched.
|
||||||
|
|
||||||
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
|
||||||
// GPU residue variant: check 2^p % q == 1 for q = 2*p*k + 1.
|
// GPU residue variant: check 2^p % q == 1 for q = 2*p*k + 1.
|
||||||
public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
|
public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
|
||||||
{
|
{
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
|
|
||||||
// Monitor.Enter(gpuLease.ExecutionLock);
|
// Monitor.Enter(gpuLease.ExecutionLock);
|
||||||
|
|
||||||
|
|||||||
@@ -574,7 +574,8 @@ public static class NttGpuMath
|
|||||||
{
|
{
|
||||||
int n = values.Length;
|
int n = values.Length;
|
||||||
int bits = (int)Math.Log2(n);
|
int bits = (int)Math.Log2(n);
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
var pool = ThreadStaticPools.GpuUInt128Pool;
|
var pool = ThreadStaticPools.GpuUInt128Pool;
|
||||||
var array = pool.Rent(n);
|
var array = pool.Rent(n);
|
||||||
values.CopyTo(array);
|
values.CopyTo(array);
|
||||||
@@ -636,7 +637,8 @@ public static class NttGpuMath
|
|||||||
private static void ForwardGpuReference(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
|
private static void ForwardGpuReference(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
|
||||||
{
|
{
|
||||||
int n = (int)values.Length;
|
int n = (int)values.Length;
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
var stream = accelerator.CreateStream();
|
var stream = accelerator.CreateStream();
|
||||||
var pool = ThreadStaticPools.GpuUInt128Pool;
|
var pool = ThreadStaticPools.GpuUInt128Pool;
|
||||||
var inputArray = pool.Rent(n);
|
var inputArray = pool.Rent(n);
|
||||||
@@ -732,7 +734,8 @@ public static class NttGpuMath
|
|||||||
private static void InverseGpuReference(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
|
private static void InverseGpuReference(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
|
||||||
{
|
{
|
||||||
int n = values.Length;
|
int n = values.Length;
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
var stream = accelerator.CreateStream();
|
var stream = accelerator.CreateStream();
|
||||||
var pool = ThreadStaticPools.GpuUInt128Pool;
|
var pool = ThreadStaticPools.GpuUInt128Pool;
|
||||||
var inputArray = pool.Rent(n);
|
var inputArray = pool.Rent(n);
|
||||||
@@ -780,7 +783,8 @@ public static class NttGpuMath
|
|||||||
private static void ForwardGpuStaged(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
|
private static void ForwardGpuStaged(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
|
||||||
{
|
{
|
||||||
int n = values.Length;
|
int n = values.Length;
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
var stream = accelerator.CreateStream();
|
var stream = accelerator.CreateStream();
|
||||||
var buffer = accelerator.Allocate1D<GpuUInt128>(n);
|
var buffer = accelerator.Allocate1D<GpuUInt128>(n);
|
||||||
buffer.View.CopyFromCPU(stream, ref values[0], n);
|
buffer.View.CopyFromCPU(stream, ref values[0], n);
|
||||||
@@ -795,7 +799,8 @@ public static class NttGpuMath
|
|||||||
private static void InverseGpuStaged(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
|
private static void InverseGpuStaged(Span<GpuUInt128> values, GpuUInt128 modulus, GpuUInt128 primitiveRoot)
|
||||||
{
|
{
|
||||||
int n = values.Length;
|
int n = values.Length;
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
var stream = accelerator.CreateStream();
|
var stream = accelerator.CreateStream();
|
||||||
var buffer = accelerator.Allocate1D<GpuUInt128>(n);
|
var buffer = accelerator.Allocate1D<GpuUInt128>(n);
|
||||||
buffer.View.CopyFromCPU(stream, ref values[0], n);
|
buffer.View.CopyFromCPU(stream, ref values[0], n);
|
||||||
@@ -998,9 +1003,12 @@ public static class NttGpuMath
|
|||||||
InverseDevice(accelerator, stream, values, (int)values.Length, modulus, cache);
|
InverseDevice(accelerator, stream, values, (int)values.Length, modulus, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
|
||||||
public static void PointwiseMultiply(Span<GpuUInt128> left, Span<GpuUInt128> right, GpuUInt128 modulus)
|
public static void PointwiseMultiply(Span<GpuUInt128> left, Span<GpuUInt128> right, GpuUInt128 modulus)
|
||||||
{
|
{
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
var stream = accelerator.CreateStream();
|
var stream = accelerator.CreateStream();
|
||||||
var pool = ThreadStaticPools.GpuUInt128Pool;
|
var pool = ThreadStaticPools.GpuUInt128Pool;
|
||||||
var leftArray = pool.Rent(left.Length);
|
var leftArray = pool.Rent(left.Length);
|
||||||
|
|||||||
@@ -14,12 +14,13 @@ public static class Pow2MontgomeryGpuCalculator
|
|||||||
|
|
||||||
ulong result = 0UL;
|
ulong result = 0UL;
|
||||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
Accelerator? accelerator = gpu.Accelerator;
|
Accelerator? accelerator = gpu.Accelerator;
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
|
MemoryBuffer1D<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
||||||
var kernel = gpu.KeepMontgomeryKernel;
|
var kernel = gpu.KeepMontgomeryKernel;
|
||||||
|
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
|
|
||||||
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
|
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
|
||||||
// We don't need to worry about any left-overs here.
|
// We don't need to worry about any left-overs here.
|
||||||
@@ -31,7 +32,7 @@ public static class Pow2MontgomeryGpuCalculator
|
|||||||
|
|
||||||
resultBuffer.View.CopyToCPU(stream, ref result, 1);
|
resultBuffer.View.CopyToCPU(stream, ref result, 1);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
AcceleratorStreamPool.Return(stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
// GpuPrimeWorkLimiter.Release();
|
// GpuPrimeWorkLimiter.Release();
|
||||||
|
|
||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
@@ -48,7 +49,8 @@ public static class Pow2MontgomeryGpuCalculator
|
|||||||
MemoryBuffer1D<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
|
MemoryBuffer1D<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
||||||
|
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
|
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
|
||||||
// We don't need to worry about any left-overs here.
|
// We don't need to worry about any left-overs here.
|
||||||
// resultBuffer.MemSetToZero(stream);
|
// resultBuffer.MemSetToZero(stream);
|
||||||
@@ -58,7 +60,7 @@ public static class Pow2MontgomeryGpuCalculator
|
|||||||
resultBuffer.View.CopyToCPU(stream, ref result, 1);
|
resultBuffer.View.CopyToCPU(stream, ref result, 1);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
// GpuPrimeWorkLimiter.Release();
|
// GpuPrimeWorkLimiter.Release();
|
||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
|
|
||||||
@@ -73,7 +75,8 @@ public static class Pow2MontgomeryGpuCalculator
|
|||||||
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
||||||
var kernel = gpu.ConvertToStandardKernel;
|
var kernel = gpu.ConvertToStandardKernel;
|
||||||
|
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
|
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
|
||||||
// We don't need to worry about any left-overs here.
|
// We don't need to worry about any left-overs here.
|
||||||
// resultBuffer.MemSetToZero(stream);
|
// resultBuffer.MemSetToZero(stream);
|
||||||
@@ -83,7 +86,7 @@ public static class Pow2MontgomeryGpuCalculator
|
|||||||
resultBuffer.View.CopyToCPU(stream, ref result, 1);
|
resultBuffer.View.CopyToCPU(stream, ref result, 1);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,6 +205,8 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
|
||||||
private static bool TryLaunchPartialFactorKernel(
|
private static bool TryLaunchPartialFactorKernel(
|
||||||
PrimeOrderCalculatorAccelerator gpu,
|
PrimeOrderCalculatorAccelerator gpu,
|
||||||
ulong value,
|
ulong value,
|
||||||
@@ -220,7 +222,8 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
Accelerator accelerator = AcceleratorPool.Shared.Rent();
|
int acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
Accelerator accelerator = _accelerators[acceleratorIndex];
|
||||||
AcceleratorStream stream = accelerator.CreateStream();
|
AcceleratorStream stream = accelerator.CreateStream();
|
||||||
|
|
||||||
SmallPrimeDeviceCache cache = GetSmallPrimeDeviceCache(accelerator, stream);
|
SmallPrimeDeviceCache cache = GetSmallPrimeDeviceCache(accelerator, stream);
|
||||||
@@ -382,8 +385,9 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
order = 0UL;
|
order = 0UL;
|
||||||
|
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
Accelerator accelerator = AcceleratorPool.Shared.Rent();
|
int acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator);
|
Accelerator accelerator = _accelerators[acceleratorIndex];
|
||||||
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
SmallPrimeDeviceCache cache = GetSmallPrimeDeviceCache(accelerator, stream);
|
SmallPrimeDeviceCache cache = GetSmallPrimeDeviceCache(accelerator, stream);
|
||||||
|
|
||||||
// TODO: These buffers should be created reallocated once and assigned to an accelerator. Callers should use their own
|
// TODO: These buffers should be created reallocated once and assigned to an accelerator. Callers should use their own
|
||||||
@@ -553,7 +557,8 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
private static bool TryComputeOnGpu(ReadOnlySpan<ulong> exponents, ulong prime, in MontgomeryDivisorData divisorData, Span<ulong> results)
|
private static bool TryComputeOnGpu(ReadOnlySpan<ulong> exponents, ulong prime, in MontgomeryDivisorData divisorData, Span<ulong> results)
|
||||||
{
|
{
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
Accelerator accelerator = AcceleratorPool.Shared.Rent();
|
int acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
Accelerator accelerator = _accelerators[acceleratorIndex];
|
||||||
AcceleratorStream? stream = accelerator.CreateStream();
|
AcceleratorStream? stream = accelerator.CreateStream();
|
||||||
// TODO: These buffers should be allocated once per accelerator and only reallocated when the new length exceeds capacity.
|
// TODO: These buffers should be allocated once per accelerator and only reallocated when the new length exceeds capacity.
|
||||||
// Modify the callers to use their own pool of buffers per accelerator, so that other threads don't use the accelerators
|
// Modify the callers to use their own pool of buffers per accelerator, so that other threads don't use the accelerators
|
||||||
@@ -630,19 +635,20 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
|
|
||||||
GpuUInt128 modulus = (GpuUInt128)prime;
|
GpuUInt128 modulus = (GpuUInt128)prime;
|
||||||
gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
Accelerator accelerator = gpu.Accelerator;
|
Accelerator accelerator = gpu.Accelerator;
|
||||||
|
|
||||||
MemoryBuffer1D<GpuUInt128, Stride1D.Dense> exponentBuffer = accelerator.Allocate1D<GpuUInt128>(length);
|
MemoryBuffer1D<GpuUInt128, Stride1D.Dense> exponentBuffer = accelerator.Allocate1D<GpuUInt128>(length);
|
||||||
MemoryBuffer1D<GpuUInt128, Stride1D.Dense> remainderBuffer = accelerator.Allocate1D<GpuUInt128>(length);
|
MemoryBuffer1D<GpuUInt128, Stride1D.Dense> remainderBuffer = accelerator.Allocate1D<GpuUInt128>(length);
|
||||||
|
|
||||||
AcceleratorStream? stream = AcceleratorStreamPool.Rent(accelerator);
|
AcceleratorStream? stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
exponentBuffer.View.CopyFromCPU(stream, exponentSpan);
|
exponentBuffer.View.CopyFromCPU(stream, exponentSpan);
|
||||||
|
|
||||||
gpu.Pow2ModWideKernel.Launch(stream, length, exponentBuffer.View, modulus, remainderBuffer.View);
|
gpu.Pow2ModWideKernel.Launch(stream, length, exponentBuffer.View, modulus, remainderBuffer.View);
|
||||||
remainderBuffer.View.CopyToCPU(stream, ref MemoryMarshal.GetReference(resultSpan), length);
|
remainderBuffer.View.CopyToCPU(stream, ref MemoryMarshal.GetReference(resultSpan), length);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
results[i] = (UInt128)resultSpan[i];
|
results[i] = (UInt128)resultSpan[i];
|
||||||
|
|||||||
@@ -791,6 +791,8 @@ public class MersenneDivisorCycles
|
|||||||
[ThreadStatic]
|
[ThreadStatic]
|
||||||
private static Dictionary<Accelerator, Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>? _divisorCycleKernel;
|
private static Dictionary<Accelerator, Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>? _divisorCycleKernel;
|
||||||
|
|
||||||
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
|
||||||
public static void GenerateGpu(string path, ulong maxDivisor, int batchSize = 1_000_000, long skipCount = 0L, long nextPosition = 0L)
|
public static void GenerateGpu(string path, ulong maxDivisor, int batchSize = 1_000_000, long skipCount = 0L, long nextPosition = 0L)
|
||||||
{
|
{
|
||||||
// Prepare output file with header
|
// Prepare output file with header
|
||||||
@@ -805,7 +807,8 @@ public class MersenneDivisorCycles
|
|||||||
divisors = pool.Rent(count);
|
divisors = pool.Rent(count);
|
||||||
outCycles = pool.Rent(count);
|
outCycles = pool.Rent(count);
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
var stream = accelerator.CreateStream();
|
var stream = accelerator.CreateStream();
|
||||||
|
|
||||||
using Stream outputStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, BufferSize10M, useAsync: true);
|
using Stream outputStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, BufferSize10M, useAsync: true);
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ public sealed class MersenneNumberTester(
|
|||||||
// TODO: Ensure Program passes useResidue correctly and that residue-vs-incremental-vs-LL selection respects CLI flags.
|
// TODO: Ensure Program passes useResidue correctly and that residue-vs-incremental-vs-LL selection respects CLI flags.
|
||||||
// Also consider injecting a shared cycles cache (MersenneDivisorCycles.Shared) to both CPU and GPU testers.
|
// Also consider injecting a shared cycles cache (MersenneDivisorCycles.Shared) to both CPU and GPU testers.
|
||||||
|
|
||||||
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
|
||||||
public void WarmUpOrders(ulong exponent, ulong limit = 5_000_000UL)
|
public void WarmUpOrders(ulong exponent, ulong limit = 5_000_000UL)
|
||||||
{
|
{
|
||||||
bool cacheEnabled = useOrderCache;
|
bool cacheEnabled = useOrderCache;
|
||||||
@@ -148,7 +150,8 @@ public sealed class MersenneNumberTester(
|
|||||||
UInt128[] qs = qsBuffer;
|
UInt128[] qs = qsBuffer;
|
||||||
|
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
var accelerator = AcceleratorPool.Shared.Rent();
|
var acceleratorIndex = AcceleratorPool.Shared.Rent();
|
||||||
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
var stream = accelerator.CreateStream();
|
var stream = accelerator.CreateStream();
|
||||||
var orderKernel = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.OrderKernelScan).Order!;
|
var orderKernel = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.OrderKernelScan).Order!;
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ public static class PerfectNumberConstants
|
|||||||
public static readonly uint PrimesLimit = 1_000_000; //(ulong)Array.MaxLength;// 1_000_000;
|
public static readonly uint PrimesLimit = 1_000_000; //(ulong)Array.MaxLength;// 1_000_000;
|
||||||
public const int MaxOddPowersCount = 128;
|
public const int MaxOddPowersCount = 128;
|
||||||
public const int PooledArrayThreshold = 64;
|
public const int PooledArrayThreshold = 64;
|
||||||
public static readonly int RollingAccelerators = 256; //SharedGpuContext.Device.MaxNumThreadsPerGroup;
|
public static readonly int RollingAccelerators = 298; //SharedGpuContext.Device.MaxNumThreadsPerGroup;
|
||||||
public const int ThreadsByStream = 1;
|
public const int ThreadsByAccelerator = 4096;
|
||||||
// TODO: Load these limits from the benchmark-driven configuration so CPU and GPU scans stay aligned with the optimal
|
// TODO: Load these limits from the benchmark-driven configuration so CPU and GPU scans stay aligned with the optimal
|
||||||
// divisor-cycle datasets we generate offline.
|
// divisor-cycle datasets we generate offline.
|
||||||
// TODO: Promote these magic numbers into a runtime profile derived from EvenPerfectBitScanner.Benchmarks so we can retune
|
// TODO: Promote these magic numbers into a runtime profile derived from EvenPerfectBitScanner.Benchmarks so we can retune
|
||||||
|
|||||||
@@ -65,7 +65,10 @@ internal static partial class PrimeOrderCalculator
|
|||||||
ulong result;
|
ulong result;
|
||||||
if (phiFactors.Factors is null)
|
if (phiFactors.Factors is null)
|
||||||
{
|
{
|
||||||
result = CalculateByFactorizationGpu(gpu, prime, divisorData);
|
result = prime <= PerfectNumberConstants.MaxQForDivisorCycles
|
||||||
|
? CalculateByFactorizationGpu(gpu, prime, divisorData)
|
||||||
|
: CalculateByFactorizationCpu(gpu, prime, divisorData);
|
||||||
|
|
||||||
phiFactors.Dispose();
|
phiFactors.Dispose();
|
||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -36,11 +36,12 @@ internal static partial class PrimeOrderCalculator
|
|||||||
entries.Sort(entries, static (a, b) => a.Key.CompareTo(b.Key));
|
entries.Sort(entries, static (a, b) => a.Key.CompareTo(b.Key));
|
||||||
|
|
||||||
ulong order = phi;
|
ulong order = phi;
|
||||||
|
var acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
var kernel = gpu.CheckFactorsKernel;
|
var kernel = gpu.CheckFactorsKernel;
|
||||||
gpu.EnsureCapacity(entryCount, 1);
|
gpu.EnsureCapacity(entryCount, 1);
|
||||||
|
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
gpu.Pow2ModEntriesToTestOnDevice.View.CopyFromCPU(stream, entries);
|
gpu.Pow2ModEntriesToTestOnDevice.View.CopyFromCPU(stream, entries);
|
||||||
|
|
||||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
|
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
@@ -49,7 +50,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
|
|
||||||
gpu.OutputUlong.View.CopyToCPU(stream, ref order, 1);
|
gpu.OutputUlong.View.CopyToCPU(stream, ref order, 1);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
AcceleratorStreamPool.Return(stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
|
|
||||||
// GpuPrimeWorkLimiter.Release();
|
// GpuPrimeWorkLimiter.Release();
|
||||||
return order;
|
return order;
|
||||||
@@ -64,10 +65,11 @@ internal static partial class PrimeOrderCalculator
|
|||||||
remaining = value;
|
remaining = value;
|
||||||
|
|
||||||
gpu.EnsureSmallPrimeFactorSlotsCapacity(GpuSmallPrimeFactorSlots);
|
gpu.EnsureSmallPrimeFactorSlotsCapacity(GpuSmallPrimeFactorSlots);
|
||||||
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
var accelerator = gpu.Accelerator;
|
var accelerator = gpu.Accelerator;
|
||||||
|
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
var stream = AcceleratorStreamPool.Rent(accelerator);
|
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.SmallPrimeFactorKernelScan);
|
KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.SmallPrimeFactorKernelScan);
|
||||||
SmallPrimeFactorViews tables = GpuKernelPool.GetSmallPrimeFactorTables(kernels);
|
SmallPrimeFactorViews tables = GpuKernelPool.GetSmallPrimeFactorTables(kernels);
|
||||||
|
|
||||||
@@ -112,7 +114,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
smallPrimeFactorRemainingSlotView.CopyToCPU(stream, ref remaining, 1);
|
smallPrimeFactorRemainingSlotView.CopyToCPU(stream, ref remaining, 1);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
// GpuPrimeWorkLimiter.Release();
|
// GpuPrimeWorkLimiter.Release();
|
||||||
|
|
||||||
for (int i = 0; i < factorCount; i++)
|
for (int i = 0; i < factorCount; i++)
|
||||||
@@ -135,9 +137,10 @@ internal static partial class PrimeOrderCalculator
|
|||||||
int factorCount = factors.Length;
|
int factorCount = factors.Length;
|
||||||
gpu.EnsureSpecialMaxFactorsCapacity(factorCount);
|
gpu.EnsureSpecialMaxFactorsCapacity(factorCount);
|
||||||
|
|
||||||
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
Accelerator accelerator = gpu.Accelerator;
|
Accelerator accelerator = gpu.Accelerator;
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
var stream = AcceleratorStreamPool.Rent(accelerator);
|
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
var kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.EvaluateSpecialMaxCandidatesKernel);
|
var kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.EvaluateSpecialMaxCandidatesKernel);
|
||||||
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> specialMaxFactorsView = gpu.SpecialMaxFactors.View;
|
ArrayView1D<ulong, Stride1D.Dense> specialMaxFactorsView = gpu.SpecialMaxFactors.View;
|
||||||
@@ -161,7 +164,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
specialMaxResultView.CopyToCPU(stream, ref result, 1);
|
specialMaxResultView.CopyToCPU(stream, ref result, 1);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
// GpuPrimeWorkLimiter.Release();
|
// GpuPrimeWorkLimiter.Release();
|
||||||
return result != 0;
|
return result != 0;
|
||||||
}
|
}
|
||||||
@@ -174,7 +177,8 @@ internal static partial class PrimeOrderCalculator
|
|||||||
Span<byte> factoredSpan = stackalloc byte[1];
|
Span<byte> factoredSpan = stackalloc byte[1];
|
||||||
Span<ulong> factorSpan = stackalloc ulong[1];
|
Span<ulong> factorSpan = stackalloc ulong[1];
|
||||||
|
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
gpu.Input.View.CopyFromCPU(stream, randomStateSpan);
|
gpu.Input.View.CopyFromCPU(stream, randomStateSpan);
|
||||||
|
|
||||||
var kernelLauncher = gpu.PollardRhoKernel.CreateLauncherDelegate<Action<AcceleratorStream, ulong, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
var kernelLauncher = gpu.PollardRhoKernel.CreateLauncherDelegate<Action<AcceleratorStream, ulong, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
@@ -186,7 +190,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
gpu.Input.View.CopyToCPU(stream, randomStateSpan);
|
gpu.Input.View.CopyToCPU(stream, randomStateSpan);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
ThreadStaticDeterministicRandomGpu.Exclusive.SetState(randomStateSpan[0]);
|
ThreadStaticDeterministicRandomGpu.Exclusive.SetState(randomStateSpan[0]);
|
||||||
|
|
||||||
bool factored = factoredSpan[0] != 0;
|
bool factored = factoredSpan[0] != 0;
|
||||||
|
|||||||
@@ -95,12 +95,13 @@ public sealed class PrimeTester
|
|||||||
byte flag = 0;
|
byte flag = 0;
|
||||||
|
|
||||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
var inputView = gpu.PrimeTestInput.View;
|
var inputView = gpu.PrimeTestInput.View;
|
||||||
var outputView = gpu.OutputByte.View;
|
var outputView = gpu.OutputByte.View;
|
||||||
var kernel = gpu.SmallPrimeSieveKernel!;
|
var kernel = gpu.SmallPrimeSieveKernel!;
|
||||||
|
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
inputView.CopyFromCPU(stream, ref n, 1);
|
inputView.CopyFromCPU(stream, ref n, 1);
|
||||||
|
|
||||||
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>>>();
|
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>>>();
|
||||||
@@ -122,7 +123,7 @@ public sealed class PrimeTester
|
|||||||
outputView.CopyToCPU(stream, ref flag, 1);
|
outputView.CopyToCPU(stream, ref flag, 1);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
// GpuPrimeWorkLimiter.Release();
|
// GpuPrimeWorkLimiter.Release();
|
||||||
|
|
||||||
@@ -139,7 +140,8 @@ public sealed class PrimeTester
|
|||||||
var outputView = output.View;
|
var outputView = output.View;
|
||||||
Kernel kernel = gpu.SmallPrimeSieveKernel!;
|
Kernel kernel = gpu.SmallPrimeSieveKernel!;
|
||||||
|
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
inputView.CopyFromCPU(stream, ref n, 1);
|
inputView.CopyFromCPU(stream, ref n, 1);
|
||||||
|
|
||||||
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>>>();
|
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>>>();
|
||||||
@@ -160,7 +162,7 @@ public sealed class PrimeTester
|
|||||||
|
|
||||||
outputView.CopyToCPU(stream, ref flag, 1);
|
outputView.CopyToCPU(stream, ref flag, 1);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
AcceleratorStreamPool.Return(stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
|
|
||||||
return flag != 0;
|
return flag != 0;
|
||||||
}
|
}
|
||||||
@@ -195,6 +197,7 @@ public sealed class PrimeTester
|
|||||||
{
|
{
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(GpuBatchSize);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(GpuBatchSize);
|
||||||
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
var accelerator = gpu.Accelerator;
|
var accelerator = gpu.Accelerator;
|
||||||
var kernel = gpu.SmallPrimeSieveKernel!;
|
var kernel = gpu.SmallPrimeSieveKernel!;
|
||||||
int totalLength = values.Length;
|
int totalLength = values.Length;
|
||||||
@@ -206,7 +209,7 @@ public sealed class PrimeTester
|
|||||||
var outputView = output.View;
|
var outputView = output.View;
|
||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
while (pos < totalLength)
|
while (pos < totalLength)
|
||||||
{
|
{
|
||||||
int remaining = totalLength - pos;
|
int remaining = totalLength - pos;
|
||||||
@@ -236,7 +239,7 @@ public sealed class PrimeTester
|
|||||||
}
|
}
|
||||||
|
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
AcceleratorStreamPool.Return(stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
// GpuPrimeWorkLimiter.Release();
|
// GpuPrimeWorkLimiter.Release();
|
||||||
}
|
}
|
||||||
@@ -280,13 +283,14 @@ public sealed class PrimeTester
|
|||||||
int length = values.Length;
|
int length = values.Length;
|
||||||
|
|
||||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
var accelerator = gpu.Accelerator;
|
var accelerator = gpu.Accelerator;
|
||||||
var kernel = gpu.SharesFactorKernel;
|
var kernel = gpu.SharesFactorKernel;
|
||||||
gpu.EnsureCapacity(0, length);
|
gpu.EnsureCapacity(0, length);
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense>? inputBuffer = gpu.PrimeTestInput;
|
MemoryBuffer1D<ulong, Stride1D.Dense>? inputBuffer = gpu.PrimeTestInput;
|
||||||
MemoryBuffer1D<byte, Stride1D.Dense>? resultBuffer = gpu.OutputByte;
|
MemoryBuffer1D<byte, Stride1D.Dense>? resultBuffer = gpu.OutputByte;
|
||||||
|
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
inputBuffer.View.CopyFromCPU(stream, values);
|
inputBuffer.View.CopyFromCPU(stream, values);
|
||||||
|
|
||||||
kernel.Launch(stream, length, inputBuffer.View, resultBuffer.View);
|
kernel.Launch(stream, length, inputBuffer.View, resultBuffer.View);
|
||||||
@@ -294,7 +298,7 @@ public sealed class PrimeTester
|
|||||||
resultBuffer.View.CopyToCPU(stream, in results);
|
resultBuffer.View.CopyToCPU(stream, in results);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user