Most device buffers integrated into PrimeOrderCalculatorAccelerator. PrimeOrderCalculator switched to partial factoring on GPU.
This commit is contained in:
1 parent
5b48a89448
commit
13498dc460
17 files changed
+466
-415
No files matched your search
@@ -321,7 +321,7 @@ public class GpuKernelCompilationTests
|
|||||||
|
|
||||||
private static void CompilePrimeOrderPow2ModWideKernel(Accelerator accelerator)
|
private static void CompilePrimeOrderPow2ModWideKernel(Accelerator accelerator)
|
||||||
{
|
{
|
||||||
var kernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>(PrimeOrderGpuHeuristics.Pow2ModKernelWide);
|
var kernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>(PrimeOrderKernels.Pow2ModKernelWide);
|
||||||
_ = kernel;
|
_ = kernel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,17 +21,19 @@ public class PrimeOrderGpuHeuristicsTests
|
|||||||
public void TryPow2Mod_returns_overflow_for_marked_prime()
|
public void TryPow2Mod_returns_overflow_for_marked_prime()
|
||||||
{
|
{
|
||||||
const ulong prime = 97UL;
|
const ulong prime = 97UL;
|
||||||
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
PrimeOrderGpuHeuristics.OverflowRegistry[prime] = 0;
|
PrimeOrderGpuHeuristics.OverflowRegistry[prime] = 0;
|
||||||
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
||||||
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2Mod(1UL, prime, out ulong remainder, divisorData);
|
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2Mod(gpu, 1UL, prime, out ulong remainder, divisorData);
|
||||||
|
|
||||||
status.Should().Be(GpuPow2ModStatus.Overflow);
|
status.Should().Be(GpuPow2ModStatus.Overflow);
|
||||||
remainder.Should().Be(0UL);
|
remainder.Should().Be(0UL);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
PrimeOrderGpuHeuristics.OverflowRegistry.TryRemove(prime, out _);
|
PrimeOrderGpuHeuristics.OverflowRegistry.TryRemove(prime, out _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,7 +44,10 @@ public class PrimeOrderGpuHeuristicsTests
|
|||||||
const ulong exponent = 138_000_001UL;
|
const ulong exponent = 138_000_001UL;
|
||||||
const ulong prime = 138_000_001UL;
|
const ulong prime = 138_000_001UL;
|
||||||
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
||||||
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2Mod(exponent, prime, out ulong remainder, divisorData);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
|
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2Mod(gpu, exponent, prime, out ulong remainder, divisorData);
|
||||||
|
|
||||||
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
|
|
||||||
status.Should().Be(GpuPow2ModStatus.Success);
|
status.Should().Be(GpuPow2ModStatus.Success);
|
||||||
remainder.Should().Be(2UL);
|
remainder.Should().Be(2UL);
|
||||||
@@ -54,16 +59,18 @@ public class PrimeOrderGpuHeuristicsTests
|
|||||||
const ulong prime = 97UL;
|
const ulong prime = 97UL;
|
||||||
var capability = new PrimeOrderGpuHeuristics.PrimeOrderGpuCapability(6, 64);
|
var capability = new PrimeOrderGpuHeuristics.PrimeOrderGpuCapability(6, 64);
|
||||||
PrimeOrderGpuHeuristics.OverrideCapabilitiesForTesting(capability);
|
PrimeOrderGpuHeuristics.OverrideCapabilitiesForTesting(capability);
|
||||||
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
||||||
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2Mod(1UL, prime, out ulong remainder, divisorData);
|
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2Mod(gpu, 1UL, prime, out ulong remainder, divisorData);
|
||||||
|
|
||||||
status.Should().Be(GpuPow2ModStatus.Overflow);
|
status.Should().Be(GpuPow2ModStatus.Overflow);
|
||||||
remainder.Should().Be(0UL);
|
remainder.Should().Be(0UL);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
PrimeOrderGpuHeuristics.ResetCapabilitiesForTesting();
|
PrimeOrderGpuHeuristics.ResetCapabilitiesForTesting();
|
||||||
PrimeOrderGpuHeuristics.OverflowRegistry.TryRemove(prime, out _);
|
PrimeOrderGpuHeuristics.OverflowRegistry.TryRemove(prime, out _);
|
||||||
}
|
}
|
||||||
@@ -73,22 +80,24 @@ public class PrimeOrderGpuHeuristicsTests
|
|||||||
public void TryPow2Mod_returns_overflow_when_exponent_exceeds_capability()
|
public void TryPow2Mod_returns_overflow_when_exponent_exceeds_capability()
|
||||||
{
|
{
|
||||||
var capability = new PrimeOrderGpuHeuristics.PrimeOrderGpuCapability(64, 3);
|
var capability = new PrimeOrderGpuHeuristics.PrimeOrderGpuCapability(64, 3);
|
||||||
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
PrimeOrderGpuHeuristics.OverrideCapabilitiesForTesting(capability);
|
PrimeOrderGpuHeuristics.OverrideCapabilitiesForTesting(capability);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const ulong prime = 193UL;
|
const ulong prime = 193UL;
|
||||||
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
||||||
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2Mod(16UL, prime, out ulong remainder, divisorData);
|
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2Mod(gpu, 16UL, prime, out ulong remainder, divisorData);
|
||||||
|
|
||||||
status.Should().Be(GpuPow2ModStatus.Overflow);
|
status.Should().Be(GpuPow2ModStatus.Overflow);
|
||||||
remainder.Should().Be(0UL);
|
remainder.Should().Be(0UL);
|
||||||
|
|
||||||
GpuPow2ModStatus followUp = PrimeOrderGpuHeuristics.TryPow2Mod(4UL, prime, out ulong followUpRemainder, divisorData);
|
GpuPow2ModStatus followUp = PrimeOrderGpuHeuristics.TryPow2Mod(gpu, 4UL, prime, out ulong followUpRemainder, divisorData);
|
||||||
followUp.Should().Be(GpuPow2ModStatus.Success);
|
followUp.Should().Be(GpuPow2ModStatus.Success);
|
||||||
followUpRemainder.Should().Be(16UL);
|
followUpRemainder.Should().Be(16UL);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
PrimeOrderGpuHeuristics.ResetCapabilitiesForTesting();
|
PrimeOrderGpuHeuristics.ResetCapabilitiesForTesting();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,6 +106,7 @@ public class PrimeOrderGpuHeuristicsTests
|
|||||||
public void TryPow2ModBatch_returns_overflow_for_marked_prime()
|
public void TryPow2ModBatch_returns_overflow_for_marked_prime()
|
||||||
{
|
{
|
||||||
const ulong prime = 193UL;
|
const ulong prime = 193UL;
|
||||||
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
PrimeOrderGpuHeuristics.OverflowRegistry[prime] = 0;
|
PrimeOrderGpuHeuristics.OverflowRegistry[prime] = 0;
|
||||||
@@ -104,7 +114,7 @@ public class PrimeOrderGpuHeuristicsTests
|
|||||||
ulong[] remainders = new ulong[2];
|
ulong[] remainders = new ulong[2];
|
||||||
ulong[] exponents = { 1UL, 2UL };
|
ulong[] exponents = { 1UL, 2UL };
|
||||||
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
||||||
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2ModBatch(exponents, prime, remainders, divisorData);
|
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2ModBatch(gpu, exponents, prime, remainders, divisorData);
|
||||||
|
|
||||||
status.Should().Be(GpuPow2ModStatus.Overflow);
|
status.Should().Be(GpuPow2ModStatus.Overflow);
|
||||||
remainders[0].Should().Be(0UL);
|
remainders[0].Should().Be(0UL);
|
||||||
@@ -112,6 +122,7 @@ public class PrimeOrderGpuHeuristicsTests
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
PrimeOrderGpuHeuristics.OverflowRegistry.TryRemove(prime, out _);
|
PrimeOrderGpuHeuristics.OverflowRegistry.TryRemove(prime, out _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,7 +134,11 @@ public class PrimeOrderGpuHeuristicsTests
|
|||||||
ulong[] exponents = { 138_000_001UL, 138_000_011UL };
|
ulong[] exponents = { 138_000_001UL, 138_000_011UL };
|
||||||
const ulong prime = 138_000_001UL;
|
const ulong prime = 138_000_001UL;
|
||||||
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
||||||
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2ModBatch(exponents, prime, remainders, divisorData);
|
|
||||||
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
|
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2ModBatch(gpu, exponents, prime, remainders, divisorData);
|
||||||
|
|
||||||
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
|
|
||||||
ulong expectedFirst = (ulong)BigInteger.ModPow(2, exponents[0], prime);
|
ulong expectedFirst = (ulong)BigInteger.ModPow(2, exponents[0], prime);
|
||||||
ulong expectedSecond = (ulong)BigInteger.ModPow(2, exponents[1], prime);
|
ulong expectedSecond = (ulong)BigInteger.ModPow(2, exponents[1], prime);
|
||||||
@@ -140,6 +155,7 @@ public class PrimeOrderGpuHeuristicsTests
|
|||||||
{
|
{
|
||||||
const ulong prime = 97UL;
|
const ulong prime = 97UL;
|
||||||
var capability = new PrimeOrderGpuHeuristics.PrimeOrderGpuCapability(6, 64);
|
var capability = new PrimeOrderGpuHeuristics.PrimeOrderGpuCapability(6, 64);
|
||||||
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
PrimeOrderGpuHeuristics.OverrideCapabilitiesForTesting(capability);
|
PrimeOrderGpuHeuristics.OverrideCapabilitiesForTesting(capability);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -147,7 +163,7 @@ public class PrimeOrderGpuHeuristicsTests
|
|||||||
ulong[] remainders = { 5UL, 6UL };
|
ulong[] remainders = { 5UL, 6UL };
|
||||||
|
|
||||||
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
||||||
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2ModBatch(exponents, prime, remainders, divisorData);
|
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2ModBatch(gpu, exponents, prime, remainders, divisorData);
|
||||||
|
|
||||||
status.Should().Be(GpuPow2ModStatus.Overflow);
|
status.Should().Be(GpuPow2ModStatus.Overflow);
|
||||||
remainders[0].Should().Be(0UL);
|
remainders[0].Should().Be(0UL);
|
||||||
@@ -155,6 +171,7 @@ public class PrimeOrderGpuHeuristicsTests
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
PrimeOrderGpuHeuristics.ResetCapabilitiesForTesting();
|
PrimeOrderGpuHeuristics.ResetCapabilitiesForTesting();
|
||||||
PrimeOrderGpuHeuristics.OverflowRegistry.TryRemove(prime, out _);
|
PrimeOrderGpuHeuristics.OverflowRegistry.TryRemove(prime, out _);
|
||||||
}
|
}
|
||||||
@@ -164,6 +181,7 @@ public class PrimeOrderGpuHeuristicsTests
|
|||||||
public void TryPow2ModBatch_returns_overflow_when_any_exponent_exceeds_capability()
|
public void TryPow2ModBatch_returns_overflow_when_any_exponent_exceeds_capability()
|
||||||
{
|
{
|
||||||
var capability = new PrimeOrderGpuHeuristics.PrimeOrderGpuCapability(64, 3);
|
var capability = new PrimeOrderGpuHeuristics.PrimeOrderGpuCapability(64, 3);
|
||||||
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
PrimeOrderGpuHeuristics.OverrideCapabilitiesForTesting(capability);
|
PrimeOrderGpuHeuristics.OverrideCapabilitiesForTesting(capability);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -172,7 +190,7 @@ public class PrimeOrderGpuHeuristicsTests
|
|||||||
|
|
||||||
const ulong prime = 193UL;
|
const ulong prime = 193UL;
|
||||||
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(prime);
|
||||||
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2ModBatch(exponents, prime, remainders, divisorData);
|
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2ModBatch(gpu, exponents, prime, remainders, divisorData);
|
||||||
|
|
||||||
status.Should().Be(GpuPow2ModStatus.Overflow);
|
status.Should().Be(GpuPow2ModStatus.Overflow);
|
||||||
remainders[0].Should().Be(0UL);
|
remainders[0].Should().Be(0UL);
|
||||||
@@ -180,6 +198,7 @@ public class PrimeOrderGpuHeuristicsTests
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
PrimeOrderGpuHeuristics.ResetCapabilitiesForTesting();
|
PrimeOrderGpuHeuristics.ResetCapabilitiesForTesting();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
stream.Dispose();
|
stream.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -105,21 +104,57 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
|
|
||||||
public readonly Accelerator Accelerator;
|
public readonly Accelerator Accelerator;
|
||||||
public readonly int AcceleratorIndex;
|
public readonly int AcceleratorIndex;
|
||||||
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> Input;
|
public MemoryBuffer1D<ulong, Stride1D.Dense> Input;
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> OutputUlong;
|
public ArrayView1D<ulong, Stride1D.Dense> InputView;
|
||||||
|
|
||||||
public MemoryBuffer1D<byte, Stride1D.Dense> OutputByte;
|
public MemoryBuffer1D<byte, Stride1D.Dense> OutputByte;
|
||||||
|
public ArrayView1D<byte, Stride1D.Dense> OutputByteView;
|
||||||
|
|
||||||
|
public MemoryBuffer1D<ulong, Stride1D.Dense> OutputUlong;
|
||||||
|
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> OutputUlong2;
|
||||||
|
public ArrayView1D<ulong, Stride1D.Dense> OutputUlongView;
|
||||||
|
public readonly ArrayView1D<ulong, Stride1D.Dense> OutputUlongView2;
|
||||||
|
|
||||||
public MemoryBuffer1D<int, Stride1D.Dense> OutputInt;
|
public MemoryBuffer1D<int, Stride1D.Dense> OutputInt;
|
||||||
|
public readonly MemoryBuffer1D<int, Stride1D.Dense> OutputInt2;
|
||||||
|
public ArrayView1D<int, Stride1D.Dense> OutputIntView;
|
||||||
|
public readonly ArrayView1D<int, Stride1D.Dense> OutputIntView2;
|
||||||
|
|
||||||
public MemoryBuffer1D<KeyValuePair<ulong, int>, Stride1D.Dense> Pow2ModEntriesToTestOnDevice;
|
public MemoryBuffer1D<KeyValuePair<ulong, int>, Stride1D.Dense> Pow2ModEntriesToTestOnDevice;
|
||||||
public readonly MemoryBuffer1D<int, Stride1D.Dense> SmallPrimeFactorCountSlot;
|
public ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense> Pow2ModEntriesToTestOnDeviceView;
|
||||||
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> SpecialMaxResult;
|
|
||||||
|
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> WorkFactorBuffer;
|
||||||
|
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> CandidateBuffer;
|
||||||
|
public readonly MemoryBuffer1D<int, Stride1D.Dense> StackIndexBuffer;
|
||||||
|
public readonly MemoryBuffer1D<int, Stride1D.Dense> StackExponentBuffer;
|
||||||
|
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> StackProductBuffer;
|
||||||
|
|
||||||
|
public OrderKernelBuffers CalculateOrderKernelBuffers;
|
||||||
|
public readonly ArrayView1D<ulong, Stride1D.Dense> WorkFactorBufferView;
|
||||||
|
public readonly ArrayView1D<ulong, Stride1D.Dense> CandidateBufferView;
|
||||||
|
public readonly ArrayView1D<int, Stride1D.Dense> StackIndexBufferView;
|
||||||
|
public readonly ArrayView1D<int, Stride1D.Dense> StackExponentBufferView;
|
||||||
|
public readonly ArrayView1D<ulong, Stride1D.Dense> StackProductBufferView;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public MemoryBuffer1D<GpuUInt128, Stride1D.Dense> CalculateOrderWideExponentBuffer;
|
||||||
|
public MemoryBuffer1D<GpuUInt128, Stride1D.Dense> CalculateOrderWideRemainderBuffer;
|
||||||
|
public ArrayView1D<GpuUInt128, Stride1D.Dense> CalculateOrderWideExponentBufferView;
|
||||||
|
public ArrayView1D<GpuUInt128, Stride1D.Dense> CalculateOrderWideRemainderBufferView;
|
||||||
|
|
||||||
|
|
||||||
public Dictionary<ulong, int> Pow2ModEntriesToTestOnHost = [];
|
public Dictionary<ulong, int> Pow2ModEntriesToTestOnHost = [];
|
||||||
|
|
||||||
private static readonly CalculatorKernels[] _kernels =new CalculatorKernels[AcceleratorPool.Shared.Accelerators.Length];
|
private static readonly CalculatorKernels[] _kernels = new CalculatorKernels[_accelerators.Length];
|
||||||
|
|
||||||
private sealed class CalculatorKernels(Accelerator accelerator)
|
private sealed class CalculatorKernels(Accelerator accelerator)
|
||||||
{
|
{
|
||||||
public readonly Kernel CheckFactorsKernel = KernelUtil.GetKernel(accelerator.LoadStreamKernel<int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.CheckFactorsKernel));
|
public readonly Action<AcceleratorStream, Index1D, ulong, CalculateOrderKernelConfig, ulong, ulong, ulong, ulong, ulong, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers> CalculateOrderKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, CalculateOrderKernelConfig, ulong, ulong, ulong, ulong, ulong, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers>(PrimeOrderKernels.CalculateOrderKernel)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, CalculateOrderKernelConfig, ulong, ulong, ulong, ulong, ulong, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers>>();
|
||||||
|
|
||||||
|
public readonly Kernel CheckFactorsKernel = KernelUtil.GetKernel(accelerator.LoadStreamKernel<int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderKernels.CheckFactorsKernel));
|
||||||
|
|
||||||
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>> ConvertToStandardKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelConvertToStandard)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>>();
|
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>> ConvertToStandardKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelConvertToStandard)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
|
|
||||||
@@ -127,9 +162,13 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
|
|
||||||
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>> KeepMontgomeryKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelKeepMontgomery)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>>();
|
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>> KeepMontgomeryKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelKeepMontgomery)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
|
|
||||||
|
public readonly 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>> PartialFactorKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<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>>(PrimeOrderKernels.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>>>();
|
||||||
|
|
||||||
public readonly Kernel PollardRhoKernel = KernelUtil.GetKernel(accelerator.LoadStreamKernel<ulong, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.TryPollardRhoKernel));
|
public readonly Kernel PollardRhoKernel = KernelUtil.GetKernel(accelerator.LoadStreamKernel<ulong, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.TryPollardRhoKernel));
|
||||||
|
|
||||||
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>> Pow2ModWideKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>(PrimeOrderGpuHeuristics.Pow2ModKernelWide)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>>();
|
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>> Pow2ModKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderKernels.Pow2ModKernel)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
|
|
||||||
|
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>> Pow2ModWideKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>(PrimeOrderKernels.Pow2ModKernelWide)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>>();
|
||||||
|
|
||||||
public readonly Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<byte>> SharesFactorKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SharesFactorKernel)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<byte>>>();
|
public readonly Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<byte>> SharesFactorKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SharesFactorKernel)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<byte>>>();
|
||||||
|
|
||||||
@@ -140,17 +179,38 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
public readonly Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, ulong, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> SpecialMaxKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, ulong, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.EvaluateSpecialMaxCandidatesKernel)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, ulong, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
public readonly Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, ulong, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> SpecialMaxKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, ulong, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.EvaluateSpecialMaxCandidatesKernel)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, ulong, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly Action<AcceleratorStream, Index1D, ulong, CalculateOrderKernelConfig, ulong, ulong, ulong, ulong, ulong, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers> CalculateOrderKernelLauncher;
|
||||||
public readonly Kernel CheckFactorsKernel;
|
public readonly Kernel CheckFactorsKernel;
|
||||||
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>> ConvertToStandardKernelLauncher;
|
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>> ConvertToStandardKernelLauncher;
|
||||||
public readonly Action<AcceleratorStream, Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicCombinedGpuViews> HeuristicCombinedTrialDivisionKernelLauncher;
|
public readonly Action<AcceleratorStream, Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicCombinedGpuViews> HeuristicCombinedTrialDivisionKernelLauncher;
|
||||||
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>> KeepMontgomeryKernelLauncher;
|
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>> KeepMontgomeryKernelLauncher;
|
||||||
|
public readonly 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>> PartialFactorKernelLauncher;
|
||||||
public readonly Kernel PollardRhoKernel;
|
public readonly Kernel PollardRhoKernel;
|
||||||
|
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>> Pow2ModKernelLauncher;
|
||||||
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>> Pow2ModWideKernelLauncher;
|
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>> Pow2ModWideKernelLauncher;
|
||||||
public readonly Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<byte>> SharesFactorKernelLauncher;
|
public readonly Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<byte>> SharesFactorKernelLauncher;
|
||||||
public readonly 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>> SmallPrimeFactorKernelLauncher;
|
public readonly 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>> SmallPrimeFactorKernelLauncher;
|
||||||
public readonly Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>> SmallPrimeSieveKernelLauncher;
|
public readonly Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>> SmallPrimeSieveKernelLauncher;
|
||||||
public readonly Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, ulong, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> SpecialMaxKernelLauncher;
|
public readonly Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, ulong, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> SpecialMaxKernelLauncher;
|
||||||
|
|
||||||
|
public void EnsureCalculateOrderWideCapacity(int newSize)
|
||||||
|
{
|
||||||
|
if (newSize > Input.Length)
|
||||||
|
{
|
||||||
|
CalculateOrderWideExponentBuffer.Dispose();
|
||||||
|
CalculateOrderWideRemainderBuffer.Dispose();
|
||||||
|
|
||||||
|
var accelerator = Accelerator;
|
||||||
|
// lock (accelerator)
|
||||||
|
// {
|
||||||
|
CalculateOrderWideExponentBuffer = accelerator.Allocate1D<GpuUInt128>(newSize);
|
||||||
|
CalculateOrderWideRemainderBuffer = accelerator.Allocate1D<GpuUInt128>(newSize);
|
||||||
|
CalculateOrderWideExponentBufferView = CalculateOrderWideExponentBuffer.View;
|
||||||
|
CalculateOrderWideRemainderBufferView = CalculateOrderWideRemainderBuffer.View;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void EnsureCapacity(int factorsCount, int primeTesterCapacity)
|
public void EnsureCapacity(int factorsCount, int primeTesterCapacity)
|
||||||
{
|
{
|
||||||
Accelerator accelerator = Accelerator;
|
Accelerator accelerator = Accelerator;
|
||||||
@@ -159,40 +219,76 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
if (pow2ModEntriesToTestOnDevice.Length < factorsCount)
|
if (pow2ModEntriesToTestOnDevice.Length < factorsCount)
|
||||||
{
|
{
|
||||||
// lock (accelerator)
|
// lock (accelerator)
|
||||||
{
|
// {
|
||||||
pow2ModEntriesToTestOnDevice.Dispose();
|
pow2ModEntriesToTestOnDevice.Dispose();
|
||||||
Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount);
|
pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount);
|
||||||
}
|
Pow2ModEntriesToTestOnDevice = pow2ModEntriesToTestOnDevice;
|
||||||
|
Pow2ModEntriesToTestOnDeviceView = pow2ModEntriesToTestOnDevice.View;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> input = Input;
|
MemoryBuffer1D<ulong, Stride1D.Dense> input = Input;
|
||||||
if (input.Length < primeTesterCapacity)
|
if (input.Length < primeTesterCapacity)
|
||||||
{
|
{
|
||||||
// lock (accelerator)
|
// lock (accelerator)
|
||||||
{
|
// {
|
||||||
input.Dispose();
|
input.Dispose();
|
||||||
Input = accelerator.Allocate1D<ulong>(primeTesterCapacity);
|
|
||||||
}
|
input = accelerator.Allocate1D<ulong>(primeTesterCapacity);
|
||||||
|
Input = input;
|
||||||
|
InputView = input.View;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBuffer1D<byte, Stride1D.Dense> outputByte = OutputByte;
|
MemoryBuffer1D<byte, Stride1D.Dense> outputByte = OutputByte;
|
||||||
if (outputByte.Length < primeTesterCapacity)
|
if (outputByte.Length < primeTesterCapacity)
|
||||||
{
|
{
|
||||||
// lock (accelerator)
|
// lock (accelerator)
|
||||||
{
|
// {
|
||||||
outputByte.Dispose();
|
outputByte.Dispose();
|
||||||
OutputByte = accelerator.Allocate1D<byte>(primeTesterCapacity);
|
|
||||||
}
|
outputByte = accelerator.Allocate1D<byte>(primeTesterCapacity);
|
||||||
|
OutputByte = outputByte;
|
||||||
|
OutputByteView = outputByte.View;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBuffer1D<int, Stride1D.Dense> outputInt = OutputInt;
|
MemoryBuffer1D<int, Stride1D.Dense> outputInt = OutputInt;
|
||||||
if (outputInt.Length < primeTesterCapacity)
|
if (outputInt.Length < primeTesterCapacity)
|
||||||
{
|
{
|
||||||
// lock (accelerator)
|
// lock (accelerator)
|
||||||
|
// {
|
||||||
|
outputInt.Dispose();
|
||||||
|
|
||||||
|
outputInt = accelerator.Allocate1D<int>(primeTesterCapacity);
|
||||||
|
OutputInt = outputInt;
|
||||||
|
OutputIntView = outputInt.View;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EnsurePartialFactorCapacity(int newSize)
|
||||||
|
{
|
||||||
|
var accelerator = Accelerator;
|
||||||
|
|
||||||
|
var outputUlong = OutputUlong;
|
||||||
|
if (newSize > outputUlong.Length)
|
||||||
|
{
|
||||||
|
outputUlong.Dispose();
|
||||||
|
|
||||||
|
outputUlong = accelerator.Allocate1D<ulong>(newSize);
|
||||||
|
OutputUlong = outputUlong;
|
||||||
|
OutputUlongView = outputUlong.View;
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputInt = OutputInt;
|
||||||
|
if (newSize > outputInt.Length)
|
||||||
{
|
{
|
||||||
outputInt.Dispose();
|
outputInt.Dispose();
|
||||||
OutputInt = accelerator.Allocate1D<int>(primeTesterCapacity);
|
|
||||||
}
|
outputInt = accelerator.Allocate1D<int>(newSize);
|
||||||
|
OutputInt = outputInt;
|
||||||
|
OutputIntView = outputInt.View;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,44 +300,56 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
if (outputUlong.Length < newSize)
|
if (outputUlong.Length < newSize)
|
||||||
{
|
{
|
||||||
// lock (accelerator)
|
// lock (accelerator)
|
||||||
{
|
// {
|
||||||
outputUlong.Dispose();
|
outputUlong.Dispose();
|
||||||
OutputUlong = accelerator.Allocate1D<ulong>(newSize);
|
|
||||||
}
|
outputUlong = accelerator.Allocate1D<ulong>(newSize);
|
||||||
|
OutputUlong = outputUlong;
|
||||||
|
OutputUlongView = outputUlong.View;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBuffer1D<int, Stride1D.Dense> outputInt = OutputInt;
|
MemoryBuffer1D<int, Stride1D.Dense> outputInt = OutputInt;
|
||||||
if (outputInt.Length < newSize)
|
if (outputInt.Length < newSize)
|
||||||
{
|
{
|
||||||
// lock (accelerator)
|
// lock (accelerator)
|
||||||
{
|
// {
|
||||||
outputInt.Dispose();
|
outputInt.Dispose();
|
||||||
OutputInt = accelerator.Allocate1D<int>(newSize);
|
|
||||||
}
|
outputInt = accelerator.Allocate1D<int>(newSize);
|
||||||
|
OutputInt = outputInt;
|
||||||
|
OutputIntView = outputInt.View;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnsureSpecialMaxFactorsCapacity(int newSize)
|
public void EnsureUlongInputOutputCapacity(int newSize)
|
||||||
{
|
{
|
||||||
var accelerator = Accelerator;
|
var accelerator = Accelerator;
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> input = Input;
|
MemoryBuffer1D<ulong, Stride1D.Dense> buffer = Input;
|
||||||
if (input.Length < newSize)
|
if (buffer.Length < newSize)
|
||||||
{
|
{
|
||||||
// lock (accelerator)
|
// lock (accelerator)
|
||||||
{
|
// {
|
||||||
input.Dispose();
|
buffer.Dispose();
|
||||||
Input = accelerator.Allocate1D<ulong>(newSize);
|
|
||||||
}
|
buffer = accelerator.Allocate1D<ulong>(newSize);
|
||||||
|
Input = buffer;
|
||||||
|
InputView = buffer.View;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> outputUlong = OutputUlong;
|
buffer = OutputUlong;
|
||||||
if (outputUlong.Length < newSize)
|
if (buffer.Length < newSize)
|
||||||
{
|
{
|
||||||
// lock (accelerator)
|
// lock (accelerator)
|
||||||
{
|
// {
|
||||||
outputUlong.Dispose();
|
buffer.Dispose();
|
||||||
OutputUlong = accelerator.Allocate1D<ulong>(newSize);
|
|
||||||
}
|
buffer = accelerator.Allocate1D<ulong>(newSize);
|
||||||
|
OutputUlong = buffer;
|
||||||
|
OutputUlongView = buffer.View;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,15 +358,59 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
var accelerator = _accelerators[acceleratorIndex];
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
Accelerator = accelerator;
|
Accelerator = accelerator;
|
||||||
AcceleratorIndex = acceleratorIndex;
|
AcceleratorIndex = acceleratorIndex;
|
||||||
|
|
||||||
// lock (accelerator)
|
// lock (accelerator)
|
||||||
{
|
// {
|
||||||
Input = accelerator.Allocate1D<ulong>(Math.Max(specialMaxFactorCapacity, primeTesterCapacity));
|
Input = accelerator.Allocate1D<ulong>(Math.Max(Math.Max(specialMaxFactorCapacity, primeTesterCapacity), PrimeOrderConstants.MaxGpuBatchSize));
|
||||||
|
InputView = Input.View;
|
||||||
|
|
||||||
OutputByte = Accelerator.Allocate1D<byte>(primeTesterCapacity);
|
OutputByte = Accelerator.Allocate1D<byte>(primeTesterCapacity);
|
||||||
OutputInt = Accelerator.Allocate1D<int>(Math.Max(primeTesterCapacity, smallPrimeFactorSlotCount));
|
OutputByteView = OutputByte.View;
|
||||||
OutputUlong = accelerator.Allocate1D<ulong>(Math.Max(specialMaxFactorCapacity, smallPrimeFactorSlotCount));
|
|
||||||
|
OutputInt = Accelerator.Allocate1D<int>(Math.Max(Math.Max(primeTesterCapacity, smallPrimeFactorSlotCount), PrimeOrderConstants.GpuSmallPrimeFactorSlots));
|
||||||
|
OutputIntView = OutputInt.View;
|
||||||
|
|
||||||
|
OutputInt2 = accelerator.Allocate1D<int>(PrimeOrderConstants.GpuSmallPrimeFactorSlots);
|
||||||
|
OutputIntView2 = OutputInt2.View;
|
||||||
|
|
||||||
|
OutputUlong = accelerator.Allocate1D<ulong>(Math.Max(Math.Max(Math.Max(specialMaxFactorCapacity, smallPrimeFactorSlotCount), PrimeOrderConstants.MaxGpuBatchSize), PrimeOrderConstants.GpuSmallPrimeFactorSlots));
|
||||||
|
OutputUlongView = OutputUlong.View;
|
||||||
|
|
||||||
|
OutputUlong2 = accelerator.Allocate1D<ulong>(1);
|
||||||
|
OutputUlongView2 = OutputUlong2.View;
|
||||||
|
|
||||||
Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount);
|
Pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount);
|
||||||
SmallPrimeFactorCountSlot = accelerator.Allocate1D<int>(1);
|
Pow2ModEntriesToTestOnDeviceView = Pow2ModEntriesToTestOnDevice.View;
|
||||||
SpecialMaxResult = accelerator.Allocate1D<ulong>(1);
|
|
||||||
|
WorkFactorBuffer = accelerator.Allocate1D<ulong>(PrimeOrderConstants.GpuSmallPrimeFactorSlots);
|
||||||
|
CandidateBuffer = accelerator.Allocate1D<ulong>(PrimeOrderConstants.HeuristicCandidateLimit);
|
||||||
|
StackIndexBuffer = accelerator.Allocate1D<int>(PrimeOrderConstants.HeuristicStackCapacity);
|
||||||
|
StackExponentBuffer = accelerator.Allocate1D<int>(PrimeOrderConstants.HeuristicStackCapacity);
|
||||||
|
StackProductBuffer = accelerator.Allocate1D<ulong>(PrimeOrderConstants.HeuristicStackCapacity);
|
||||||
|
|
||||||
|
WorkFactorBufferView = WorkFactorBuffer.View;
|
||||||
|
CandidateBufferView = CandidateBuffer.View;
|
||||||
|
StackIndexBufferView = StackIndexBuffer.View;
|
||||||
|
StackExponentBufferView = StackExponentBuffer.View;
|
||||||
|
StackProductBufferView = StackProductBuffer.View;
|
||||||
|
|
||||||
|
CalculateOrderKernelBuffers = new OrderKernelBuffers(
|
||||||
|
OutputUlongView,
|
||||||
|
OutputIntView,
|
||||||
|
WorkFactorBufferView,
|
||||||
|
OutputIntView2,
|
||||||
|
CandidateBufferView,
|
||||||
|
StackIndexBufferView,
|
||||||
|
StackExponentBufferView,
|
||||||
|
StackProductBufferView,
|
||||||
|
OutputUlongView2,
|
||||||
|
OutputByteView
|
||||||
|
);
|
||||||
|
|
||||||
|
CalculateOrderWideExponentBuffer = accelerator.Allocate1D<GpuUInt128>(PrimeOrderConstants.MaxGpuBatchSize);
|
||||||
|
CalculateOrderWideRemainderBuffer = accelerator.Allocate1D<GpuUInt128>(PrimeOrderConstants.MaxGpuBatchSize);
|
||||||
|
CalculateOrderWideExponentBufferView = CalculateOrderWideExponentBuffer.View;
|
||||||
|
CalculateOrderWideRemainderBufferView = CalculateOrderWideRemainderBuffer.View;
|
||||||
|
|
||||||
LastDigitGpuTables lastDigitSharedTables = LastDigitGpuTables.GetStaticTables(acceleratorIndex);
|
LastDigitGpuTables lastDigitSharedTables = LastDigitGpuTables.GetStaticTables(acceleratorIndex);
|
||||||
DevicePrimesLastOne = lastDigitSharedTables.DevicePrimesLastOne.View;
|
DevicePrimesLastOne = lastDigitSharedTables.DevicePrimesLastOne.View;
|
||||||
@@ -285,17 +437,20 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
|
|
||||||
var kernels = _kernels[acceleratorIndex];
|
var kernels = _kernels[acceleratorIndex];
|
||||||
|
|
||||||
|
CalculateOrderKernelLauncher = kernels.CalculateOrderKernelLauncher;
|
||||||
CheckFactorsKernel = kernels.CheckFactorsKernel;
|
CheckFactorsKernel = kernels.CheckFactorsKernel;
|
||||||
ConvertToStandardKernelLauncher = kernels.ConvertToStandardKernelLauncher;
|
ConvertToStandardKernelLauncher = kernels.ConvertToStandardKernelLauncher;
|
||||||
HeuristicCombinedTrialDivisionKernelLauncher = kernels.HeuristicCombinedTrialDivisionKernelLauncher;
|
HeuristicCombinedTrialDivisionKernelLauncher = kernels.HeuristicCombinedTrialDivisionKernelLauncher;
|
||||||
KeepMontgomeryKernelLauncher = kernels.KeepMontgomeryKernelLauncher;
|
KeepMontgomeryKernelLauncher = kernels.KeepMontgomeryKernelLauncher;
|
||||||
|
PartialFactorKernelLauncher = kernels.PartialFactorKernelLauncher;
|
||||||
PollardRhoKernel = kernels.PollardRhoKernel;
|
PollardRhoKernel = kernels.PollardRhoKernel;
|
||||||
|
Pow2ModKernelLauncher = kernels.Pow2ModKernelLauncher;
|
||||||
Pow2ModWideKernelLauncher = kernels.Pow2ModWideKernelLauncher;
|
Pow2ModWideKernelLauncher = kernels.Pow2ModWideKernelLauncher;
|
||||||
SharesFactorKernelLauncher = kernels.SharesFactorKernelLauncher;
|
SharesFactorKernelLauncher = kernels.SharesFactorKernelLauncher;
|
||||||
SmallPrimeFactorKernelLauncher = kernels.SmallPrimeFactorKernelLauncher;
|
SmallPrimeFactorKernelLauncher = kernels.SmallPrimeFactorKernelLauncher;
|
||||||
SmallPrimeSieveKernelLauncher = kernels.SmallPrimeSieveKernelLauncher;
|
SmallPrimeSieveKernelLauncher = kernels.SmallPrimeSieveKernelLauncher;
|
||||||
SpecialMaxKernelLauncher = kernels.SpecialMaxKernelLauncher;
|
SpecialMaxKernelLauncher = kernels.SpecialMaxKernelLauncher;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -303,10 +458,20 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
Input.Dispose();
|
Input.Dispose();
|
||||||
OutputByte.Dispose();
|
OutputByte.Dispose();
|
||||||
OutputInt.Dispose();
|
OutputInt.Dispose();
|
||||||
|
OutputInt2.Dispose();
|
||||||
OutputUlong.Dispose();
|
OutputUlong.Dispose();
|
||||||
|
OutputUlong2.Dispose();
|
||||||
|
|
||||||
Pow2ModEntriesToTestOnDevice.Dispose();
|
Pow2ModEntriesToTestOnDevice.Dispose();
|
||||||
SmallPrimeFactorCountSlot.Dispose();
|
|
||||||
SpecialMaxResult.Dispose();
|
WorkFactorBuffer.Dispose();
|
||||||
|
CandidateBuffer.Dispose();
|
||||||
|
StackIndexBuffer.Dispose();
|
||||||
|
StackExponentBuffer.Dispose();
|
||||||
|
StackProductBuffer.Dispose();
|
||||||
|
|
||||||
|
CalculateOrderWideExponentBuffer.Dispose();
|
||||||
|
CalculateOrderWideRemainderBuffer.Dispose();
|
||||||
|
|
||||||
// These resources are shared between GPU leases
|
// These resources are shared between GPU leases
|
||||||
// Stream.Dispose();
|
// Stream.Dispose();
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace PerfectNumbers.Core.Gpu;
|
||||||
|
|
||||||
|
public readonly struct CalculateOrderKernelConfig(ulong previousOrder, byte hasPreviousOrder, uint smallFactorLimit, int maxPowChecks, int mode)
|
||||||
|
{
|
||||||
|
public readonly ulong PreviousOrder = previousOrder;
|
||||||
|
public readonly byte HasPreviousOrder = hasPreviousOrder;
|
||||||
|
public readonly uint SmallFactorLimit = smallFactorLimit;
|
||||||
|
public readonly int MaxPowChecks = maxPowChecks;
|
||||||
|
public readonly int Mode = mode;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace PerfectNumbers.Core.Gpu.Kernels;
|
||||||
|
|
||||||
|
public enum PrimeOrderKernelStatus : byte
|
||||||
|
{
|
||||||
|
Fallback = 0,
|
||||||
|
Found = 1,
|
||||||
|
HeuristicUnresolved = 2,
|
||||||
|
PollardOverflow = 3,
|
||||||
|
FactoringFailure = 4,
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ using PerfectNumbers.Core.Gpu.Kernels;
|
|||||||
|
|
||||||
namespace PerfectNumbers.Core.Gpu;
|
namespace PerfectNumbers.Core.Gpu;
|
||||||
|
|
||||||
internal static partial class PrimeOrderGpuHeuristics
|
internal static partial class PrimeOrderKernels
|
||||||
{
|
{
|
||||||
internal static void CheckFactorsKernel(
|
internal static void CheckFactorsKernel(
|
||||||
int count,
|
int count,
|
||||||
@@ -115,15 +115,6 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
fullyFactoredOut[0] = remainingLocal == 1UL ? (byte)1 : (byte)0;
|
fullyFactoredOut[0] = remainingLocal == 1UL ? (byte)1 : (byte)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal enum PrimeOrderKernelStatus : byte
|
|
||||||
{
|
|
||||||
Fallback = 0,
|
|
||||||
Found = 1,
|
|
||||||
HeuristicUnresolved = 2,
|
|
||||||
PollardOverflow = 3,
|
|
||||||
FactoringFailure = 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly struct CandidateKey
|
private readonly struct CandidateKey
|
||||||
{
|
{
|
||||||
public CandidateKey(int primary, long secondary, long tertiary)
|
public CandidateKey(int primary, long secondary, long tertiary)
|
||||||
@@ -160,7 +151,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
internal static void CalculateOrderKernel(
|
internal static void CalculateOrderKernel(
|
||||||
Index1D index,
|
Index1D index,
|
||||||
ulong prime,
|
ulong prime,
|
||||||
OrderKernelConfig config,
|
CalculateOrderKernelConfig config,
|
||||||
ulong divisorModulus,
|
ulong divisorModulus,
|
||||||
ulong divisorNPrime,
|
ulong divisorNPrime,
|
||||||
ulong divisorMontgomeryOne,
|
ulong divisorMontgomeryOne,
|
||||||
@@ -189,7 +180,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
ArrayView1D<ulong, Stride1D.Dense> resultOut = buffers.Result;
|
ArrayView1D<ulong, Stride1D.Dense> resultOut = buffers.Result;
|
||||||
ArrayView1D<byte, Stride1D.Dense> statusOut = buffers.Status;
|
ArrayView1D<byte, Stride1D.Dense> statusOut = buffers.Status;
|
||||||
|
|
||||||
uint limit = config.SmallFactorLimit == 0 ? uint.MaxValue : config.SmallFactorLimit;
|
uint limit = config.SmallFactorLimit;
|
||||||
ulong previousOrder = config.PreviousOrder;
|
ulong previousOrder = config.PreviousOrder;
|
||||||
byte hasPreviousOrder = config.HasPreviousOrder;
|
byte hasPreviousOrder = config.HasPreviousOrder;
|
||||||
int maxPowChecks = config.MaxPowChecks;
|
int maxPowChecks = config.MaxPowChecks;
|
||||||
@@ -589,7 +580,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
SortFactors(workFactors, workExponents, factorCount);
|
SortFactors(workFactors, workExponents, factorCount);
|
||||||
|
|
||||||
long candidateCapacity = candidates.Length;
|
long candidateCapacity = candidates.Length;
|
||||||
int candidateLimit = candidateCapacity < HeuristicCandidateLimit ? (int)candidateCapacity : HeuristicCandidateLimit;
|
int candidateLimit = candidateCapacity < PrimeOrderConstants.HeuristicCandidateLimit ? (int)candidateCapacity : PrimeOrderConstants.HeuristicCandidateLimit;
|
||||||
int candidateCount = BuildCandidatesKernel(order, workFactors, workExponents, factorCount, candidates, stackIndex, stackExponent, stackProduct, candidateLimit);
|
int candidateCount = BuildCandidatesKernel(order, workFactors, workExponents, factorCount, candidates, stackIndex, stackExponent, stackProduct, candidateLimit);
|
||||||
if (candidateCount == 0)
|
if (candidateCount == 0)
|
||||||
{
|
{
|
||||||
@@ -1328,11 +1319,11 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static bool ShouldUseSingleBit(GpuUInt128 exponent) => exponent.High == 0UL && exponent.Low <= Pow2WindowFallbackThreshold;
|
private static bool ShouldUseSingleBit(GpuUInt128 exponent) => exponent.High == 0UL && exponent.Low <= PrimeOrderConstants.Pow2WindowFallbackThreshold;
|
||||||
|
|
||||||
private static int GetWindowSize(int bitLength)
|
private static int GetWindowSize(int bitLength)
|
||||||
{
|
{
|
||||||
if (bitLength <= Pow2WindowSizeBits)
|
if (bitLength <= PrimeOrderConstants.Pow2WindowSizeBits)
|
||||||
{
|
{
|
||||||
return Math.Max(bitLength, 1);
|
return Math.Max(bitLength, 1);
|
||||||
}
|
}
|
||||||
@@ -1357,7 +1348,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
return 7;
|
return 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Pow2WindowSizeBits;
|
return PrimeOrderConstants.Pow2WindowSizeBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static GpuUInt128 Pow2MontgomeryModSingleBit(GpuUInt128 exponent, GpuUInt128 modulus, GpuUInt128 baseValue)
|
private static GpuUInt128 Pow2MontgomeryModSingleBit(GpuUInt128 exponent, GpuUInt128 modulus, GpuUInt128 baseValue)
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using ILGPU;
|
||||||
|
using ILGPU.Runtime;
|
||||||
|
|
||||||
|
namespace PerfectNumbers.Core.Gpu;
|
||||||
|
|
||||||
|
public readonly struct OrderKernelBuffers(
|
||||||
|
ArrayView1D<ulong, Stride1D.Dense> phiFactors,
|
||||||
|
ArrayView1D<int, Stride1D.Dense> phiExponents,
|
||||||
|
ArrayView1D<ulong, Stride1D.Dense> workFactors,
|
||||||
|
ArrayView1D<int, Stride1D.Dense> workExponents,
|
||||||
|
ArrayView1D<ulong, Stride1D.Dense> candidates,
|
||||||
|
ArrayView1D<int, Stride1D.Dense> stackIndex,
|
||||||
|
ArrayView1D<int, Stride1D.Dense> stackExponent,
|
||||||
|
ArrayView1D<ulong, Stride1D.Dense> stackProduct,
|
||||||
|
ArrayView1D<ulong, Stride1D.Dense> result,
|
||||||
|
ArrayView1D<byte, Stride1D.Dense> status)
|
||||||
|
{
|
||||||
|
public readonly ArrayView1D<ulong, Stride1D.Dense> PhiFactors = phiFactors;
|
||||||
|
public readonly ArrayView1D<int, Stride1D.Dense> PhiExponents = phiExponents;
|
||||||
|
public readonly ArrayView1D<ulong, Stride1D.Dense> WorkFactors = workFactors;
|
||||||
|
public readonly ArrayView1D<int, Stride1D.Dense> WorkExponents = workExponents;
|
||||||
|
public readonly ArrayView1D<ulong, Stride1D.Dense> Candidates = candidates;
|
||||||
|
public readonly ArrayView1D<int, Stride1D.Dense> StackIndex = stackIndex;
|
||||||
|
public readonly ArrayView1D<int, Stride1D.Dense> StackExponent = stackExponent;
|
||||||
|
public readonly ArrayView1D<ulong, Stride1D.Dense> StackProduct = stackProduct;
|
||||||
|
public readonly ArrayView1D<ulong, Stride1D.Dense> Result = result;
|
||||||
|
public readonly ArrayView1D<byte, Stride1D.Dense> Status = status;
|
||||||
|
}
|
||||||
@@ -15,18 +15,18 @@ public static class Pow2MontgomeryGpuCalculator
|
|||||||
ulong result = 0UL;
|
ulong result = 0UL;
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
Accelerator? accelerator = gpu.Accelerator;
|
Accelerator? accelerator = gpu.Accelerator;
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
|
var exponentBufferView = gpu.InputView;
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
var resultBufferView = gpu.OutputUlongView;
|
||||||
|
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
|
exponentBufferView.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);
|
||||||
|
|
||||||
var kernelLauncher = gpu.KeepMontgomeryKernelLauncher;
|
var kernelLauncher = gpu.KeepMontgomeryKernelLauncher;
|
||||||
kernelLauncher(stream, 1, exponentBuffer.View, divisor.Modulus, divisor.NPrime, divisor.MontgomeryOne, divisor.MontgomeryTwo, divisor.MontgomeryTwoSquared, resultBuffer.View);
|
kernelLauncher(stream, 1, exponentBufferView, divisor.Modulus, divisor.NPrime, divisor.MontgomeryOne, divisor.MontgomeryTwo, divisor.MontgomeryTwoSquared, resultBufferView);
|
||||||
|
|
||||||
resultBuffer.View.CopyToCPU(stream, ref result, 1);
|
resultBufferView.CopyToCPU(stream, ref result, 1);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
// GpuPrimeWorkLimiter.Release();
|
// GpuPrimeWorkLimiter.Release();
|
||||||
@@ -38,21 +38,21 @@ public static class Pow2MontgomeryGpuCalculator
|
|||||||
public static ulong CalculateConvert(PrimeOrderCalculatorAccelerator gpu, ulong exponent, in MontgomeryDivisorData divisor)
|
public static ulong CalculateConvert(PrimeOrderCalculatorAccelerator gpu, ulong exponent, in MontgomeryDivisorData divisor)
|
||||||
{
|
{
|
||||||
ulong result = 0UL;
|
ulong result = 0UL;
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
|
var exponentBufferView = gpu.InputView;
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
var resultBufferView = gpu.OutputUlongView;
|
||||||
|
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
|
exponentBufferView.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);
|
||||||
|
|
||||||
|
|
||||||
var accelerator = gpu.Accelerator;
|
var accelerator = gpu.Accelerator;
|
||||||
var kernelLauncher = gpu.ConvertToStandardKernelLauncher;
|
var kernelLauncher = gpu.ConvertToStandardKernelLauncher;
|
||||||
kernelLauncher(stream, 1, exponentBuffer.View, divisor.Modulus, divisor.NPrime, divisor.MontgomeryOne, divisor.MontgomeryTwo, divisor.MontgomeryTwoSquared, resultBuffer.View);
|
kernelLauncher(stream, 1, exponentBufferView, divisor.Modulus, divisor.NPrime, divisor.MontgomeryOne, divisor.MontgomeryTwo, divisor.MontgomeryTwoSquared, resultBufferView);
|
||||||
|
|
||||||
resultBuffer.View.CopyToCPU(stream, ref result, 1);
|
resultBufferView.CopyToCPU(stream, ref result, 1);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace PerfectNumbers.Core.Gpu;
|
||||||
|
|
||||||
|
public static class PrimeOrderConstants
|
||||||
|
{
|
||||||
|
public const int GpuSmallPrimeFactorSlots = 64;
|
||||||
|
public const int HeuristicCandidateLimit = 512;
|
||||||
|
public const int HeuristicStackCapacity = 256;
|
||||||
|
public const int MaxGpuBatchSize = 256;
|
||||||
|
public const ulong Pow2WindowFallbackThreshold = 32UL;
|
||||||
|
public const int Pow2WindowOddPowerCount = 1 << (Pow2WindowSizeBits - 1);
|
||||||
|
public const int Pow2WindowSizeBits = 8;
|
||||||
|
public const int WideStackThreshold = 12;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using ILGPU;
|
|
||||||
using ILGPU.Runtime;
|
using ILGPU.Runtime;
|
||||||
using ILGPU.Runtime.OpenCL;
|
|
||||||
using PerfectNumbers.Core.Gpu.Accelerators;
|
using PerfectNumbers.Core.Gpu.Accelerators;
|
||||||
using PerfectNumbers.Core.Gpu.Kernels;
|
using PerfectNumbers.Core.Gpu.Kernels;
|
||||||
|
|
||||||
@@ -26,58 +24,9 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
private static readonly ConcurrentDictionary<ulong, byte> OverflowedPrimes = new();
|
private static readonly ConcurrentDictionary<ulong, byte> OverflowedPrimes = new();
|
||||||
private static readonly ConcurrentDictionary<UInt128, byte> OverflowedPrimesWide = new();
|
private static readonly ConcurrentDictionary<UInt128, byte> OverflowedPrimesWide = new();
|
||||||
|
|
||||||
[ThreadStatic]
|
|
||||||
private static Kernel[]? _pow2ModKernel;
|
|
||||||
|
|
||||||
[ThreadStatic]
|
|
||||||
private static Kernel[]? _partialFactorKernel;
|
|
||||||
|
|
||||||
[ThreadStatic]
|
|
||||||
private static Kernel[]? _orderKernel;
|
|
||||||
|
|
||||||
public readonly struct OrderKernelConfig(ulong previousOrder, byte hasPreviousOrder, uint smallFactorLimit, int maxPowChecks, int mode)
|
|
||||||
{
|
|
||||||
public readonly ulong PreviousOrder = previousOrder;
|
|
||||||
public readonly byte HasPreviousOrder = hasPreviousOrder;
|
|
||||||
public readonly uint SmallFactorLimit = smallFactorLimit;
|
|
||||||
public readonly int MaxPowChecks = maxPowChecks;
|
|
||||||
public readonly int Mode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public readonly struct OrderKernelBuffers(
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> phiFactors,
|
|
||||||
ArrayView1D<int, Stride1D.Dense> phiExponents,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> workFactors,
|
|
||||||
ArrayView1D<int, Stride1D.Dense> workExponents,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> candidates,
|
|
||||||
ArrayView1D<int, Stride1D.Dense> stackIndex,
|
|
||||||
ArrayView1D<int, Stride1D.Dense> stackExponent,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> stackProduct,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> result,
|
|
||||||
ArrayView1D<byte, Stride1D.Dense> status)
|
|
||||||
{
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> PhiFactors = phiFactors;
|
|
||||||
public readonly ArrayView1D<int, Stride1D.Dense> PhiExponents = phiExponents;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> WorkFactors = workFactors;
|
|
||||||
public readonly ArrayView1D<int, Stride1D.Dense> WorkExponents = workExponents;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> Candidates = candidates;
|
|
||||||
public readonly ArrayView1D<int, Stride1D.Dense> StackIndex = stackIndex;
|
|
||||||
public readonly ArrayView1D<int, Stride1D.Dense> StackExponent = stackExponent;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> StackProduct = stackProduct;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> Result = result;
|
|
||||||
public readonly ArrayView1D<byte, Stride1D.Dense> Status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
private const int WideStackThreshold = 12;
|
|
||||||
private static PrimeOrderGpuCapability s_capability = PrimeOrderGpuCapability.Default;
|
private static PrimeOrderGpuCapability s_capability = PrimeOrderGpuCapability.Default;
|
||||||
|
|
||||||
private const int Pow2WindowSizeBits = 8;
|
|
||||||
private const int Pow2WindowOddPowerCount = 1 << (Pow2WindowSizeBits - 1);
|
|
||||||
private const ulong Pow2WindowFallbackThreshold = 32UL;
|
|
||||||
private const int HeuristicCandidateLimit = 512;
|
|
||||||
private const int HeuristicStackCapacity = 256;
|
|
||||||
|
|
||||||
private const int GpuSmallPrimeFactorSlots = 64;
|
|
||||||
|
|
||||||
internal static ConcurrentDictionary<ulong, byte> OverflowRegistry => OverflowedPrimes;
|
internal static ConcurrentDictionary<ulong, byte> OverflowRegistry => OverflowedPrimes;
|
||||||
internal static ConcurrentDictionary<UInt128, byte> OverflowRegistryWide => OverflowedPrimesWide;
|
internal static ConcurrentDictionary<UInt128, byte> OverflowRegistryWide => OverflowedPrimesWide;
|
||||||
@@ -92,22 +41,6 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
s_capability = PrimeOrderGpuCapability.Default;
|
s_capability = PrimeOrderGpuCapability.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Kernel GetPartialFactorKernel(int acceleratorIndex)
|
|
||||||
{
|
|
||||||
var pool = _partialFactorKernel ??= [];
|
|
||||||
if (pool[acceleratorIndex] is {} cached)
|
|
||||||
{
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
var accelerator = _accelerators[acceleratorIndex];
|
|
||||||
var loaded = accelerator.LoadAutoGroupedStreamKernel<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);
|
|
||||||
|
|
||||||
cached = KernelUtil.GetKernel(loaded);
|
|
||||||
pool[acceleratorIndex] = cached;
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryPartialFactor(
|
public static bool TryPartialFactor(
|
||||||
PrimeOrderCalculatorAccelerator gpu,
|
PrimeOrderCalculatorAccelerator gpu,
|
||||||
ulong value,
|
ulong value,
|
||||||
@@ -167,32 +100,30 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
factorCount = 0;
|
factorCount = 0;
|
||||||
remaining = value;
|
remaining = value;
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
int acceleratorIndex = AcceleratorPool.Shared.Rent();
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
Accelerator accelerator = _accelerators[acceleratorIndex];
|
|
||||||
AcceleratorStream stream = accelerator.CreateStream();
|
|
||||||
|
|
||||||
var smallPrimesView = gpu.SmallPrimeFactorPrimes;
|
var smallPrimesView = gpu.SmallPrimeFactorPrimes;
|
||||||
var smallSquaresView = gpu.SmallPrimeFactorSquares;
|
var smallSquaresView = gpu.SmallPrimeFactorSquares;
|
||||||
|
|
||||||
// TODO: We should create / reallocate these buffer only once or if the new required length is bigger than capacity.
|
var kernelLauncher = gpu.PartialFactorKernelLauncher;
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense>? factorBuffer = accelerator.Allocate1D<ulong>(primeTargets.Length);
|
|
||||||
MemoryBuffer1D<int, Stride1D.Dense>? exponentBuffer = accelerator.Allocate1D<int>(exponentTargets.Length);
|
int primeTargetsLength = primeTargets.Length;
|
||||||
MemoryBuffer1D<int, Stride1D.Dense>? countBuffer = accelerator.Allocate1D<int>(1);
|
gpu.EnsurePartialFactorCapacity(primeTargetsLength);
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense>? remainingBuffer = accelerator.Allocate1D<ulong>(1);
|
|
||||||
MemoryBuffer1D<byte, Stride1D.Dense>? fullyFactoredBuffer = accelerator.Allocate1D<byte>(1);
|
var factorBufferView = gpu.OutputUlongView;
|
||||||
|
var exponentBufferView = gpu.OutputIntView;
|
||||||
|
var countBufferView = gpu.OutputIntView2;
|
||||||
|
var remainingBufferView = gpu.OutputUlongView2;
|
||||||
|
var fullyFactoredBufferView = gpu.OutputByteView;
|
||||||
|
|
||||||
// There is no need to clear these buffers because the kernel will always assign values within the required bounds. Keep it commented out.
|
// There is no need to clear these buffers because the kernel will always assign values within the required bounds. Keep it commented out.
|
||||||
// factorBuffer.MemSetToZero(stream);
|
// factorBufferView.MemSetToZero(stream);
|
||||||
// exponentBuffer.MemSetToZero(stream);
|
// exponentBufferView.MemSetToZero(stream);
|
||||||
// countBuffer.MemSetToZero(stream);
|
// countBufferView.MemSetToZero(stream);
|
||||||
// remainingBuffer.MemSetToZero(stream);
|
// remainingBufferView.MemSetToZero(stream);
|
||||||
// fullyFactoredBuffer.MemSetToZero(stream);
|
// fullyFactoredBufferView.MemSetToZero(stream);
|
||||||
|
|
||||||
var partialFactorKernel = GetPartialFactorKernel(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(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>>>();
|
|
||||||
|
|
||||||
kernelLauncher(
|
kernelLauncher(
|
||||||
stream,
|
stream,
|
||||||
@@ -200,61 +131,43 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
smallPrimesView,
|
smallPrimesView,
|
||||||
smallSquaresView,
|
smallSquaresView,
|
||||||
(int)smallPrimesView.Length,
|
(int)smallPrimesView.Length,
|
||||||
primeTargets.Length,
|
primeTargetsLength,
|
||||||
value,
|
value,
|
||||||
limit,
|
limit,
|
||||||
factorBuffer.View,
|
factorBufferView,
|
||||||
exponentBuffer.View,
|
exponentBufferView,
|
||||||
countBuffer.View,
|
countBufferView,
|
||||||
remainingBuffer.View,
|
remainingBufferView,
|
||||||
fullyFactoredBuffer.View);
|
fullyFactoredBufferView);
|
||||||
|
|
||||||
|
|
||||||
countBuffer.View.CopyToCPU(stream, ref factorCount, 1);
|
|
||||||
factorBuffer.View.CopyToCPU(stream, ref MemoryMarshal.GetReference(primeTargets), primeTargets.Length);
|
|
||||||
exponentBuffer.View.CopyToCPU(stream, ref MemoryMarshal.GetReference(exponentTargets), exponentTargets.Length);
|
|
||||||
remainingBuffer.View.CopyToCPU(stream, ref remaining, 1);
|
|
||||||
|
|
||||||
byte fullyFactoredFlag = 0;
|
byte fullyFactoredFlag = 0;
|
||||||
fullyFactoredBuffer.View.CopyToCPU(stream, ref fullyFactoredFlag, 1);
|
factorBufferView.CopyToCPU(stream, primeTargets);
|
||||||
|
exponentBufferView.CopyToCPU(stream, exponentTargets);
|
||||||
|
countBufferView.CopyToCPU(stream, ref factorCount, 1);
|
||||||
|
remainingBufferView.CopyToCPU(stream, ref remaining, 1);
|
||||||
|
fullyFactoredBufferView.CopyToCPU(stream, ref fullyFactoredFlag, 1);
|
||||||
|
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
stream.Dispose();
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
|
|
||||||
factorCount = Math.Min(factorCount, primeTargets.Length);
|
factorCount = Math.Min(factorCount, primeTargetsLength);
|
||||||
|
|
||||||
// TODO: These buffers shouldn't be disposed but rather reused accross call with the assigned accelerator.
|
|
||||||
factorBuffer.Dispose();
|
|
||||||
exponentBuffer.Dispose();
|
|
||||||
countBuffer.Dispose();
|
|
||||||
remainingBuffer.Dispose();
|
|
||||||
fullyFactoredBuffer.Dispose();
|
|
||||||
// GpuPrimeWorkLimiter.Release();
|
// GpuPrimeWorkLimiter.Release();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (CLException ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"GPU ERROR ({ex.Error}): {ex.Message}");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
catch (Exception ex) when (ex is AcceleratorException or InternalCompilerException or NotSupportedException or InvalidOperationException or AggregateException)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"GPU ERROR: {ex.Message}");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GpuPow2ModStatus TryPow2Mod(ulong exponent, ulong prime, out ulong remainder, in MontgomeryDivisorData? divisorData)
|
public static GpuPow2ModStatus TryPow2Mod(PrimeOrderCalculatorAccelerator gpu, ulong exponent, ulong prime, out ulong remainder, in MontgomeryDivisorData? divisorData)
|
||||||
{
|
{
|
||||||
Span<ulong> exponents = stackalloc ulong[1];
|
Span<ulong> exponents = stackalloc ulong[1];
|
||||||
Span<ulong> remainders = stackalloc ulong[1];
|
Span<ulong> remainders = stackalloc ulong[1];
|
||||||
exponents[0] = exponent;
|
exponents[0] = exponent;
|
||||||
|
|
||||||
GpuPow2ModStatus status = TryPow2ModBatch(exponents, prime, remainders, divisorData);
|
GpuPow2ModStatus status = TryPow2ModBatch(gpu, exponents, prime, remainders, divisorData);
|
||||||
remainder = remainders[0];
|
remainder = remainders[0];
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GpuPow2ModStatus TryPow2ModBatch(ReadOnlySpan<ulong> exponents, ulong prime, Span<ulong> remainders, in MontgomeryDivisorData? divisorData)
|
public static GpuPow2ModStatus TryPow2ModBatch(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<ulong> exponents, ulong prime, Span<ulong> remainders, in MontgomeryDivisorData? divisorData)
|
||||||
{
|
{
|
||||||
// This will never occur in production code
|
// This will never occur in production code
|
||||||
// if (exponents.Length == 0)
|
// if (exponents.Length == 0)
|
||||||
@@ -305,7 +218,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool computed = TryComputeOnGpu(exponents, prime, divisorData, remainders);
|
bool computed = TryComputeOnGpu(gpu, exponents, prime, divisorData, remainders);
|
||||||
return computed ? GpuPow2ModStatus.Success : GpuPow2ModStatus.Unavailable;
|
return computed ? GpuPow2ModStatus.Success : GpuPow2ModStatus.Unavailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,71 +249,41 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
order = 0UL;
|
order = 0UL;
|
||||||
|
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
int acceleratorIndex = AcceleratorPool.Shared.Rent();
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
Accelerator accelerator = _accelerators[acceleratorIndex];
|
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
|
||||||
var smallPrimesView = gpu.SmallPrimeFactorPrimes;
|
var smallPrimesView = gpu.SmallPrimeFactorPrimes;
|
||||||
var smallSquaresView = gpu.SmallPrimeFactorSquares;
|
var smallSquaresView = gpu.SmallPrimeFactorSquares;
|
||||||
|
// var phiFactorBufferView = gpu.PhiFactorBufferView;
|
||||||
// TODO: These buffers should be created reallocated once and assigned to an accelerator. Callers should use their own
|
// var phiExponentBufferView = gpu.PhiExponentBufferView;
|
||||||
// thread static cache to prevent other threads from using taking accelerators with pre-allocated buffers if they don't
|
// var workFactorBufferView = gpu.WorkFactorBufferView;
|
||||||
// use them.
|
// var workExponentBufferView = gpu.WorkExponentBufferView;
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense>? phiFactorBuffer;
|
// var candidateBufferView = gpu.CandidateBufferView;
|
||||||
MemoryBuffer1D<int, Stride1D.Dense>? phiExponentBuffer;
|
// var stackIndexBufferView = gpu.StackIndexBufferView;
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense>? workFactorBuffer;
|
// var stackExponentBufferView = gpu.StackExponentBufferView;
|
||||||
MemoryBuffer1D<int, Stride1D.Dense>? workExponentBuffer;
|
// var stackProductBufferView = gpu.StackProductBufferView;
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense>? candidateBuffer;
|
var resultBufferView = gpu.OutputUlongView2;
|
||||||
MemoryBuffer1D<int, Stride1D.Dense>? stackIndexBuffer;
|
var statusBufferView = gpu.OutputByteView;
|
||||||
MemoryBuffer1D<int, Stride1D.Dense>? stackExponentBuffer;
|
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense>? stackProductBuffer;
|
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense>? resultBuffer;
|
|
||||||
MemoryBuffer1D<byte, Stride1D.Dense>? statusBuffer;
|
|
||||||
|
|
||||||
// lock (accelerator)
|
|
||||||
{
|
|
||||||
phiFactorBuffer = accelerator.Allocate1D<ulong>(GpuSmallPrimeFactorSlots);
|
|
||||||
phiExponentBuffer = accelerator.Allocate1D<int>(GpuSmallPrimeFactorSlots);
|
|
||||||
workFactorBuffer = accelerator.Allocate1D<ulong>(GpuSmallPrimeFactorSlots);
|
|
||||||
workExponentBuffer = accelerator.Allocate1D<int>(GpuSmallPrimeFactorSlots);
|
|
||||||
candidateBuffer = accelerator.Allocate1D<ulong>(HeuristicCandidateLimit);
|
|
||||||
stackIndexBuffer = accelerator.Allocate1D<int>(HeuristicStackCapacity);
|
|
||||||
stackExponentBuffer = accelerator.Allocate1D<int>(HeuristicStackCapacity);
|
|
||||||
stackProductBuffer = accelerator.Allocate1D<ulong>(HeuristicStackCapacity);
|
|
||||||
resultBuffer = accelerator.Allocate1D<ulong>(1);
|
|
||||||
statusBuffer = accelerator.Allocate1D<byte>(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Remove the cleaning after the order kernel is modified to always set the result.
|
|
||||||
phiFactorBuffer.MemSetToZero(stream);
|
|
||||||
phiExponentBuffer.MemSetToZero(stream);
|
|
||||||
workFactorBuffer.MemSetToZero(stream);
|
|
||||||
workExponentBuffer.MemSetToZero(stream);
|
|
||||||
candidateBuffer.MemSetToZero(stream);
|
|
||||||
stackIndexBuffer.MemSetToZero(stream);
|
|
||||||
stackExponentBuffer.MemSetToZero(stream);
|
|
||||||
stackProductBuffer.MemSetToZero(stream);
|
|
||||||
resultBuffer.MemSetToZero(stream);
|
|
||||||
statusBuffer.MemSetToZero(stream);
|
|
||||||
|
|
||||||
uint limit = config.SmallFactorLimit == 0 ? uint.MaxValue : config.SmallFactorLimit;
|
uint limit = config.SmallFactorLimit == 0 ? uint.MaxValue : config.SmallFactorLimit;
|
||||||
byte hasPrevious = previousOrder.HasValue ? (byte)1 : (byte)0;
|
byte hasPrevious = previousOrder.HasValue ? (byte)1 : (byte)0;
|
||||||
ulong previousValue = previousOrder ?? 0UL;
|
ulong previousValue = previousOrder ?? 0UL;
|
||||||
|
|
||||||
var kernelConfig = new OrderKernelConfig(previousValue, hasPrevious, limit, config.MaxPowChecks, (int)config.Mode);
|
var kernelConfig = new CalculateOrderKernelConfig(previousValue, hasPrevious, limit, config.MaxPowChecks, (int)config.Mode);
|
||||||
var buffers = new OrderKernelBuffers(
|
ref var buffers = ref gpu.CalculateOrderKernelBuffers;
|
||||||
phiFactorBuffer.View,
|
|
||||||
phiExponentBuffer.View,
|
|
||||||
workFactorBuffer.View,
|
|
||||||
workExponentBuffer.View,
|
|
||||||
candidateBuffer.View,
|
|
||||||
stackIndexBuffer.View,
|
|
||||||
stackExponentBuffer.View,
|
|
||||||
stackProductBuffer.View,
|
|
||||||
resultBuffer.View,
|
|
||||||
statusBuffer.View);
|
|
||||||
|
|
||||||
var orderKernel = GetOrderKernel(acceleratorIndex);
|
var kernelLauncher = gpu.CalculateOrderKernelLauncher;
|
||||||
var kernelLauncher = orderKernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, OrderKernelConfig, ulong, ulong, ulong, ulong, ulong, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers>>();
|
|
||||||
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
|
// TODO: Remove the cleaning after the order kernel is modified to always set the result.
|
||||||
|
// phiFactorBufferView.MemSetToZero(stream);
|
||||||
|
// phiExponentBufferView.MemSetToZero(stream);
|
||||||
|
// workFactorBufferView.MemSetToZero(stream);
|
||||||
|
// workExponentBufferView.MemSetToZero(stream);
|
||||||
|
// candidateBufferView.MemSetToZero(stream);
|
||||||
|
// stackIndexBufferView.MemSetToZero(stream);
|
||||||
|
// stackExponentBufferView.MemSetToZero(stream);
|
||||||
|
// stackProductBufferView.MemSetToZero(stream);
|
||||||
|
resultBufferView.MemSetToZero(stream);
|
||||||
|
statusBufferView.MemSetToZero(stream);
|
||||||
|
|
||||||
kernelLauncher(
|
kernelLauncher(
|
||||||
stream,
|
stream,
|
||||||
@@ -419,21 +302,11 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
|
|
||||||
|
|
||||||
byte status = 0;
|
byte status = 0;
|
||||||
statusBuffer.View.CopyToCPU(stream, ref status, 1);
|
statusBufferView.CopyToCPU(stream, ref status, 1);
|
||||||
resultBuffer.View.CopyToCPU(stream, ref order, 1);
|
resultBufferView.CopyToCPU(stream, ref order, 1);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
phiFactorBuffer.Dispose();
|
|
||||||
phiExponentBuffer.Dispose();
|
|
||||||
workFactorBuffer.Dispose();
|
|
||||||
workExponentBuffer.Dispose();
|
|
||||||
candidateBuffer.Dispose();
|
|
||||||
stackIndexBuffer.Dispose();
|
|
||||||
stackExponentBuffer.Dispose();
|
|
||||||
stackProductBuffer.Dispose();
|
|
||||||
resultBuffer.Dispose();
|
|
||||||
statusBuffer.Dispose();
|
|
||||||
// GpuPrimeWorkLimiter.Release();
|
// GpuPrimeWorkLimiter.Release();
|
||||||
|
|
||||||
PrimeOrderKernelStatus kernelStatus = (PrimeOrderKernelStatus)status;
|
PrimeOrderKernelStatus kernelStatus = (PrimeOrderKernelStatus)status;
|
||||||
@@ -455,22 +328,6 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
return order != 0UL;
|
return order != 0UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Kernel GetOrderKernel(int acceleratorIndex)
|
|
||||||
{
|
|
||||||
var pool = _orderKernel ??= [];
|
|
||||||
if (pool[acceleratorIndex] is {} cached)
|
|
||||||
{
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
var accelerator = _accelerators[acceleratorIndex];
|
|
||||||
var loaded = accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, OrderKernelConfig, ulong, ulong, ulong, ulong, ulong, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers>(CalculateOrderKernel);
|
|
||||||
|
|
||||||
var kernel = KernelUtil.GetKernel(loaded);
|
|
||||||
pool[acceleratorIndex] = kernel;
|
|
||||||
return kernel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static GpuPow2ModStatus TryPow2ModBatchInternal(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<UInt128> exponents, UInt128 prime, Span<UInt128> remainders)
|
private static GpuPow2ModStatus TryPow2ModBatchInternal(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<UInt128> exponents, UInt128 prime, Span<UInt128> remainders)
|
||||||
{
|
{
|
||||||
if (exponents.Length == 0)
|
if (exponents.Length == 0)
|
||||||
@@ -513,58 +370,39 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
return GpuPow2ModStatus.Success;
|
return GpuPow2ModStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TryComputeOnGpu(ReadOnlySpan<ulong> exponents, ulong prime, MontgomeryDivisorData? divisorData, Span<ulong> results)
|
private static bool TryComputeOnGpu(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<ulong> exponents, ulong prime, MontgomeryDivisorData? divisorData, Span<ulong> results)
|
||||||
{
|
{
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
int acceleratorIndex = AcceleratorPool.Shared.Rent();
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
Accelerator accelerator = _accelerators[acceleratorIndex];
|
Accelerator accelerator = gpu.Accelerator;
|
||||||
AcceleratorStream? stream = accelerator.CreateStream();
|
var kernelLauncher = gpu.Pow2ModKernelLauncher;
|
||||||
// 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
|
||||||
// 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>? remainderBuffer;
|
|
||||||
// lock (accelerator)
|
|
||||||
{
|
|
||||||
exponentBuffer = accelerator.Allocate1D<ulong>(exponents.Length);
|
|
||||||
remainderBuffer = accelerator.Allocate1D<ulong>(exponents.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
exponentBuffer.View.CopyFromCPU(stream, ref MemoryMarshal.GetReference(exponents), exponents.Length);
|
gpu.EnsureUlongInputOutputCapacity(exponents.Length);
|
||||||
|
|
||||||
// Pow2Mod kernel always assigns the required output elements so we don't need to worry about clearing these.
|
var exponentBufferView = gpu.InputView;
|
||||||
// remainderBuffer.MemSetToZero(stream);
|
var remainderBufferView = gpu.OutputUlongView;
|
||||||
|
|
||||||
var pow2ModKernel = GetPow2ModKernel(acceleratorIndex);
|
|
||||||
var kernelLauncher = pow2ModKernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>>();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (divisorData is null)
|
if (divisorData is null)
|
||||||
{
|
{
|
||||||
divisorData = MontgomeryDivisorData.Empty;
|
divisorData = MontgomeryDivisorData.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
kernelLauncher(stream, exponents.Length, exponentBuffer.View, divisorData.Modulus, divisorData.NPrime, divisorData.MontgomeryOne, divisorData.MontgomeryTwo, divisorData.MontgomeryTwoSquared, remainderBuffer.View);
|
AcceleratorStream? stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
|
exponentBufferView.CopyFromCPU(stream, exponents);
|
||||||
|
|
||||||
remainderBuffer.View.CopyToCPU(stream, ref MemoryMarshal.GetReference(results), exponents.Length);
|
// Pow2Mod kernel always assigns the required output elements so we don't need to worry about clearing these.
|
||||||
|
// remainderBuffer.MemSetToZero(stream);
|
||||||
|
|
||||||
|
kernelLauncher(stream, exponents.Length, exponentBufferView, divisorData.Modulus, divisorData.NPrime, divisorData.MontgomeryOne, divisorData.MontgomeryTwo, divisorData.MontgomeryTwoSquared, remainderBufferView);
|
||||||
|
|
||||||
|
remainderBufferView.CopyToCPU(stream, results);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
stream.Dispose();
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
stream = null;
|
|
||||||
exponentBuffer.Dispose();
|
|
||||||
remainderBuffer.Dispose();
|
|
||||||
// GpuPrimeWorkLimiter.Release();
|
// GpuPrimeWorkLimiter.Release();
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Exception for {prime} and exponents: {string.Join(",", exponents.ToArray())}.");
|
|
||||||
stream?.Dispose();
|
|
||||||
exponentBuffer.Dispose();
|
|
||||||
remainderBuffer.Dispose();
|
|
||||||
// GpuPrimeWorkLimiter.Release();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -585,11 +423,11 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
GpuUInt128[]? rentedExponents = null;
|
GpuUInt128[]? rentedExponents = null;
|
||||||
GpuUInt128[]? rentedResults = null;
|
GpuUInt128[]? rentedResults = null;
|
||||||
ArrayPool<GpuUInt128> gpuUInt128Pool = ThreadStaticPools.GpuUInt128Pool;
|
ArrayPool<GpuUInt128> gpuUInt128Pool = ThreadStaticPools.GpuUInt128Pool;
|
||||||
bool poolingRequired = length > WideStackThreshold;
|
bool poolingRequired = length > PrimeOrderConstants.WideStackThreshold;
|
||||||
Span<GpuUInt128> exponentSpan = poolingRequired
|
Span<GpuUInt128> exponentSpan = poolingRequired
|
||||||
? stackalloc GpuUInt128[length]
|
? stackalloc GpuUInt128[length]
|
||||||
: new Span<GpuUInt128>(rentedExponents = gpuUInt128Pool.Rent(length), 0, length);
|
: new Span<GpuUInt128>(rentedExponents = gpuUInt128Pool.Rent(length), 0, length);
|
||||||
Span<GpuUInt128> resultSpan = length <= WideStackThreshold
|
Span<GpuUInt128> resultSpan = length <= PrimeOrderConstants.WideStackThreshold
|
||||||
? stackalloc GpuUInt128[length]
|
? stackalloc GpuUInt128[length]
|
||||||
: new Span<GpuUInt128>(rentedResults = gpuUInt128Pool.Rent(length), 0, length);
|
: new Span<GpuUInt128>(rentedResults = gpuUInt128Pool.Rent(length), 0, length);
|
||||||
|
|
||||||
@@ -603,32 +441,26 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
Accelerator accelerator = gpu.Accelerator;
|
Accelerator accelerator = gpu.Accelerator;
|
||||||
|
|
||||||
AcceleratorStream? stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
gpu.EnsureCalculateOrderWideCapacity(length);
|
||||||
MemoryBuffer1D<GpuUInt128, Stride1D.Dense> exponentBuffer;
|
|
||||||
MemoryBuffer1D<GpuUInt128, Stride1D.Dense> remainderBuffer;
|
|
||||||
|
|
||||||
// lock (accelerator)
|
var exponentBufferView = gpu.CalculateOrderWideExponentBufferView;
|
||||||
{
|
var remainderBufferView = gpu.CalculateOrderWideRemainderBufferView;
|
||||||
exponentBuffer = accelerator.Allocate1D<GpuUInt128>(length);
|
|
||||||
remainderBuffer = accelerator.Allocate1D<GpuUInt128>(length);
|
|
||||||
}
|
|
||||||
|
|
||||||
exponentBuffer.View.CopyFromCPU(stream, exponentSpan);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
|
exponentBufferView.CopyFromCPU(stream, exponentSpan);
|
||||||
var kernelLauncher = gpu.Pow2ModWideKernelLauncher;
|
var kernelLauncher = gpu.Pow2ModWideKernelLauncher;
|
||||||
|
|
||||||
kernelLauncher(stream, length, exponentBuffer.View, modulus, remainderBuffer.View);
|
kernelLauncher(stream, length, exponentBufferView, modulus, remainderBufferView);
|
||||||
remainderBuffer.View.CopyToCPU(stream, ref MemoryMarshal.GetReference(resultSpan), length);
|
remainderBufferView.CopyToCPU(stream, ref MemoryMarshal.GetReference(resultSpan), length);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(acceleratorIndex, 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];
|
||||||
}
|
}
|
||||||
|
|
||||||
remainderBuffer.Dispose();
|
|
||||||
exponentBuffer.Dispose();
|
|
||||||
|
|
||||||
if (rentedExponents is not null)
|
if (rentedExponents is not null)
|
||||||
{
|
{
|
||||||
gpuUInt128Pool.Return(rentedExponents, clearArray: false);
|
gpuUInt128Pool.Return(rentedExponents, clearArray: false);
|
||||||
@@ -655,21 +487,6 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
return divisorData.Pow2MontgomeryModWindowedGpuConvertToStandard(exponent);
|
return divisorData.Pow2MontgomeryModWindowedGpuConvertToStandard(exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Kernel GetPow2ModKernel(int acceleratorIndex)
|
|
||||||
{
|
|
||||||
var pool = _pow2ModKernel ??= [];
|
|
||||||
if (pool[acceleratorIndex] is {} cached)
|
|
||||||
{
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
var accelerator = _accelerators[acceleratorIndex];
|
|
||||||
var loaded = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>(Pow2ModKernel));
|
|
||||||
|
|
||||||
pool[acceleratorIndex] = loaded;
|
|
||||||
return loaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal readonly record struct PrimeOrderGpuCapability(int ModulusBits, int ExponentBits)
|
internal readonly record struct PrimeOrderGpuCapability(int ModulusBits, int ExponentBits)
|
||||||
{
|
{
|
||||||
public static PrimeOrderGpuCapability Default => new(128, 128);
|
public static PrimeOrderGpuCapability Default => new(128, 128);
|
||||||
|
|||||||
@@ -225,24 +225,24 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
private static bool HeuristicTrialDivisionGpuDetectsDivisor(PrimeOrderCalculatorAccelerator gpu, ulong n, ulong maxDivisorSquare, byte nMod10)
|
private static bool HeuristicTrialDivisionGpuDetectsDivisor(PrimeOrderCalculatorAccelerator gpu, ulong n, ulong maxDivisorSquare, byte nMod10)
|
||||||
{
|
{
|
||||||
var acceleratorIndex = gpu.AcceleratorIndex;
|
var acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
var flagView1D = gpu.OutputInt!.View;
|
var flagView1DView = gpu.OutputIntView;
|
||||||
|
var kernelLauncher = gpu.HeuristicCombinedTrialDivisionKernelLauncher;
|
||||||
bool compositeDetected;
|
bool compositeDetected;
|
||||||
Span<int> compositeFlag = stackalloc int[1];
|
Span<int> compositeFlag = stackalloc int[1];
|
||||||
// int compositeFlag = 0;
|
// int compositeFlag = 0;
|
||||||
|
|
||||||
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
flagView1D.MemSetToZero(stream);
|
flagView1DView.MemSetToZero(stream);
|
||||||
|
|
||||||
var kernelLauncher = gpu.HeuristicCombinedTrialDivisionKernelLauncher;
|
|
||||||
kernelLauncher(
|
kernelLauncher(
|
||||||
stream,
|
stream,
|
||||||
1,
|
1,
|
||||||
nMod10,
|
nMod10,
|
||||||
flagView1D,
|
flagView1DView,
|
||||||
n,
|
n,
|
||||||
maxDivisorSquare,
|
maxDivisorSquare,
|
||||||
gpu.DivisorTables);
|
gpu.DivisorTables);
|
||||||
flagView1D.CopyToCPU(stream, compositeFlag);
|
flagView1DView.CopyToCPU(stream, compositeFlag);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
|
|||||||
@@ -244,12 +244,12 @@ public sealed class HeuristicPrimeTester
|
|||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
var flagView1D = gpu.OutputInt!.View;
|
var flagView1DView = gpu.OutputIntView;
|
||||||
|
|
||||||
bool compositeDetected;
|
bool compositeDetected;
|
||||||
int compositeFlag = 0;
|
int compositeFlag = 0;
|
||||||
|
|
||||||
flagView1D.CopyFromCPU(stream, ref compositeFlag, 1);
|
flagView1DView.CopyFromCPU(stream, ref compositeFlag, 1);
|
||||||
|
|
||||||
// Index1D index,
|
// Index1D index,
|
||||||
// ArrayView<int> resultFlag,
|
// ArrayView<int> resultFlag,
|
||||||
@@ -263,13 +263,13 @@ public sealed class HeuristicPrimeTester
|
|||||||
stream,
|
stream,
|
||||||
1,
|
1,
|
||||||
nMod10,
|
nMod10,
|
||||||
flagView1D,
|
flagView1DView,
|
||||||
n,
|
n,
|
||||||
maxDivisorSquare,
|
maxDivisorSquare,
|
||||||
gpu.DivisorTables);
|
gpu.DivisorTables);
|
||||||
|
|
||||||
flagView1D.CopyToCPU(stream, ref compositeFlag, 1);
|
flagView1DView.CopyToCPU(stream, ref compositeFlag, 1);
|
||||||
stream!.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
compositeDetected = compositeFlag != 0;
|
compositeDetected = compositeFlag != 0;
|
||||||
// compositeDetected = compositeFlag != 0;
|
// compositeDetected = compositeFlag != 0;
|
||||||
|
|||||||
@@ -415,8 +415,9 @@ public class MersenneDivisorCycles
|
|||||||
// Console.WriteLine($"MersenneDivisorCycles.TryFactorIntoCountsInternal hits {Volatile.Read(ref _tryFactorIntoCountsInternalHits)}");
|
// Console.WriteLine($"MersenneDivisorCycles.TryFactorIntoCountsInternal hits {Volatile.Read(ref _tryFactorIntoCountsInternalHits)}");
|
||||||
|
|
||||||
// HeuristicPrimeTester primeTester = _primeTester ??= new();
|
// HeuristicPrimeTester primeTester = _primeTester ??= new();
|
||||||
|
if (HeuristicCombinedPrimeTester.IsPrimeCpu(remaining))
|
||||||
// if (HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, remaining))
|
// if (HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, remaining))
|
||||||
if (PrimeTester.IsPrime(remaining))
|
// if (PrimeTester.IsPrime(remaining))
|
||||||
{
|
{
|
||||||
AddFactor(counts, remaining);
|
AddFactor(counts, remaining);
|
||||||
return true;
|
return true;
|
||||||
@@ -965,7 +966,7 @@ public class MersenneDivisorCycles
|
|||||||
|
|
||||||
// HeuristicPrimeTester primeTester = _primeTester ??= new();
|
// HeuristicPrimeTester primeTester = _primeTester ??= new();
|
||||||
// if (!skipPrimeOrderHeuristic && HeuristicPrimeTester.Exclusive.IsPrimeCpu(divisor, CancellationToken.None))
|
// if (!skipPrimeOrderHeuristic && HeuristicPrimeTester.Exclusive.IsPrimeCpu(divisor, CancellationToken.None))
|
||||||
if (!skipPrimeOrderHeuristic && PrimeTester.IsPrime(divisor))
|
if (!skipPrimeOrderHeuristic && HeuristicCombinedPrimeTester.IsPrimeCpu(divisor))
|
||||||
// if (!skipPrimeOrderHeuristic && HeuristicCombinedPrimeTester.IsPrimeGpu(divisor))
|
// if (!skipPrimeOrderHeuristic && HeuristicCombinedPrimeTester.IsPrimeGpu(divisor))
|
||||||
{
|
{
|
||||||
ulong computedOrder = PrimeOrderCalculator.Calculate(
|
ulong computedOrder = PrimeOrderCalculator.Calculate(
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ internal static partial class PrimeOrderCalculator
|
|||||||
|
|
||||||
ulong phi = prime - 1UL;
|
ulong phi = prime - 1UL;
|
||||||
|
|
||||||
if (IsGpuHeuristicDevice && PrimeOrderGpuHeuristics.TryCalculateOrder(gpu, prime, previousOrder, config, divisorData, out ulong gpuOrder))
|
if (PrimeOrderGpuHeuristics.TryCalculateOrder(gpu, prime, previousOrder, config, divisorData, out ulong gpuOrder))
|
||||||
|
// if (IsGpuHeuristicDevice && PrimeOrderGpuHeuristics.TryCalculateOrder(gpu, prime, previousOrder, config, divisorData, out ulong gpuOrder))
|
||||||
{
|
{
|
||||||
return gpuOrder;
|
return gpuOrder;
|
||||||
}
|
}
|
||||||
@@ -567,7 +568,6 @@ internal static partial class PrimeOrderCalculator
|
|||||||
|
|
||||||
// DebugLog(() => $"Checking candidates ({candidateCount} candidates, {powBudget} pow budget)");
|
// DebugLog(() => $"Checking candidates ({candidateCount} candidates, {powBudget} pow budget)");
|
||||||
int index = 0;
|
int index = 0;
|
||||||
const int MaxGpuBatchSize = 256;
|
|
||||||
const int StackGpuBatchSize = 64;
|
const int StackGpuBatchSize = 64;
|
||||||
Span<ulong> stackGpuRemainders = stackalloc ulong[StackGpuBatchSize];
|
Span<ulong> stackGpuRemainders = stackalloc ulong[StackGpuBatchSize];
|
||||||
ArrayPool<ulong> pool = ThreadStaticPools.UlongPool;
|
ArrayPool<ulong> pool = ThreadStaticPools.UlongPool;
|
||||||
@@ -575,7 +575,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
{
|
{
|
||||||
int remaining = candidateCount - index;
|
int remaining = candidateCount - index;
|
||||||
int budgetRemaining = powBudget - powUsed;
|
int budgetRemaining = powBudget - powUsed;
|
||||||
int batchSize = Math.Min(remaining, Math.Min(budgetRemaining, MaxGpuBatchSize));
|
int batchSize = Math.Min(remaining, Math.Min(budgetRemaining, PrimeOrderConstants.MaxGpuBatchSize));
|
||||||
if (batchSize <= 0)
|
if (batchSize <= 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@@ -593,7 +593,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
if (batchSize <= StackGpuBatchSize)
|
if (batchSize <= StackGpuBatchSize)
|
||||||
{
|
{
|
||||||
Span<ulong> localRemainders = stackGpuRemainders[..batchSize];
|
Span<ulong> localRemainders = stackGpuRemainders[..batchSize];
|
||||||
status = PrimeOrderGpuHeuristics.TryPow2ModBatch(batch, prime, localRemainders, divisorData);
|
status = PrimeOrderGpuHeuristics.TryPow2ModBatch(gpu, batch, prime, localRemainders, divisorData);
|
||||||
if (status == GpuPow2ModStatus.Success)
|
if (status == GpuPow2ModStatus.Success)
|
||||||
{
|
{
|
||||||
gpuSuccess = true;
|
gpuSuccess = true;
|
||||||
@@ -604,7 +604,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
{
|
{
|
||||||
gpuPool = pool.Rent(batchSize);
|
gpuPool = pool.Rent(batchSize);
|
||||||
Span<ulong> pooledRemainders = gpuPool.AsSpan(0, batchSize);
|
Span<ulong> pooledRemainders = gpuPool.AsSpan(0, batchSize);
|
||||||
status = PrimeOrderGpuHeuristics.TryPow2ModBatch(batch, prime, pooledRemainders, divisorData);
|
status = PrimeOrderGpuHeuristics.TryPow2ModBatch(gpu, batch, prime, pooledRemainders, divisorData);
|
||||||
if (status == GpuPow2ModStatus.Success)
|
if (status == GpuPow2ModStatus.Success)
|
||||||
{
|
{
|
||||||
pooledGpuRemainders = pooledRemainders;
|
pooledGpuRemainders = pooledRemainders;
|
||||||
@@ -1086,7 +1086,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return PartialFactorResult.Empty;
|
return PartialFactorResult.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int FactorSlotCount = GpuSmallPrimeFactorSlots;
|
const int FactorSlotCount = PrimeOrderConstants.GpuSmallPrimeFactorSlots;
|
||||||
|
|
||||||
// stackalloc is faster than pooling
|
// stackalloc is faster than pooling
|
||||||
// ulong[] primeSlotsArray = ThreadStaticPools.UlongPool.Rent(FactorSlotCount);
|
// ulong[] primeSlotsArray = ThreadStaticPools.UlongPool.Rent(FactorSlotCount);
|
||||||
@@ -1176,7 +1176,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
// bool isPrime = HeuristicCombinedPrimeTester.IsPrimeCpu(composite);
|
// bool isPrime = HeuristicCombinedPrimeTester.IsPrimeCpu(composite);
|
||||||
// bool isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite);
|
// bool isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite);
|
||||||
bool runOnGpu = RunOnGpu();
|
bool runOnGpu = RunOnGpu();
|
||||||
bool isPrime = !runOnGpu ? PrimeTester.IsPrime(composite) : HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite);
|
bool isPrime = !runOnGpu ? HeuristicCombinedPrimeTester.IsPrimeCpu(composite) : HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite);
|
||||||
// bool isPrime = PrimeTester.IsPrime(composite);
|
// bool isPrime = PrimeTester.IsPrime(composite);
|
||||||
// bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite);
|
// bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite);
|
||||||
|
|
||||||
@@ -1252,7 +1252,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
|
|
||||||
bool isPrime = RunOnGpu()
|
bool isPrime = RunOnGpu()
|
||||||
? HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite)
|
? HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite)
|
||||||
: PrimeTester.IsPrime(composite);
|
: HeuristicCombinedPrimeTester.IsPrimeCpu(composite);
|
||||||
// bool isPrime = PrimeTester.IsPrime(composite);
|
// 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);
|
||||||
@@ -1297,7 +1297,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
// cofactorIsPrime = PrimeTester.IsPrimeGpu(gpu, cofactor);
|
// cofactorIsPrime = PrimeTester.IsPrimeGpu(gpu, cofactor);
|
||||||
cofactorIsPrime = RunOnGpu()
|
cofactorIsPrime = RunOnGpu()
|
||||||
? HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, cofactor)
|
? HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, cofactor)
|
||||||
: PrimeTester.IsPrime(cofactor);
|
: HeuristicCombinedPrimeTester.IsPrimeCpu(cofactor);
|
||||||
// cofactorIsPrime = PrimeTester.IsPrime(cofactor);
|
// cofactorIsPrime = PrimeTester.IsPrime(cofactor);
|
||||||
// cofactorIsPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(cofactor);
|
// cofactorIsPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(cofactor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,20 +36,21 @@ internal static partial class PrimeOrderCalculator
|
|||||||
|
|
||||||
ulong order = phi;
|
ulong order = phi;
|
||||||
var acceleratorIndex = gpu.AcceleratorIndex;
|
var acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
|
var kernel = gpu.CheckFactorsKernel;
|
||||||
|
|
||||||
gpu.EnsureCapacity(entryCount, 1);
|
gpu.EnsureCapacity(entryCount, 1);
|
||||||
|
var pow2ModEntriesToTestOnDeviceView = gpu.Pow2ModEntriesToTestOnDeviceView;
|
||||||
|
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
gpu.Pow2ModEntriesToTestOnDevice.View.CopyFromCPU(stream, entries);
|
pow2ModEntriesToTestOnDeviceView.CopyFromCPU(stream, entries);
|
||||||
|
|
||||||
// var kernelLauncher = gpu.CheckFactorsKernelLauncher;
|
kernel.Launch(stream, 1, entryCount, phi, pow2ModEntriesToTestOnDeviceView, divisorData.Modulus, divisorData.NPrime, divisorData.MontgomeryOne, divisorData.MontgomeryTwo, divisorData.MontgomeryTwoSquared, gpu.OutputUlongView);
|
||||||
var kernel = gpu.CheckFactorsKernel;
|
|
||||||
kernel.Launch(stream, 1, entryCount, phi, gpu.Pow2ModEntriesToTestOnDevice.View, divisorData.Modulus, divisorData.NPrime, divisorData.MontgomeryOne, divisorData.MontgomeryTwo, divisorData.MontgomeryTwoSquared, gpu.OutputUlong.View);
|
|
||||||
|
|
||||||
gpu.OutputUlong.View.CopyToCPU(stream, ref order, 1);
|
gpu.OutputUlongView.CopyToCPU(stream, ref order, 1);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
|
||||||
|
|
||||||
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
// GpuPrimeWorkLimiter.Release();
|
// GpuPrimeWorkLimiter.Release();
|
||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
@@ -67,10 +68,10 @@ internal static partial class PrimeOrderCalculator
|
|||||||
var accelerator = gpu.Accelerator;
|
var accelerator = gpu.Accelerator;
|
||||||
|
|
||||||
var kernelLauncher = gpu.SmallPrimeFactorKernelLauncher;
|
var kernelLauncher = gpu.SmallPrimeFactorKernelLauncher;
|
||||||
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorCountSlotView = gpu.SmallPrimeFactorCountSlot.View;
|
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorCountSlotView = gpu.OutputIntView2;
|
||||||
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorRemainingSlotView = gpu.Input.View;
|
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorRemainingSlotView = gpu.InputView;
|
||||||
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorPrimeSlotsView = gpu.OutputUlong.View;
|
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorPrimeSlotsView = gpu.OutputUlongView;
|
||||||
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorExponentSlotsView = gpu.OutputInt.View;
|
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorExponentSlotsView = gpu.OutputIntView;
|
||||||
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorsSquaresView = gpu.SmallPrimeFactorSquares;
|
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorsSquaresView = gpu.SmallPrimeFactorSquares;
|
||||||
ArrayView1D<uint, Stride1D.Dense> smallPrimeFactorsPrimesView = gpu.SmallPrimeFactorPrimes;
|
ArrayView1D<uint, Stride1D.Dense> smallPrimeFactorsPrimesView = gpu.SmallPrimeFactorPrimes;
|
||||||
|
|
||||||
@@ -128,18 +129,17 @@ internal static partial class PrimeOrderCalculator
|
|||||||
in MontgomeryDivisorData divisorData)
|
in MontgomeryDivisorData divisorData)
|
||||||
{
|
{
|
||||||
int factorCount = factors.Length;
|
int factorCount = factors.Length;
|
||||||
gpu.EnsureSpecialMaxFactorsCapacity(factorCount);
|
gpu.EnsureUlongInputOutputCapacity(factorCount);
|
||||||
|
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
ArrayView1D<ulong, Stride1D.Dense> specialMaxFactorsView = gpu.Input.View;
|
ArrayView1D<ulong, Stride1D.Dense> specialMaxFactorsView = gpu.InputView;
|
||||||
|
ArrayView1D<ulong, Stride1D.Dense> specialMaxResultView = gpu.OutputUlongView2;
|
||||||
|
var kernelLauncher = gpu.SpecialMaxKernelLauncher;
|
||||||
|
|
||||||
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
specialMaxFactorsView.SubView(0, factorCount).CopyFromCPU(stream, factors);
|
specialMaxFactorsView.SubView(0, factorCount).CopyFromCPU(stream, factors);
|
||||||
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> specialMaxResultView = gpu.SpecialMaxResult.View;
|
|
||||||
|
|
||||||
var kernelLauncher = gpu.SpecialMaxKernelLauncher;
|
|
||||||
kernelLauncher(
|
kernelLauncher(
|
||||||
stream,
|
stream,
|
||||||
1,
|
1,
|
||||||
@@ -147,7 +147,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
specialMaxFactorsView,
|
specialMaxFactorsView,
|
||||||
factorCount,
|
factorCount,
|
||||||
divisorData.Modulus,
|
divisorData.Modulus,
|
||||||
gpu.OutputUlong.View,
|
gpu.OutputUlongView,
|
||||||
specialMaxResultView);
|
specialMaxResultView);
|
||||||
|
|
||||||
ulong result = 0UL;
|
ulong result = 0UL;
|
||||||
@@ -168,16 +168,16 @@ internal static partial class PrimeOrderCalculator
|
|||||||
Span<ulong> factorSpan = stackalloc ulong[1];
|
Span<ulong> factorSpan = stackalloc ulong[1];
|
||||||
|
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
|
||||||
gpu.Input.View.CopyFromCPU(stream, randomStateSpan);
|
|
||||||
|
|
||||||
var kernel = gpu.PollardRhoKernel;
|
var kernel = gpu.PollardRhoKernel;
|
||||||
|
|
||||||
kernel.Launch(stream, 1, n, 1, gpu.Input.View, gpu.OutputByte.View, gpu.OutputUlong.View);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
|
gpu.InputView.CopyFromCPU(stream, randomStateSpan);
|
||||||
|
|
||||||
gpu.OutputByte.View.CopyToCPU(stream, factoredSpan);
|
kernel.Launch(stream, 1, n, 1, gpu.InputView, gpu.OutputByteView, gpu.OutputUlongView);
|
||||||
gpu.OutputUlong.View.CopyToCPU(stream, factorSpan);
|
|
||||||
gpu.Input.View.CopyToCPU(stream, randomStateSpan);
|
gpu.OutputByteView.CopyToCPU(stream, factoredSpan);
|
||||||
|
gpu.OutputUlongView.CopyToCPU(stream, factorSpan);
|
||||||
|
gpu.InputView.CopyToCPU(stream, randomStateSpan);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
|
|||||||
@@ -1042,7 +1042,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
{
|
{
|
||||||
ulong prime64 = (ulong)modulus;
|
ulong prime64 = (ulong)modulus;
|
||||||
ulong exponent64 = (ulong)exponent;
|
ulong exponent64 = (ulong)exponent;
|
||||||
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2Mod(exponent64, prime64, out ulong remainder, divisorData);
|
GpuPow2ModStatus status = PrimeOrderGpuHeuristics.TryPow2Mod(gpu, exponent64, prime64, out ulong remainder, divisorData);
|
||||||
if (status == GpuPow2ModStatus.Success)
|
if (status == GpuPow2ModStatus.Success)
|
||||||
{
|
{
|
||||||
return remainder;
|
return remainder;
|
||||||
|
|||||||
@@ -91,10 +91,8 @@ 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.Input;
|
var inputView = gpu.InputView;
|
||||||
var inputView = input.View;
|
var outputView = gpu.OutputByteView;
|
||||||
var output = gpu.OutputByte;
|
|
||||||
var outputView = output.View;
|
|
||||||
|
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
@@ -156,10 +154,8 @@ public sealed class PrimeTester
|
|||||||
int totalLength = values.Length;
|
int totalLength = values.Length;
|
||||||
int batchSize = GpuBatchSize;
|
int batchSize = GpuBatchSize;
|
||||||
|
|
||||||
var input = gpu.Input;
|
var inputView = gpu.InputView;
|
||||||
var output = gpu.OutputByte;
|
var outputView = gpu.OutputByteView;
|
||||||
var inputView = input.View;
|
|
||||||
var outputView = output.View;
|
|
||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
@@ -235,16 +231,16 @@ public sealed class PrimeTester
|
|||||||
|
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
gpu.EnsureCapacity(0, length);
|
gpu.EnsureCapacity(0, length);
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense>? inputBuffer = gpu.Input;
|
var inputBufferView = gpu.InputView;
|
||||||
|
var resultBufferView = gpu.OutputByteView;
|
||||||
|
var kernelLauncher = gpu.SharesFactorKernelLauncher;
|
||||||
|
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
inputBuffer.View.CopyFromCPU(stream, values);
|
inputBufferView.CopyFromCPU(stream, values);
|
||||||
|
|
||||||
MemoryBuffer1D<byte, Stride1D.Dense>? resultBuffer = gpu.OutputByte;
|
kernelLauncher(stream, length, inputBufferView, resultBufferView);
|
||||||
var kernelLauncher = gpu.SharesFactorKernelLauncher;
|
|
||||||
kernelLauncher(stream, length, inputBuffer.View, resultBuffer.View);
|
|
||||||
|
|
||||||
resultBuffer.View.CopyToCPU(stream, in results);
|
resultBufferView.CopyToCPU(stream, in results);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
|
|||||||
Reference in new issue
Block a user