Various optimizations
This commit is contained in:
1 parent
3147728d5b
commit
4c79c4087e
9 files changed
+51
-101
No files matched your search
@@ -55,7 +55,7 @@ public class ProgramTests
|
|||||||
[InlineData(81UL, false)]
|
[InlineData(81UL, false)]
|
||||||
public void IsPrime_identifies_primes_correctly(ulong n, bool expected)
|
public void IsPrime_identifies_primes_correctly(ulong n, bool expected)
|
||||||
{
|
{
|
||||||
new PrimeTester().IsPrime(n, CancellationToken.None).Should().Be(expected);
|
PrimeTester.IsPrime(n, CancellationToken.None).Should().Be(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -622,7 +622,7 @@ internal static class Program
|
|||||||
if (!_cliArguments.UseByDivisor)
|
if (!_cliArguments.UseByDivisor)
|
||||||
{
|
{
|
||||||
if (!(GpuContextPool.ForceCpu
|
if (!(GpuContextPool.ForceCpu
|
||||||
? PrimeTesters.Value!.IsPrime(p, CancellationToken.None)
|
? PrimeTester.IsPrime(p, CancellationToken.None)
|
||||||
: PrimeTesters.Value!.IsPrimeGpu(p, CancellationToken.None)))
|
: PrimeTesters.Value!.IsPrimeGpu(p, CancellationToken.None)))
|
||||||
{
|
{
|
||||||
_lastCompositeP = true;
|
_lastCompositeP = true;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class PrimeTesterIsPrimeTests
|
|||||||
{
|
{
|
||||||
var tester = new PrimeTester();
|
var tester = new PrimeTester();
|
||||||
|
|
||||||
tester.IsPrime(n, CancellationToken.None).Should().Be(expected);
|
PrimeTester.IsPrime(n, CancellationToken.None).Should().Be(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ namespace PerfectNumbers.Core.Gpu;
|
|||||||
public static class GpuPrimeWorkLimiter
|
public static class GpuPrimeWorkLimiter
|
||||||
{
|
{
|
||||||
private static SemaphoreSlim _semaphore = new(1, int.MaxValue);
|
private static SemaphoreSlim _semaphore = new(1, int.MaxValue);
|
||||||
private static readonly object _lock = new();
|
|
||||||
private static int _currentLimit = 1;
|
private static int _currentLimit = 1;
|
||||||
|
|
||||||
public static Lease Acquire()
|
public static Lease Acquire()
|
||||||
@@ -11,18 +10,11 @@ public static class GpuPrimeWorkLimiter
|
|||||||
// TODO: Inline the pooled limiter guard from the GpuLimiterThroughputBenchmarks so prime-sieve
|
// TODO: Inline the pooled limiter guard from the GpuLimiterThroughputBenchmarks so prime-sieve
|
||||||
// GPU jobs stop allocating Lease instances on every acquisition.
|
// GPU jobs stop allocating Lease instances on every acquisition.
|
||||||
var sem = _semaphore;
|
var sem = _semaphore;
|
||||||
sem.Wait();
|
// sem.Wait();
|
||||||
return new Lease(sem);
|
return new Lease(sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetLimit(int value)
|
public static void SetLimit(int value)
|
||||||
{
|
|
||||||
if (value < 1)
|
|
||||||
{
|
|
||||||
value = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
{
|
||||||
if (value == _currentLimit)
|
if (value == _currentLimit)
|
||||||
{
|
{
|
||||||
@@ -34,7 +26,6 @@ public static class GpuPrimeWorkLimiter
|
|||||||
_semaphore = new SemaphoreSlim(value, value);
|
_semaphore = new SemaphoreSlim(value, value);
|
||||||
_currentLimit = value;
|
_currentLimit = value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class Lease
|
public sealed class Lease
|
||||||
{
|
{
|
||||||
@@ -47,7 +38,7 @@ public static class GpuPrimeWorkLimiter
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_sem.Release();
|
// _sem.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
var gpuLease = RentAccelerator();
|
var gpuLease = RentAccelerator();
|
||||||
var accelerator = gpuLease.Accelerator;
|
var accelerator = gpuLease.Accelerator;
|
||||||
|
|
||||||
Monitor.Enter(gpuLease.ExecutionLock);
|
// Monitor.Enter(gpuLease.ExecutionLock);
|
||||||
|
|
||||||
var kernel = GetKernel(accelerator);
|
var kernel = GetKernel(accelerator);
|
||||||
var resources = RentBatchResources(accelerator, batchCapacity);
|
var resources = RentBatchResources(accelerator, batchCapacity);
|
||||||
@@ -121,7 +121,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
out processedCount);
|
out processedCount);
|
||||||
|
|
||||||
ReturnBatchResources(resources);
|
ReturnBatchResources(resources);
|
||||||
Monitor.Exit(gpuLease.ExecutionLock);
|
// Monitor.Exit(gpuLease.ExecutionLock);
|
||||||
ReturnAccelerator(gpuLease);
|
ReturnAccelerator(gpuLease);
|
||||||
|
|
||||||
if (composite)
|
if (composite)
|
||||||
@@ -560,7 +560,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Monitor.Enter(_lease.ExecutionLock);
|
// Monitor.Enter(_lease.ExecutionLock);
|
||||||
|
|
||||||
EnsureExecutionResourcesLocked(length);
|
EnsureExecutionResourcesLocked(length);
|
||||||
|
|
||||||
@@ -601,7 +601,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
ref byte hitRef = ref MemoryMarshal.GetReference(hitSlice);
|
ref byte hitRef = ref MemoryMarshal.GetReference(hitSlice);
|
||||||
hitView.CopyToCPU(ref hitRef, length);
|
hitView.CopyToCPU(ref hitRef, length);
|
||||||
|
|
||||||
Monitor.Exit(_lease.ExecutionLock);
|
// Monitor.Exit(_lease.ExecutionLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
|||||||
var gpuLease = RentAccelerator();
|
var gpuLease = RentAccelerator();
|
||||||
var accelerator = gpuLease.Accelerator;
|
var accelerator = gpuLease.Accelerator;
|
||||||
|
|
||||||
Monitor.Enter(gpuLease.ExecutionLock);
|
// Monitor.Enter(gpuLease.ExecutionLock);
|
||||||
|
|
||||||
var stream = accelerator.CreateStream();
|
var stream = accelerator.CreateStream();
|
||||||
var kernel = GetPow2ModKernel(accelerator);
|
var kernel = GetPow2ModKernel(accelerator);
|
||||||
@@ -108,7 +108,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
|||||||
|
|
||||||
ReturnResources(accelerator, resources);
|
ReturnResources(accelerator, resources);
|
||||||
stream.Dispose();
|
stream.Dispose();
|
||||||
Monitor.Exit(gpuLease.ExecutionLock);
|
// Monitor.Exit(gpuLease.ExecutionLock);
|
||||||
ReturnAccelerator(gpuLease);
|
ReturnAccelerator(gpuLease);
|
||||||
limiter.Dispose();
|
limiter.Dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,19 +112,16 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static int HeuristicGpuDivisorBatchSize { get; set; } = 4_096;
|
internal static int HeuristicGpuDivisorBatchSize = 4_096;
|
||||||
|
internal static int HeuristicDivisorInterleaveBatchSize = 64;
|
||||||
public static int HeuristicDivisorInterleaveBatchSize { get; set; } = 64;
|
|
||||||
|
|
||||||
[ThreadStatic]
|
[ThreadStatic]
|
||||||
private static HeuristicCombinedPrimeTester? _tester;
|
private static HeuristicCombinedPrimeTester? _tester;
|
||||||
|
|
||||||
public static HeuristicCombinedPrimeTester Exclusive => _tester ??= new();
|
public static HeuristicCombinedPrimeTester Exclusive => _tester ??= new();
|
||||||
|
|
||||||
public bool IsPrimeCpu(ulong n, CancellationToken ct)
|
public static bool IsPrimeCpu(ulong n)
|
||||||
{
|
{
|
||||||
ct.ThrowIfCancellationRequested();
|
|
||||||
|
|
||||||
byte nMod10 = (byte)n.Mod10();
|
byte nMod10 = (byte)n.Mod10();
|
||||||
ulong sqrtLimit = ComputeHeuristicSqrt(n);
|
ulong sqrtLimit = ComputeHeuristicSqrt(n);
|
||||||
|
|
||||||
@@ -136,24 +133,14 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
return HeuristicTrialDivisionCpu(n, sqrtLimit, nMod10);
|
return HeuristicTrialDivisionCpu(n, sqrtLimit, nMod10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsPrimeCpu(ulong n)
|
public static bool IsPrimeGpu(ulong n)
|
||||||
{
|
|
||||||
return IsPrimeCpu(n, CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsPrimeGpu(ulong n)
|
|
||||||
{
|
{
|
||||||
byte nMod10 = (byte)n.Mod10();
|
byte nMod10 = (byte)n.Mod10();
|
||||||
ulong sqrtLimit = ComputeHeuristicSqrt(n);
|
ulong sqrtLimit = ComputeHeuristicSqrt(n);
|
||||||
return IsPrimeGpu(n, sqrtLimit, nMod10);
|
return IsPrimeGpu(n, sqrtLimit, nMod10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsPrimeGpu(ulong n, ulong sqrtLimit, byte nMod10)
|
public static bool IsPrimeGpu(ulong n, ulong sqrtLimit, byte nMod10)
|
||||||
{
|
|
||||||
return HeuristicIsPrimeGpuCore(n, sqrtLimit, nMod10);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool HeuristicIsPrimeGpuCore(ulong n, ulong sqrtLimit, byte nMod10)
|
|
||||||
{
|
{
|
||||||
// TODO: Is this condition ever met on the execution path in EvenPerfectBitScanner?
|
// TODO: Is this condition ever met on the execution path in EvenPerfectBitScanner?
|
||||||
if (sqrtLimit < 3UL)
|
if (sqrtLimit < 3UL)
|
||||||
@@ -161,11 +148,6 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
return EvaluateWithOpenNumericFallback(n);
|
return EvaluateWithOpenNumericFallback(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!UseHeuristicGroupBTrialDivision)
|
|
||||||
{
|
|
||||||
return HeuristicTrialDivisionCpu(n, sqrtLimit, nMod10);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool compositeDetected = HeuristicTrialDivisionGpuDetectsDivisor(n, sqrtLimit, nMod10);
|
bool compositeDetected = HeuristicTrialDivisionGpuDetectsDivisor(n, sqrtLimit, nMod10);
|
||||||
return !compositeDetected;
|
return !compositeDetected;
|
||||||
}
|
}
|
||||||
@@ -196,7 +178,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
return EvaluateWithOpenNumericFallback(n);
|
return EvaluateWithOpenNumericFallback(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong sqrtLimit, byte nMod10)
|
private static bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong sqrtLimit, byte nMod10)
|
||||||
{
|
{
|
||||||
int batchCapacity = Math.Max(1, HeuristicGpuDivisorBatchSize);
|
int batchCapacity = Math.Max(1, HeuristicGpuDivisorBatchSize);
|
||||||
var divisorPool = ThreadStaticPools.UlongPool;
|
var divisorPool = ThreadStaticPools.UlongPool;
|
||||||
@@ -214,8 +196,6 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
bool compositeDetected = false;
|
bool compositeDetected = false;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
lock (gpu.ExecutionLock)
|
|
||||||
{
|
|
||||||
var input = scratch.Input;
|
var input = scratch.Input;
|
||||||
var output = scratch.Output;
|
var output = scratch.Output;
|
||||||
|
|
||||||
@@ -238,11 +218,12 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong divisor = divisorArray[i];
|
|
||||||
if (divisor > 1UL && n % divisor == 0UL)
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
// ulong divisor = divisorArray[i];
|
||||||
|
// if (divisor > 1UL && n % divisor == 0UL)
|
||||||
|
// {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -285,9 +266,6 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
compositeDetected = true;
|
compositeDetected = true;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
|
|||||||
@@ -122,10 +122,10 @@ public sealed class HeuristicPrimeTester
|
|||||||
return EvaluateWithOpenNumericFallback(n);
|
return EvaluateWithOpenNumericFallback(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!UseHeuristicGroupBTrialDivision)
|
// if (!UseHeuristicGroupBTrialDivision)
|
||||||
{
|
// {
|
||||||
return HeuristicTrialDivisionCpu(n, sqrtLimit, nMod10, includeGroupB: false);
|
// return HeuristicTrialDivisionCpu(n, sqrtLimit, nMod10, includeGroupB: false);
|
||||||
}
|
// }
|
||||||
|
|
||||||
bool compositeDetected = HeuristicTrialDivisionGpuDetectsDivisor(n, sqrtLimit, nMod10);
|
bool compositeDetected = HeuristicTrialDivisionGpuDetectsDivisor(n, sqrtLimit, nMod10);
|
||||||
return !compositeDetected;
|
return !compositeDetected;
|
||||||
@@ -260,8 +260,8 @@ public sealed class HeuristicPrimeTester
|
|||||||
|
|
||||||
private bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong sqrtLimit, byte nMod10)
|
private bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong sqrtLimit, byte nMod10)
|
||||||
{
|
{
|
||||||
int batchCapacity = Math.Max(1, HeuristicGpuDivisorBatchSize);
|
int batchCapacity = HeuristicGpuDivisorBatchSize;
|
||||||
int interleaveBatchSize = Math.Max(1, HeuristicDivisorInterleaveBatchSize);
|
int interleaveBatchSize = HeuristicDivisorInterleaveBatchSize;
|
||||||
var divisorPool = ThreadStaticPools.UlongPool;
|
var divisorPool = ThreadStaticPools.UlongPool;
|
||||||
var hitPool = ThreadStaticPools.BytePool;
|
var hitPool = ThreadStaticPools.BytePool;
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@ public sealed class HeuristicPrimeTester
|
|||||||
bool compositeDetected = false;
|
bool compositeDetected = false;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
lock (gpu.ExecutionLock)
|
// lock (gpu.ExecutionLock)
|
||||||
{
|
{
|
||||||
var input = scratch.Input;
|
var input = scratch.Input;
|
||||||
var output = scratch.Output;
|
var output = scratch.Output;
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
using System;
|
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
|
||||||
using ILGPU;
|
using ILGPU;
|
||||||
using ILGPU.Algorithms;
|
|
||||||
using ILGPU.Runtime;
|
using ILGPU.Runtime;
|
||||||
using PerfectNumbers.Core.Gpu;
|
using PerfectNumbers.Core.Gpu;
|
||||||
|
|
||||||
@@ -22,7 +19,7 @@ public sealed class PrimeTester
|
|||||||
|
|
||||||
public static PrimeTester Exclusive => _tester ??= new();
|
public static PrimeTester Exclusive => _tester ??= new();
|
||||||
|
|
||||||
public bool IsPrime(ulong n, CancellationToken ct)
|
public static bool IsPrime(ulong n, CancellationToken ct)
|
||||||
{
|
{
|
||||||
if (n <= 1UL)
|
if (n <= 1UL)
|
||||||
{
|
{
|
||||||
@@ -121,7 +118,7 @@ public sealed class PrimeTester
|
|||||||
public static bool IsPrimeCpu(ulong n, CancellationToken ct)
|
public static bool IsPrimeCpu(ulong n, CancellationToken ct)
|
||||||
{
|
{
|
||||||
// Preserve the legacy entry point for callers that bypass the thread-local caches.
|
// Preserve the legacy entry point for callers that bypass the thread-local caches.
|
||||||
return Exclusive.IsPrime(n, ct);
|
return IsPrime(n, ct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -137,8 +134,6 @@ public sealed class PrimeTester
|
|||||||
int totalLength = values.Length;
|
int totalLength = values.Length;
|
||||||
int batchSize = Math.Max(1, GpuBatchSize);
|
int batchSize = Math.Max(1, GpuBatchSize);
|
||||||
|
|
||||||
lock (gpu.ExecutionLock)
|
|
||||||
{
|
|
||||||
var scratch = state.RentScratch(batchSize, accelerator);
|
var scratch = state.RentScratch(batchSize, accelerator);
|
||||||
var input = scratch.Input;
|
var input = scratch.Input;
|
||||||
var output = scratch.Output;
|
var output = scratch.Output;
|
||||||
@@ -176,7 +171,6 @@ public sealed class PrimeTester
|
|||||||
|
|
||||||
pool.Return(temp, clearArray: false);
|
pool.Return(temp, clearArray: false);
|
||||||
state.ReturnScratch(scratch);
|
state.ReturnScratch(scratch);
|
||||||
}
|
|
||||||
|
|
||||||
gpu.Dispose();
|
gpu.Dispose();
|
||||||
limiter.Dispose();
|
limiter.Dispose();
|
||||||
@@ -190,8 +184,6 @@ public sealed class PrimeTester
|
|||||||
|
|
||||||
public Accelerator Accelerator { get; }
|
public Accelerator Accelerator { get; }
|
||||||
|
|
||||||
public object ExecutionLock { get; } = new();
|
|
||||||
|
|
||||||
private KernelState? _kernelState;
|
private KernelState? _kernelState;
|
||||||
|
|
||||||
public PooledContext()
|
public PooledContext()
|
||||||
@@ -226,7 +218,6 @@ public sealed class PrimeTester
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static readonly ConcurrentQueue<PooledContext> Pool = new();
|
private static readonly ConcurrentQueue<PooledContext> Pool = new();
|
||||||
private static readonly object CreationLock = new();
|
|
||||||
|
|
||||||
internal static PrimeTesterGpuContextLease Rent()
|
internal static PrimeTesterGpuContextLease Rent()
|
||||||
{
|
{
|
||||||
@@ -235,11 +226,8 @@ public sealed class PrimeTester
|
|||||||
return new PrimeTesterGpuContextLease(ctx);
|
return new PrimeTesterGpuContextLease(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (CreationLock)
|
|
||||||
{
|
|
||||||
return new PrimeTesterGpuContextLease(new PooledContext());
|
return new PrimeTesterGpuContextLease(new PooledContext());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
internal static void DisposeAll()
|
internal static void DisposeAll()
|
||||||
{
|
{
|
||||||
@@ -255,22 +243,16 @@ public sealed class PrimeTester
|
|||||||
Pool.Enqueue(ctx);
|
Pool.Enqueue(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal struct PrimeTesterGpuContextLease
|
internal readonly struct PrimeTesterGpuContextLease(PrimeTesterGpuContextPool.PooledContext ctx)
|
||||||
{
|
{
|
||||||
private PooledContext? _ctx;
|
private readonly PooledContext? _ctx = ctx;
|
||||||
|
|
||||||
internal PrimeTesterGpuContextLease(PooledContext ctx)
|
public readonly Accelerator Accelerator => _ctx!.Accelerator;
|
||||||
{
|
|
||||||
_ctx = ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Accelerator Accelerator => _ctx!.Accelerator;
|
|
||||||
|
|
||||||
public object ExecutionLock => _ctx!.ExecutionLock;
|
public readonly KernelState State => _ctx!.KernelState;
|
||||||
|
|
||||||
public KernelState State => _ctx!.KernelState;
|
public readonly void Dispose()
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
{
|
||||||
Return(_ctx ?? throw new InvalidOperationException("GPU context lease is not initialized."));
|
Return(_ctx ?? throw new InvalidOperationException("GPU context lease is not initialized."));
|
||||||
}
|
}
|
||||||
@@ -280,20 +262,20 @@ public sealed class PrimeTester
|
|||||||
// Per-accelerator GPU state for prime sieve (kernel + uploaded primes).
|
// Per-accelerator GPU state for prime sieve (kernel + uploaded primes).
|
||||||
internal sealed class KernelState
|
internal sealed class KernelState
|
||||||
{
|
{
|
||||||
public Action<Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>> Kernel { get; }
|
public Action<Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>> Kernel;
|
||||||
public Action<Index1D, ArrayView<ulong>, ulong, ArrayView<byte>> HeuristicTrialDivisionKernel { get; }
|
public Action<Index1D, ArrayView<ulong>, ulong, ArrayView<byte>> HeuristicTrialDivisionKernel;
|
||||||
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesDefault { get; }
|
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesDefault;
|
||||||
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastOne { get; }
|
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastOne;
|
||||||
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastSeven { get; }
|
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastSeven;
|
||||||
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastThree { get; }
|
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastThree;
|
||||||
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastNine { get; }
|
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastNine;
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2Default { get; }
|
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2Default;
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastOne { get; }
|
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastOne;
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastSeven { get; }
|
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastSeven;
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastThree { get; }
|
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastThree;
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastNine { get; }
|
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastNine;
|
||||||
public bool IsDisposed { get; private set; }
|
public bool IsDisposed;
|
||||||
private readonly System.Collections.Concurrent.ConcurrentBag<ScratchBuffers> _scratchPool = [];
|
private readonly ConcurrentBag<ScratchBuffers> _scratchPool = [];
|
||||||
// TODO: Replace this ConcurrentBag with the lock-free ring buffer variant validated in
|
// TODO: Replace this ConcurrentBag with the lock-free ring buffer variant validated in
|
||||||
// GpuModularArithmeticBenchmarks so renting scratch buffers stops contending on the bag's internal locks when
|
// GpuModularArithmeticBenchmarks so renting scratch buffers stops contending on the bag's internal locks when
|
||||||
// thousands of GPU batches execute per second.
|
// thousands of GPU batches execute per second.
|
||||||
@@ -369,7 +351,6 @@ public sealed class PrimeTester
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public ScratchBuffers RentScratch(int minCapacity, Accelerator accel)
|
public ScratchBuffers RentScratch(int minCapacity, Accelerator accel)
|
||||||
{
|
{
|
||||||
minCapacity = Math.Max(1, minCapacity);
|
|
||||||
while (_scratchPool.TryTake(out var sb))
|
while (_scratchPool.TryTake(out var sb))
|
||||||
{
|
{
|
||||||
if (sb.Capacity >= minCapacity)
|
if (sb.Capacity >= minCapacity)
|
||||||
@@ -428,7 +409,7 @@ public sealed class PrimeTester
|
|||||||
{
|
{
|
||||||
var lazy = States.GetOrAdd(
|
var lazy = States.GetOrAdd(
|
||||||
accelerator,
|
accelerator,
|
||||||
acc => new Lazy<KernelState>(() => new KernelState(acc), System.Threading.LazyThreadSafetyMode.ExecutionAndPublication));
|
acc => new Lazy<KernelState>(() => new KernelState(acc), LazyThreadSafetyMode.ExecutionAndPublication));
|
||||||
return lazy.Value;
|
return lazy.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user