diff --git a/PerfectNumbers.Core/ULongExtensions.Gpu.cs b/PerfectNumbers.Core/ULongExtensions.Gpu.cs index 9a2cfda..4c6c2a5 100644 --- a/PerfectNumbers.Core/ULongExtensions.Gpu.cs +++ b/PerfectNumbers.Core/ULongExtensions.Gpu.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Concurrent; using System.Runtime.CompilerServices; using ILGPU; @@ -18,6 +19,7 @@ public static partial class ULongExtensions } [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Obsolete("Deprecated: use ULongExtensions.MulMod64 for CPU code and GpuUInt128.MulMod inside GPU kernels.")] public static ulong MulMod64Gpu(this ulong a, ulong b, ulong modulus) { // TODO: Remove this GPU-compatible shim from production once callers migrate to MulMod64, @@ -71,7 +73,7 @@ public static partial class ULongExtensions while (index >= 0) { ulong currentBit = (exponent >> index) & 1UL; - ulong squared = result.MulMod64Gpu(result, modulus); + ulong squared = result.MulMod64(result, modulus); result = currentBit == 0UL ? squared : result; index = currentBit == 0UL ? index - 1 : index; if (currentBit == 0UL) @@ -91,14 +93,14 @@ public static partial class ULongExtensions int windowLength = index - windowStart + 1; for (int square = 0; square < windowLength; square++) { - result = result.MulMod64Gpu(result, modulus); + result = result.MulMod64(result, modulus); } ulong mask = (1UL << windowLength) - 1UL; ulong windowValue = (exponent >> windowStart) & mask; int tableIndex = (int)((windowValue - 1UL) >> 1); ulong multiplier = oddPowers[tableIndex]; - result = result.MulMod64Gpu(multiplier, modulus); + result = result.MulMod64(multiplier, modulus); index = windowStart - 1; } @@ -301,11 +303,11 @@ public static partial class ULongExtensions return; } - ulong square = baseValue.MulMod64Gpu(baseValue, modulus); + ulong square = baseValue.MulMod64(baseValue, modulus); for (int i = 1; i < oddPowers.Length; i++) { ulong previous = oddPowers[i - 1]; - oddPowers[i] = previous.MulMod64Gpu(square, modulus); + oddPowers[i] = previous.MulMod64(square, modulus); } } diff --git a/docs/gpu-bydivisor-mulmod-audit.md b/docs/gpu-bydivisor-mulmod-audit.md index d66b467..c47b503 100644 --- a/docs/gpu-bydivisor-mulmod-audit.md +++ b/docs/gpu-bydivisor-mulmod-audit.md @@ -1,16 +1,16 @@ # GPU By-Divisor `MulMod` Usage Audit -This note tracks every `MulMod` call site in the GPU-only `--mersenne=bydivisor` pipeline that changed in the recent optimizer work. It flags host-side helpers that still lean on the slower GPU shim and confirms which kernel paths already align with the fastest benchmarked helpers. +This note tracks every `MulMod` call site in the GPU-only `--mersenne=bydivisor` pipeline that changed in the recent optimizer work. It now records where the host path swapped over to the fast helpers and which kernel paths already aligned with the benchmark winners. ## CPU helpers invoked by the GPU path | Location | Notes | | --- | --- | -| `ULongExtensions.MulMod64Gpu` | Still routes through the legacy GPU-compatible shim. Benchmarks show the standard `MulMod64` implementation runs 6–18× faster on dense inputs, so callers that execute on the CPU should migrate to the baseline helper.【F:PerfectNumbers.Core/ULongExtensions.Gpu.cs†L21-L27】【F:Benchmarks.txt†L24-L46】 | -| `ULongExtensions.Pow2ModWindowedGpu` | Squares and multiplies via `MulMod64Gpu`, so every ladder step pays the same 6–18× penalty noted above. The method executes entirely on the host, so it should also be switched to the baseline `MulMod64` helper in a follow-up.【F:PerfectNumbers.Core/ULongExtensions.Gpu.cs†L39-L109】【F:Benchmarks.txt†L24-L46】 | -| `ULongExtensions.InitializeStandardOddPowers` | Populates the CPU-side table with repeated `MulMod64Gpu` calls. Replacing those calls with `MulMod64` will eliminate the overhead once the surrounding helper is updated.【F:PerfectNumbers.Core/ULongExtensions.Gpu.cs†L288-L309】【F:Benchmarks.txt†L24-L46】 | +| `ULongExtensions.MulMod64Gpu` | Marked as deprecated to steer new code toward `MulMod64` on the CPU and `GpuUInt128.MulMod` inside GPU kernels. The shim remains only for legacy callers that require the GPU-compatible arithmetic façade.【F:PerfectNumbers.Core/ULongExtensions.Gpu.cs†L1-L33】 | +| `ULongExtensions.Pow2ModWindowedGpu` | Migrated to call `MulMod64` for every square and multiply, eliminating the 6–18× slowdown that the shim introduced while executing on the host.【F:PerfectNumbers.Core/ULongExtensions.Gpu.cs†L39-L109】 | +| `ULongExtensions.InitializeStandardOddPowers` | Populates the odd-power table through `MulMod64`, so the host setup costs now match the CPU benchmark baseline.【F:PerfectNumbers.Core/ULongExtensions.Gpu.cs†L286-L309】 | -These are the only host-executed `MulMod` operations remaining in the GPU pipeline, so they form the to-do list for the next pass. +All host-executed `MulMod` operations in the GPU pipeline now target the optimized CPU helper. ## GPU kernel and device-side code paths @@ -18,6 +18,6 @@ These are the only host-executed `MulMod` operations remaining in the GPU pipeli | --- | --- | | `ULongExtensions.Pow2ModWindowedGpuKernel` | Uses the in-place `GpuUInt128.MulMod` helper, which benchmarks as the fastest device-compatible option when the modulus fits in 64 bits—the case for divisor scans.【F:PerfectNumbers.Core/ULongExtensions.Gpu.cs†L112-L149】【F:Benchmarks.txt†L604-L614】 | | `ULongExtensions.ComputeWindowedOddPowerGpuKernel` | Also relies on the in-place helper while iterating the odd-power ladder, so no slower variants are in play.【F:PerfectNumbers.Core/ULongExtensions.Gpu.cs†L153-L181】【F:Benchmarks.txt†L604-L614】 | -| `ExponentRemainderStepperGpu.AdvanceStateGpu` | Advances residues via `_currentResidue.MulMod` with the cached modulus. This matches the in-place approach validated by the GPU benchmarks, so nothing to fix here.【F:PerfectNumbers.Core/Gpu/ExponentRemainderStepperGpu.cs†L104-L111】【F:Benchmarks.txt†L604-L614】 | +| `ExponentRemainderStepperGpu.AdvanceStateGpu` | Advances residues via `_currentResidue.MulMod` with the cached modulus. This matches the in-place approach validated by the GPU benchmarks, so nothing to fix here.【F:PerfectNumbers.Core/Gpu/ExponentRemainderStepperGpu.cs†L99-L111】【F:Benchmarks.txt†L604-L614】 | No other GPU-side `MulMod` calls exist in the by-divisor path, so the device kernels already use the most efficient helper available.