GpuPrimeWorkLimiter.Acquire() / .Release() removed to save time on the hot-path with billions of calls. We'll rely on AcceleratorStreamPool limits and synchronization.
This commit is contained in:
1 parent
1552e10ff0
commit
0d2a88c45f
17 files changed
+108
-124
No files matched your search
@@ -365,7 +365,7 @@ public class GpuKernelCompilationTests
|
||||
{
|
||||
stream.Synchronize();
|
||||
stream.Dispose();
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
}
|
||||
|
||||
stream = accelerator.CreateStream();
|
||||
@@ -383,7 +383,7 @@ public class GpuKernelCompilationTests
|
||||
{
|
||||
stream.Synchronize();
|
||||
stream.Dispose();
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,8 +41,9 @@ public sealed class DivisorCycleCache
|
||||
private DivisorCycleCache(int divisorCyclesBatchSize)
|
||||
{
|
||||
_divisorCyclesBatchSize = Math.Max(1, divisorCyclesBatchSize);
|
||||
_accelerator = SharedGpuContext.Device.CreateAccelerator(SharedGpuContext.Context);
|
||||
_gpuKernel = LoadKernel(_accelerator);
|
||||
var accelerator = AcceleratorPool.Shared.Rent();
|
||||
_accelerator = accelerator;
|
||||
_gpuKernel = LoadKernel(accelerator);
|
||||
_snapshot = MersenneDivisorCycles.Shared.ExportSmallCyclesSnapshot();
|
||||
}
|
||||
|
||||
@@ -83,7 +84,6 @@ public sealed class DivisorCycleCache
|
||||
throw new InvalidDataException($"Divisor cycle is missing for {divisor}");
|
||||
}
|
||||
|
||||
// ObserveCycleCacheDivisor(divisor);
|
||||
return cached;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,6 @@ public sealed class DivisorCycleCache
|
||||
throw new InvalidDataException($"Divisor cycle is missing for {divisor}");
|
||||
}
|
||||
|
||||
// ObserveCycleCacheDivisor(divisor);
|
||||
cycles[i] = cached;
|
||||
}
|
||||
else
|
||||
@@ -257,18 +256,15 @@ public sealed class DivisorCycleCache
|
||||
powBuffer!.Dispose();
|
||||
orderBuffer!.Dispose();
|
||||
resultBuffer!.Dispose();
|
||||
statusBuffer!.Dispose();
|
||||
statusBuffer!.Dispose();
|
||||
}
|
||||
|
||||
Accelerator accelerator = _accelerator;
|
||||
// lock(accelerator)
|
||||
{
|
||||
divisorBuffer = accelerator.Allocate1D<ulong>(requiredCapacity);
|
||||
powBuffer = accelerator.Allocate1D<ulong>(requiredCapacity);
|
||||
orderBuffer = accelerator.Allocate1D<ulong>(requiredCapacity);
|
||||
resultBuffer = accelerator.Allocate1D<ulong>(requiredCapacity);
|
||||
statusBuffer = accelerator.Allocate1D<byte>(requiredCapacity);
|
||||
}
|
||||
divisorBuffer = accelerator.Allocate1D<ulong>(requiredCapacity);
|
||||
powBuffer = accelerator.Allocate1D<ulong>(requiredCapacity);
|
||||
orderBuffer = accelerator.Allocate1D<ulong>(requiredCapacity);
|
||||
resultBuffer = accelerator.Allocate1D<ulong>(requiredCapacity);
|
||||
statusBuffer = accelerator.Allocate1D<byte>(requiredCapacity);
|
||||
}
|
||||
|
||||
private void ComputeCyclesGpuCore(ReadOnlySpan<ulong> divisors, Span<ulong> destination)
|
||||
@@ -312,8 +308,10 @@ public sealed class DivisorCycleCache
|
||||
statusSpan[i] = ByteZero;
|
||||
}
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
var stream = AcceleratorStreamPool.Rent(_accelerator);// accelerator.CreateStream();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
int pending;
|
||||
var kernel = _gpuKernel;
|
||||
var stream = AcceleratorStreamPool.Rent(_accelerator);
|
||||
|
||||
divisorBuffer!.View.CopyFromCPU(stream, divisors);
|
||||
powBuffer!.View.CopyFromCPU(stream, powSpan);
|
||||
@@ -321,8 +319,6 @@ public sealed class DivisorCycleCache
|
||||
resultBuffer!.View.CopyFromCPU(stream, resultSpan);
|
||||
statusBuffer!.View.CopyFromCPU(stream, statusSpan);
|
||||
|
||||
int pending;
|
||||
var kernel = _gpuKernel;
|
||||
do
|
||||
{
|
||||
kernel(stream, length, _divisorCyclesBatchSize, divisorBuffer.View, powBuffer.View, orderBuffer.View, resultBuffer.View, statusBuffer.View);
|
||||
@@ -341,7 +337,7 @@ public sealed class DivisorCycleCache
|
||||
}
|
||||
while (pending > 0);
|
||||
|
||||
resultBuffer.View.CopyToCPU(stream,resultSpan);
|
||||
resultBuffer.View.CopyToCPU(stream, resultSpan);
|
||||
stream.Synchronize();
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
|
||||
@@ -354,7 +350,7 @@ public sealed class DivisorCycleCache
|
||||
ThreadStaticPools.BytePool.Return(rentedStatus!, clearArray: false);
|
||||
}
|
||||
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
}
|
||||
|
||||
private static Action<AcceleratorStream, Index1D, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>> LoadKernel(Accelerator accelerator)
|
||||
|
||||
@@ -280,13 +280,13 @@ public class GpuKernelPool
|
||||
/// <param name="action">Action to run with (Accelerator, Stream).</param>
|
||||
public static void Run(Action<Accelerator, AcceleratorStream> action)
|
||||
{
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
var accelerator = SharedGpuContext.CreateAccelerator();
|
||||
var stream = accelerator.CreateStream();
|
||||
action(accelerator, stream);
|
||||
stream.Synchronize();
|
||||
stream.Dispose();
|
||||
accelerator.Dispose();
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
||||
ulong processedCount;
|
||||
ulong lastProcessed;
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter();
|
||||
var accelerator = AcceleratorPool.Shared.Rent();
|
||||
var stream = accelerator.CreateStream();
|
||||
|
||||
@@ -137,7 +137,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
||||
stream.Dispose();
|
||||
ReturnBatchResources(resources);
|
||||
// Monitor.Exit(gpuLease.ExecutionLock);
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
|
||||
if (composite)
|
||||
{
|
||||
@@ -509,7 +509,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
||||
internal DivisorScanSession(MersenneNumberDivisorByDivisorGpuTester owner)
|
||||
{
|
||||
_owner = owner;
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
Accelerator accelerator = AcceleratorPool.Shared.Rent();
|
||||
_accelerator = accelerator;
|
||||
_stream = accelerator.CreateStream();
|
||||
|
||||
@@ -16,7 +16,7 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
|
||||
{
|
||||
throw new NotImplementedException($"GPU incremental scanning requires the device cycle heuristics implementation (kernel: {_kernelType}, GPU order: {_useGpuOrder}).");
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
var accelerator = AcceleratorPool.Shared.Rent();
|
||||
var stream = accelerator.CreateStream();
|
||||
int batchSize = GpuConstants.ScanBatchSize; // large batch improves GPU occupancy
|
||||
@@ -125,6 +125,6 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
|
||||
stream.Dispose();
|
||||
ulongPool.Return(orderArray);
|
||||
orderBuffer.Dispose();
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
}
|
||||
}
|
||||
@@ -159,7 +159,7 @@ public class MersenneNumberLucasLehmerGpuTester
|
||||
}
|
||||
else
|
||||
{
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
var accelerator = AcceleratorPool.Shared.Rent();
|
||||
var stream = accelerator.CreateStream();
|
||||
var modulus = new GpuUInt128(((UInt128)1 << (int)exponent) - 1UL); // TODO: Cache these Mersenne moduli per exponent so LL GPU runs skip rebuilding them every launch.
|
||||
@@ -173,7 +173,7 @@ public class MersenneNumberLucasLehmerGpuTester
|
||||
stream.Dispose();
|
||||
}
|
||||
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
|
||||
|
||||
public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
|
||||
{
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
// var accelerator = SharedGpuContext.Accelerator;
|
||||
var accelerator = AcceleratorPool.Shared.Rent();
|
||||
var stream = accelerator.CreateStream();
|
||||
@@ -71,6 +71,6 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
|
||||
|
||||
stream.Dispose();
|
||||
foundBuffer.Dispose();
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
||||
// GPU residue variant: check 2^p % q == 1 for q = 2*p*k + 1.
|
||||
public void Scan(ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
|
||||
{
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
var accelerator = AcceleratorPool.Shared.Rent();
|
||||
|
||||
// Monitor.Enter(gpuLease.ExecutionLock);
|
||||
@@ -110,7 +110,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
||||
stream.Dispose();
|
||||
// Monitor.Exit(gpuLease.ExecutionLock);
|
||||
gpuKernels.Dispose();
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
}
|
||||
|
||||
private static Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> GetPow2ModKernel(Accelerator accelerator)
|
||||
|
||||
@@ -10,28 +10,29 @@ public static class Pow2MontgomeryGpuCalculator
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ulong CalculateKeep(ulong exponent, in MontgomeryDivisorData divisor)
|
||||
{
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
|
||||
ulong result = 0UL;
|
||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||
Accelerator? accelerator = gpu.Accelerator;
|
||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator);
|
||||
MemoryBuffer1D<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
|
||||
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
||||
var kernel = gpu.KeepMontgomeryKernel;
|
||||
|
||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator);
|
||||
|
||||
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
|
||||
// We don't need to worry about any left-overs here.
|
||||
// resultBuffer.MemSetToZero(stream);
|
||||
|
||||
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
||||
var kernel = gpu.KeepMontgomeryKernel;
|
||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||
|
||||
kernelLauncher(stream, 1, exponentBuffer.View, divisor, resultBuffer.View);
|
||||
|
||||
ulong result = 0UL;
|
||||
resultBuffer.View.CopyToCPU(stream, ref result, 1);
|
||||
stream.Synchronize();
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
|
||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||
return result;
|
||||
@@ -40,50 +41,48 @@ public static class Pow2MontgomeryGpuCalculator
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ulong CalculateConvert(ulong exponent, in MontgomeryDivisorData divisor)
|
||||
{
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
|
||||
ulong result = 0UL;
|
||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
||||
MemoryBuffer1D<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
|
||||
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
||||
|
||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
||||
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
|
||||
// We don't need to worry about any left-overs here.
|
||||
// resultBuffer.MemSetToZero(stream);
|
||||
|
||||
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
||||
var kernel = gpu.ConvertToStandardKernel;
|
||||
|
||||
kernel.Launch(stream, 1, 1, exponentBuffer.View, divisor, resultBuffer.View);
|
||||
|
||||
ulong result = 0UL;
|
||||
resultBuffer.View.CopyToCPU(stream, ref result, 1);
|
||||
stream.Synchronize();
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ulong CalculateConvert(PrimeOrderCalculatorAccelerator gpu, ulong exponent, in MontgomeryDivisorData divisor)
|
||||
{
|
||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
||||
ulong result = 0UL;
|
||||
MemoryBuffer1D<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
|
||||
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
||||
var kernel = gpu.ConvertToStandardKernel;
|
||||
|
||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
||||
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
|
||||
// We don't need to worry about any left-overs here.
|
||||
// resultBuffer.MemSetToZero(stream);
|
||||
|
||||
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
||||
var kernel = gpu.ConvertToStandardKernel;
|
||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||
|
||||
kernelLauncher(stream, 1,exponentBuffer.View, divisor, resultBuffer.View);
|
||||
|
||||
ulong result = 0UL;
|
||||
resultBuffer.View.CopyToCPU(stream, ref result, 1);
|
||||
stream.Synchronize();
|
||||
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
|
||||
return result;
|
||||
|
||||
@@ -225,7 +225,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
||||
|
||||
try
|
||||
{
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
Accelerator accelerator = AcceleratorPool.Shared.Rent();
|
||||
AcceleratorStream stream = accelerator.CreateStream();
|
||||
|
||||
@@ -290,7 +290,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
||||
countBuffer.Dispose();
|
||||
remainingBuffer.Dispose();
|
||||
fullyFactoredBuffer.Dispose();
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
return true;
|
||||
}
|
||||
catch (CLException ex)
|
||||
@@ -402,7 +402,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
||||
{
|
||||
order = 0UL;
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
Accelerator accelerator = AcceleratorPool.Shared.Rent();
|
||||
AcceleratorStream stream = accelerator.CreateStream();
|
||||
|
||||
@@ -494,7 +494,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
||||
stackProductBuffer.Dispose();
|
||||
resultBuffer.Dispose();
|
||||
statusBuffer.Dispose();
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
|
||||
PrimeOrderKernelStatus kernelStatus = (PrimeOrderKernelStatus)status;
|
||||
if (kernelStatus == PrimeOrderKernelStatus.Fallback)
|
||||
@@ -574,7 +574,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
||||
|
||||
private static bool TryComputeOnGpu(ReadOnlySpan<ulong> exponents, ulong prime, in MontgomeryDivisorData divisorData, Span<ulong> results)
|
||||
{
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
Accelerator accelerator = AcceleratorPool.Shared.Rent();
|
||||
AcceleratorStream? stream = accelerator.CreateStream();
|
||||
// TODO: These buffers should be allocated once per accelerator and only reallocated when the new length exceeds capacity.
|
||||
@@ -604,7 +604,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
||||
stream = null;
|
||||
exponentBuffer.Dispose();
|
||||
remainderBuffer.Dispose();
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -612,7 +612,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
||||
stream?.Dispose();
|
||||
exponentBuffer.Dispose();
|
||||
remainderBuffer.Dispose();
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -638,7 +638,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
||||
|
||||
GpuUInt128[]? rentedExponents = null;
|
||||
GpuUInt128[]? rentedResults = null;
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
ArrayPool<GpuUInt128> gpuUInt128Pool = ThreadStaticPools.GpuUInt128Pool;
|
||||
|
||||
try
|
||||
@@ -704,7 +704,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
||||
gpuUInt128Pool.Return(rentedResults!, clearArray: false);
|
||||
}
|
||||
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -224,11 +224,11 @@ public sealed class HeuristicCombinedPrimeTester
|
||||
|
||||
private static bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10)
|
||||
{
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
var gpu = HeuristicPrimeTesterAccelerator.Rent(1);
|
||||
var accelerator = gpu.Accelerator;
|
||||
var stream = gpu.Stream;
|
||||
var kernel = HeuristicPrimeTesterAccelerator.GetHeuristicTrialDivisionKernel(accelerator);
|
||||
var kernel = HeuristicPrimeTesterAccelerator.HeuristicTrialDivisionKernel;
|
||||
var flagView1D = gpu.HeuristicFlag.View;
|
||||
var flagView = flagView1D.AsContiguous();
|
||||
|
||||
@@ -251,7 +251,7 @@ public sealed class HeuristicCombinedPrimeTester
|
||||
flagView1D.CopyToCPU(stream, ref compositeFlag, 1);
|
||||
stream.Synchronize();
|
||||
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
|
||||
compositeDetected = compositeFlag != 0;
|
||||
HeuristicPrimeTesterAccelerator.Return(gpu);
|
||||
|
||||
@@ -241,7 +241,7 @@ public sealed class HeuristicPrimeTester
|
||||
|
||||
private bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10)
|
||||
{
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
var gpu = HeuristicPrimeTesterAccelerator.Rent(1);
|
||||
var accelerator = gpu.Accelerator;
|
||||
var stream = gpu.Stream;
|
||||
@@ -307,7 +307,7 @@ public sealed class HeuristicPrimeTester
|
||||
}
|
||||
|
||||
gpu.Dispose();
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
return compositeDetected;
|
||||
}
|
||||
|
||||
|
||||
@@ -804,7 +804,7 @@ public class MersenneDivisorCycles
|
||||
|
||||
divisors = pool.Rent(count);
|
||||
outCycles = pool.Rent(count);
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
var accelerator = AcceleratorPool.Shared.Rent();
|
||||
var stream = accelerator.CreateStream();
|
||||
|
||||
@@ -897,7 +897,7 @@ public class MersenneDivisorCycles
|
||||
pool.Return(divisors, clearArray: false);
|
||||
pool.Return(outCycles, clearArray: false);
|
||||
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
}
|
||||
|
||||
private static Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> GetDivisorCycleKernel(Accelerator accelerator)
|
||||
|
||||
@@ -147,7 +147,7 @@ public sealed class MersenneNumberTester(
|
||||
|
||||
UInt128[] qs = qsBuffer;
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
var accelerator = AcceleratorPool.Shared.Rent();
|
||||
var stream = accelerator.CreateStream();
|
||||
var orderKernel = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.OrderKernelScan).Order!;
|
||||
@@ -164,11 +164,8 @@ public sealed class MersenneNumberTester(
|
||||
while (offset < idx)
|
||||
{
|
||||
int count = Math.Min(batchSize, idx - offset);
|
||||
// lock (accelerator)
|
||||
{
|
||||
qBuffer = accelerator.Allocate1D<GpuUInt128>(count);
|
||||
orderBuffer = accelerator.Allocate1D<ulong>(count);
|
||||
}
|
||||
qBuffer = accelerator.Allocate1D<GpuUInt128>(count);
|
||||
orderBuffer = accelerator.Allocate1D<ulong>(count);
|
||||
|
||||
// Convert to device-friendly GpuUInt128 on the fly
|
||||
var tmp = gpuUInt128Pool.Rent(count);
|
||||
@@ -204,7 +201,7 @@ public sealed class MersenneNumberTester(
|
||||
}
|
||||
|
||||
stream.Dispose();
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
uInt128Pool.Return(qs);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,30 +91,30 @@ internal static partial class PrimeOrderCalculator
|
||||
return phi;
|
||||
}
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
ulong candidateOrder = InitializeStartingOrderCpu(gpu, prime, phi, divisorData);
|
||||
candidateOrder = ExponentLoweringCpu(candidateOrder, prime, phiFactors, divisorData);
|
||||
|
||||
if (TryConfirmOrderCpu(gpu, prime, candidateOrder, divisorData, config, out PartialFactorResult? orderFactors))
|
||||
{
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
return candidateOrder;
|
||||
}
|
||||
|
||||
if (config.Mode == PrimeOrderMode.Strict)
|
||||
{
|
||||
orderFactors?.Dispose();
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
return CalculateByFactorizationGpu(gpu, prime, divisorData);
|
||||
}
|
||||
|
||||
if (TryHeuristicFinishCpu(gpu, prime, candidateOrder, previousOrder, divisorData, config, phiFactors, orderFactors, out ulong order))
|
||||
{
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
return order;
|
||||
}
|
||||
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
return candidateOrder;
|
||||
}
|
||||
|
||||
@@ -1148,7 +1148,7 @@ internal static partial class PrimeOrderCalculator
|
||||
bool pollardRhoDeadlineReached = Stopwatch.GetTimestamp() > deadlineTimestamp;
|
||||
if (!pollardRhoDeadlineReached)
|
||||
{
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
|
||||
while (compositeStack.Count > 0)
|
||||
{
|
||||
@@ -1200,7 +1200,7 @@ internal static partial class PrimeOrderCalculator
|
||||
pollardRhoDeadlineReached = Stopwatch.GetTimestamp() > deadlineTimestamp;
|
||||
}
|
||||
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
}
|
||||
|
||||
if (pollardRhoDeadlineReached)
|
||||
@@ -1216,7 +1216,7 @@ internal static partial class PrimeOrderCalculator
|
||||
bool cofactorContainsComposite = false;
|
||||
int pendingCount = pending.Count;
|
||||
int index = 0;
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
for (; index < pendingCount; index++)
|
||||
{
|
||||
PendingEntry entry = pending[index];
|
||||
@@ -1280,7 +1280,7 @@ internal static partial class PrimeOrderCalculator
|
||||
// cofactorIsPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(cofactor);
|
||||
}
|
||||
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
|
||||
// ArrayPool<FactorEntry> pool = ThreadStaticPools.FactorEntryPool;
|
||||
bool temp;
|
||||
@@ -1331,19 +1331,14 @@ internal static partial class PrimeOrderCalculator
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// factorsArray[arrayIndex] = new FactorEntry(primeValue, exponentValue, true);
|
||||
factorsArray[arrayIndex] = primeValue;
|
||||
exponentsArray[arrayIndex] = exponentValue;
|
||||
// cofactorIsPrimesArray[arrayIndex] = true;
|
||||
arrayIndex++;
|
||||
}
|
||||
|
||||
// Span<FactorEntry> arraySpan = factorsArray.AsSpan(0, arrayIndex);
|
||||
// Span<ulong> arraySpan = factorsArray.AsSpan(0, arrayIndex);
|
||||
// arraySpan.Sort(static (a, b) => a.CompareTo(b));
|
||||
Array.Sort(factorsArray, exponentsArray, 0, arrayIndex);
|
||||
temp = cofactor == 1UL;
|
||||
// result = PartialFactorResult.Rent(factorsArray, exponentsArray, cofactorIsPrimesArray, cofactor, temp, arrayIndex, cofactorIsPrime);
|
||||
|
||||
result = PartialFactorResult.Rent(factorsArray, exponentsArray, cofactor, temp, arrayIndex, cofactorIsPrime);
|
||||
|
||||
ReturnResult:
|
||||
@@ -1716,7 +1711,7 @@ internal static partial class PrimeOrderCalculator
|
||||
ulong order = phi;
|
||||
int entryCount = entries.Length;
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
for (int i = 0; i < entryCount; i++)
|
||||
{
|
||||
ulong primeFactor = entries[i].Key;
|
||||
@@ -1744,7 +1739,7 @@ internal static partial class PrimeOrderCalculator
|
||||
}
|
||||
}
|
||||
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
return order;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ internal static partial class PrimeOrderCalculator
|
||||
var kernel = gpu.CheckFactorsKernel;
|
||||
gpu.EnsureCapacity(entryCount, 1);
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
||||
gpu.Pow2ModEntriesToTestOnDevice.View.CopyFromCPU(stream, entries);
|
||||
|
||||
@@ -51,7 +51,7 @@ internal static partial class PrimeOrderCalculator
|
||||
stream.Synchronize();
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
return order;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ internal static partial class PrimeOrderCalculator
|
||||
gpu.EnsureSmallPrimeFactorSlotsCapacity(GpuSmallPrimeFactorSlots);
|
||||
var accelerator = gpu.Accelerator;
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
var stream = AcceleratorStreamPool.Rent(accelerator);
|
||||
KernelContainer kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.SmallPrimeFactorKernelScan);
|
||||
SmallPrimeFactorViews tables = GpuKernelPool.GetSmallPrimeFactorTables(kernels);
|
||||
@@ -113,7 +113,7 @@ internal static partial class PrimeOrderCalculator
|
||||
stream.Synchronize();
|
||||
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
|
||||
for (int i = 0; i < factorCount; i++)
|
||||
{
|
||||
@@ -136,7 +136,7 @@ internal static partial class PrimeOrderCalculator
|
||||
gpu.EnsureSpecialMaxFactorsCapacity(factorCount);
|
||||
|
||||
Accelerator accelerator = gpu.Accelerator;
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
var stream = AcceleratorStreamPool.Rent(accelerator);
|
||||
var kernels = GpuKernelPool.GetOrAddKernels(accelerator, stream, KernelType.EvaluateSpecialMaxCandidatesKernel);
|
||||
|
||||
@@ -162,7 +162,7 @@ internal static partial class PrimeOrderCalculator
|
||||
stream.Synchronize();
|
||||
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
@@ -171,11 +171,12 @@ internal static partial class PrimeOrderCalculator
|
||||
Span<ulong> randomStateSpan = stackalloc ulong[1];
|
||||
randomStateSpan[0] = ThreadStaticDeterministicRandomGpu.Exclusive.State;
|
||||
|
||||
Span<byte> factoredSpan = stackalloc byte[1];
|
||||
Span<ulong> factorSpan = stackalloc ulong[1];
|
||||
|
||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
||||
gpu.Input.View.CopyFromCPU(stream, randomStateSpan);
|
||||
|
||||
Span<byte> factoredSpan = stackalloc byte[1];
|
||||
Span<ulong> factorSpan = stackalloc ulong[1];
|
||||
var kernelLauncher = gpu.PollardRhoKernel.CreateLauncherDelegate<Action<AcceleratorStream, ulong, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||
|
||||
kernelLauncher(stream, n, 1, gpu.Input.View, gpu.OutputByte.View, gpu.OutputUlong.View);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Buffers;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using ILGPU;
|
||||
using ILGPU.Runtime;
|
||||
using PerfectNumbers.Core.Gpu;
|
||||
@@ -93,15 +92,15 @@ public sealed class PrimeTester
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsPrimeGpu(ulong n)
|
||||
{
|
||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||
byte flag = 0;
|
||||
|
||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||
var inputView = gpu.PrimeTestInput.View;
|
||||
var outputView = gpu.OutputByte.View;
|
||||
var kernel = gpu.SmallPrimeSieveKernel!;
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(gpu.Accelerator);
|
||||
// var stream = gpu.Stream!;
|
||||
inputView.CopyFromCPU(stream, ref n, 1);
|
||||
|
||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>>();
|
||||
@@ -120,13 +119,12 @@ public sealed class PrimeTester
|
||||
gpu.DevicePrimesPow2LastNine.View,
|
||||
outputView);
|
||||
|
||||
byte flag = 0;
|
||||
outputView.CopyToCPU(stream, ref flag, 1);
|
||||
stream.Synchronize();
|
||||
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
|
||||
return flag != 0;
|
||||
}
|
||||
@@ -134,6 +132,7 @@ public sealed class PrimeTester
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n)
|
||||
{
|
||||
byte flag = 0;
|
||||
var input = gpu.PrimeTestInput;
|
||||
var inputView = input.View;
|
||||
var output = gpu.OutputByte;
|
||||
@@ -159,7 +158,6 @@ public sealed class PrimeTester
|
||||
gpu.DevicePrimesPow2LastNine.View,
|
||||
outputView);
|
||||
|
||||
byte flag = 0;
|
||||
outputView.CopyToCPU(stream, ref flag, 1);
|
||||
stream.Synchronize();
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
@@ -195,7 +193,7 @@ public sealed class PrimeTester
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void IsPrimeBatchGpu(ReadOnlySpan<ulong> values, Span<byte> results)
|
||||
{
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
// GpuPrimeWorkLimiter.Acquire();
|
||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(GpuBatchSize);
|
||||
var accelerator = gpu.Accelerator;
|
||||
var kernel = gpu.SmallPrimeSieveKernel!;
|
||||
@@ -240,7 +238,7 @@ public sealed class PrimeTester
|
||||
stream.Synchronize();
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||
GpuPrimeWorkLimiter.Release();
|
||||
// GpuPrimeWorkLimiter.Release();
|
||||
}
|
||||
|
||||
// Expose cache clearing for accelerator disposal coordination
|
||||
@@ -276,31 +274,27 @@ public sealed class PrimeTester
|
||||
// TODO: Route this batch helper through the shared GPU kernel pool from
|
||||
// GpuUInt128BinaryGcdBenchmarks so we reuse cached kernels, pinned host buffers,
|
||||
// and divisor-cycle staging instead of allocating new device buffers per call.
|
||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||
var accelerator = gpu.Accelerator;
|
||||
// Check in benchmarks, which implementation was the fastest, is compatible with GPU,
|
||||
// and implement it.
|
||||
|
||||
int length = values.Length;
|
||||
ArrayPool<ulong> pool = ThreadStaticPools.UlongPool;
|
||||
ulong[] temp = pool.Rent(length);
|
||||
values.CopyTo(temp);
|
||||
|
||||
MemoryBuffer1D<ulong, Stride1D.Dense>? inputBuffer;
|
||||
MemoryBuffer1D<byte, Stride1D.Dense>? resultBuffer;
|
||||
|
||||
inputBuffer = accelerator.Allocate1D<ulong>(length);
|
||||
resultBuffer = accelerator.Allocate1D<byte>(length);
|
||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||
var accelerator = gpu.Accelerator;
|
||||
gpu.EnsureCapacity(0, length);
|
||||
MemoryBuffer1D<ulong, Stride1D.Dense>? inputBuffer = gpu.PrimeTestInput;
|
||||
MemoryBuffer1D<byte, Stride1D.Dense>? resultBuffer = gpu.OutputByte;
|
||||
|
||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(accelerator);
|
||||
inputBuffer.View.CopyFromCPU(stream, ref temp[0], length);
|
||||
inputBuffer.View.CopyFromCPU(stream, values);
|
||||
|
||||
var kernel = GetSharesFactorKernel(accelerator);
|
||||
kernel(stream, length, inputBuffer.View, resultBuffer.View);
|
||||
resultBuffer.View.CopyToCPU(stream, in results);
|
||||
stream.Synchronize();
|
||||
|
||||
AcceleratorStreamPool.Return(stream);
|
||||
pool.Return(temp, clearArray: false);
|
||||
resultBuffer.Dispose();
|
||||
inputBuffer.Dispose();
|
||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||
}
|
||||
|
||||
@@ -323,6 +317,8 @@ public sealed class PrimeTester
|
||||
// TODO: Swap this handwritten binary GCD for the optimized helper measured in
|
||||
// GpuUInt128BinaryGcdBenchmarks so CPU callers share the faster subtract-less
|
||||
// ladder once the common implementation is promoted into PerfectNumbers.Core.
|
||||
// You have an example in the benchmarks and you already implemented it in
|
||||
// GpuUInt128, iirc.
|
||||
if (u == 0UL)
|
||||
{
|
||||
return v;
|
||||
|
||||
Reference in new issue
Block a user