Use GpuUInt128 in by-divisor GPU scan

This commit is contained in:
Marek Lemańczyk committed 2025-10-13 01:35:40 +02:00
1 parent cd47b122a5
commit ea29035c55
2 files changed
+40 -37

No files matched your search

+3 -7
View File
@@ -579,9 +579,6 @@ internal static class Program
Console.WriteLine("Initialization..."); Console.WriteLine("Initialization...");
// Compose a results file name that encodes configuration (before opening file) // Compose a results file name that encodes configuration (before opening file)
string byDivisorDeltasLabel = mersenneOnGpu
? "gpu"
: (byDivisorDeltasDevice == ByDivisorDeltasDevice.Gpu ? "cpu-gpu" : "cpu");
var builtName = BuildResultsFileName( var builtName = BuildResultsFileName(
useBitTransform, useBitTransform,
threadCount, threadCount,
@@ -602,8 +599,7 @@ internal static class Program
NttGpuMath.ReductionMode, NttGpuMath.ReductionMode,
mersenneOnGpu ? "gpu" : "cpu", mersenneOnGpu ? "gpu" : "cpu",
(GpuContextPool.ForceCpu ? "cpu" : "gpu"), (GpuContextPool.ForceCpu ? "cpu" : "gpu"),
orderOnGpu ? "gpu" : "cpu", orderOnGpu ? "gpu" : "cpu");
byDivisorDeltasLabel);
if (!string.IsNullOrEmpty(_resultsPrefix)) if (!string.IsNullOrEmpty(_resultsPrefix))
{ {
@@ -1020,7 +1016,7 @@ internal static class Program
Console.WriteLine(" --help, -help, --?, -?, /? show this help message"); Console.WriteLine(" --help, -help, --?, -?, /? show this help message");
} }
private static string BuildResultsFileName(bool bitInc, int threads, int block, GpuKernelType kernelType, bool useLucasFlag, bool useDivisorFlag, bool useByDivisorFlag, bool mersenneOnGpu, bool useOrder, bool useModWorkaround, bool useGcd, NttBackend nttBackend, int gpuPrimeThreads, int llSlice, int gpuScanBatch, ulong warmupLimit, ModReductionMode reduction, string mersenneDevice, string primesDevice, string orderDevice, string byDivisorDeltasDevice) private static string BuildResultsFileName(bool bitInc, int threads, int block, GpuKernelType kernelType, bool useLucasFlag, bool useDivisorFlag, bool useByDivisorFlag, bool mersenneOnGpu, bool useOrder, bool useModWorkaround, bool useGcd, NttBackend nttBackend, int gpuPrimeThreads, int llSlice, int gpuScanBatch, ulong warmupLimit, ModReductionMode reduction, string mersenneDevice, string primesDevice, string orderDevice)
{ {
string inc = bitInc ? "bit" : "add"; string inc = bitInc ? "bit" : "add";
string mers = useDivisorFlag string mers = useDivisorFlag
@@ -1028,7 +1024,7 @@ internal static class Program
: (useLucasFlag : (useLucasFlag
? "lucas" ? "lucas"
: (useByDivisorFlag : (useByDivisorFlag
? $"bydivisor-{byDivisorDeltasDevice}" ? "bydivisor"
: (kernelType == GpuKernelType.Pow2Mod ? "pow2mod" : "incremental"))); : (kernelType == GpuKernelType.Pow2Mod ? "pow2mod" : "incremental")));
string ntt = nttBackend == NttBackend.Staged ? "staged" : "reference"; string ntt = nttBackend == NttBackend.Staged ? "staged" : "reference";
string red = reduction switch { ModReductionMode.Mont64 => "mont64", ModReductionMode.Barrett128 => "barrett128", ModReductionMode.GpuUInt128 => "uint128", _ => "auto" }; string red = reduction switch { ModReductionMode.Mont64 => "mont64", ModReductionMode.Barrett128 => "barrett128", ModReductionMode.GpuUInt128 => "uint128", _ => "auto" };
@@ -363,27 +363,24 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
return false; return false;
} }
UInt128 step128 = (UInt128)prime << 1; GpuUInt128 step128 = new GpuUInt128(prime);
if (step128 == UInt128.Zero) step128.ShiftLeft(1);
if (step128.IsZero)
{ {
processedAll = true; processedAll = true;
return false; return false;
} }
if (step128 > ulong.MaxValue) GpuUInt128 limit128 = new GpuUInt128(allowedMax);
{ GpuUInt128 divisor128 = step128;
return CheckDivisorsCpu(prime, allowedMax, out lastProcessed, out processedAll, out processedCount, timeLimit); divisor128.Add(1UL);
} if (divisor128.CompareTo(limit128) > 0)
UInt128 limit = allowedMax;
UInt128 divisor128 = step128 + UInt128.One;
if (divisor128 > limit)
{ {
processedAll = true; processedAll = true;
return false; return false;
} }
ulong step = (ulong)step128; ulong step = step128.Low;
ulong limit64 = allowedMax; ulong limit64 = allowedMax;
int batchCapacity = Math.Max(1, _batchSize); int batchCapacity = Math.Max(1, _batchSize);
@@ -412,20 +409,27 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
byte step7 = (byte)(step % 7UL); byte step7 = (byte)(step % 7UL);
byte step11 = (byte)(step % 11UL); byte step11 = (byte)(step % 11UL);
byte remainder10 = (byte)((ulong)divisor128 % 10UL); ulong startDivisor64 = divisor128.Low;
byte remainder8 = (byte)((ulong)divisor128 % 8UL); byte remainder10 = (byte)(startDivisor64 % 10UL);
byte remainder5 = (byte)((ulong)divisor128 % 5UL); byte remainder8 = (byte)(startDivisor64 % 8UL);
byte remainder3 = (byte)((ulong)divisor128 % 3UL); byte remainder5 = (byte)(startDivisor64 % 5UL);
byte remainder7 = (byte)((ulong)divisor128 % 7UL); byte remainder3 = (byte)(startDivisor64 % 3UL);
byte remainder11 = (byte)((ulong)divisor128 % 11UL); byte remainder7 = (byte)(startDivisor64 % 7UL);
byte remainder11 = (byte)(startDivisor64 % 11UL);
bool lastIsSeven = (prime & 3UL) == 3UL; bool lastIsSeven = (prime & 3UL) == 3UL;
try try
{ {
while (divisor128 <= limit) while (divisor128.CompareTo(limit128) <= 0)
{ {
int chunkCount = ComputeChunkCount(divisor128, limit, step128, batchCapacity); if (divisor128.High != 0UL)
{
break;
}
ulong currentDivisor = divisor128.Low;
int chunkCount = ComputeChunkCount(currentDivisor, limit64, step, batchCapacity);
if (chunkCount <= 0) if (chunkCount <= 0)
{ {
break; break;
@@ -435,7 +439,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
Span<byte> maskSpan = maskBuffer.AsSpan(0, chunkCount); Span<byte> maskSpan = maskBuffer.AsSpan(0, chunkCount);
candidateEvaluator.EvaluateCandidates( candidateEvaluator.EvaluateCandidates(
(ulong)divisor128, currentDivisor,
step, step,
limit64, limit64,
remainder10, remainder10,
@@ -508,7 +512,10 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
} }
} }
divisor128 += step128 * (UInt128)chunkCount; GpuUInt128 increment = step128;
increment.Mul((ulong)chunkCount);
divisor128.Add(increment);
remainder10 = AdvanceRemainder(remainder10, step10, 10, chunkCount); remainder10 = AdvanceRemainder(remainder10, step10, 10, chunkCount);
remainder8 = AdvanceRemainder(remainder8, step8, 8, chunkCount); remainder8 = AdvanceRemainder(remainder8, step8, 8, chunkCount);
remainder5 = AdvanceRemainder(remainder5, step5, 5, chunkCount); remainder5 = AdvanceRemainder(remainder5, step5, 5, chunkCount);
@@ -524,26 +531,26 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
candidateEvaluator.Dispose(); candidateEvaluator.Dispose();
} }
processedAll = divisor128 > limit; processedAll = divisor128.CompareTo(limit128) > 0;
return false; return false;
} }
private static int ComputeChunkCount(UInt128 currentDivisor, UInt128 limit, UInt128 step, int maxCount) private static int ComputeChunkCount(ulong currentDivisor, ulong limit, ulong step, int maxCount)
{ {
if (maxCount <= 0 || step == UInt128.Zero || currentDivisor > limit) if (maxCount <= 0 || step == 0UL || currentDivisor > limit)
{ {
return 0; return 0;
} }
UInt128 distance = limit - currentDivisor; ulong distance = limit - currentDivisor;
UInt128 stepsAvailable = distance / step; ulong stepsAvailable = step == 0UL ? 0UL : distance / step;
UInt128 total = stepsAvailable + UInt128.One; ulong total = stepsAvailable + 1UL;
if (total > (UInt128)maxCount) if (total > (ulong)maxCount)
{ {
total = (UInt128)maxCount; total = (ulong)maxCount;
} }
if (total > (UInt128)int.MaxValue) if (total > (ulong)int.MaxValue)
{ {
return int.MaxValue; return int.MaxValue;
} }