Rename GPU mul-mod helper
This commit is contained in:
1 parent
4b13bc6497
commit
04d4d18f37
6 files changed
+24
-65
No files matched your search
+8
-8
@@ -23,7 +23,7 @@ Job=.NET 8.0 Runtime=.NET 8.0
|
||||
|------------------------------------------- |------------------ |-----------:|----------:|----------:|------:|--------:|----------:|------------:|
|
||||
| ExtensionBaseline | CrossWordBlend | 3.606 ns | 0.0030 ns | 0.0025 ns | 1.00 | 0.00 | - | NA |
|
||||
| GpuCompatibleMulModExtension | CrossWordBlend | 22.870 ns | 0.1463 ns | 0.1297 ns | 6.34 | 0.04 | - | NA |
|
||||
| GpuCompatibleMulModSimplifiedExtension | CrossWordBlend | 22.780 ns | 0.4463 ns | 0.8600 ns | 6.32 | 0.23 | - | NA |
|
||||
| MulModGpu | CrossWordBlend | 22.780 ns | 0.4463 ns | 0.8600 ns | 6.32 | 0.23 | - | NA |
|
||||
| InlineUInt128Operands | CrossWordBlend | 22.218 ns | 0.0319 ns | 0.0266 ns | 6.16 | 0.01 | - | NA |
|
||||
| InlineUInt128OperandsWithReductionFirst | CrossWordBlend | 22.626 ns | 0.0553 ns | 0.0517 ns | 6.27 | 0.02 | - | NA |
|
||||
| InlineUInt128OperandsWithOperandReduction | CrossWordBlend | 22.548 ns | 0.0487 ns | 0.0432 ns | 6.25 | 0.01 | - | NA |
|
||||
@@ -35,7 +35,7 @@ Job=.NET 8.0 Runtime=.NET 8.0
|
||||
| | | | | | | | | |
|
||||
| ExtensionBaseline | MixedBitPattern | 3.564 ns | 0.0059 ns | 0.0052 ns | 1.00 | 0.00 | - | NA |
|
||||
| GpuCompatibleMulModExtension | MixedBitPattern | 64.800 ns | 0.3399 ns | 0.3179 ns | 18.17 | 0.09 | - | NA |
|
||||
| GpuCompatibleMulModSimplifiedExtension | MixedBitPattern | 59.165 ns | 0.4243 ns | 0.3969 ns | 16.60 | 0.11 | - | NA |
|
||||
| MulModGpu | MixedBitPattern | 59.165 ns | 0.4243 ns | 0.3969 ns | 16.60 | 0.11 | - | NA |
|
||||
| InlineUInt128Operands | MixedBitPattern | 30.539 ns | 0.1396 ns | 0.1306 ns | 8.57 | 0.03 | - | NA |
|
||||
| InlineUInt128OperandsWithReductionFirst | MixedBitPattern | 31.237 ns | 0.1013 ns | 0.0898 ns | 8.76 | 0.03 | - | NA |
|
||||
| InlineUInt128OperandsWithOperandReduction | MixedBitPattern | 30.210 ns | 0.1323 ns | 0.1237 ns | 8.48 | 0.04 | - | NA |
|
||||
@@ -47,7 +47,7 @@ Job=.NET 8.0 Runtime=.NET 8.0
|
||||
| | | | | | | | | |
|
||||
| ExtensionBaseline | NearFullRange | 3.583 ns | 0.0105 ns | 0.0098 ns | 1.00 | 0.00 | - | NA |
|
||||
| GpuCompatibleMulModExtension | NearFullRange | 5.708 ns | 0.0520 ns | 0.0486 ns | 1.59 | 0.02 | - | NA |
|
||||
| GpuCompatibleMulModSimplifiedExtension | NearFullRange | 5.952 ns | 0.1253 ns | 0.1172 ns | 1.66 | 0.04 | - | NA |
|
||||
| MulModGpu | NearFullRange | 5.952 ns | 0.1253 ns | 0.1172 ns | 1.66 | 0.04 | - | NA |
|
||||
| InlineUInt128Operands | NearFullRange | 27.159 ns | 0.0936 ns | 0.0781 ns | 7.58 | 0.03 | - | NA |
|
||||
| InlineUInt128OperandsWithReductionFirst | NearFullRange | 4.357 ns | 0.0205 ns | 0.0182 ns | 1.22 | 0.00 | - | NA |
|
||||
| InlineUInt128OperandsWithOperandReduction | NearFullRange | 4.319 ns | 0.0158 ns | 0.0140 ns | 1.21 | 0.00 | - | NA |
|
||||
@@ -59,7 +59,7 @@ Job=.NET 8.0 Runtime=.NET 8.0
|
||||
| | | | | | | | | |
|
||||
| ExtensionBaseline | PrimeSizedModulus | 3.593 ns | 0.0039 ns | 0.0037 ns | 1.00 | 0.00 | - | NA |
|
||||
| GpuCompatibleMulModExtension | PrimeSizedModulus | 52.766 ns | 0.3086 ns | 0.2887 ns | 14.69 | 0.08 | - | NA |
|
||||
| GpuCompatibleMulModSimplifiedExtension | PrimeSizedModulus | 50.490 ns | 0.1977 ns | 0.1752 ns | 14.05 | 0.05 | - | NA |
|
||||
| MulModGpu | PrimeSizedModulus | 50.490 ns | 0.1977 ns | 0.1752 ns | 14.05 | 0.05 | - | NA |
|
||||
| InlineUInt128Operands | PrimeSizedModulus | 31.409 ns | 0.0984 ns | 0.0920 ns | 8.74 | 0.03 | - | NA |
|
||||
| InlineUInt128OperandsWithReductionFirst | PrimeSizedModulus | 32.176 ns | 0.3427 ns | 0.3206 ns | 8.96 | 0.09 | - | NA |
|
||||
| InlineUInt128OperandsWithOperandReduction | PrimeSizedModulus | 31.786 ns | 0.1483 ns | 0.1387 ns | 8.85 | 0.04 | - | NA |
|
||||
@@ -71,7 +71,7 @@ Job=.NET 8.0 Runtime=.NET 8.0
|
||||
| | | | | | | | | |
|
||||
| ExtensionBaseline | SparseOperands | 3.555 ns | 0.0087 ns | 0.0082 ns | 1.00 | 0.00 | - | NA |
|
||||
| GpuCompatibleMulModExtension | SparseOperands | 5.671 ns | 0.0043 ns | 0.0036 ns | 1.60 | 0.00 | - | NA |
|
||||
| GpuCompatibleMulModSimplifiedExtension | SparseOperands | 5.239 ns | 0.0103 ns | 0.0096 ns | 1.47 | 0.00 | - | NA |
|
||||
| MulModGpu | SparseOperands | 5.239 ns | 0.0103 ns | 0.0096 ns | 1.47 | 0.00 | - | NA |
|
||||
| InlineUInt128Operands | SparseOperands | 3.563 ns | 0.0217 ns | 0.0203 ns | 1.00 | 0.01 | - | NA |
|
||||
| InlineUInt128OperandsWithReductionFirst | SparseOperands | 4.617 ns | 0.0095 ns | 0.0089 ns | 1.30 | 0.00 | - | NA |
|
||||
| InlineUInt128OperandsWithOperandReduction | SparseOperands | 4.282 ns | 0.0193 ns | 0.0181 ns | 1.20 | 0.01 | - | NA |
|
||||
@@ -83,7 +83,7 @@ Job=.NET 8.0 Runtime=.NET 8.0
|
||||
| | | | | | | | | |
|
||||
| ExtensionBaseline | ZeroOperands | 3.599 ns | 0.0069 ns | 0.0065 ns | 1.00 | 0.00 | - | NA |
|
||||
| GpuCompatibleMulModExtension | ZeroOperands | 1.976 ns | 0.0053 ns | 0.0049 ns | 0.55 | 0.00 | - | NA |
|
||||
| GpuCompatibleMulModSimplifiedExtension | ZeroOperands | 1.986 ns | 0.0048 ns | 0.0045 ns | 0.55 | 0.00 | - | NA |
|
||||
| MulModGpu | ZeroOperands | 1.986 ns | 0.0048 ns | 0.0045 ns | 0.55 | 0.00 | - | NA |
|
||||
| InlineUInt128Operands | ZeroOperands | 3.542 ns | 0.0125 ns | 0.0117 ns | 0.98 | 0.00 | - | NA |
|
||||
| InlineUInt128OperandsWithReductionFirst | ZeroOperands | 4.286 ns | 0.0178 ns | 0.0167 ns | 1.19 | 0.01 | - | NA |
|
||||
| InlineUInt128OperandsWithOperandReduction | ZeroOperands | 4.256 ns | 0.0116 ns | 0.0097 ns | 1.18 | 0.00 | - | NA |
|
||||
@@ -97,7 +97,7 @@ Job=.NET 8.0 Runtime=.NET 8.0
|
||||
Outliers
|
||||
MulMod64Benchmarks.ExtensionBaseline: .NET 8.0 -> 2 outliers were removed (4.92 ns, 5.01 ns)
|
||||
MulMod64Benchmarks.GpuCompatibleMulModExtension: .NET 8.0 -> 1 outlier was removed, 2 outliers were detected (23.75 ns, 25.37 ns)
|
||||
MulMod64Benchmarks.GpuCompatibleMulModSimplifiedExtension: .NET 8.0 -> 2 outliers were removed, 3 outliers were detected (22.07 ns, 26.53 ns, 26.65 ns)
|
||||
MulMod64Benchmarks.MulModGpu: .NET 8.0 -> 2 outliers were removed, 3 outliers were detected (22.07 ns, 26.53 ns, 26.65 ns)
|
||||
MulMod64Benchmarks.InlineUInt128Operands: .NET 8.0 -> 2 outliers were removed (23.62 ns, 23.64 ns)
|
||||
MulMod64Benchmarks.InlineUInt128OperandsWithOperandReduction: .NET 8.0 -> 1 outlier was removed (24.42 ns)
|
||||
MulMod64Benchmarks.MultiplyHighDecomposition: .NET 8.0 -> 2 outliers were removed (25.12 ns, 25.31 ns)
|
||||
@@ -112,7 +112,7 @@ Outliers
|
||||
MulMod64Benchmarks.InlineUInt128Operands: .NET 8.0 -> 2 outliers were removed (29.01 ns, 29.49 ns)
|
||||
MulMod64Benchmarks.InlineUInt128OperandsWithReductionFirst: .NET 8.0 -> 1 outlier was removed (5.72 ns)
|
||||
MulMod64Benchmarks.InlineUInt128OperandsWithOperandReduction: .NET 8.0 -> 1 outlier was removed (5.73 ns)
|
||||
MulMod64Benchmarks.GpuCompatibleMulModSimplifiedExtension: .NET 8.0 -> 1 outlier was removed, 3 outliers were detected (51.41 ns, 51.47 ns, 52.10 ns)
|
||||
MulMod64Benchmarks.MulModGpu: .NET 8.0 -> 1 outlier was removed, 3 outliers were detected (51.41 ns, 51.47 ns, 52.10 ns)
|
||||
MulMod64Benchmarks.InlineUInt128Operands: .NET 8.0 -> 1 outlier was detected (32.44 ns)
|
||||
MulMod64Benchmarks.InlineUInt128WithLocals: .NET 8.0 -> 2 outliers were removed (33.47 ns, 34.46 ns)
|
||||
MulMod64Benchmarks.MultiplyHighDecomposition: .NET 8.0 -> 1 outlier was removed (33.93 ns)
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace EvenPerfectBitScanner.Benchmarks;
|
||||
|
||||
/// <summary>
|
||||
/// GPU benchmarks for 64-bit modular multiplication helpers.
|
||||
/// Windows 11 results ranged from 0.62 ms to 1.63 ms, and GpuCompatibleMulModSimplifiedExtension led the PrimeSizedModulus case at 0.641 ms.
|
||||
/// Recommended helper for p ≥ 138,000,000 is GpuCompatibleMulModSimplifiedExtension.
|
||||
/// Windows 11 results ranged from 0.62 ms to 1.63 ms, and MulModGpu led the PrimeSizedModulus case at 0.641 ms.
|
||||
/// Recommended helper for p ≥ 138,000,000 is MulModGpu.
|
||||
/// </summary>
|
||||
[SimpleJob(RuntimeMoniker.Net80)]
|
||||
[MemoryDiagnoser]
|
||||
@@ -106,7 +106,7 @@ public class MulMod64BenchmarksGpu : IDisposable
|
||||
/// Recommended for production GPU scans, especially for large p ≥ 138,000,000.
|
||||
/// </summary>
|
||||
[Benchmark]
|
||||
public void GpuCompatibleMulModSimplifiedExtension()
|
||||
public void MulModGpu()
|
||||
{
|
||||
LaunchKernel(_gpuCompatibleSimplifiedKernel);
|
||||
}
|
||||
@@ -249,7 +249,7 @@ public class MulMod64BenchmarksGpu : IDisposable
|
||||
|
||||
MulMod64GpuKernelInput input = inputs[index];
|
||||
GpuUInt128 state = new(input.Left);
|
||||
results[index] = state.MulModSimplified(input.Right, input.Modulus);
|
||||
results[index] = state.MulMod(input.Right, input.Modulus);
|
||||
}
|
||||
|
||||
private static void InlineKernel(Index1D index, ArrayView<MulMod64GpuKernelInput> inputs, ArrayView<ulong> results)
|
||||
|
||||
@@ -58,7 +58,7 @@ public class MulMod64Benchmarks
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls the UInt128-based <see cref="ULongExtensions.MulModSimplified(ulong, ulong, ulong)"/> helper; performance mirrors
|
||||
/// Calls the UInt128-based <see cref="ULongExtensions.MulMod(ulong, ulong, ulong)"/> helper; performance mirrors
|
||||
/// the full helper with 5.24–5.95 ns on sparse inputs and 1.99 ns when zeros dominate, but 22.8–59.2 ns on dense blends.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
@@ -66,10 +66,10 @@ public class MulMod64Benchmarks
|
||||
/// PrimeSizedModulus 50.490 ns, SparseOperands 5.239 ns, ZeroOperands 1.986 ns.
|
||||
/// </remarks>
|
||||
[Benchmark]
|
||||
public ulong GpuCompatibleMulModSimplifiedExtension()
|
||||
public ulong MulModGpu()
|
||||
{
|
||||
GpuUInt128 gpuUInt128 = new(Input.Left);
|
||||
return gpuUInt128.MulModSimplified(Input.Right, Input.Modulus);
|
||||
return gpuUInt128.MulMod(Input.Right, Input.Modulus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -900,23 +900,6 @@ public struct GpuUInt128 : IComparable<GpuUInt128>, IEquatable<GpuUInt128>
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly ulong MulMod(ulong value, ulong modulus)
|
||||
{
|
||||
ulong a = Low % modulus;
|
||||
ulong b = value % modulus;
|
||||
|
||||
if (a == 0UL || b == 0UL)
|
||||
{
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
ulong ulongRange = ulong.MaxValue / a;
|
||||
return b <= ulongRange
|
||||
? (a * b) % modulus
|
||||
: MulMod64(a, b, modulus);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly ulong MulModSimplified(ulong value, ulong modulus)
|
||||
{
|
||||
ulong modulusLocal = modulus;
|
||||
ulong a = Low % modulusLocal;
|
||||
|
||||
@@ -19,7 +19,7 @@ public static partial class ULongExtensions
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[Obsolete("Use ULongExtensions.GpuCompatibleMulModSimplifiedExtension for GPU-compatible host code or GpuUInt128.MulMod inside kernels.")]
|
||||
[Obsolete("Use ULongExtensions.MulModGpu for GPU-compatible host code or GpuUInt128.MulMod inside 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,
|
||||
@@ -29,7 +29,7 @@ public static partial class ULongExtensions
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[Obsolete("Use ULongExtensions.GpuCompatibleMulModSimplifiedExtension for GPU-compatible host code or GpuUInt128.MulMod inside kernels.")]
|
||||
[Obsolete("Use ULongExtensions.MulModGpu for GPU-compatible host code or GpuUInt128.MulMod inside kernels.")]
|
||||
public static ulong MulMod64GpuDeferred(this ulong a, ulong b, ulong modulus)
|
||||
{
|
||||
// TODO: Move this deferred helper to the benchmark suite; the baseline MulMod64 avoids the
|
||||
@@ -39,10 +39,10 @@ public static partial class ULongExtensions
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ulong GpuCompatibleMulModSimplifiedExtension(this ulong left, ulong right, ulong modulus)
|
||||
public static ulong MulModGpu(this ulong left, ulong right, ulong modulus)
|
||||
{
|
||||
GpuUInt128 state = new(left);
|
||||
return state.MulModSimplified(right, modulus);
|
||||
return state.MulMod(right, modulus);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -81,7 +81,7 @@ public static partial class ULongExtensions
|
||||
while (index >= 0)
|
||||
{
|
||||
ulong currentBit = (exponent >> index) & 1UL;
|
||||
ulong squared = result.GpuCompatibleMulModSimplifiedExtension(result, modulus);
|
||||
ulong squared = result.MulModGpu(result, modulus);
|
||||
result = currentBit == 0UL ? squared : result;
|
||||
index = currentBit == 0UL ? index - 1 : index;
|
||||
if (currentBit == 0UL)
|
||||
@@ -101,14 +101,14 @@ public static partial class ULongExtensions
|
||||
int windowLength = index - windowStart + 1;
|
||||
for (int square = 0; square < windowLength; square++)
|
||||
{
|
||||
result = result.GpuCompatibleMulModSimplifiedExtension(result, modulus);
|
||||
result = result.MulModGpu(result, modulus);
|
||||
}
|
||||
|
||||
ulong mask = (1UL << windowLength) - 1UL;
|
||||
ulong windowValue = (exponent >> windowStart) & mask;
|
||||
int tableIndex = (int)((windowValue - 1UL) >> 1);
|
||||
ulong multiplier = oddPowers[tableIndex];
|
||||
result = result.GpuCompatibleMulModSimplifiedExtension(multiplier, modulus);
|
||||
result = result.MulModGpu(multiplier, modulus);
|
||||
|
||||
index = windowStart - 1;
|
||||
}
|
||||
@@ -311,11 +311,11 @@ public static partial class ULongExtensions
|
||||
return;
|
||||
}
|
||||
|
||||
ulong square = baseValue.GpuCompatibleMulModSimplifiedExtension(baseValue, modulus);
|
||||
ulong square = baseValue.MulModGpu(baseValue, modulus);
|
||||
for (int i = 1; i < oddPowers.Length; i++)
|
||||
{
|
||||
ulong previous = oddPowers[i - 1];
|
||||
oddPowers[i] = previous.GpuCompatibleMulModSimplifiedExtension(square, modulus);
|
||||
oddPowers[i] = previous.MulModGpu(square, modulus);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
# 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 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.GpuCompatibleMulModSimplifiedExtension` | Wraps `GpuUInt128.MulModSimplified` so host code mirrors the benchmark winner without reimplementing GPU logic.【F:PerfectNumbers.Core/ULongExtensions.Gpu.cs†L23-L31】 |
|
||||
| `ULongExtensions.MulMod64Gpu` | Marked obsolete; migrate to `ULongExtensions.GpuCompatibleMulModSimplifiedExtension` for GPU-compatible host code or `GpuUInt128.MulMod` when running inside kernels.【F:PerfectNumbers.Core/ULongExtensions.Gpu.cs†L17-L24】 |
|
||||
| `ULongExtensions.Pow2ModWindowedGpu` | Migrated to call `GpuCompatibleMulModSimplifiedExtension` for every square and multiply, eliminating the 6–18× slowdown that the shim introduced while executing on the host and aligning host math with the new production helper.【F:PerfectNumbers.Core/ULongExtensions.Gpu.cs†L39-L109】 |
|
||||
| `ULongExtensions.InitializeStandardOddPowers` | Populates the odd-power table through `GpuCompatibleMulModSimplifiedExtension`, so the host setup costs now match the GPU-compatible benchmark winner.【F:PerfectNumbers.Core/ULongExtensions.Gpu.cs†L286-L309】 |
|
||||
|
||||
All host-executed `MulMod` operations in the GPU pipeline now target the optimized CPU helper.
|
||||
|
||||
## GPU kernel and device-side code paths
|
||||
|
||||
| Location | Notes |
|
||||
| --- | --- |
|
||||
| `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†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.
|
||||
Reference in new issue
Block a user