Address windowed pow2 review feedback

This commit is contained in:
Marek Lemańczyk committed 2025-10-20 18:37:29 +02:00
1 parent 481d1010e8
commit da6ea25729
9 files changed
+17 -20

No files matched your search

@@ -21,7 +21,7 @@ internal static class DivisorKernels
ReadOnlyGpuUInt128 readOnlyMod = divisor;
if (x == 0)
{
baseVal = GpuUInt128.Pow2Mod(exponent, in readOnlyMod); // Uses the eight-bit windowed ladder measured fastest in GPU benchmarks.
baseVal = GpuUInt128.Pow2Mod(exponent, in readOnlyMod);
result[0] = baseVal.High == 0UL && baseVal.Low == 1UL ? (byte)1 : (byte)0;
return;
}
@@ -38,7 +38,7 @@ internal static class DivisorKernels
GpuUInt128 pow = baseVal;
pow.ModPow(exponent / ux, in readOnlyMod);
var part2 = GpuUInt128.Pow2Mod(exponent % ux, in readOnlyMod); // Windowed pow2 keeps the mixed-radix tail fast.
var part2 = GpuUInt128.Pow2Mod(exponent % ux, in readOnlyMod);
GpuUInt128 product = pow;
ReadOnlyGpuUInt128 part2ReadOnly = part2.AsReadOnly();
product.MulMod(in part2ReadOnly, in readOnlyMod);
@@ -96,7 +96,7 @@ internal static class IncrementalKernels
}
ulong phi64 = phi.Low;
if (GpuUInt128.Pow2Mod(phi64, in readOnlyQ) != GpuUInt128.One) // Windowed pow2 keeps the totient check fast.
if (GpuUInt128.Pow2Mod(phi64, in readOnlyQ) != GpuUInt128.One)
{
orders[index] = 0UL;
return;
@@ -192,7 +192,7 @@ internal static class IncrementalKernels
}
ulong phi64 = phi.Low;
if (GpuUInt128.Pow2Mod(phi64, in readOnlyQ) != GpuUInt128.One) // Windowed pow2 keeps the order probe aligned with benchmarks.
if (GpuUInt128.Pow2Mod(phi64, in readOnlyQ) != GpuUInt128.One)
{
return;
}
@@ -22,7 +22,7 @@ internal static class OrderKernels
}
ulong phi64 = phi.Low;
GpuUInt128 pow = GpuUInt128.Pow2Mod(phi64, in readOnlyQ); // Windowed pow2 keeps the cycle check aligned with benchmark wins.
GpuUInt128 pow = GpuUInt128.Pow2Mod(phi64, in readOnlyQ);
if (pow != GpuUInt128.One)
{
orders[index] = 0UL;
@@ -77,7 +77,6 @@ internal static class Pow2ModKernels
return;
}
}
// Pow2Minus1Mod already routes through the windowed pow2 helper benchmarked as fastest for large divisors.
if (GpuUInt128.Pow2Minus1Mod(exponent, in readOnlyQ) != GpuUInt128.Zero)
{
orders[index] = 0UL;
@@ -169,7 +168,7 @@ internal static class Pow2ModKernels
return;
}
}
if (GpuUInt128.Pow2Mod(exponent, in readOnlyQ) != GpuUInt128.One) // Windowed pow2 keeps the order guard aligned with GPU benchmarks.
if (GpuUInt128.Pow2Mod(exponent, in readOnlyQ) != GpuUInt128.One)
{
return;
}
@@ -112,7 +112,7 @@ public class MersenneNumberLucasLehmerGpuTester
var gpu = GpuContextPool.RentPreferred(preferCpu: false);
var accelerator = gpu.Accelerator;
var kernel = GetBatchKernel(accelerator); // Batch kernel already relies on the Mersenne squaring reducer; windowed pow2 helpers do not apply here.
var kernel = GetBatchKernel(accelerator);
var expBuffer = accelerator.Allocate1D<ulong>(count);
ulong[] expArray = ArrayPool<ulong>.Shared.Rent(count);
@@ -479,7 +479,6 @@ public class MersenneNumberLucasLehmerGpuTester
{
if ((exponent & 1UL) != 0UL)
{
// The base varies per primitive-root candidate, so pow2-specific ladders do not apply.
result = MulMod(result, value, modulus);
}
@@ -22,9 +22,7 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
{
GpuKernelType.Pow2Mod => gpuLease.Pow2ModOrderKernel,
_ => gpuLease.IncrementalOrderKernel,
}; // Pow2ModOrderKernel already routes through the windowed pow2 helper measured fastest for large divisors.
// Both GPU order kernels already rely on the windowed pow2 helper, so this wrapper only selects the delegate
// and manages the scoped GPU resources.
};
var foundBuffer = accelerator.Allocate1D<int>(1); // TODO: Replace this allocation with the pooled device buffer from GpuOrderKernelBenchmarks so repeated scans reuse the pinned staging memory instead of allocating per run.
exponent.Mod10_8_5_3Steps(out ulong step10, out ulong step8, out ulong step5, out ulong step3);