Warm GPU resources before thread startup

This commit is contained in:
Marek Lemańczyk committed 2025-10-31 16:56:25 +01:00
1 parent e14b77e504
commit 6864b316d5
9 files changed
+822 -403

No files matched your search

+80 -144
View File
@@ -111,7 +111,7 @@ public sealed class HeuristicPrimeTester
private static bool HeuristicTrialDivisionCpu(ulong n, ulong maxDivisorSquare, byte nMod10, bool includeGroupB)
{
ReadOnlySpan<int> groupADivisors = HeuristicPrimeSieves.GroupADivisors;
ReadOnlySpan<ulong> groupADivisors = HeuristicPrimeSieves.GroupADivisors;
ReadOnlySpan<ulong> groupADivisorSquares = HeuristicPrimeSieves.GroupADivisorSquares;
int interleaveBatchSize = HeuristicCombinedPrimeTester.GetBatchSize(n);
int groupAIndex = 0;
@@ -237,149 +237,85 @@ public sealed class HeuristicPrimeTester
return true;
}
private bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10)
{
int batchCapacity = HeuristicCombinedPrimeTester.GetBatchSize(n);
int interleaveBatchSize = batchCapacity;
private bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10)
{
var limiter = GpuPrimeWorkLimiter.Acquire();
var gpu = PrimeTester.PrimeTesterGpuContextPool.Rent(1);
var accelerator = gpu.Accelerator;
var kernel = gpu.HeuristicTrialDivisionKernel;
var flagView1D = gpu.HeuristicFlag.View;
var flagView = flagView1D.AsContiguous();
bool compositeDetected = false;
int compositeFlag = 0;
int groupALength = HeuristicPrimeSieves.GroupADivisors.Length;
if (groupALength > 0)
{
flagView1D.CopyFromCPU(ref compositeFlag, 1);
kernel(
groupALength,
flagView,
n,
maxDivisorSquare,
HeuristicGpuDivisorTableKind.GroupA,
gpu.HeuristicGpuTables);
accelerator.Synchronize();
flagView1D.CopyToCPU(ref compositeFlag, 1);
compositeDetected = compositeFlag != 0;
}
if (!compositeDetected)
{
ReadOnlySpan<byte> endingOrder = GetGroupBEndingOrder(nMod10);
for (int i = 0; i < endingOrder.Length && !compositeDetected; i++)
{
byte ending = endingOrder[i];
HeuristicGpuDivisorTableKind tableKind = ending switch
{
1 => HeuristicGpuDivisorTableKind.GroupBEnding1,
7 => HeuristicGpuDivisorTableKind.GroupBEnding7,
9 => HeuristicGpuDivisorTableKind.GroupBEnding9,
_ => HeuristicGpuDivisorTableKind.GroupA,
};
if (tableKind == HeuristicGpuDivisorTableKind.GroupA)
{
continue;
}
int divisorLength = GetGroupBDivisors(ending).Length;
if (divisorLength == 0)
{
continue;
}
compositeFlag = 0;
flagView1D.CopyFromCPU(ref compositeFlag, 1);
kernel(
divisorLength,
flagView,
n,
maxDivisorSquare,
tableKind,
gpu.HeuristicGpuTables);
accelerator.Synchronize();
flagView1D.CopyToCPU(ref compositeFlag, 1);
compositeDetected = compositeFlag != 0;
}
}
gpu.Dispose();
limiter.Dispose();
return compositeDetected;
}
var limiter = GpuPrimeWorkLimiter.Acquire();
var gpu = PrimeTester.PrimeTesterGpuContextPool.Rent(batchCapacity);
var accelerator = gpu.Accelerator;
var kernel = gpu.HeuristicTrialDivisionKernel;
bool compositeDetected = false;
int count = 0;
var inputView = gpu.Input.View;
var flagView = gpu.HeuristicFlag.View;
ulong[] divisorArray = gpu.DivisorArray;
bool ProcessBatch(int length)
{
if (length <= 0)
{
return false;
}
inputView.CopyFromCPU(ref divisorArray[0], length);
int compositeFlag = 0;
flagView.CopyFromCPU(ref compositeFlag, 1);
kernel(length, inputView, n, flagView);
accelerator.Synchronize();
flagView.CopyToCPU(ref compositeFlag, 1);
return compositeFlag != 0;
}
ReadOnlySpan<int> groupADivisors = HeuristicPrimeSieves.GroupADivisors;
ReadOnlySpan<ulong> groupADivisorSquares = HeuristicPrimeSieves.GroupADivisorSquares;
int groupAIndex = 0;
ReadOnlySpan<byte> endingOrder = GetGroupBEndingOrder(nMod10);
Span<int> indices = endingOrder.Length <= 8
? stackalloc int[endingOrder.Length]
: new int[endingOrder.Length];
bool groupAHasMore = groupAIndex < groupADivisors.Length && groupADivisorSquares[groupAIndex] <= maxDivisorSquare;
bool groupBHasMore = !endingOrder.IsEmpty && HasGroupBCandidates(endingOrder, indices, maxDivisorSquare);
while (!compositeDetected && (groupAHasMore || groupBHasMore))
{
if (groupAHasMore)
{
int processed = 0;
while (processed < interleaveBatchSize && groupAIndex < groupADivisors.Length)
{
ulong divisorSquare = groupADivisorSquares[groupAIndex];
if (divisorSquare > maxDivisorSquare)
{
groupAIndex = groupADivisors.Length;
groupAHasMore = false;
break;
}
divisorArray[count] = (ulong)groupADivisors[groupAIndex];
count++;
if (count == batchCapacity)
{
if (ProcessBatch(count))
{
compositeDetected = true;
break;
}
count = 0;
}
groupAIndex++;
processed++;
}
if (compositeDetected)
{
break;
}
if (groupAIndex >= groupADivisors.Length)
{
groupAHasMore = false;
}
else
{
groupAHasMore = groupADivisorSquares[groupAIndex] <= maxDivisorSquare;
if (!groupAHasMore)
{
groupAIndex = groupADivisors.Length;
}
}
}
if (!compositeDetected && groupBHasMore)
{
int processed = 0;
while (processed < interleaveBatchSize)
{
if (!TrySelectNextGroupBDivisor(endingOrder, indices, maxDivisorSquare, out ulong divisor))
{
groupBHasMore = false;
break;
}
divisorArray[count] = divisor;
count++;
if (count == batchCapacity)
{
if (ProcessBatch(count))
{
compositeDetected = true;
break;
}
count = 0;
}
processed++;
}
if (!compositeDetected && groupBHasMore)
{
groupBHasMore = HasGroupBCandidates(endingOrder, indices, maxDivisorSquare);
}
}
}
if (!compositeDetected && count > 0 && ProcessBatch(count))
{
compositeDetected = true;
}
gpu.Dispose();
limiter.Dispose();
return compositeDetected;
}
private static bool EvaluateWithOpenNumericFallback(ulong n)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool EvaluateWithOpenNumericFallback(ulong n)
{
return Prime.Numbers.IsPrime(n);
}
@@ -398,7 +334,7 @@ public sealed class HeuristicPrimeTester
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TrySelectNextGroupBDivisor(ReadOnlySpan<byte> endingOrder, Span<int> indices, ulong maxDivisorSquare, out ulong divisor)
private static bool TrySelectNextGroupBDivisor(ReadOnlySpan<byte> endingOrder, Span<int> indices, ulong maxDivisorSquare, out ulong divisor)
{
ulong bestCandidate = ulong.MaxValue;
int bestEndingIndex = -1;
@@ -581,7 +517,7 @@ public sealed class HeuristicPrimeTester
internal ref struct HeuristicDivisorEnumerator
{
private readonly ulong maxDivisorSquare;
private readonly ReadOnlySpan<int> groupADivisors;
private readonly ReadOnlySpan<ulong> groupADivisors;
private readonly ReadOnlySpan<ulong> groupADivisorSquares;
private int groupAIndex;
private Span<HeuristicGroupBSequenceState> groupBStates;
@@ -609,7 +545,7 @@ public sealed class HeuristicPrimeTester
}
int currentIndex = groupAIndex;
ulong divisor = (ulong)groupADivisors[currentIndex];
ulong divisor = groupADivisors[currentIndex];
groupAIndex++;
HeuristicDivisorGroup group = currentIndex < GroupAConstantCount