Accelerator buffers integrated

This commit is contained in:
mlemanczyk committed 2025-11-18 01:13:12 +01:00
1 parent 342eff2726
commit bf7c4bab39
6 files changed
+65 -62

No files matched your search

@@ -4,13 +4,13 @@ using ILGPU.Runtime;
namespace PerfectNumbers.Core.Gpu.Accelerators; namespace PerfectNumbers.Core.Gpu.Accelerators;
internal sealed class LastDigitGpuTables internal readonly struct LastDigitGpuTables
{ {
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators; private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
private static readonly LastDigitGpuTables[] _sharedTables = new LastDigitGpuTables[PerfectNumberConstants.RollingAccelerators]; private static readonly LastDigitGpuTables[] _sharedTables = new LastDigitGpuTables[PerfectNumberConstants.RollingAccelerators];
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static LastDigitGpuTables EnsureStaticTables(int acceleratorIndex) => _sharedTables[acceleratorIndex]; internal static LastDigitGpuTables GetStaticTables(int acceleratorIndex) => _sharedTables[acceleratorIndex];
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void WarmUp(int acceleratorIndex, AcceleratorStream stream) => _sharedTables[acceleratorIndex] = new LastDigitGpuTables(_accelerators[acceleratorIndex], stream); internal static void WarmUp(int acceleratorIndex, AcceleratorStream stream) => _sharedTables[acceleratorIndex] = new LastDigitGpuTables(_accelerators[acceleratorIndex], stream);
@@ -88,13 +88,15 @@ public sealed class PrimeOrderCalculatorAccelerator
public readonly Accelerator Accelerator; public readonly Accelerator Accelerator;
public readonly int AcceleratorIndex; public readonly int AcceleratorIndex;
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> Input; public MemoryBuffer1D<ulong, Stride1D.Dense> Input;
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> OutputUlong; public MemoryBuffer1D<ulong, Stride1D.Dense> OutputUlong;
public MemoryBuffer1D<ulong, Stride1D.Dense> PrimeTestInput;
public MemoryBuffer1D<byte, Stride1D.Dense> OutputByte; public MemoryBuffer1D<byte, Stride1D.Dense> OutputByte;
public MemoryBuffer1D<int, Stride1D.Dense> HeuristicFlag; public MemoryBuffer1D<int, Stride1D.Dense> OutputInt;
public MemoryBuffer1D<KeyValuePair<ulong, int>, Stride1D.Dense> Pow2ModEntriesToTestOnDevice; public MemoryBuffer1D<KeyValuePair<ulong, int>, Stride1D.Dense> Pow2ModEntriesToTestOnDevice;
public Dictionary<ulong, int> Pow2ModEntriesToTestOnHost = []; public Dictionary<ulong, int> Pow2ModEntriesToTestOnHost = [];
#region Static Tables
public readonly MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastOne; public readonly MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastOne;
public readonly MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastSeven; public readonly MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastSeven;
public readonly MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastThree; public readonly MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastThree;
@@ -103,30 +105,26 @@ public sealed class PrimeOrderCalculatorAccelerator
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastSeven; public readonly MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastSeven;
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastThree; public readonly MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastThree;
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastNine; public readonly MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastNine;
#endregion
public readonly MemoryBuffer1D<int, Stride1D.Dense> SmallPrimeFactorCountSlot; 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 readonly MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxResult;
public readonly HeuristicGpuCombinedDivisorTables DivisorTables; public readonly HeuristicGpuCombinedDivisorTables DivisorTables;
public readonly SmallPrimeFactorGpuTables SmallPrimeFactorTables; public readonly SmallPrimeFactorGpuTables SmallPrimeFactorTables;
public readonly Kernel SmallPrimeSieveKernel;
public readonly Kernel CheckFactorsKernel; public readonly Kernel CheckFactorsKernel;
public readonly Kernel ConvertToStandardKernel; public readonly Kernel ConvertToStandardKernel;
public readonly Kernel HeuristicCombinedTrialDivisionKernel; public readonly Kernel HeuristicCombinedTrialDivisionKernel;
public readonly Kernel KeepMontgomeryKernel; public readonly Kernel KeepMontgomeryKernel;
public readonly Kernel PollardRhoKernel; public readonly Kernel PollardRhoKernel;
public readonly Kernel Pow2ModWideKernel; public readonly Kernel Pow2ModWideKernel;
public readonly Kernel SharesFactorKernel;
public readonly Kernel SmallPrimeFactorKernel; public readonly Kernel SmallPrimeFactorKernel;
public readonly Kernel SmallPrimeSieveKernel;
public readonly Kernel SpecialMaxKernel; public readonly Kernel SpecialMaxKernel;
public Kernel SharesFactorKernel;
public void EnsureCapacity(int factorsCount, int primeTesterCapacity) public void EnsureCapacity(int factorsCount, int primeTesterCapacity)
{ {
if (factorsCount > Pow2ModEntriesToTestOnDevice.Length) if (factorsCount > Pow2ModEntriesToTestOnDevice.Length)
@@ -136,42 +134,61 @@ public sealed class PrimeOrderCalculatorAccelerator
Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount); Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount);
} }
if (primeTesterCapacity > PrimeTestInput.Length) if (primeTesterCapacity > Input.Length)
{ {
PrimeTestInput.Dispose(); Input.Dispose();
OutputByte.Dispose(); Input = Accelerator.Allocate1D<ulong>(primeTesterCapacity);
HeuristicFlag.Dispose(); }
PrimeTestInput = Accelerator.Allocate1D<ulong>(primeTesterCapacity); if (primeTesterCapacity > OutputByte.Length)
{
OutputByte.Dispose();
OutputByte = Accelerator.Allocate1D<byte>(primeTesterCapacity); OutputByte = Accelerator.Allocate1D<byte>(primeTesterCapacity);
HeuristicFlag = Accelerator.Allocate1D<int>(primeTesterCapacity); }
if (primeTesterCapacity > OutputInt.Length)
{
OutputInt.Dispose();
OutputInt = Accelerator.Allocate1D<int>(primeTesterCapacity);
} }
} }
public void EnsureSmallPrimeFactorSlotsCapacity(int newSize) public void EnsureSmallPrimeFactorSlotsCapacity(int newSize)
{ {
// Console.WriteLine($"Resizing GPU scratch buffer from pool ({buffer.SmallPrimeFactorPrimeSlots.Length} / {smallPrimeFactorSlotCount}), ({buffer.SpecialMaxFactors.Length}/{specialMaxFactorCapacity})"); // Console.WriteLine($"Resizing GPU scratch buffer from pool ({buffer.SmallPrimeFactorPrimeSlots.Length} / {smallPrimeFactorSlotCount}), ({buffer.SpecialMaxFactors.Length}/{specialMaxFactorCapacity})");
if (SmallPrimeFactorPrimeSlots.Length < newSize) if (OutputUlong.Length < newSize)
{ {
SmallPrimeFactorPrimeSlots.Dispose(); OutputUlong.Dispose();
SmallPrimeFactorExponentSlots.Dispose();
var accelerator = Accelerator; var accelerator = Accelerator;
SmallPrimeFactorPrimeSlots = accelerator.Allocate1D<ulong>(newSize); OutputUlong = accelerator.Allocate1D<ulong>(newSize);
SmallPrimeFactorExponentSlots = accelerator.Allocate1D<int>(newSize); }
if (OutputInt.Length < newSize)
{
OutputInt.Dispose();
var accelerator = Accelerator;
OutputInt = accelerator.Allocate1D<int>(newSize);
} }
} }
public void EnsureSpecialMaxFactorsCapacity(int newSize) public void EnsureSpecialMaxFactorsCapacity(int newSize)
{ {
if (SpecialMaxFactors.Length < newSize) if (Input.Length < newSize)
{ {
SpecialMaxFactors.Dispose(); Input.Dispose();
SpecialMaxCandidates.Dispose();
var accelerator = Accelerator; var accelerator = Accelerator;
SpecialMaxFactors = accelerator.Allocate1D<ulong>(newSize); Input = accelerator.Allocate1D<ulong>(newSize);
SpecialMaxCandidates = accelerator.Allocate1D<ulong>(newSize); }
if (OutputUlong.Length < newSize)
{
OutputUlong.Dispose();
var accelerator = Accelerator;
OutputUlong = accelerator.Allocate1D<ulong>(newSize);
} }
} }
@@ -180,22 +197,16 @@ public sealed class PrimeOrderCalculatorAccelerator
var accelerator = _accelerators[acceleratorIndex]; var accelerator = _accelerators[acceleratorIndex];
Accelerator = accelerator; Accelerator = accelerator;
AcceleratorIndex = acceleratorIndex; AcceleratorIndex = acceleratorIndex;
Input = accelerator.Allocate1D<ulong>(1); Input = accelerator.Allocate1D<ulong>(Math.Max(specialMaxFactorCapacity, primeTesterCapacity));
OutputUlong = accelerator.Allocate1D<ulong>(1); OutputUlong = accelerator.Allocate1D<ulong>(Math.Max(specialMaxFactorCapacity, smallPrimeFactorSlotCount));
Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount); Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount);
PrimeTestInput = Accelerator.Allocate1D<ulong>(primeTesterCapacity);
OutputByte = Accelerator.Allocate1D<byte>(primeTesterCapacity); OutputByte = Accelerator.Allocate1D<byte>(primeTesterCapacity);
HeuristicFlag = Accelerator.Allocate1D<int>(primeTesterCapacity); OutputInt = Accelerator.Allocate1D<int>(Math.Max(primeTesterCapacity, smallPrimeFactorSlotCount));
SmallPrimeFactorPrimeSlots = accelerator.Allocate1D<ulong>(smallPrimeFactorSlotCount);
SmallPrimeFactorExponentSlots = accelerator.Allocate1D<int>(smallPrimeFactorSlotCount);
SmallPrimeFactorCountSlot = accelerator.Allocate1D<int>(1); SmallPrimeFactorCountSlot = accelerator.Allocate1D<int>(1);
SmallPrimeFactorRemainingSlot = accelerator.Allocate1D<ulong>(1);
SpecialMaxFactors = accelerator.Allocate1D<ulong>(specialMaxFactorCapacity);
SpecialMaxCandidates = accelerator.Allocate1D<ulong>(specialMaxFactorCapacity);
SpecialMaxResult = accelerator.Allocate1D<ulong>(1); SpecialMaxResult = accelerator.Allocate1D<ulong>(1);
var lastDigitSharedTables = LastDigitGpuTables.EnsureStaticTables(acceleratorIndex); LastDigitGpuTables lastDigitSharedTables = LastDigitGpuTables.GetStaticTables(acceleratorIndex);
DevicePrimesLastOne = lastDigitSharedTables.DevicePrimesLastOne; DevicePrimesLastOne = lastDigitSharedTables.DevicePrimesLastOne;
DevicePrimesLastSeven = lastDigitSharedTables.DevicePrimesLastSeven; DevicePrimesLastSeven = lastDigitSharedTables.DevicePrimesLastSeven;
@@ -240,15 +251,9 @@ public sealed class PrimeOrderCalculatorAccelerator
Input.Dispose(); Input.Dispose();
OutputUlong.Dispose(); OutputUlong.Dispose();
Pow2ModEntriesToTestOnDevice.Dispose(); Pow2ModEntriesToTestOnDevice.Dispose();
PrimeTestInput.Dispose();
OutputByte.Dispose(); OutputByte.Dispose();
HeuristicFlag.Dispose(); OutputInt.Dispose();
SmallPrimeFactorPrimeSlots.Dispose();
SmallPrimeFactorExponentSlots.Dispose();
SmallPrimeFactorCountSlot.Dispose(); SmallPrimeFactorCountSlot.Dispose();
SmallPrimeFactorRemainingSlot.Dispose();
SpecialMaxFactors.Dispose();
SpecialMaxCandidates.Dispose();
SpecialMaxResult.Dispose(); SpecialMaxResult.Dispose();
// These resources are shared between GPU leases // These resources are shared between GPU leases
@@ -238,7 +238,7 @@ public sealed class HeuristicCombinedPrimeTester
var acceleratorIndex = gpu.AcceleratorIndex; var acceleratorIndex = gpu.AcceleratorIndex;
var stream = AcceleratorStreamPool.Rent(acceleratorIndex); var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
var kernel = gpu.HeuristicCombinedTrialDivisionKernel; var kernel = gpu.HeuristicCombinedTrialDivisionKernel;
var flagView1D = gpu.HeuristicFlag!.View; var flagView1D = gpu.OutputInt!.View;
bool compositeDetected = false; bool compositeDetected = false;
int divisorLength = GetCombinedDivisors(nMod10).Length; int divisorLength = GetCombinedDivisors(nMod10).Length;
+1 -1
View File
@@ -247,7 +247,7 @@ public sealed class HeuristicPrimeTester
int acceleratorIndex = gpu.AcceleratorIndex; int acceleratorIndex = gpu.AcceleratorIndex;
var stream = AcceleratorStreamPool.Rent(acceleratorIndex); var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
var kernel = gpu.HeuristicCombinedTrialDivisionKernel; var kernel = gpu.HeuristicCombinedTrialDivisionKernel;
var flagView1D = gpu.HeuristicFlag!.View; var flagView1D = gpu.OutputInt!.View;
bool compositeDetected; bool compositeDetected;
int compositeFlag = 0; int compositeFlag = 0;
@@ -75,9 +75,9 @@ internal static partial class PrimeOrderCalculator
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>>>(); 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 = gpu.SmallPrimeFactorCountSlot.View; ArrayView1D<int, Stride1D.Dense> smallPrimeFactorCountSlotView = gpu.SmallPrimeFactorCountSlot.View;
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorRemainingSlotView = gpu.SmallPrimeFactorRemainingSlot.View; ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorRemainingSlotView = gpu.Input.View;
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorPrimeSlotsView = gpu.SmallPrimeFactorPrimeSlots.View; ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorPrimeSlotsView = gpu.OutputUlong.View;
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorExponentSlotsView = gpu.SmallPrimeFactorExponentSlots.View; ArrayView1D<int, Stride1D.Dense> smallPrimeFactorExponentSlotsView = gpu.OutputInt.View;
ArrayView1D<uint, Stride1D.Dense> smallPrimeFactorsPrimesView = gpu.SmallPrimeFactorTables.Primes.View; ArrayView1D<uint, Stride1D.Dense> smallPrimeFactorsPrimesView = gpu.SmallPrimeFactorTables.Primes.View;
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorsSquaresView = gpu.SmallPrimeFactorTables.Squares.View; ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorsSquaresView = gpu.SmallPrimeFactorTables.Squares.View;
@@ -94,7 +94,6 @@ internal static partial class PrimeOrderCalculator
smallPrimeFactorCountSlotView, smallPrimeFactorCountSlotView,
smallPrimeFactorRemainingSlotView); smallPrimeFactorRemainingSlotView);
factorCount = 0; factorCount = 0;
smallPrimeFactorCountSlotView.CopyToCPU(stream, ref factorCount, 1); smallPrimeFactorCountSlotView.CopyToCPU(stream, ref factorCount, 1);
stream.Synchronize(); stream.Synchronize();
@@ -140,8 +139,8 @@ internal static partial class PrimeOrderCalculator
// GpuPrimeWorkLimiter.Acquire(); // GpuPrimeWorkLimiter.Acquire();
var stream = AcceleratorStreamPool.Rent(acceleratorIndex); var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
ArrayView1D<ulong, Stride1D.Dense> specialMaxFactorsView = gpu.SpecialMaxFactors.View; ArrayView1D<ulong, Stride1D.Dense> specialMaxFactorsView = gpu.Input.View;
specialMaxFactorsView.SubView(0, factorCount).CopyFromCPU(stream, ref MemoryMarshal.GetReference(factors), factorCount); specialMaxFactorsView.SubView(0, factorCount).CopyFromCPU(stream, factors);
var kernel = gpu.SpecialMaxKernel; var kernel = gpu.SpecialMaxKernel;
@@ -155,7 +154,7 @@ internal static partial class PrimeOrderCalculator
specialMaxFactorsView, specialMaxFactorsView,
factorCount, factorCount,
divisorData, divisorData,
gpu.SpecialMaxCandidates.View, gpu.OutputUlong.View,
specialMaxResultView); specialMaxResultView);
ulong result = 0UL; ulong result = 0UL;
+4 -5
View File
@@ -96,7 +96,7 @@ public sealed class PrimeTester
var gpu = PrimeOrderCalculatorAccelerator.Rent(1); var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
int acceleratorIndex = gpu.AcceleratorIndex; int acceleratorIndex = gpu.AcceleratorIndex;
var inputView = gpu.PrimeTestInput.View; var inputView = gpu.Input.View;
var outputView = gpu.OutputByte.View; var outputView = gpu.OutputByte.View;
var kernel = gpu.SmallPrimeSieveKernel!; var kernel = gpu.SmallPrimeSieveKernel!;
@@ -134,7 +134,7 @@ public sealed class PrimeTester
public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n) public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n)
{ {
byte flag = 0; byte flag = 0;
var input = gpu.PrimeTestInput; var input = gpu.Input;
var inputView = input.View; var inputView = input.View;
var output = gpu.OutputByte; var output = gpu.OutputByte;
var outputView = output.View; var outputView = output.View;
@@ -203,7 +203,7 @@ public sealed class PrimeTester
int totalLength = values.Length; int totalLength = values.Length;
int batchSize = GpuBatchSize; int batchSize = GpuBatchSize;
var input = gpu.PrimeTestInput; var input = gpu.Input;
var output = gpu.OutputByte; var output = gpu.OutputByte;
var inputView = input.View; var inputView = input.View;
var outputView = output.View; var outputView = output.View;
@@ -281,10 +281,9 @@ public sealed class PrimeTester
var gpu = PrimeOrderCalculatorAccelerator.Rent(1); var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
int acceleratorIndex = gpu.AcceleratorIndex; int acceleratorIndex = gpu.AcceleratorIndex;
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.Input;
MemoryBuffer1D<byte, Stride1D.Dense>? resultBuffer = gpu.OutputByte; MemoryBuffer1D<byte, Stride1D.Dense>? resultBuffer = gpu.OutputByte;
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex); AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);