Add TODOs for divisor metadata caching

This commit is contained in:
Marek Lemańczyk committed 2025-10-01 22:52:21 +02:00
1 parent 513fc7acb0
commit 36d316d19c
53 files changed
+929 -393

No files matched your search

+20
View File
@@ -256,6 +256,9 @@ public struct GpuUInt128 : IComparable<GpuUInt128>, IEquatable<GpuUInt128>
return Zero;
}
// TODO: Replace this single-bit ladder with the ProcessEightBitWindows strategy measured
// in GpuPow2ModBenchmarks once the GPU kernels can share the windowed helper. The windowed
// version held 21.5 µs for 33-bit moduli versus 51.0 µs here when scanning large divisors.
GpuUInt128 result = Zero;
ulong i = 0UL;
while (i < exponent)
@@ -287,6 +290,8 @@ public struct GpuUInt128 : IComparable<GpuUInt128>, IEquatable<GpuUInt128>
ulong e0 = 0UL, e1 = 0UL, e2 = 0UL, e3 = 0UL, e4 = 0UL, e5 = 0UL, e6 = 0UL, e7 = 0UL;
bool a0 = false, a1 = false, a2 = false, a3 = false, a4 = false, a5 = false, a6 = false, a7 = false;
// TODO: Mirror the eight-bit window batching once the scalar helper above switches; the
// current bit-serial loop lags by ~3× on 8k–33-bit moduli compared to the windowed path.
int len = exponents.Length;
if (len > 0) { e0 = exponents[0]; a0 = true; }
if (len > 1) { e1 = exponents[1]; a1 = true; }
@@ -372,6 +377,9 @@ public struct GpuUInt128 : IComparable<GpuUInt128>, IEquatable<GpuUInt128>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddMod(GpuUInt128 value, ulong modulus)
{
// TODO: Pre-reduce the operands via the Montgomery ladder used in MulMod64Benchmarks so the GPU
// compatible shim stops paying for `%` on every call; the InlineUInt128 helper ran 6–82× faster on
// large 64-bit workloads while preserving compatibility with the CPU scanner.
ulong a = Low % modulus;
ulong b = value.Low % modulus;
ulong sum = a + b;
@@ -387,6 +395,9 @@ public struct GpuUInt128 : IComparable<GpuUInt128>, IEquatable<GpuUInt128>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddMod(ulong value, ulong modulus)
{
// TODO: Fold these operands with the ImmediateModulo helper once the GPU shim exposes it, avoiding
// repeated `%` reductions that the benchmarks showed are far slower than the Montgomery-based path
// for dense operands.
ulong a = Low % modulus;
ulong b = value % modulus;
ulong sum = a + b;
@@ -718,6 +729,8 @@ public struct GpuUInt128 : IComparable<GpuUInt128>, IEquatable<GpuUInt128>
/// </summary>
internal void MulModByLimb(GpuUInt128 other, GpuUInt128 modulus)
{
// TODO: Relocate this limb-based reducer to the benchmark project once the production
// pipeline switches to the faster allocating legacy path demonstrated in the benchmarks.
MultiplyFull(this, other, out var p3, out var p2, out var p1, out var p0);
High = p3;
@@ -808,6 +821,8 @@ public struct GpuUInt128 : IComparable<GpuUInt128>, IEquatable<GpuUInt128>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly ulong MulModWithNativeModulo(ulong value, ulong modulus)
{
// TODO: Drop this native-modulo path from production after migrating callers to MulMod,
// which benchmarked 4-8× faster on dense operands and still wins on mixed workloads.
ulong multiplicand = Low % modulus;
var remainder = value % modulus;
@@ -891,6 +906,8 @@ public struct GpuUInt128 : IComparable<GpuUInt128>, IEquatable<GpuUInt128>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong ShiftLeftByNativeChunk(ulong value, ulong modulus)
{
// TODO: Collapse this eight-step shift ladder into the ProcessEightBitWindows helper once it lands so
// we reuse the precomputed window residues instead of emitting `% modulus` after every shift.
value = (value << 1) % modulus;
value = (value << 1) % modulus;
value = (value << 1) % modulus;
@@ -929,6 +946,8 @@ public struct GpuUInt128 : IComparable<GpuUInt128>, IEquatable<GpuUInt128>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly ulong MulModMontgomery64(GpuUInt128 other, ulong modulus, ulong nPrime, ulong r2)
{
// TODO: Retire this struct-based Montgomery path from production after adopting the extension
// helper, which benchmarks 6-7× faster across dense and near-modulus operands.
ulong modulusLocal = modulus;
ulong a = Low % modulusLocal;
ulong b = other.Low % modulusLocal;
@@ -947,6 +966,7 @@ public struct GpuUInt128 : IComparable<GpuUInt128>, IEquatable<GpuUInt128>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly ulong MulModMontgomery64(ulong other, ulong modulus, ulong nPrime, ulong r2)
{
// TODO: Same as above—migrate callers to the scalar extension to avoid this 6-7× slowdown.
ulong modulusLocal = modulus;
ulong a = Low % modulusLocal;
ulong b = other % modulusLocal;