GPU memory allocations protected with lock to prevent shared memory access issues. GPU usage limited for the best performance.

This commit is contained in:
mlemanczyk committed 2025-11-19 16:49:01 +01:00
1 parent 02d16bf05c
commit 5cac51479e
12 files changed
+236 -148

No files matched your search

+8 -5
View File
@@ -260,11 +260,14 @@ public sealed class DivisorCycleCache
} }
Accelerator accelerator = _accelerator; Accelerator accelerator = _accelerator;
divisorBuffer = accelerator.Allocate1D<ulong>(requiredCapacity); lock(accelerator)
powBuffer = accelerator.Allocate1D<ulong>(requiredCapacity); {
orderBuffer = accelerator.Allocate1D<ulong>(requiredCapacity); divisorBuffer = accelerator.Allocate1D<ulong>(requiredCapacity);
resultBuffer = accelerator.Allocate1D<ulong>(requiredCapacity); powBuffer = accelerator.Allocate1D<ulong>(requiredCapacity);
statusBuffer = accelerator.Allocate1D<byte>(requiredCapacity); orderBuffer = accelerator.Allocate1D<ulong>(requiredCapacity);
resultBuffer = accelerator.Allocate1D<ulong>(requiredCapacity);
statusBuffer = accelerator.Allocate1D<byte>(requiredCapacity);
}
} }
private void ComputeCyclesGpuCore(ReadOnlySpan<ulong> divisors, Span<ulong> destination) private void ComputeCyclesGpuCore(ReadOnlySpan<ulong> divisors, Span<ulong> destination)
@@ -117,7 +117,11 @@ public sealed class PrimeOrderCalculatorAccelerator
public readonly Kernel CheckFactorsKernel; public readonly Kernel CheckFactorsKernel;
public readonly Kernel ConvertToStandardKernel; public readonly Kernel ConvertToStandardKernel;
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>> ConvertToStandardKernelLauncher;
public readonly Kernel HeuristicCombinedTrialDivisionKernel; public readonly Kernel HeuristicCombinedTrialDivisionKernel;
public readonly Action<AcceleratorStream, Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicCombinedGpuViews> HeuristicCombinedTrialDivisionKernelLauncher;
public readonly Kernel KeepMontgomeryKernel; public readonly Kernel KeepMontgomeryKernel;
public readonly Kernel PollardRhoKernel; public readonly Kernel PollardRhoKernel;
public readonly Kernel Pow2ModWideKernel; public readonly Kernel Pow2ModWideKernel;
@@ -133,29 +137,41 @@ public sealed class PrimeOrderCalculatorAccelerator
MemoryBuffer1D<KeyValuePair<ulong, int>, Stride1D.Dense> pow2ModEntriesToTestOnDevice = Pow2ModEntriesToTestOnDevice; MemoryBuffer1D<KeyValuePair<ulong, int>, Stride1D.Dense> pow2ModEntriesToTestOnDevice = Pow2ModEntriesToTestOnDevice;
if (pow2ModEntriesToTestOnDevice.Length < factorsCount) if (pow2ModEntriesToTestOnDevice.Length < factorsCount)
{ {
pow2ModEntriesToTestOnDevice.Dispose(); lock (accelerator)
Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount); {
pow2ModEntriesToTestOnDevice.Dispose();
Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount);
}
} }
MemoryBuffer1D<ulong, Stride1D.Dense> input = Input; MemoryBuffer1D<ulong, Stride1D.Dense> input = Input;
if (input.Length < primeTesterCapacity) if (input.Length < primeTesterCapacity)
{ {
input.Dispose(); lock (accelerator)
Input = accelerator.Allocate1D<ulong>(primeTesterCapacity); {
input.Dispose();
Input = accelerator.Allocate1D<ulong>(primeTesterCapacity);
}
} }
MemoryBuffer1D<byte, Stride1D.Dense> outputByte = OutputByte; MemoryBuffer1D<byte, Stride1D.Dense> outputByte = OutputByte;
if (outputByte.Length < primeTesterCapacity) if (outputByte.Length < primeTesterCapacity)
{ {
outputByte.Dispose(); lock (accelerator)
OutputByte = accelerator.Allocate1D<byte>(primeTesterCapacity); {
outputByte.Dispose();
OutputByte = accelerator.Allocate1D<byte>(primeTesterCapacity);
}
} }
MemoryBuffer1D<int, Stride1D.Dense> outputInt = OutputInt; MemoryBuffer1D<int, Stride1D.Dense> outputInt = OutputInt;
if (outputInt.Length < primeTesterCapacity) if (outputInt.Length < primeTesterCapacity)
{ {
outputInt.Dispose(); lock (accelerator)
OutputInt = accelerator.Allocate1D<int>(primeTesterCapacity); {
outputInt.Dispose();
OutputInt = accelerator.Allocate1D<int>(primeTesterCapacity);
}
} }
} }
@@ -166,15 +182,21 @@ public sealed class PrimeOrderCalculatorAccelerator
MemoryBuffer1D<ulong, Stride1D.Dense> outputUlong = OutputUlong; MemoryBuffer1D<ulong, Stride1D.Dense> outputUlong = OutputUlong;
if (outputUlong.Length < newSize) if (outputUlong.Length < newSize)
{ {
outputUlong.Dispose(); lock (accelerator)
OutputUlong = accelerator.Allocate1D<ulong>(newSize); {
outputUlong.Dispose();
OutputUlong = accelerator.Allocate1D<ulong>(newSize);
}
} }
MemoryBuffer1D<int, Stride1D.Dense> outputInt = OutputInt; MemoryBuffer1D<int, Stride1D.Dense> outputInt = OutputInt;
if (outputInt.Length < newSize) if (outputInt.Length < newSize)
{ {
outputInt.Dispose(); lock (accelerator)
OutputInt = accelerator.Allocate1D<int>(newSize); {
outputInt.Dispose();
OutputInt = accelerator.Allocate1D<int>(newSize);
}
} }
} }
@@ -184,15 +206,21 @@ public sealed class PrimeOrderCalculatorAccelerator
MemoryBuffer1D<ulong, Stride1D.Dense> input = Input; MemoryBuffer1D<ulong, Stride1D.Dense> input = Input;
if (input.Length < newSize) if (input.Length < newSize)
{ {
input.Dispose(); lock (accelerator)
Input = accelerator.Allocate1D<ulong>(newSize); {
input.Dispose();
Input = accelerator.Allocate1D<ulong>(newSize);
}
} }
MemoryBuffer1D<ulong, Stride1D.Dense> outputUlong = OutputUlong; MemoryBuffer1D<ulong, Stride1D.Dense> outputUlong = OutputUlong;
if (outputUlong.Length < newSize) if (outputUlong.Length < newSize)
{ {
outputUlong.Dispose(); lock (accelerator)
OutputUlong = accelerator.Allocate1D<ulong>(newSize); {
outputUlong.Dispose();
OutputUlong = accelerator.Allocate1D<ulong>(newSize);
}
} }
} }
@@ -201,57 +229,65 @@ public sealed class PrimeOrderCalculatorAccelerator
var accelerator = _accelerators[acceleratorIndex]; var accelerator = _accelerators[acceleratorIndex];
Accelerator = accelerator; Accelerator = accelerator;
AcceleratorIndex = acceleratorIndex; AcceleratorIndex = acceleratorIndex;
Input = accelerator.Allocate1D<ulong>(Math.Max(specialMaxFactorCapacity, primeTesterCapacity)); lock (accelerator)
OutputByte = Accelerator.Allocate1D<byte>(primeTesterCapacity);
OutputInt = Accelerator.Allocate1D<int>(Math.Max(primeTesterCapacity, smallPrimeFactorSlotCount));
OutputUlong = accelerator.Allocate1D<ulong>(Math.Max(specialMaxFactorCapacity, smallPrimeFactorSlotCount));
Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount);
SmallPrimeFactorCountSlot = accelerator.Allocate1D<int>(1);
SpecialMaxResult = accelerator.Allocate1D<ulong>(1);
LastDigitGpuTables lastDigitSharedTables = LastDigitGpuTables.GetStaticTables(acceleratorIndex);
DevicePrimesLastOne = lastDigitSharedTables.DevicePrimesLastOne.View;
DevicePrimesLastSeven = lastDigitSharedTables.DevicePrimesLastSeven.View;
DevicePrimesLastThree = lastDigitSharedTables.DevicePrimesLastThree.View;
DevicePrimesLastNine = lastDigitSharedTables.DevicePrimesLastNine.View;
DevicePrimesPow2LastOne = lastDigitSharedTables.DevicePrimesPow2LastOne.View;
DevicePrimesPow2LastSeven = lastDigitSharedTables.DevicePrimesPow2LastSeven.View;
DevicePrimesPow2LastThree = lastDigitSharedTables.DevicePrimesPow2LastThree.View;
DevicePrimesPow2LastNine = lastDigitSharedTables.DevicePrimesPow2LastNine.View;
DivisorTables = HeuristicCombinedGpuTables
.GetStaticTables(acceleratorIndex)
.CreateViews();
var smallPrimeFactorTables = SmallPrimeFactorGpuTables.GetStaticTables(acceleratorIndex);
if (smallPrimeFactorTables.HasValue)
{ {
SmallPrimeFactorGpuTables tables = smallPrimeFactorTables.Value; Input = accelerator.Allocate1D<ulong>(Math.Max(specialMaxFactorCapacity, primeTesterCapacity));
SmallPrimeFactorPrimes = tables.Primes.View; OutputByte = Accelerator.Allocate1D<byte>(primeTesterCapacity);
SmallPrimeFactorSquares = tables.Squares.View; OutputInt = Accelerator.Allocate1D<int>(Math.Max(primeTesterCapacity, smallPrimeFactorSlotCount));
OutputUlong = accelerator.Allocate1D<ulong>(Math.Max(specialMaxFactorCapacity, smallPrimeFactorSlotCount));
Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount);
SmallPrimeFactorCountSlot = accelerator.Allocate1D<int>(1);
SpecialMaxResult = accelerator.Allocate1D<ulong>(1);
LastDigitGpuTables lastDigitSharedTables = LastDigitGpuTables.GetStaticTables(acceleratorIndex);
DevicePrimesLastOne = lastDigitSharedTables.DevicePrimesLastOne.View;
DevicePrimesLastSeven = lastDigitSharedTables.DevicePrimesLastSeven.View;
DevicePrimesLastThree = lastDigitSharedTables.DevicePrimesLastThree.View;
DevicePrimesLastNine = lastDigitSharedTables.DevicePrimesLastNine.View;
DevicePrimesPow2LastOne = lastDigitSharedTables.DevicePrimesPow2LastOne.View;
DevicePrimesPow2LastSeven = lastDigitSharedTables.DevicePrimesPow2LastSeven.View;
DevicePrimesPow2LastThree = lastDigitSharedTables.DevicePrimesPow2LastThree.View;
DevicePrimesPow2LastNine = lastDigitSharedTables.DevicePrimesPow2LastNine.View;
DivisorTables = HeuristicCombinedGpuTables
.GetStaticTables(acceleratorIndex)
.CreateViews();
var smallPrimeFactorTables = SmallPrimeFactorGpuTables.GetStaticTables(acceleratorIndex);
if (smallPrimeFactorTables.HasValue)
{
SmallPrimeFactorGpuTables tables = smallPrimeFactorTables.Value;
SmallPrimeFactorPrimes = tables.Primes.View;
SmallPrimeFactorSquares = tables.Squares.View;
}
CheckFactorsKernel = KernelUtil.GetKernel(accelerator.LoadStreamKernel<int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.CheckFactorsKernel));
Kernel convertToStandardKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelConvertToStandard));
ConvertToStandardKernel = convertToStandardKernel;
ConvertToStandardKernelLauncher = convertToStandardKernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
var heuristicCombinedTrialDivisionKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicCombinedGpuViews>(PrimeTesterKernels.HeuristicTrialCombinedDivisionKernel));
HeuristicCombinedTrialDivisionKernel = heuristicCombinedTrialDivisionKernel;
HeuristicCombinedTrialDivisionKernelLauncher = heuristicCombinedTrialDivisionKernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicCombinedGpuViews>>();
KeepMontgomeryKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelKeepMontgomery));
PollardRhoKernel = KernelUtil.GetKernel(accelerator.LoadStreamKernel<ulong, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.TryPollardRhoKernel));
Pow2ModWideKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>(PrimeOrderGpuHeuristics.Pow2ModKernelWide));
SharesFactorKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SharesFactorKernel));
SmallPrimeFactorKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(SmallPrimeFactorKernels.SmallPrimeFactorKernelScan));
SmallPrimeSieveKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SmallPrimeSieveKernel));
SpecialMaxKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.EvaluateSpecialMaxCandidatesKernel));
} }
CheckFactorsKernel = KernelUtil.GetKernel(accelerator.LoadStreamKernel<int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.CheckFactorsKernel));
ConvertToStandardKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelConvertToStandard));
HeuristicCombinedTrialDivisionKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicCombinedGpuViews>(PrimeTesterKernels.HeuristicTrialCombinedDivisionKernel));
KeepMontgomeryKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelKeepMontgomery));
PollardRhoKernel = KernelUtil.GetKernel(accelerator.LoadStreamKernel<ulong, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.TryPollardRhoKernel));
Pow2ModWideKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>(PrimeOrderGpuHeuristics.Pow2ModKernelWide));
SharesFactorKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SharesFactorKernel));
SmallPrimeFactorKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(SmallPrimeFactorKernels.SmallPrimeFactorKernelScan));
SmallPrimeSieveKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SmallPrimeSieveKernel));
SpecialMaxKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.EvaluateSpecialMaxCandidatesKernel));
} }
public void Dispose() public void Dispose()
+9 -9
View File
@@ -26,7 +26,7 @@ public class GpuKernelPool
internal static KernelContainer GetOrAddKernels(int acceleratorIndex, AcceleratorStream stream, KernelType kernelType) internal static KernelContainer GetOrAddKernels(int acceleratorIndex, AcceleratorStream stream, KernelType kernelType)
{ {
var pool = _pool ??= []; var pool = _pool ??= [];
if (pool[acceleratorIndex] is not {} kernels) if (pool[acceleratorIndex] is not { } kernels)
{ {
kernels = new(); kernels = new();
} }
@@ -151,7 +151,7 @@ public class GpuKernelPool
var host = MersenneDivisorCycles.Shared.ExportSmallCyclesSnapshot(); var host = MersenneDivisorCycles.Shared.ExportSmallCyclesSnapshot();
MemoryBuffer1D<ulong, Stride1D.Dense>? device; MemoryBuffer1D<ulong, Stride1D.Dense>? device;
// lock (accelerator) lock (accelerator)
{ {
device = accelerator.Allocate1D<ulong>(host.Length); device = accelerator.Allocate1D<ulong>(host.Length);
} }
@@ -195,13 +195,13 @@ public class GpuKernelPool
MemoryBuffer1D<ulong, Stride1D.Dense>? deviceLastOnePow2; MemoryBuffer1D<ulong, Stride1D.Dense>? deviceLastOnePow2;
MemoryBuffer1D<ulong, Stride1D.Dense>? deviceLastSevenPow2; MemoryBuffer1D<ulong, Stride1D.Dense>? deviceLastSevenPow2;
// lock (accelerator) lock (accelerator)
// { {
deviceLastOne = accelerator.Allocate1D<uint>(hostLastOne.Length); deviceLastOne = accelerator.Allocate1D<uint>(hostLastOne.Length);
deviceLastSeven = accelerator.Allocate1D<uint>(hostLastSeven.Length); deviceLastSeven = accelerator.Allocate1D<uint>(hostLastSeven.Length);
deviceLastOnePow2 = accelerator.Allocate1D<ulong>(hostLastOnePow2.Length); deviceLastOnePow2 = accelerator.Allocate1D<ulong>(hostLastOnePow2.Length);
deviceLastSevenPow2 = accelerator.Allocate1D<ulong>(hostLastSevenPow2.Length); deviceLastSevenPow2 = accelerator.Allocate1D<ulong>(hostLastSevenPow2.Length);
// } }
deviceLastOne.View.CopyFromCPU(stream, hostLastOne); deviceLastOne.View.CopyFromCPU(stream, hostLastOne);
deviceLastSeven.View.CopyFromCPU(stream, hostLastSeven); deviceLastSeven.View.CopyFromCPU(stream, hostLastSeven);
@@ -540,7 +540,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
if (_divisorBuffer == null) if (_divisorBuffer == null)
{ {
// lock(accelerator) lock(accelerator)
{ {
_divisorBuffer = accelerator.Allocate1D<GpuDivisorPartialData>(1); _divisorBuffer = accelerator.Allocate1D<GpuDivisorPartialData>(1);
_offsetBuffer = accelerator.Allocate1D<int>(1); _offsetBuffer = accelerator.Allocate1D<int>(1);
@@ -570,7 +570,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
{ {
int desiredCapacity = requiredCapacity > _capacity ? requiredCapacity : _capacity; int desiredCapacity = requiredCapacity > _capacity ? requiredCapacity : _capacity;
_capacity = desiredCapacity; _capacity = desiredCapacity;
// lock (accelerator) lock (accelerator)
{ {
_exponentsBuffer = accelerator.Allocate1D<ulong>(desiredCapacity); _exponentsBuffer = accelerator.Allocate1D<ulong>(desiredCapacity);
_hitBuffer = accelerator.Allocate1D<byte>(desiredCapacity); _hitBuffer = accelerator.Allocate1D<byte>(desiredCapacity);
@@ -798,7 +798,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
private void AllocateDeviceBuffers(Accelerator accelerator, int capacity) private void AllocateDeviceBuffers(Accelerator accelerator, int capacity)
{ {
// lock (accelerator) lock (accelerator)
{ {
_divisorDataBuffer = accelerator.Allocate1D<GpuDivisorPartialData>(capacity); _divisorDataBuffer = accelerator.Allocate1D<GpuDivisorPartialData>(capacity);
_offsetBuffer = accelerator.Allocate1D<int>(capacity); _offsetBuffer = accelerator.Allocate1D<int>(capacity);
@@ -55,8 +55,10 @@ public static class Pow2MontgomeryGpuCalculator
// 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);
var kernel = gpu.ConvertToStandardKernel; var kernelLauncher = gpu.ConvertToStandardKernelLauncher!;
kernel.Launch(stream, 1, 1, exponentBuffer.View, divisor, resultBuffer.View);
kernelLauncher(stream, 1, exponentBuffer.View, divisor, resultBuffer.View);
resultBuffer.View.CopyToCPU(stream, ref result, 1); resultBuffer.View.CopyToCPU(stream, ref result, 1);
stream.Synchronize(); stream.Synchronize();
@@ -73,7 +75,6 @@ public static class Pow2MontgomeryGpuCalculator
ulong result = 0UL; ulong result = 0UL;
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.ConvertToStandardKernel;
int acceleratorIndex = gpu.AcceleratorIndex; int acceleratorIndex = gpu.AcceleratorIndex;
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex); AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
@@ -81,8 +82,11 @@ public static class Pow2MontgomeryGpuCalculator
// 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);
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
kernelLauncher(stream, 1,exponentBuffer.View, divisor, resultBuffer.View); var accelerator = gpu.Accelerator;
var kernelLauncher = gpu.ConvertToStandardKernelLauncher;
kernelLauncher(stream, 1, exponentBuffer.View, divisor, resultBuffer.View);
resultBuffer.View.CopyToCPU(stream, ref result, 1); resultBuffer.View.CopyToCPU(stream, ref result, 1);
stream.Synchronize(); stream.Synchronize();
@@ -190,14 +190,14 @@ internal static partial class PrimeOrderGpuHeuristics
// fullyFactoredBuffer.MemSetToZero(stream); // fullyFactoredBuffer.MemSetToZero(stream);
var partialFactorKernel = GetPartialFactorKernel(acceleratorIndex); var partialFactorKernel = GetPartialFactorKernel(acceleratorIndex);
var kernelLauncher = partialFactorKernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, int, ulong, uint, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>>>();
partialFactorKernel.Launch( kernelLauncher(
stream, stream,
1, 1,
1,
smallPrimesView, smallPrimesView,
smallSquaresView, smallSquaresView,
smallPrimesView.Length, (int)smallPrimesView.Length,
primeTargets.Length, primeTargets.Length,
value, value,
limit, limit,
@@ -354,7 +354,7 @@ internal static partial class PrimeOrderGpuHeuristics
MemoryBuffer1D<ulong, Stride1D.Dense>? resultBuffer; MemoryBuffer1D<ulong, Stride1D.Dense>? resultBuffer;
MemoryBuffer1D<byte, Stride1D.Dense>? statusBuffer; MemoryBuffer1D<byte, Stride1D.Dense>? statusBuffer;
// lock(accelerator) lock(accelerator)
{ {
phiFactorBuffer = accelerator.Allocate1D<ulong>(GpuSmallPrimeFactorSlots); phiFactorBuffer = accelerator.Allocate1D<ulong>(GpuSmallPrimeFactorSlots);
phiExponentBuffer = accelerator.Allocate1D<int>(GpuSmallPrimeFactorSlots); phiExponentBuffer = accelerator.Allocate1D<int>(GpuSmallPrimeFactorSlots);
@@ -398,16 +398,17 @@ internal static partial class PrimeOrderGpuHeuristics
statusBuffer.View); statusBuffer.View);
var orderKernel = GetOrderKernel(acceleratorIndex); var orderKernel = GetOrderKernel(acceleratorIndex);
orderKernel.Launch( var kernelLauncher = orderKernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, OrderKernelConfig, MontgomeryDivisorData, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers>>();
kernelLauncher(
stream, stream,
1, 1,
1,
prime, prime,
kernelConfig, kernelConfig,
divisorData, divisorData,
smallPrimesView, smallPrimesView,
smallSquaresView, smallSquaresView,
smallPrimesView.Length, (int)smallPrimesView.Length,
buffers); buffers);
@@ -517,7 +518,7 @@ internal static partial class PrimeOrderGpuHeuristics
// with out preallocated buffers. Share the pool with Pow2ModWide kernel. // with out preallocated buffers. Share the pool with Pow2ModWide kernel.
MemoryBuffer1D<ulong, Stride1D.Dense>? exponentBuffer; MemoryBuffer1D<ulong, Stride1D.Dense>? exponentBuffer;
MemoryBuffer1D<ulong, Stride1D.Dense>? remainderBuffer; MemoryBuffer1D<ulong, Stride1D.Dense>? remainderBuffer;
// lock(accelerator) lock(accelerator)
{ {
exponentBuffer = accelerator.Allocate1D<ulong>(exponents.Length); exponentBuffer = accelerator.Allocate1D<ulong>(exponents.Length);
remainderBuffer = accelerator.Allocate1D<ulong>(exponents.Length); remainderBuffer = accelerator.Allocate1D<ulong>(exponents.Length);
@@ -529,9 +530,11 @@ internal static partial class PrimeOrderGpuHeuristics
// remainderBuffer.MemSetToZero(stream); // remainderBuffer.MemSetToZero(stream);
var pow2ModKernel = GetPow2ModKernel(acceleratorIndex); var pow2ModKernel = GetPow2ModKernel(acceleratorIndex);
var kernelLauncher = pow2ModKernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
try try
{ {
pow2ModKernel.Launch(stream, 1, exponents.Length, exponentBuffer.View, divisorData, remainderBuffer.View); kernelLauncher(stream, exponents.Length, exponentBuffer.View, divisorData, remainderBuffer.View);
remainderBuffer.View.CopyToCPU(stream, ref MemoryMarshal.GetReference(results), exponents.Length); remainderBuffer.View.CopyToCPU(stream, ref MemoryMarshal.GetReference(results), exponents.Length);
stream.Synchronize(); stream.Synchronize();
@@ -590,13 +593,20 @@ internal static partial class PrimeOrderGpuHeuristics
int acceleratorIndex = gpu.AcceleratorIndex; 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> remainderBuffer = accelerator.Allocate1D<GpuUInt128>(length);
AcceleratorStream? stream = AcceleratorStreamPool.Rent(acceleratorIndex); AcceleratorStream? stream = AcceleratorStreamPool.Rent(acceleratorIndex);
exponentBuffer.View.CopyFromCPU(stream, exponentSpan); MemoryBuffer1D<GpuUInt128, Stride1D.Dense> exponentBuffer;
MemoryBuffer1D<GpuUInt128, Stride1D.Dense> remainderBuffer;
gpu.Pow2ModWideKernel.Launch(stream, length, exponentBuffer.View, modulus, remainderBuffer.View); lock(accelerator)
{
exponentBuffer = accelerator.Allocate1D<GpuUInt128>(length);
remainderBuffer = accelerator.Allocate1D<GpuUInt128>(length);
}
exponentBuffer.View.CopyFromCPU(stream, exponentSpan);
var kernelLauncher = gpu.Pow2ModWideKernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>>();
kernelLauncher(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();
@@ -240,13 +240,12 @@ public sealed class HeuristicCombinedPrimeTester
var kernel = gpu.HeuristicCombinedTrialDivisionKernel; var kernel = gpu.HeuristicCombinedTrialDivisionKernel;
var flagView1D = gpu.OutputInt!.View; var flagView1D = gpu.OutputInt!.View;
bool compositeDetected = false; bool compositeDetected;
int divisorLength = GetCombinedDivisors(nMod10).Length; // int compositeFlag = 0;
Span<int> compositeFlag = stackalloc int[1];
flagView1D.MemSetToZero(stream);
int compositeFlag = 0; var kernelLauncher = gpu.HeuristicCombinedTrialDivisionKernelLauncher;
flagView1D.CopyFromCPU(stream, ref compositeFlag, 1);
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicCombinedGpuViews>>();
kernelLauncher( kernelLauncher(
stream, stream,
1, 1,
@@ -255,13 +254,13 @@ public sealed class HeuristicCombinedPrimeTester
n, n,
maxDivisorSquare, maxDivisorSquare,
gpu.DivisorTables); gpu.DivisorTables);
flagView1D.CopyToCPU(stream, ref compositeFlag, 1); flagView1D.CopyToCPU(stream, compositeFlag);
stream.Synchronize(); stream.Synchronize();
AcceleratorStreamPool.Return(acceleratorIndex, stream); AcceleratorStreamPool.Return(acceleratorIndex, stream);
// GpuPrimeWorkLimiter.Release(); // GpuPrimeWorkLimiter.Release();
compositeDetected = compositeFlag != 0; compositeDetected = compositeFlag[0] != 0;
return compositeDetected; return compositeDetected;
} }
+4 -3
View File
@@ -840,6 +840,8 @@ public class MersenneDivisorCycles
} }
var divisorCycleKernel = GetDivisorCycleKernel(acceleratorIndex); var divisorCycleKernel = GetDivisorCycleKernel(acceleratorIndex);
var kernelLauncher = divisorCycleKernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
while (start <= maxDivisor) while (start <= maxDivisor)
{ {
end = Math.Min(start + batchSizeUL - 1UL, maxDivisor); end = Math.Min(start + batchSizeUL - 1UL, maxDivisor);
@@ -860,15 +862,14 @@ public class MersenneDivisorCycles
// GpuKernelPool.Run((accelerator, stream) => // GpuKernelPool.Run((accelerator, stream) =>
MemoryBuffer1D<ulong, Stride1D.Dense>? bufferDiv; MemoryBuffer1D<ulong, Stride1D.Dense>? bufferDiv;
MemoryBuffer1D<ulong, Stride1D.Dense>? bufferCycle; MemoryBuffer1D<ulong, Stride1D.Dense>? bufferCycle;
// lock(accelerator) lock(accelerator)
{ {
bufferDiv = accelerator.Allocate1D(validDivisors); bufferDiv = accelerator.Allocate1D(validDivisors);
bufferCycle = accelerator.Allocate1D<ulong>(idx); bufferCycle = accelerator.Allocate1D<ulong>(idx);
} }
divisorCycleKernel.Launch( kernelLauncher(
stream, stream,
1,
idx, idx,
bufferDiv.View, bufferDiv.View,
bufferCycle.View); bufferCycle.View);
@@ -13,7 +13,7 @@ public static class PerfectNumberConstants
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 = 298; //SharedGpuContext.Device.MaxNumThreadsPerGroup; public static readonly int RollingAccelerators = 298; //SharedGpuContext.Device.MaxNumThreadsPerGroup;
public const int ThreadsByAccelerator = 4096; public const int ThreadsByAccelerator = 1;
// 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
+62 -31
View File
@@ -3,6 +3,7 @@ using System.Diagnostics;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using ILGPU;
using PerfectNumbers.Core.Cpu; using PerfectNumbers.Core.Cpu;
using PerfectNumbers.Core.Gpu; using PerfectNumbers.Core.Gpu;
using PerfectNumbers.Core.Gpu.Accelerators; using PerfectNumbers.Core.Gpu.Accelerators;
@@ -65,9 +66,9 @@ internal static partial class PrimeOrderCalculator
ulong result; ulong result;
if (phiFactors.Factors is null) if (phiFactors.Factors is null)
{ {
result = prime <= PerfectNumberConstants.MaxQForDivisorCycles result = /*prime <= PerfectNumberConstants.MaxQForDivisorCycles
? CalculateByFactorizationGpu(gpu, prime, divisorData) ? CalculateByFactorizationGpu(gpu, prime, divisorData)
: CalculateByFactorizationCpu(gpu, prime, divisorData); : */CalculateByFactorizationCpu(gpu, prime, divisorData);
phiFactors.Dispose(); phiFactors.Dispose();
PrimeOrderCalculatorAccelerator.Return(gpu); PrimeOrderCalculatorAccelerator.Return(gpu);
@@ -108,7 +109,8 @@ internal static partial class PrimeOrderCalculator
{ {
orderFactors?.Dispose(); orderFactors?.Dispose();
// GpuPrimeWorkLimiter.Release(); // GpuPrimeWorkLimiter.Release();
return CalculateByFactorizationGpu(gpu, prime, divisorData); return CalculateByFactorizationCpu(gpu, prime, divisorData);
// return CalculateByFactorizationGpu(gpu, prime, divisorData);
} }
if (TryHeuristicFinishCpu(gpu, prime, candidateOrder, previousOrder, divisorData, config, phiFactors, orderFactors, out ulong order)) if (TryHeuristicFinishCpu(gpu, prime, candidateOrder, previousOrder, divisorData, config, phiFactors, orderFactors, out ulong order))
@@ -136,7 +138,7 @@ internal static partial class PrimeOrderCalculator
Span<ulong> stackBuffer = stackalloc ulong[length]; Span<ulong> stackBuffer = stackalloc ulong[length];
if (length <= 7) if (length <= 9)
{ {
return EvaluateSpecialMaxCandidates(stackBuffer, factorSpan, phi, prime, divisorData); return EvaluateSpecialMaxCandidates(stackBuffer, factorSpan, phi, prime, divisorData);
} }
@@ -1055,17 +1057,17 @@ internal static partial class PrimeOrderCalculator
private static ulong _pow2CpuHits; private static ulong _pow2CpuHits;
private static bool Pow2EqualsOneCpu(PrimeOrderCalculatorAccelerator gpu, ulong exponent, ulong prime, in MontgomeryDivisorData divisorData) private static bool Pow2EqualsOneCpu(PrimeOrderCalculatorAccelerator gpu, ulong exponent, ulong prime, in MontgomeryDivisorData divisorData)
{ {
if (exponent <= (PerfectNumberConstants.MaxQForDivisorCycles) || prime <= (PerfectNumberConstants.MaxQForDivisorCycles)) // if (exponent >= PerfectNumberConstants.MaxQForDivisorCycles || prime >= PerfectNumberConstants.MaxQForDivisorCycles)
{ // {
// Atomic.Add(ref _pow2GpuHits, 1); // // Atomic.Add(ref _pow2GpuHits, 1);
// Console.WriteLine($"pow2 GPU Hits {_pow2GpuHits}"); // // Console.WriteLine($"pow2 GPU Hits {_pow2GpuHits}");
ulong remainder = exponent.Pow2MontgomeryModWindowedConvertGpu(gpu, divisorData); // ulong remainder = exponent.Pow2MontgomeryModWindowedConvertGpu(gpu, divisorData);
// GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2Mod(exponent, prime, out ulong remainder, divisorData); // // GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2Mod(exponent, prime, out ulong remainder, divisorData);
// if (status == GpuPow2ModStatus.Success) // // if (status == GpuPow2ModStatus.Success)
// { // // {
return remainder == 1UL; // return remainder == 1UL;
// } // // }
} // }
// Atomic.Add(ref _pow2CpuHits, 1); // Atomic.Add(ref _pow2CpuHits, 1);
// Console.WriteLine($"pow2 CPU Hits {_pow2CpuHits}"); // Console.WriteLine($"pow2 CPU Hits {_pow2CpuHits}");
@@ -1077,6 +1079,7 @@ internal static partial class PrimeOrderCalculator
// private static ulong _partialFactorCofactorHits; // private static ulong _partialFactorCofactorHits;
private static bool _goToGpu = true; private static bool _goToGpu = true;
private static int _cpuCount;
private static PartialFactorResult PartialFactor(PrimeOrderCalculatorAccelerator gpu, ulong value, in PrimeOrderSearchConfig config) private static PartialFactorResult PartialFactor(PrimeOrderCalculatorAccelerator gpu, ulong value, in PrimeOrderSearchConfig config)
{ {
@@ -1163,11 +1166,19 @@ internal static partial class PrimeOrderCalculator
// Console.WriteLine($"Partial factor hits {Volatile.Read(ref _partialFactorHits)}"); // Console.WriteLine($"Partial factor hits {Volatile.Read(ref _partialFactorHits)}");
// bool isPrime = PrimeTester.IsPrimeCpu(composite, CancellationToken.None); // bool isPrime = PrimeTester.IsPrimeCpu(composite, CancellationToken.None);
bool goToGpu = Volatile.Read(ref _goToGpu); // bool goToGpu = Volatile.Read(ref _goToGpu);
Volatile.Write(ref _goToGpu, !goToGpu); // Volatile.Write(ref _goToGpu, !goToGpu);
bool isPrime = goToGpu // bool isPrime = goToGpu
? HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite) // ? HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite)
: PrimeTester.IsPrime(composite); // : PrimeTester.IsPrime(composite);
// bool isPrime = composite > PerfectNumberConstants.MaxQForDivisorCycles
// ? HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite)
// : PrimeTester.IsPrime(composite);
// bool isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite);
bool runOnGpu = RunOnGpu();
bool isPrime = runOnGpu ? PrimeTester.IsPrime(composite) : HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite);
// bool isPrime = PrimeTester.IsPrime(composite);
// bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite); // bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite);
if (isPrime) if (isPrime)
@@ -1184,8 +1195,8 @@ internal static partial class PrimeOrderCalculator
continue; continue;
} }
if (!TryPollardRhoGpu(gpu, composite, out ulong factor)) // if (!TryPollardRhoGpu(gpu, composite, out ulong factor))
// if (!TryPollardRhoCpu(composite, deadlineTimestamp, out ulong factor)) if (!TryPollardRhoCpu(composite, deadlineTimestamp, out ulong factor))
{ {
pending.Add(new PendingEntry(composite, knownComposite: true)); pending.Add(new PendingEntry(composite, knownComposite: true));
continue; continue;
@@ -1238,8 +1249,8 @@ internal static partial class PrimeOrderCalculator
// Atomic.Add(ref _partialFactorPendingHits, 1UL); // Atomic.Add(ref _partialFactorPendingHits, 1UL);
// Console.WriteLine($"Partial factor pending hits {Volatile.Read(ref _partialFactorPendingHits)}"); // Console.WriteLine($"Partial factor pending hits {Volatile.Read(ref _partialFactorPendingHits)}");
// bool isPrime = PrimeTester.IsPrimeCpu(composite, CancellationToken.None); bool isPrime = PrimeTester.IsPrime(composite);
bool isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite); // bool isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite);
// bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite); // bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite);
entry = entry.WithPrimality(isPrime); entry = entry.WithPrimality(isPrime);
@@ -1276,9 +1287,9 @@ internal static partial class PrimeOrderCalculator
// Atomic.Add(ref _partialFactorCofactorHits, 1UL); // Atomic.Add(ref _partialFactorCofactorHits, 1UL);
// Console.WriteLine($"Partial factor cofactor hits {Volatile.Read(ref _partialFactorCofactorHits)}"); // Console.WriteLine($"Partial factor cofactor hits {Volatile.Read(ref _partialFactorCofactorHits)}");
cofactorIsPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, cofactor); // cofactorIsPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, cofactor);
// cofactorIsPrime = PrimeTester.IsPrimeGpu(gpu, cofactor); // cofactorIsPrime = PrimeTester.IsPrimeGpu(gpu, cofactor);
// cofactorIsPrime = PrimeTester.IsPrimeGpu(cofactor); cofactorIsPrime = PrimeTester.IsPrime(cofactor);
// cofactorIsPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(cofactor); // cofactorIsPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(cofactor);
} }
@@ -1362,6 +1373,23 @@ internal static partial class PrimeOrderCalculator
return result; return result;
} }
private static bool RunOnGpu()
{
const int GpuFrequency = 1024 - 1;
int cpuCount = Atomic.Add(target: ref _cpuCount, 1);
if (cpuCount == GpuFrequency)
{
Atomic.Add(ref _cpuCount, -GpuFrequency);
}
else if (cpuCount > GpuFrequency)
{
cpuCount -= GpuFrequency;
}
return cpuCount != GpuFrequency;
}
private static void PopulateSmallPrimeFactorsCpu( private static void PopulateSmallPrimeFactorsCpu(
ulong value, ulong value,
uint limit, uint limit,
@@ -1731,7 +1759,8 @@ internal static partial class PrimeOrderCalculator
// ulong candidate = order / primeFactor; // ulong candidate = order / primeFactor;
// if (candidate.Pow2MontgomeryModWindowedCpu(divisorData, keepMontgomery: false) == 1UL) // if (candidate.Pow2MontgomeryModWindowedCpu(divisorData, keepMontgomery: false) == 1UL)
if (candidate.Pow2MontgomeryModWindowedConvertGpu(gpu, divisorData) == 1UL) if (candidate.Pow2MontgomeryModWindowedCpu(divisorData, keepMontgomery: false) == 1UL)
// if (candidate.Pow2MontgomeryModWindowedConvertGpu(gpu, divisorData) == 1UL)
// if (Pow2EqualsOneCpu(candidate, prime, divisorData)) // if (Pow2EqualsOneCpu(candidate, prime, divisorData))
{ {
order = candidate; order = candidate;
@@ -1768,9 +1797,9 @@ internal static partial class PrimeOrderCalculator
// HeuristicPrimeTester tester = _tester ??= new(); // HeuristicPrimeTester tester = _tester ??= new();
// bool isPrime = primeTester.HeuristicIsPrimeGpu(value); // bool isPrime = primeTester.HeuristicIsPrimeGpu(value);
bool isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, value); // bool isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, value);
// bool isPrime = PrimeTester.IsPrimeGpu(value);
// bool isPrime = PrimeTester.IsPrimeGpu(value); // bool isPrime = PrimeTester.IsPrimeGpu(value);
bool isPrime = PrimeTester.IsPrime(value);
// bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(value); // bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(value);
if (!knownComposite && isPrime) if (!knownComposite && isPrime)
{ {
@@ -1785,8 +1814,9 @@ internal static partial class PrimeOrderCalculator
// Console.WriteLine($"Factor completely after PollardRho hits {Volatile.Read(ref _factorCompletelyPollardRhoHits)}"); // Console.WriteLine($"Factor completely after PollardRho hits {Volatile.Read(ref _factorCompletelyPollardRhoHits)}");
// isPrime = primeTester.HeuristicIsPrimeGpu(factor); // isPrime = primeTester.HeuristicIsPrimeGpu(factor);
isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, factor); // isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, factor);
// isPrime = PrimeTester.IsPrimeGpu(factor); // isPrime = PrimeTester.IsPrimeGpu(factor);
isPrime = PrimeTester.IsPrime(factor);
// isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(factor); // isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(factor);
if (isPrime) if (isPrime)
{ {
@@ -1822,7 +1852,8 @@ internal static partial class PrimeOrderCalculator
// Atomic.Add(ref _partialFactorCofactorHits, 1UL); // Atomic.Add(ref _partialFactorCofactorHits, 1UL);
// Console.WriteLine($"Partial factor cofactor hits {Volatile.Read(ref _partialFactorCofactorHits)}"); // Console.WriteLine($"Partial factor cofactor hits {Volatile.Read(ref _partialFactorCofactorHits)}");
isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, quotient); // isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, quotient);
isPrime = PrimeTester.IsPrime(quotient);
// isPrime = PrimeTester.IsPrimeGpu(quotient); // isPrime = PrimeTester.IsPrimeGpu(quotient);
// isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(quotient); // isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(quotient);
} }
@@ -145,10 +145,11 @@ internal static partial class PrimeOrderCalculator
ArrayView1D<ulong, Stride1D.Dense> specialMaxResultView = gpu.SpecialMaxResult.View; ArrayView1D<ulong, Stride1D.Dense> specialMaxResultView = gpu.SpecialMaxResult.View;
kernel.Launch( var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
kernelLauncher(
stream, stream,
1, 1,
1,
phi, phi,
specialMaxFactorsView, specialMaxFactorsView,
factorCount, factorCount,
+5 -2
View File
@@ -207,6 +207,8 @@ public sealed class PrimeTester
int pos = 0; int pos = 0;
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex); AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
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>>>();
while (pos < totalLength) while (pos < totalLength)
{ {
int remaining = totalLength - pos; int remaining = totalLength - pos;
@@ -215,7 +217,7 @@ public sealed class PrimeTester
var valueSlice = values.Slice(pos, count); var valueSlice = values.Slice(pos, count);
inputView.CopyFromCPU(stream, valueSlice); inputView.CopyFromCPU(stream, valueSlice);
kernel.Launch( kernelLauncher(
stream, stream,
count, count,
inputView, inputView,
@@ -285,8 +287,9 @@ public sealed class PrimeTester
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex); AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
inputBuffer.View.CopyFromCPU(stream, values); inputBuffer.View.CopyFromCPU(stream, values);
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<byte>>>();
kernel.Launch(stream, length, inputBuffer.View, resultBuffer.View); kernelLauncher(stream, length, inputBuffer.View, resultBuffer.View);
resultBuffer.View.CopyToCPU(stream, in results); resultBuffer.View.CopyToCPU(stream, in results);
stream.Synchronize(); stream.Synchronize();