Split GPU heuristic tables by scope
This commit is contained in:
1 parent
936ce239db
commit
6027a73839
6 files changed
+472
-290
No files matched your search
@@ -8,83 +8,21 @@ internal readonly struct HeuristicGpuDivisorTables
|
|||||||
{
|
{
|
||||||
public static readonly HeuristicGpuDivisorTables Shared = default;
|
public static readonly HeuristicGpuDivisorTables Shared = default;
|
||||||
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorsEnding1;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorsEnding3;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorsEnding7;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorsEnding9;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorSquaresEnding1;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorSquaresEnding3;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorSquaresEnding7;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorSquaresEnding9;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> GroupADivisors;
|
public readonly ArrayView1D<ulong, Stride1D.Dense> GroupADivisors;
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> GroupADivisorSquares;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> GroupBDivisorsEnding1;
|
public readonly ArrayView1D<ulong, Stride1D.Dense> GroupBDivisorsEnding1;
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> GroupBDivisorSquaresEnding1;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> GroupBDivisorsEnding7;
|
public readonly ArrayView1D<ulong, Stride1D.Dense> GroupBDivisorsEnding7;
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> GroupBDivisorSquaresEnding7;
|
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> GroupBDivisorsEnding9;
|
public readonly ArrayView1D<ulong, Stride1D.Dense> GroupBDivisorsEnding9;
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> GroupBDivisorSquaresEnding9;
|
|
||||||
|
|
||||||
public HeuristicGpuDivisorTables(
|
public HeuristicGpuDivisorTables(
|
||||||
ArrayView1D<ulong, Stride1D.Dense> combinedDivisorsEnding1,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> combinedDivisorsEnding3,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> combinedDivisorsEnding7,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> combinedDivisorsEnding9,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> combinedDivisorSquaresEnding1,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> combinedDivisorSquaresEnding3,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> combinedDivisorSquaresEnding7,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> combinedDivisorSquaresEnding9,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> groupADivisors,
|
ArrayView1D<ulong, Stride1D.Dense> groupADivisors,
|
||||||
ArrayView1D<ulong, Stride1D.Dense> groupADivisorSquares,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> groupBDivisorsEnding1,
|
ArrayView1D<ulong, Stride1D.Dense> groupBDivisorsEnding1,
|
||||||
ArrayView1D<ulong, Stride1D.Dense> groupBDivisorSquaresEnding1,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> groupBDivisorsEnding7,
|
ArrayView1D<ulong, Stride1D.Dense> groupBDivisorsEnding7,
|
||||||
ArrayView1D<ulong, Stride1D.Dense> groupBDivisorSquaresEnding7,
|
ArrayView1D<ulong, Stride1D.Dense> groupBDivisorsEnding9)
|
||||||
ArrayView1D<ulong, Stride1D.Dense> groupBDivisorsEnding9,
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> groupBDivisorSquaresEnding9)
|
|
||||||
{
|
{
|
||||||
CombinedDivisorsEnding1 = combinedDivisorsEnding1;
|
|
||||||
CombinedDivisorsEnding3 = combinedDivisorsEnding3;
|
|
||||||
CombinedDivisorsEnding7 = combinedDivisorsEnding7;
|
|
||||||
CombinedDivisorsEnding9 = combinedDivisorsEnding9;
|
|
||||||
CombinedDivisorSquaresEnding1 = combinedDivisorSquaresEnding1;
|
|
||||||
CombinedDivisorSquaresEnding3 = combinedDivisorSquaresEnding3;
|
|
||||||
CombinedDivisorSquaresEnding7 = combinedDivisorSquaresEnding7;
|
|
||||||
CombinedDivisorSquaresEnding9 = combinedDivisorSquaresEnding9;
|
|
||||||
GroupADivisors = groupADivisors;
|
GroupADivisors = groupADivisors;
|
||||||
GroupADivisorSquares = groupADivisorSquares;
|
|
||||||
GroupBDivisorsEnding1 = groupBDivisorsEnding1;
|
GroupBDivisorsEnding1 = groupBDivisorsEnding1;
|
||||||
GroupBDivisorSquaresEnding1 = groupBDivisorSquaresEnding1;
|
|
||||||
GroupBDivisorsEnding7 = groupBDivisorsEnding7;
|
GroupBDivisorsEnding7 = groupBDivisorsEnding7;
|
||||||
GroupBDivisorSquaresEnding7 = groupBDivisorSquaresEnding7;
|
|
||||||
GroupBDivisorsEnding9 = groupBDivisorsEnding9;
|
GroupBDivisorsEnding9 = groupBDivisorsEnding9;
|
||||||
GroupBDivisorSquaresEnding9 = groupBDivisorSquaresEnding9;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public ArrayView1D<ulong, Stride1D.Dense> SelectCombined(byte ending)
|
|
||||||
{
|
|
||||||
return ending switch
|
|
||||||
{
|
|
||||||
1 => CombinedDivisorsEnding1,
|
|
||||||
3 => CombinedDivisorsEnding3,
|
|
||||||
7 => CombinedDivisorsEnding7,
|
|
||||||
9 => CombinedDivisorsEnding9,
|
|
||||||
_ => ArrayView1D<ulong, Stride1D.Dense>.Empty,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public ArrayView1D<ulong, Stride1D.Dense> SelectCombinedSquares(byte ending)
|
|
||||||
{
|
|
||||||
return ending switch
|
|
||||||
{
|
|
||||||
1 => CombinedDivisorSquaresEnding1,
|
|
||||||
3 => CombinedDivisorSquaresEnding3,
|
|
||||||
7 => CombinedDivisorSquaresEnding7,
|
|
||||||
9 => CombinedDivisorSquaresEnding9,
|
|
||||||
_ => ArrayView1D<ulong, Stride1D.Dense>.Empty,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -99,18 +37,6 @@ internal readonly struct HeuristicGpuDivisorTables
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public ArrayView1D<ulong, Stride1D.Dense> SelectGroupBSquares(byte ending)
|
|
||||||
{
|
|
||||||
return ending switch
|
|
||||||
{
|
|
||||||
1 => GroupBDivisorSquaresEnding1,
|
|
||||||
7 => GroupBDivisorSquaresEnding7,
|
|
||||||
9 => GroupBDivisorSquaresEnding9,
|
|
||||||
_ => ArrayView1D<ulong, Stride1D.Dense>.Empty,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public ArrayView1D<ulong, Stride1D.Dense> SelectDivisors(HeuristicGpuDivisorTableKind kind, byte ending)
|
public ArrayView1D<ulong, Stride1D.Dense> SelectDivisors(HeuristicGpuDivisorTableKind kind, byte ending)
|
||||||
{
|
{
|
||||||
@@ -120,21 +46,6 @@ internal readonly struct HeuristicGpuDivisorTables
|
|||||||
HeuristicGpuDivisorTableKind.GroupBEnding1 => GroupBDivisorsEnding1,
|
HeuristicGpuDivisorTableKind.GroupBEnding1 => GroupBDivisorsEnding1,
|
||||||
HeuristicGpuDivisorTableKind.GroupBEnding7 => GroupBDivisorsEnding7,
|
HeuristicGpuDivisorTableKind.GroupBEnding7 => GroupBDivisorsEnding7,
|
||||||
HeuristicGpuDivisorTableKind.GroupBEnding9 => GroupBDivisorsEnding9,
|
HeuristicGpuDivisorTableKind.GroupBEnding9 => GroupBDivisorsEnding9,
|
||||||
HeuristicGpuDivisorTableKind.Combined => SelectCombined(ending),
|
|
||||||
_ => ArrayView1D<ulong, Stride1D.Dense>.Empty,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public ArrayView1D<ulong, Stride1D.Dense> SelectDivisorSquares(HeuristicGpuDivisorTableKind kind, byte ending)
|
|
||||||
{
|
|
||||||
return kind switch
|
|
||||||
{
|
|
||||||
HeuristicGpuDivisorTableKind.GroupA => GroupADivisorSquares,
|
|
||||||
HeuristicGpuDivisorTableKind.GroupBEnding1 => GroupBDivisorSquaresEnding1,
|
|
||||||
HeuristicGpuDivisorTableKind.GroupBEnding7 => GroupBDivisorSquaresEnding7,
|
|
||||||
HeuristicGpuDivisorTableKind.GroupBEnding9 => GroupBDivisorSquaresEnding9,
|
|
||||||
HeuristicGpuDivisorTableKind.Combined => SelectCombinedSquares(ending),
|
|
||||||
_ => ArrayView1D<ulong, Stride1D.Dense>.Empty,
|
_ => ArrayView1D<ulong, Stride1D.Dense>.Empty,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -144,3 +55,43 @@ internal readonly struct HeuristicGpuDivisorTables
|
|||||||
Unsafe.AsRef(in Shared) = tables;
|
Unsafe.AsRef(in Shared) = tables;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal readonly struct HeuristicGpuCombinedDivisorTables
|
||||||
|
{
|
||||||
|
public static readonly HeuristicGpuCombinedDivisorTables Shared = default;
|
||||||
|
|
||||||
|
public readonly ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorsEnding1;
|
||||||
|
public readonly ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorsEnding3;
|
||||||
|
public readonly ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorsEnding7;
|
||||||
|
public readonly ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorsEnding9;
|
||||||
|
|
||||||
|
public HeuristicGpuCombinedDivisorTables(
|
||||||
|
ArrayView1D<ulong, Stride1D.Dense> combinedDivisorsEnding1,
|
||||||
|
ArrayView1D<ulong, Stride1D.Dense> combinedDivisorsEnding3,
|
||||||
|
ArrayView1D<ulong, Stride1D.Dense> combinedDivisorsEnding7,
|
||||||
|
ArrayView1D<ulong, Stride1D.Dense> combinedDivisorsEnding9)
|
||||||
|
{
|
||||||
|
CombinedDivisorsEnding1 = combinedDivisorsEnding1;
|
||||||
|
CombinedDivisorsEnding3 = combinedDivisorsEnding3;
|
||||||
|
CombinedDivisorsEnding7 = combinedDivisorsEnding7;
|
||||||
|
CombinedDivisorsEnding9 = combinedDivisorsEnding9;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public ArrayView1D<ulong, Stride1D.Dense> SelectCombined(byte ending)
|
||||||
|
{
|
||||||
|
return ending switch
|
||||||
|
{
|
||||||
|
1 => CombinedDivisorsEnding1,
|
||||||
|
3 => CombinedDivisorsEnding3,
|
||||||
|
7 => CombinedDivisorsEnding7,
|
||||||
|
9 => CombinedDivisorsEnding9,
|
||||||
|
_ => ArrayView1D<ulong, Stride1D.Dense>.Empty,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void InitializeShared(in HeuristicGpuCombinedDivisorTables tables)
|
||||||
|
{
|
||||||
|
Unsafe.AsRef(in Shared) = tables;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -82,21 +82,22 @@ internal static class PrimeTesterKernels
|
|||||||
Index1D index,
|
Index1D index,
|
||||||
ArrayView<int> resultFlag,
|
ArrayView<int> resultFlag,
|
||||||
ulong n,
|
ulong n,
|
||||||
ulong maxDivisorSquare,
|
ulong maxDivisor,
|
||||||
HeuristicGpuDivisorTableKind tableKind,
|
HeuristicGpuDivisorTableKind tableKind,
|
||||||
HeuristicGpuDivisorTables tables)
|
HeuristicGpuDivisorTables tables,
|
||||||
|
HeuristicGpuCombinedDivisorTables combinedTables)
|
||||||
{
|
{
|
||||||
byte nMod10 = (byte)(n % 10UL);
|
byte nMod10 = (byte)(n % 10UL);
|
||||||
ArrayView1D<ulong, Stride1D.Dense> divisors = tables.SelectDivisors(tableKind, nMod10);
|
ArrayView1D<ulong, Stride1D.Dense> divisors = tableKind == HeuristicGpuDivisorTableKind.Combined
|
||||||
ArrayView1D<ulong, Stride1D.Dense> divisorSquares = tables.SelectDivisorSquares(tableKind, nMod10);
|
? combinedTables.SelectCombined(nMod10)
|
||||||
|
: tables.SelectDivisors(tableKind, nMod10);
|
||||||
|
|
||||||
int divisorLength = (int)divisorSquares.Length;
|
int divisorLength = (int)divisors.Length;
|
||||||
int threadIndex = index;
|
int threadIndex = index;
|
||||||
bool skipThread = threadIndex >= divisorLength;
|
bool skipThread = threadIndex >= divisorLength;
|
||||||
ulong divisorSquare = skipThread ? 0UL : divisorSquares[threadIndex];
|
|
||||||
skipThread = skipThread | (divisorSquare > maxDivisorSquare);
|
|
||||||
|
|
||||||
ulong divisor = skipThread ? 1UL : divisors[threadIndex];
|
ulong divisor = skipThread ? 1UL : divisors[threadIndex];
|
||||||
|
skipThread = skipThread | (divisor > maxDivisor);
|
||||||
|
|
||||||
ulong remainder = skipThread ? 1UL : n % divisor;
|
ulong remainder = skipThread ? 1UL : n % divisor;
|
||||||
bool hasFactor = !skipThread & (remainder == 0UL);
|
bool hasFactor = !skipThread & (remainder == 0UL);
|
||||||
if (hasFactor)
|
if (hasFactor)
|
||||||
|
|||||||
@@ -226,12 +226,13 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
private static bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10)
|
private static bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10)
|
||||||
{
|
{
|
||||||
var limiter = GpuPrimeWorkLimiter.Acquire();
|
var limiter = GpuPrimeWorkLimiter.Acquire();
|
||||||
var gpu = PrimeTester.PrimeTesterGpuContextPool.Rent(1);
|
var gpu = PrimeTester.PrimeTesterGpuContextPool.Rent(nMod10, 1, PrimeTester.PrimeTesterGpuContextPool.HeuristicGpuTableScope.GroupABWithCombined);
|
||||||
var accelerator = gpu.Accelerator;
|
var accelerator = gpu.Accelerator;
|
||||||
var kernel = gpu.HeuristicTrialDivisionKernel;
|
var kernel = gpu.HeuristicTrialDivisionKernel;
|
||||||
var flagView1D = gpu.HeuristicFlag.View;
|
var flagView1D = gpu.HeuristicFlag.View;
|
||||||
var flagView = flagView1D.AsContiguous();
|
var flagView = flagView1D.AsContiguous();
|
||||||
|
|
||||||
|
ulong maxDivisor = ComputeMaxDivisorLimit(maxDivisorSquare);
|
||||||
bool compositeDetected = false;
|
bool compositeDetected = false;
|
||||||
int divisorLength = GetCombinedDivisors(nMod10).Length;
|
int divisorLength = GetCombinedDivisors(nMod10).Length;
|
||||||
|
|
||||||
@@ -241,9 +242,10 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
divisorLength,
|
divisorLength,
|
||||||
flagView,
|
flagView,
|
||||||
n,
|
n,
|
||||||
maxDivisorSquare,
|
maxDivisor,
|
||||||
HeuristicGpuDivisorTableKind.Combined,
|
HeuristicGpuDivisorTableKind.Combined,
|
||||||
gpu.HeuristicGpuTables);
|
gpu.HeuristicGpuTables,
|
||||||
|
gpu.HeuristicCombinedTables);
|
||||||
accelerator.Synchronize();
|
accelerator.Synchronize();
|
||||||
flagView1D.CopyToCPU(ref compositeFlag, 1);
|
flagView1D.CopyToCPU(ref compositeFlag, 1);
|
||||||
compositeDetected = compositeFlag != 0;
|
compositeDetected = compositeFlag != 0;
|
||||||
@@ -255,6 +257,23 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
|
||||||
|
private static ulong ComputeMaxDivisorLimit(ulong maxDivisorSquare)
|
||||||
|
{
|
||||||
|
ulong maxDivisor = (ulong)Math.Sqrt(maxDivisorSquare);
|
||||||
|
|
||||||
|
while ((maxDivisor + 1) != 0 && (maxDivisor + 1) <= maxDivisorSquare / (maxDivisor + 1))
|
||||||
|
{
|
||||||
|
maxDivisor++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (maxDivisor != 0 && maxDivisor > maxDivisorSquare / maxDivisor)
|
||||||
|
{
|
||||||
|
maxDivisor--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxDivisor;
|
||||||
|
}
|
||||||
private static bool EvaluateWithOpenNumericFallback(ulong n)
|
private static bool EvaluateWithOpenNumericFallback(ulong n)
|
||||||
{
|
{
|
||||||
return Prime.Numbers.IsPrime(n);
|
return Prime.Numbers.IsPrime(n);
|
||||||
|
|||||||
@@ -241,12 +241,13 @@ public sealed class HeuristicPrimeTester
|
|||||||
private bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10)
|
private bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10)
|
||||||
{
|
{
|
||||||
var limiter = GpuPrimeWorkLimiter.Acquire();
|
var limiter = GpuPrimeWorkLimiter.Acquire();
|
||||||
var gpu = PrimeTester.PrimeTesterGpuContextPool.Rent(1);
|
var gpu = PrimeTester.PrimeTesterGpuContextPool.Rent(nMod10, 1, PrimeTester.PrimeTesterGpuContextPool.HeuristicGpuTableScope.GroupAB);
|
||||||
var accelerator = gpu.Accelerator;
|
var accelerator = gpu.Accelerator;
|
||||||
var kernel = gpu.HeuristicTrialDivisionKernel;
|
var kernel = gpu.HeuristicTrialDivisionKernel;
|
||||||
var flagView1D = gpu.HeuristicFlag.View;
|
var flagView1D = gpu.HeuristicFlag.View;
|
||||||
var flagView = flagView1D.AsContiguous();
|
var flagView = flagView1D.AsContiguous();
|
||||||
|
|
||||||
|
ulong maxDivisor = ComputeMaxDivisorLimit(maxDivisorSquare);
|
||||||
bool compositeDetected = false;
|
bool compositeDetected = false;
|
||||||
int compositeFlag = 0;
|
int compositeFlag = 0;
|
||||||
|
|
||||||
@@ -257,9 +258,10 @@ public sealed class HeuristicPrimeTester
|
|||||||
groupALength,
|
groupALength,
|
||||||
flagView,
|
flagView,
|
||||||
n,
|
n,
|
||||||
maxDivisorSquare,
|
maxDivisor,
|
||||||
HeuristicGpuDivisorTableKind.GroupA,
|
HeuristicGpuDivisorTableKind.GroupA,
|
||||||
gpu.HeuristicGpuTables);
|
gpu.HeuristicGpuTables,
|
||||||
|
gpu.HeuristicCombinedTables);
|
||||||
accelerator.Synchronize();
|
accelerator.Synchronize();
|
||||||
flagView1D.CopyToCPU(ref compositeFlag, 1);
|
flagView1D.CopyToCPU(ref compositeFlag, 1);
|
||||||
compositeDetected = compositeFlag != 0;
|
compositeDetected = compositeFlag != 0;
|
||||||
@@ -291,9 +293,10 @@ public sealed class HeuristicPrimeTester
|
|||||||
divisorLength,
|
divisorLength,
|
||||||
flagView,
|
flagView,
|
||||||
n,
|
n,
|
||||||
maxDivisorSquare,
|
maxDivisor,
|
||||||
tableKind,
|
tableKind,
|
||||||
gpu.HeuristicGpuTables);
|
gpu.HeuristicGpuTables,
|
||||||
|
gpu.HeuristicCombinedTables);
|
||||||
accelerator.Synchronize();
|
accelerator.Synchronize();
|
||||||
flagView1D.CopyToCPU(ref compositeFlag, 1);
|
flagView1D.CopyToCPU(ref compositeFlag, 1);
|
||||||
compositeDetected = compositeFlag != 0;
|
compositeDetected = compositeFlag != 0;
|
||||||
@@ -312,6 +315,23 @@ public sealed class HeuristicPrimeTester
|
|||||||
{
|
{
|
||||||
return Prime.Numbers.IsPrime(n);
|
return Prime.Numbers.IsPrime(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ulong ComputeMaxDivisorLimit(ulong maxDivisorSquare)
|
||||||
|
{
|
||||||
|
ulong maxDivisor = (ulong)Math.Sqrt(maxDivisorSquare);
|
||||||
|
|
||||||
|
while ((maxDivisor + 1) != 0 && (maxDivisor + 1) <= maxDivisorSquare / (maxDivisor + 1))
|
||||||
|
{
|
||||||
|
maxDivisor++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (maxDivisor != 0 && maxDivisor > maxDivisorSquare / maxDivisor)
|
||||||
|
{
|
||||||
|
maxDivisor--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxDivisor;
|
||||||
|
}
|
||||||
internal static ulong ComputeHeuristicDivisorSquareLimit(ulong n)
|
internal static ulong ComputeHeuristicDivisorSquareLimit(ulong n)
|
||||||
{
|
{
|
||||||
return n;
|
return n;
|
||||||
|
|||||||
+367
-184
@@ -161,9 +161,17 @@ public sealed class PrimeTester
|
|||||||
|
|
||||||
int toWarm = target - WarmedGpuLeaseCount;
|
int toWarm = target - WarmedGpuLeaseCount;
|
||||||
var leases = new PrimeTesterGpuContextPool.PrimeTesterGpuContextLease[toWarm];
|
var leases = new PrimeTesterGpuContextPool.PrimeTesterGpuContextLease[toWarm];
|
||||||
|
ReadOnlySpan<byte> supportedDigits = PrimeTesterGpuContextPool.SupportedDigits;
|
||||||
|
int digitIndex = 0;
|
||||||
for (int i = 0; i < toWarm; i++)
|
for (int i = 0; i < toWarm; i++)
|
||||||
{
|
{
|
||||||
leases[i] = PrimeTesterGpuContextPool.Rent(GpuBatchSize);
|
byte trailingDigit = supportedDigits[digitIndex];
|
||||||
|
leases[i] = PrimeTesterGpuContextPool.Rent(trailingDigit, GpuBatchSize);
|
||||||
|
digitIndex++;
|
||||||
|
if (digitIndex == supportedDigits.Length)
|
||||||
|
{
|
||||||
|
digitIndex = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < toWarm; i++)
|
for (int i = 0; i < toWarm; i++)
|
||||||
@@ -179,24 +187,44 @@ public sealed class PrimeTester
|
|||||||
public static void IsPrimeBatchGpu(ReadOnlySpan<ulong> values, Span<byte> results)
|
public static void IsPrimeBatchGpu(ReadOnlySpan<ulong> values, Span<byte> results)
|
||||||
{
|
{
|
||||||
var limiter = GpuPrimeWorkLimiter.Acquire();
|
var limiter = GpuPrimeWorkLimiter.Acquire();
|
||||||
var gpu = PrimeTesterGpuContextPool.Rent(GpuBatchSize);
|
|
||||||
var accelerator = gpu.Accelerator;
|
|
||||||
var kernel = gpu.Kernel;
|
|
||||||
int totalLength = values.Length;
|
int totalLength = values.Length;
|
||||||
int batchSize = GpuBatchSize;
|
int batchSize = GpuBatchSize;
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
while (pos < totalLength)
|
||||||
|
{
|
||||||
|
ulong currentValue = values[pos];
|
||||||
|
byte trailingDigit = (byte)(currentValue % 10UL);
|
||||||
|
var gpu = PrimeTesterGpuContextPool.Rent(trailingDigit, GpuBatchSize);
|
||||||
|
var accelerator = gpu.Accelerator;
|
||||||
|
var kernel = gpu.Kernel;
|
||||||
var input = gpu.Input;
|
var input = gpu.Input;
|
||||||
var output = gpu.Output;
|
var output = gpu.Output;
|
||||||
var inputView = input.View;
|
var inputView = input.View;
|
||||||
var outputView = output.View;
|
var outputView = output.View;
|
||||||
|
|
||||||
int pos = 0;
|
int blockStart = pos;
|
||||||
while (pos < totalLength)
|
while (blockStart < totalLength)
|
||||||
{
|
{
|
||||||
int remaining = totalLength - pos;
|
byte blockDigit = (byte)(values[blockStart] % 10UL);
|
||||||
int count = remaining > batchSize ? batchSize : remaining;
|
if (blockDigit != trailingDigit)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
var valueSlice = values.Slice(pos, count);
|
int limit = Math.Min(batchSize, totalLength - blockStart);
|
||||||
|
int count = 0;
|
||||||
|
while (count < limit && (byte)(values[blockStart + count] % 10UL) == trailingDigit)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var valueSlice = values.Slice(blockStart, count);
|
||||||
ref ulong valueRef = ref MemoryMarshal.GetReference(valueSlice);
|
ref ulong valueRef = ref MemoryMarshal.GetReference(valueSlice);
|
||||||
inputView.CopyFromCPU(ref valueRef, count);
|
inputView.CopyFromCPU(ref valueRef, count);
|
||||||
|
|
||||||
@@ -215,63 +243,77 @@ public sealed class PrimeTester
|
|||||||
gpu.DevicePrimesPow2LastNine.View,
|
gpu.DevicePrimesPow2LastNine.View,
|
||||||
outputView);
|
outputView);
|
||||||
accelerator.Synchronize();
|
accelerator.Synchronize();
|
||||||
var resultSlice = results.Slice(pos, count);
|
var resultSlice = results.Slice(blockStart, count);
|
||||||
ref byte resultRef = ref MemoryMarshal.GetReference(resultSlice);
|
ref byte resultRef = ref MemoryMarshal.GetReference(resultSlice);
|
||||||
outputView.CopyToCPU(ref resultRef, count);
|
outputView.CopyToCPU(ref resultRef, count);
|
||||||
|
|
||||||
pos += count;
|
blockStart += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu.Dispose();
|
gpu.Dispose();
|
||||||
|
pos = blockStart;
|
||||||
|
}
|
||||||
|
|
||||||
limiter.Dispose();
|
limiter.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static class PrimeTesterGpuContextPool
|
internal static class PrimeTesterGpuContextPool
|
||||||
{
|
{
|
||||||
private static readonly ConcurrentQueue<PrimeTesterGpuContextLease> Pool = new();
|
internal enum HeuristicGpuTableScope : byte
|
||||||
|
{
|
||||||
|
GroupAB = 0,
|
||||||
|
GroupABWithCombined = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly byte[] SupportedTrailingDigits = [1, 3, 7, 9];
|
||||||
|
private const int ScopeCount = 2;
|
||||||
|
private static readonly ConcurrentQueue<PrimeTesterGpuContextLease>[,] Pools;
|
||||||
private static readonly object SharedTablesLock = new();
|
private static readonly object SharedTablesLock = new();
|
||||||
private static readonly Dictionary<string, SharedHeuristicGpuTables> SharedTables = new();
|
private static readonly Dictionary<string, SharedKernelTables> SharedTables = new();
|
||||||
|
private static readonly Dictionary<(string Key, byte Digit, HeuristicGpuTableScope Scope), TrailingDigitTables> DigitTables = new();
|
||||||
|
|
||||||
private static string CreateAcceleratorKey(Accelerator accelerator)
|
static PrimeTesterGpuContextPool()
|
||||||
{
|
{
|
||||||
return accelerator.AcceleratorType + ":" + accelerator.Name;
|
Pools = new ConcurrentQueue<PrimeTesterGpuContextLease>[SupportedTrailingDigits.Length, ScopeCount];
|
||||||
|
for (int digitIndex = 0; digitIndex < SupportedTrailingDigits.Length; digitIndex++)
|
||||||
|
{
|
||||||
|
for (int scopeIndex = 0; scopeIndex < ScopeCount; scopeIndex++)
|
||||||
|
{
|
||||||
|
Pools[digitIndex, scopeIndex] = new ConcurrentQueue<PrimeTesterGpuContextLease>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SharedHeuristicGpuTables RentSharedTables(Accelerator accelerator)
|
|
||||||
{
|
|
||||||
string key = CreateAcceleratorKey(accelerator);
|
|
||||||
|
|
||||||
lock (SharedTablesLock)
|
|
||||||
{
|
|
||||||
if (!SharedTables.TryGetValue(key, out var tables))
|
|
||||||
{
|
|
||||||
tables = new SharedHeuristicGpuTables(accelerator, key);
|
|
||||||
SharedTables.Add(key, tables);
|
|
||||||
}
|
|
||||||
|
|
||||||
tables.AddReference();
|
|
||||||
return tables;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReleaseSharedTables(SharedHeuristicGpuTables tables)
|
internal static ReadOnlySpan<byte> SupportedDigits => SupportedTrailingDigits;
|
||||||
|
|
||||||
|
private static int GetPoolIndex(byte trailingDigit)
|
||||||
{
|
{
|
||||||
if (tables is null)
|
return trailingDigit switch
|
||||||
{
|
{
|
||||||
return;
|
1 => 0,
|
||||||
|
3 => 1,
|
||||||
|
7 => 2,
|
||||||
|
9 => 3,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(trailingDigit), trailingDigit, "Only trailing digits 1, 3, 7, and 9 are supported."),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (SharedTablesLock)
|
private static int GetScopeIndex(HeuristicGpuTableScope scope)
|
||||||
{
|
{
|
||||||
tables.Release();
|
return scope switch
|
||||||
}
|
{
|
||||||
|
HeuristicGpuTableScope.GroupAB => 0,
|
||||||
|
HeuristicGpuTableScope.GroupABWithCombined => 1,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(scope), scope, "Unsupported heuristic table scope."),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static PrimeTesterGpuContextLease Rent(int minBufferCapacity = 1)
|
internal static PrimeTesterGpuContextLease Rent(byte trailingDigit, int minBufferCapacity = 1, HeuristicGpuTableScope tableScope = HeuristicGpuTableScope.GroupAB)
|
||||||
{
|
{
|
||||||
if (!Pool.TryDequeue(out var lease))
|
var pool = Pools[GetPoolIndex(trailingDigit), GetScopeIndex(tableScope)];
|
||||||
|
if (!pool.TryDequeue(out var lease))
|
||||||
{
|
{
|
||||||
lease = new PrimeTesterGpuContextLease(minBufferCapacity);
|
lease = new PrimeTesterGpuContextLease(trailingDigit, minBufferCapacity, tableScope);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -285,18 +327,32 @@ public sealed class PrimeTester
|
|||||||
internal static void Return(PrimeTesterGpuContextLease lease)
|
internal static void Return(PrimeTesterGpuContextLease lease)
|
||||||
{
|
{
|
||||||
lease.Accelerator.Synchronize();
|
lease.Accelerator.Synchronize();
|
||||||
Pool.Enqueue(lease);
|
Pools[GetPoolIndex(lease.TrailingDigit), GetScopeIndex(lease.TableScope)].Enqueue(lease);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void DisposeAll()
|
internal static void DisposeAll()
|
||||||
{
|
{
|
||||||
while (Pool.TryDequeue(out var lease))
|
for (int digitIndex = 0; digitIndex < SupportedTrailingDigits.Length; digitIndex++)
|
||||||
|
{
|
||||||
|
for (int scopeIndex = 0; scopeIndex < ScopeCount; scopeIndex++)
|
||||||
|
{
|
||||||
|
var pool = Pools[digitIndex, scopeIndex];
|
||||||
|
while (pool.TryDequeue(out var lease))
|
||||||
{
|
{
|
||||||
lease.DisposeResources();
|
lease.DisposeResources();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lock (SharedTablesLock)
|
lock (SharedTablesLock)
|
||||||
{
|
{
|
||||||
|
foreach (var entry in DigitTables.Values)
|
||||||
|
{
|
||||||
|
entry.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
DigitTables.Clear();
|
||||||
|
|
||||||
foreach (var entry in SharedTables.Values)
|
foreach (var entry in SharedTables.Values)
|
||||||
{
|
{
|
||||||
entry.Dispose();
|
entry.Dispose();
|
||||||
@@ -314,7 +370,12 @@ public sealed class PrimeTester
|
|||||||
}
|
}
|
||||||
|
|
||||||
var retained = new List<PrimeTesterGpuContextLease>();
|
var retained = new List<PrimeTesterGpuContextLease>();
|
||||||
while (Pool.TryDequeue(out var lease))
|
for (int digitIndex = 0; digitIndex < SupportedTrailingDigits.Length; digitIndex++)
|
||||||
|
{
|
||||||
|
for (int scopeIndex = 0; scopeIndex < ScopeCount; scopeIndex++)
|
||||||
|
{
|
||||||
|
var pool = Pools[digitIndex, scopeIndex];
|
||||||
|
while (pool.TryDequeue(out var lease))
|
||||||
{
|
{
|
||||||
if (lease.Accelerator == accelerator)
|
if (lease.Accelerator == accelerator)
|
||||||
{
|
{
|
||||||
@@ -329,26 +390,172 @@ public sealed class PrimeTester
|
|||||||
int retainedCount = retained.Count;
|
int retainedCount = retained.Count;
|
||||||
for (int i = 0; i < retainedCount; i++)
|
for (int i = 0; i < retainedCount; i++)
|
||||||
{
|
{
|
||||||
Pool.Enqueue(retained[i]);
|
pool.Enqueue(retained[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
retained.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (SharedTablesLock)
|
||||||
|
{
|
||||||
|
string key = CreateAcceleratorKey(accelerator);
|
||||||
|
|
||||||
|
if (SharedTables.Remove(key, out var shared))
|
||||||
|
{
|
||||||
|
shared.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DigitTables.Count > 0)
|
||||||
|
{
|
||||||
|
var toRemove = new List<(string Key, byte Digit, HeuristicGpuTableScope Scope)>();
|
||||||
|
foreach (var entry in DigitTables)
|
||||||
|
{
|
||||||
|
if (entry.Key.Key == key)
|
||||||
|
{
|
||||||
|
entry.Value.Dispose();
|
||||||
|
toRemove.Add(entry.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < toRemove.Count; i++)
|
||||||
|
{
|
||||||
|
DigitTables.Remove(toRemove[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string CreateAcceleratorKey(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
return accelerator.AcceleratorType + ":" + accelerator.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SharedKernelTables RentSharedTables(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
string key = CreateAcceleratorKey(accelerator);
|
||||||
|
|
||||||
|
lock (SharedTablesLock)
|
||||||
|
{
|
||||||
|
if (!SharedTables.TryGetValue(key, out var tables))
|
||||||
|
{
|
||||||
|
tables = new SharedKernelTables(accelerator, key);
|
||||||
|
SharedTables.Add(key, tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
tables.AddReference();
|
||||||
|
return tables;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ReleaseSharedTables(SharedKernelTables tables)
|
||||||
|
{
|
||||||
|
if (tables is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (SharedTablesLock)
|
||||||
|
{
|
||||||
|
if (tables.Release() && SharedTables.Remove(tables.Key, out _))
|
||||||
|
{
|
||||||
|
tables.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TrailingDigitTables RentTrailingDigitTables(Accelerator accelerator, byte trailingDigit, HeuristicGpuTableScope scope)
|
||||||
|
{
|
||||||
|
string key = CreateAcceleratorKey(accelerator);
|
||||||
|
var compositeKey = (key, trailingDigit, scope);
|
||||||
|
|
||||||
|
lock (SharedTablesLock)
|
||||||
|
{
|
||||||
|
if (!DigitTables.TryGetValue(compositeKey, out var tables))
|
||||||
|
{
|
||||||
|
tables = new TrailingDigitTables(accelerator, key, trailingDigit, scope);
|
||||||
|
DigitTables.Add(compositeKey, tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
tables.AddReference();
|
||||||
|
return tables;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ReleaseTrailingDigitTables(TrailingDigitTables tables)
|
||||||
|
{
|
||||||
|
if (tables is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (SharedTablesLock)
|
||||||
|
{
|
||||||
|
var compositeKey = (tables.Key, tables.TrailingDigit, tables.Scope);
|
||||||
|
if (tables.Release() && DigitTables.Remove(compositeKey))
|
||||||
|
{
|
||||||
|
tables.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class PrimeTesterGpuContextLease : IDisposable
|
internal sealed class PrimeTesterGpuContextLease : IDisposable
|
||||||
{
|
{
|
||||||
|
|
||||||
private bool _returned;
|
private bool _returned;
|
||||||
private readonly SharedHeuristicGpuTables _sharedTables;
|
private readonly SharedKernelTables _sharedTables;
|
||||||
|
private readonly TrailingDigitTables _digitTables;
|
||||||
private readonly HeuristicGpuDivisorTables _heuristicDivisorTables;
|
private readonly HeuristicGpuDivisorTables _heuristicDivisorTables;
|
||||||
|
private readonly HeuristicGpuCombinedDivisorTables _heuristicCombinedTables;
|
||||||
|
|
||||||
internal readonly Context AcceleratorContext;
|
internal readonly Context AcceleratorContext;
|
||||||
public readonly Accelerator Accelerator;
|
public readonly Accelerator Accelerator;
|
||||||
|
public readonly byte TrailingDigit;
|
||||||
|
public readonly HeuristicGpuTableScope TableScope;
|
||||||
public readonly 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 readonly 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 readonly Action<Index1D, ArrayView<int>, ulong, ulong, HeuristicGpuDivisorTableKind, HeuristicGpuDivisorTables> HeuristicTrialDivisionKernel;
|
public readonly Action<Index1D, ArrayView<int>, ulong, ulong, HeuristicGpuDivisorTableKind, HeuristicGpuDivisorTables, HeuristicGpuCombinedDivisorTables> HeuristicTrialDivisionKernel;
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> Input = null!;
|
public MemoryBuffer1D<ulong, Stride1D.Dense> Input = null!;
|
||||||
public MemoryBuffer1D<byte, Stride1D.Dense> Output = null!;
|
public MemoryBuffer1D<byte, Stride1D.Dense> Output = null!;
|
||||||
public MemoryBuffer1D<int, Stride1D.Dense> HeuristicFlag = null!;
|
public MemoryBuffer1D<int, Stride1D.Dense> HeuristicFlag = null!;
|
||||||
public int BufferCapacity;
|
public int BufferCapacity;
|
||||||
|
|
||||||
|
internal PrimeTesterGpuContextLease(byte trailingDigit, int minBufferCapacity, HeuristicGpuTableScope tableScope)
|
||||||
|
{
|
||||||
|
TrailingDigit = trailingDigit;
|
||||||
|
TableScope = tableScope;
|
||||||
|
|
||||||
|
AcceleratorContext = Context.CreateDefault();
|
||||||
|
Accelerator = AcceleratorContext.GetPreferredDevice(false).CreateAccelerator(AcceleratorContext);
|
||||||
|
Kernel = Accelerator.LoadAutoGroupedStreamKernel<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>>(PrimeTesterKernels.SmallPrimeSieveKernel);
|
||||||
|
HeuristicTrialDivisionKernel = Accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<int>, ulong, ulong, HeuristicGpuDivisorTableKind, HeuristicGpuDivisorTables, HeuristicGpuCombinedDivisorTables>(PrimeTesterKernels.HeuristicTrialDivisionKernel);
|
||||||
|
|
||||||
|
_sharedTables = RentSharedTables(Accelerator);
|
||||||
|
_digitTables = RentTrailingDigitTables(Accelerator, trailingDigit, tableScope);
|
||||||
|
|
||||||
|
_heuristicDivisorTables = new HeuristicGpuDivisorTables(
|
||||||
|
_sharedTables.HeuristicGroupADivisors.View,
|
||||||
|
_digitTables.GroupBDivisorsEnding1View,
|
||||||
|
_digitTables.GroupBDivisorsEnding7View,
|
||||||
|
_digitTables.GroupBDivisorsEnding9View);
|
||||||
|
HeuristicGpuDivisorTables.InitializeShared(in _heuristicDivisorTables);
|
||||||
|
|
||||||
|
if (_digitTables.HasCombinedTables)
|
||||||
|
{
|
||||||
|
_heuristicCombinedTables = new HeuristicGpuCombinedDivisorTables(
|
||||||
|
_digitTables.CombinedDivisorsEnding1View,
|
||||||
|
_digitTables.CombinedDivisorsEnding3View,
|
||||||
|
_digitTables.CombinedDivisorsEnding7View,
|
||||||
|
_digitTables.CombinedDivisorsEnding9View);
|
||||||
|
HeuristicGpuCombinedDivisorTables.InitializeShared(in _heuristicCombinedTables);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_heuristicCombinedTables = HeuristicGpuCombinedDivisorTables.Shared;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureCapacity(minBufferCapacity);
|
||||||
|
_returned = false;
|
||||||
|
}
|
||||||
|
|
||||||
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesDefault => _sharedTables.DevicePrimesDefault;
|
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesDefault => _sharedTables.DevicePrimesDefault;
|
||||||
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastOne => _sharedTables.DevicePrimesLastOne;
|
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastOne => _sharedTables.DevicePrimesLastOne;
|
||||||
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastSeven => _sharedTables.DevicePrimesLastSeven;
|
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimesLastSeven => _sharedTables.DevicePrimesLastSeven;
|
||||||
@@ -359,58 +566,11 @@ public sealed class PrimeTester
|
|||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastSeven => _sharedTables.DevicePrimesPow2LastSeven;
|
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastSeven => _sharedTables.DevicePrimesPow2LastSeven;
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastThree => _sharedTables.DevicePrimesPow2LastThree;
|
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastThree => _sharedTables.DevicePrimesPow2LastThree;
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastNine => _sharedTables.DevicePrimesPow2LastNine;
|
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastNine => _sharedTables.DevicePrimesPow2LastNine;
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupADivisors => _sharedTables.HeuristicGroupADivisors;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupADivisorSquares => _sharedTables.HeuristicGroupADivisorSquares;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupBDivisorsEnding1 => _sharedTables.HeuristicGroupBDivisorsEnding1;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupBDivisorSquaresEnding1 => _sharedTables.HeuristicGroupBDivisorSquaresEnding1;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupBDivisorsEnding7 => _sharedTables.HeuristicGroupBDivisorsEnding7;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupBDivisorSquaresEnding7 => _sharedTables.HeuristicGroupBDivisorSquaresEnding7;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupBDivisorsEnding9 => _sharedTables.HeuristicGroupBDivisorsEnding9;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupBDivisorSquaresEnding9 => _sharedTables.HeuristicGroupBDivisorSquaresEnding9;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding1 => _sharedTables.HeuristicCombinedDivisorsEnding1;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding1 => _sharedTables.HeuristicCombinedDivisorSquaresEnding1;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding3 => _sharedTables.HeuristicCombinedDivisorsEnding3;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding3 => _sharedTables.HeuristicCombinedDivisorSquaresEnding3;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding7 => _sharedTables.HeuristicCombinedDivisorsEnding7;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding7 => _sharedTables.HeuristicCombinedDivisorSquaresEnding7;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding9 => _sharedTables.HeuristicCombinedDivisorsEnding9;
|
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding9 => _sharedTables.HeuristicCombinedDivisorSquaresEnding9;
|
|
||||||
|
|
||||||
public HeuristicGpuDivisorTables HeuristicGpuTables => _heuristicDivisorTables;
|
public HeuristicGpuDivisorTables HeuristicGpuTables => _heuristicDivisorTables;
|
||||||
|
public HeuristicGpuCombinedDivisorTables HeuristicCombinedTables => _heuristicCombinedTables;
|
||||||
|
|
||||||
internal PrimeTesterGpuContextLease(int minBufferCapacity)
|
internal void EnsureCapacity(int minCapacity)
|
||||||
{
|
|
||||||
AcceleratorContext = Context.CreateDefault();
|
|
||||||
Accelerator = AcceleratorContext.GetPreferredDevice(false).CreateAccelerator(AcceleratorContext);
|
|
||||||
Kernel = Accelerator.LoadAutoGroupedStreamKernel<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>>(PrimeTesterKernels.SmallPrimeSieveKernel);
|
|
||||||
HeuristicTrialDivisionKernel = Accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<int>, ulong, ulong, HeuristicGpuDivisorTableKind, HeuristicGpuDivisorTables>(PrimeTesterKernels.HeuristicTrialDivisionKernel);
|
|
||||||
|
|
||||||
_sharedTables = RentSharedTables(Accelerator);
|
|
||||||
|
|
||||||
_heuristicDivisorTables = new HeuristicGpuDivisorTables(
|
|
||||||
_sharedTables.HeuristicCombinedDivisorsEnding1.View,
|
|
||||||
_sharedTables.HeuristicCombinedDivisorsEnding3.View,
|
|
||||||
_sharedTables.HeuristicCombinedDivisorsEnding7.View,
|
|
||||||
_sharedTables.HeuristicCombinedDivisorsEnding9.View,
|
|
||||||
_sharedTables.HeuristicCombinedDivisorSquaresEnding1.View,
|
|
||||||
_sharedTables.HeuristicCombinedDivisorSquaresEnding3.View,
|
|
||||||
_sharedTables.HeuristicCombinedDivisorSquaresEnding7.View,
|
|
||||||
_sharedTables.HeuristicCombinedDivisorSquaresEnding9.View,
|
|
||||||
_sharedTables.HeuristicGroupADivisors.View,
|
|
||||||
_sharedTables.HeuristicGroupADivisorSquares.View,
|
|
||||||
_sharedTables.HeuristicGroupBDivisorsEnding1.View,
|
|
||||||
_sharedTables.HeuristicGroupBDivisorSquaresEnding1.View,
|
|
||||||
_sharedTables.HeuristicGroupBDivisorsEnding7.View,
|
|
||||||
_sharedTables.HeuristicGroupBDivisorSquaresEnding7.View,
|
|
||||||
_sharedTables.HeuristicGroupBDivisorsEnding9.View,
|
|
||||||
_sharedTables.HeuristicGroupBDivisorSquaresEnding9.View);
|
|
||||||
HeuristicGpuDivisorTables.InitializeShared(in _heuristicDivisorTables);
|
|
||||||
|
|
||||||
EnsureCapacity(minBufferCapacity);
|
|
||||||
_returned = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EnsureCapacity(int minCapacity)
|
|
||||||
{
|
{
|
||||||
if (minCapacity <= BufferCapacity)
|
if (minCapacity <= BufferCapacity)
|
||||||
{
|
{
|
||||||
@@ -447,17 +607,17 @@ public sealed class PrimeTester
|
|||||||
Input?.Dispose();
|
Input?.Dispose();
|
||||||
Output?.Dispose();
|
Output?.Dispose();
|
||||||
HeuristicFlag?.Dispose();
|
HeuristicFlag?.Dispose();
|
||||||
|
ReleaseTrailingDigitTables(_digitTables);
|
||||||
ReleaseSharedTables(_sharedTables);
|
ReleaseSharedTables(_sharedTables);
|
||||||
Accelerator.Dispose();
|
Accelerator.Dispose();
|
||||||
AcceleratorContext.Dispose();
|
AcceleratorContext.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private sealed class SharedKernelTables
|
||||||
private sealed class SharedHeuristicGpuTables
|
|
||||||
{
|
{
|
||||||
private int _referenceCount;
|
private int _referenceCount;
|
||||||
|
|
||||||
internal SharedHeuristicGpuTables(Accelerator accelerator, string key)
|
internal SharedKernelTables(Accelerator accelerator, string key)
|
||||||
{
|
{
|
||||||
Key = key;
|
Key = key;
|
||||||
|
|
||||||
@@ -502,42 +662,7 @@ public sealed class PrimeTester
|
|||||||
DevicePrimesPow2LastNine.View.CopyFromCPU(primesPow2LastNine);
|
DevicePrimesPow2LastNine.View.CopyFromCPU(primesPow2LastNine);
|
||||||
|
|
||||||
HeuristicPrimeSieves.EnsureInitialized();
|
HeuristicPrimeSieves.EnsureInitialized();
|
||||||
HeuristicCombinedPrimeTester.EnsureInitialized();
|
HeuristicGroupADivisors = CopySpanToDevice(accelerator, HeuristicPrimeSieves.GroupADivisors);
|
||||||
|
|
||||||
var heuristicGroupA = HeuristicPrimeSieves.GroupADivisors;
|
|
||||||
HeuristicGroupADivisors = CopySpanToDevice(accelerator, heuristicGroupA);
|
|
||||||
|
|
||||||
var heuristicGroupASquares = HeuristicPrimeSieves.GroupADivisorSquares;
|
|
||||||
HeuristicGroupADivisorSquares = CopySpanToDevice(accelerator, heuristicGroupASquares);
|
|
||||||
|
|
||||||
HeuristicGroupBDivisorsEnding1 = CopyUintSpanToDevice(accelerator, DivisorGenerator.SmallPrimesLastOneWithoutLastThree);
|
|
||||||
HeuristicGroupBDivisorSquaresEnding1 = CopySpanToDevice(accelerator, DivisorGenerator.SmallPrimesPow2LastOneWithoutLastThree);
|
|
||||||
|
|
||||||
HeuristicGroupBDivisorsEnding7 = CopyUintSpanToDevice(accelerator, DivisorGenerator.SmallPrimesLastSevenWithoutLastThree);
|
|
||||||
HeuristicGroupBDivisorSquaresEnding7 = CopySpanToDevice(accelerator, DivisorGenerator.SmallPrimesPow2LastSevenWithoutLastThree);
|
|
||||||
|
|
||||||
HeuristicGroupBDivisorsEnding9 = CopyUintSpanToDevice(accelerator, DivisorGenerator.SmallPrimesLastNineWithoutLastThree);
|
|
||||||
HeuristicGroupBDivisorSquaresEnding9 = CopySpanToDevice(accelerator, DivisorGenerator.SmallPrimesPow2LastNineWithoutLastThree);
|
|
||||||
|
|
||||||
var combinedEnding1 = HeuristicCombinedPrimeTester.CombinedDivisorsEnding1Span;
|
|
||||||
HeuristicCombinedDivisorsEnding1 = CopySpanToDevice(accelerator, combinedEnding1);
|
|
||||||
var combinedSquaresEnding1 = HeuristicCombinedPrimeTester.CombinedDivisorsEnding1SquaresSpan;
|
|
||||||
HeuristicCombinedDivisorSquaresEnding1 = CopySpanToDevice(accelerator, combinedSquaresEnding1);
|
|
||||||
|
|
||||||
var combinedEnding3 = HeuristicCombinedPrimeTester.CombinedDivisorsEnding3Span;
|
|
||||||
HeuristicCombinedDivisorsEnding3 = CopySpanToDevice(accelerator, combinedEnding3);
|
|
||||||
var combinedSquaresEnding3 = HeuristicCombinedPrimeTester.CombinedDivisorsEnding3SquaresSpan;
|
|
||||||
HeuristicCombinedDivisorSquaresEnding3 = CopySpanToDevice(accelerator, combinedSquaresEnding3);
|
|
||||||
|
|
||||||
var combinedEnding7 = HeuristicCombinedPrimeTester.CombinedDivisorsEnding7Span;
|
|
||||||
HeuristicCombinedDivisorsEnding7 = CopySpanToDevice(accelerator, combinedEnding7);
|
|
||||||
var combinedSquaresEnding7 = HeuristicCombinedPrimeTester.CombinedDivisorsEnding7SquaresSpan;
|
|
||||||
HeuristicCombinedDivisorSquaresEnding7 = CopySpanToDevice(accelerator, combinedSquaresEnding7);
|
|
||||||
|
|
||||||
var combinedEnding9 = HeuristicCombinedPrimeTester.CombinedDivisorsEnding9Span;
|
|
||||||
HeuristicCombinedDivisorsEnding9 = CopySpanToDevice(accelerator, combinedEnding9);
|
|
||||||
var combinedSquaresEnding9 = HeuristicCombinedPrimeTester.CombinedDivisorsEnding9SquaresSpan;
|
|
||||||
HeuristicCombinedDivisorSquaresEnding9 = CopySpanToDevice(accelerator, combinedSquaresEnding9);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal string Key { get; }
|
internal string Key { get; }
|
||||||
@@ -552,33 +677,122 @@ public sealed class PrimeTester
|
|||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastThree { get; }
|
internal MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastThree { get; }
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastNine { get; }
|
internal MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimesPow2LastNine { get; }
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupADivisors { get; }
|
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupADivisors { get; }
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupADivisorSquares { get; }
|
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupBDivisorsEnding1 { get; }
|
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupBDivisorSquaresEnding1 { get; }
|
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupBDivisorsEnding7 { get; }
|
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupBDivisorSquaresEnding7 { get; }
|
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupBDivisorsEnding9 { get; }
|
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicGroupBDivisorSquaresEnding9 { get; }
|
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding1 { get; }
|
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding1 { get; }
|
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding3 { get; }
|
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding3 { get; }
|
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding7 { get; }
|
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding7 { get; }
|
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding9 { get; }
|
|
||||||
internal MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding9 { get; }
|
|
||||||
|
|
||||||
internal void AddReference()
|
internal void AddReference()
|
||||||
{
|
{
|
||||||
_referenceCount++;
|
_referenceCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Release()
|
internal bool Release()
|
||||||
{
|
{
|
||||||
if (_referenceCount > 0)
|
if (_referenceCount > 0)
|
||||||
{
|
{
|
||||||
_referenceCount--;
|
_referenceCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return _referenceCount == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Dispose()
|
||||||
|
{
|
||||||
|
DevicePrimesDefault.Dispose();
|
||||||
|
DevicePrimesLastOne.Dispose();
|
||||||
|
DevicePrimesLastSeven.Dispose();
|
||||||
|
DevicePrimesLastThree.Dispose();
|
||||||
|
DevicePrimesLastNine.Dispose();
|
||||||
|
DevicePrimesPow2Default.Dispose();
|
||||||
|
DevicePrimesPow2LastOne.Dispose();
|
||||||
|
DevicePrimesPow2LastSeven.Dispose();
|
||||||
|
DevicePrimesPow2LastThree.Dispose();
|
||||||
|
DevicePrimesPow2LastNine.Dispose();
|
||||||
|
HeuristicGroupADivisors.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class TrailingDigitTables
|
||||||
|
{
|
||||||
|
private int _referenceCount;
|
||||||
|
|
||||||
|
internal TrailingDigitTables(Accelerator accelerator, string key, byte trailingDigit, HeuristicGpuTableScope scope)
|
||||||
|
{
|
||||||
|
Key = key;
|
||||||
|
TrailingDigit = trailingDigit;
|
||||||
|
Scope = scope;
|
||||||
|
|
||||||
|
HeuristicPrimeSieves.EnsureInitialized();
|
||||||
|
HeuristicCombinedPrimeTester.EnsureInitialized();
|
||||||
|
|
||||||
|
if (trailingDigit == 1 || trailingDigit == 7 || trailingDigit == 9)
|
||||||
|
{
|
||||||
|
GroupBDivisorsEnding1 = CopyUintSpanToDevice(accelerator, DivisorGenerator.SmallPrimesLastOneWithoutLastThree);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trailingDigit == 3 || trailingDigit == 7 || trailingDigit == 9)
|
||||||
|
{
|
||||||
|
GroupBDivisorsEnding7 = CopyUintSpanToDevice(accelerator, DivisorGenerator.SmallPrimesLastSevenWithoutLastThree);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trailingDigit == 1 || trailingDigit == 3 || trailingDigit == 9)
|
||||||
|
{
|
||||||
|
GroupBDivisorsEnding9 = CopyUintSpanToDevice(accelerator, DivisorGenerator.SmallPrimesLastNineWithoutLastThree);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scope == HeuristicGpuTableScope.GroupABWithCombined)
|
||||||
|
{
|
||||||
|
CombinedDivisorsEnding1 = trailingDigit == 1 ? CopySpanToDevice(accelerator, HeuristicCombinedPrimeTester.CombinedDivisorsEnding1Span) : null;
|
||||||
|
CombinedDivisorsEnding3 = trailingDigit == 3 ? CopySpanToDevice(accelerator, HeuristicCombinedPrimeTester.CombinedDivisorsEnding3Span) : null;
|
||||||
|
CombinedDivisorsEnding7 = trailingDigit == 7 ? CopySpanToDevice(accelerator, HeuristicCombinedPrimeTester.CombinedDivisorsEnding7Span) : null;
|
||||||
|
CombinedDivisorsEnding9 = trailingDigit == 9 ? CopySpanToDevice(accelerator, HeuristicCombinedPrimeTester.CombinedDivisorsEnding9Span) : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal string Key { get; }
|
||||||
|
internal byte TrailingDigit { get; }
|
||||||
|
internal HeuristicGpuTableScope Scope { get; }
|
||||||
|
|
||||||
|
internal bool HasCombinedTables => Scope == HeuristicGpuTableScope.GroupABWithCombined;
|
||||||
|
|
||||||
|
internal MemoryBuffer1D<ulong, Stride1D.Dense>? CombinedDivisorsEnding1 { get; }
|
||||||
|
internal MemoryBuffer1D<ulong, Stride1D.Dense>? CombinedDivisorsEnding3 { get; }
|
||||||
|
internal MemoryBuffer1D<ulong, Stride1D.Dense>? CombinedDivisorsEnding7 { get; }
|
||||||
|
internal MemoryBuffer1D<ulong, Stride1D.Dense>? CombinedDivisorsEnding9 { get; }
|
||||||
|
internal MemoryBuffer1D<ulong, Stride1D.Dense>? GroupBDivisorsEnding1 { get; }
|
||||||
|
internal MemoryBuffer1D<ulong, Stride1D.Dense>? GroupBDivisorsEnding7 { get; }
|
||||||
|
internal MemoryBuffer1D<ulong, Stride1D.Dense>? GroupBDivisorsEnding9 { get; }
|
||||||
|
|
||||||
|
internal ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorsEnding1View => CombinedDivisorsEnding1?.View ?? ArrayView1D<ulong, Stride1D.Dense>.Empty;
|
||||||
|
internal ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorsEnding3View => CombinedDivisorsEnding3?.View ?? ArrayView1D<ulong, Stride1D.Dense>.Empty;
|
||||||
|
internal ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorsEnding7View => CombinedDivisorsEnding7?.View ?? ArrayView1D<ulong, Stride1D.Dense>.Empty;
|
||||||
|
internal ArrayView1D<ulong, Stride1D.Dense> CombinedDivisorsEnding9View => CombinedDivisorsEnding9?.View ?? ArrayView1D<ulong, Stride1D.Dense>.Empty;
|
||||||
|
internal ArrayView1D<ulong, Stride1D.Dense> GroupBDivisorsEnding1View => GroupBDivisorsEnding1?.View ?? ArrayView1D<ulong, Stride1D.Dense>.Empty;
|
||||||
|
internal ArrayView1D<ulong, Stride1D.Dense> GroupBDivisorsEnding7View => GroupBDivisorsEnding7?.View ?? ArrayView1D<ulong, Stride1D.Dense>.Empty;
|
||||||
|
internal ArrayView1D<ulong, Stride1D.Dense> GroupBDivisorsEnding9View => GroupBDivisorsEnding9?.View ?? ArrayView1D<ulong, Stride1D.Dense>.Empty;
|
||||||
|
|
||||||
|
internal void AddReference()
|
||||||
|
{
|
||||||
|
_referenceCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool Release()
|
||||||
|
{
|
||||||
|
if (_referenceCount > 0)
|
||||||
|
{
|
||||||
|
_referenceCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _referenceCount == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Dispose()
|
||||||
|
{
|
||||||
|
CombinedDivisorsEnding1?.Dispose();
|
||||||
|
CombinedDivisorsEnding3?.Dispose();
|
||||||
|
CombinedDivisorsEnding7?.Dispose();
|
||||||
|
CombinedDivisorsEnding9?.Dispose();
|
||||||
|
GroupBDivisorsEnding1?.Dispose();
|
||||||
|
GroupBDivisorsEnding7?.Dispose();
|
||||||
|
GroupBDivisorsEnding9?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MemoryBuffer1D<ulong, Stride1D.Dense> CopySpanToDevice(Accelerator accelerator, ReadOnlySpan<ulong> span)
|
private static MemoryBuffer1D<ulong, Stride1D.Dense> CopySpanToDevice(Accelerator accelerator, ReadOnlySpan<ulong> span)
|
||||||
@@ -586,8 +800,8 @@ public sealed class PrimeTester
|
|||||||
var buffer = accelerator.Allocate1D<ulong>(span.Length);
|
var buffer = accelerator.Allocate1D<ulong>(span.Length);
|
||||||
if (!span.IsEmpty)
|
if (!span.IsEmpty)
|
||||||
{
|
{
|
||||||
ref ulong sourceRef = ref MemoryMarshal.GetReference(span);
|
ref ulong source = ref MemoryMarshal.GetReference(span);
|
||||||
buffer.View.CopyFromCPU(ref sourceRef, span.Length);
|
buffer.View.CopyFromCPU(ref source, span.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
@@ -609,37 +823,6 @@ public sealed class PrimeTester
|
|||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Dispose()
|
|
||||||
{
|
|
||||||
DevicePrimesDefault.Dispose();
|
|
||||||
DevicePrimesLastOne.Dispose();
|
|
||||||
DevicePrimesLastSeven.Dispose();
|
|
||||||
DevicePrimesLastThree.Dispose();
|
|
||||||
DevicePrimesLastNine.Dispose();
|
|
||||||
DevicePrimesPow2Default.Dispose();
|
|
||||||
DevicePrimesPow2LastOne.Dispose();
|
|
||||||
DevicePrimesPow2LastSeven.Dispose();
|
|
||||||
DevicePrimesPow2LastThree.Dispose();
|
|
||||||
DevicePrimesPow2LastNine.Dispose();
|
|
||||||
HeuristicGroupADivisors.Dispose();
|
|
||||||
HeuristicGroupADivisorSquares.Dispose();
|
|
||||||
HeuristicGroupBDivisorsEnding1.Dispose();
|
|
||||||
HeuristicGroupBDivisorSquaresEnding1.Dispose();
|
|
||||||
HeuristicGroupBDivisorsEnding7.Dispose();
|
|
||||||
HeuristicGroupBDivisorSquaresEnding7.Dispose();
|
|
||||||
HeuristicGroupBDivisorsEnding9.Dispose();
|
|
||||||
HeuristicGroupBDivisorSquaresEnding9.Dispose();
|
|
||||||
HeuristicCombinedDivisorsEnding1.Dispose();
|
|
||||||
HeuristicCombinedDivisorSquaresEnding1.Dispose();
|
|
||||||
HeuristicCombinedDivisorsEnding3.Dispose();
|
|
||||||
HeuristicCombinedDivisorSquaresEnding3.Dispose();
|
|
||||||
HeuristicCombinedDivisorsEnding7.Dispose();
|
|
||||||
HeuristicCombinedDivisorSquaresEnding7.Dispose();
|
|
||||||
HeuristicCombinedDivisorsEnding9.Dispose();
|
|
||||||
HeuristicCombinedDivisorSquaresEnding9.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expose cache clearing for accelerator disposal coordination
|
// Expose cache clearing for accelerator disposal coordination
|
||||||
@@ -672,7 +855,7 @@ public sealed class PrimeTester
|
|||||||
// TODO: Route this batch helper through the shared GPU kernel pool from
|
// TODO: Route this batch helper through the shared GPU kernel pool from
|
||||||
// GpuUInt128BinaryGcdBenchmarks so we reuse cached kernels, pinned host buffers,
|
// GpuUInt128BinaryGcdBenchmarks so we reuse cached kernels, pinned host buffers,
|
||||||
// and divisor-cycle staging instead of allocating new device buffers per call.
|
// and divisor-cycle staging instead of allocating new device buffers per call.
|
||||||
var gpu = PrimeTesterGpuContextPool.Rent();
|
var gpu = PrimeTesterGpuContextPool.Rent(1);
|
||||||
var accelerator = gpu.Accelerator;
|
var accelerator = gpu.Accelerator;
|
||||||
var kernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SharesFactorKernel);
|
var kernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SharesFactorKernel);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# GPU context pooling and heuristic divisor updates
|
||||||
|
|
||||||
|
- [x] Review existing GPU context pooling in `PerfectNumbers.Core/PrimeTester.cs` and determine shared table allocations that can be scoped per trailing digit.
|
||||||
|
- [x] Split `PrimeTesterGpuContextPool` into trailing-digit specific pools so each lease only uploads the divisor tables required for that digit.
|
||||||
|
- [x] Update GPU warm-up and rental code paths to pick pools based on `n % 10` and ensure thread-safe reuse.
|
||||||
|
- [x] Replace square-table usage in GPU heuristic trial division with square-root limits so divisor tables no longer need squared values on the accelerator.
|
||||||
|
- [x] Remove GPU square buffers and adjust kernels, table types, and callers accordingly.
|
||||||
|
- [x] Build solution to confirm the new pooling and divisor logic compiles; tests documented in summary.
|
||||||
Reference in new issue
Block a user