Merge pull request #52 from mlemanczyk/codex/optimize-mersennenumberresiduegputester.scan-method
Restore struct residue args and add benchmarking project
This commit is contained in:
10 files changed
+324
-163
No files matched your search
Vendored
+30
-2
@@ -7,7 +7,8 @@
|
|||||||
"description": "Select project to run",
|
"description": "Select project to run",
|
||||||
"options": [
|
"options": [
|
||||||
"EvenPerfectBitScanner",
|
"EvenPerfectBitScanner",
|
||||||
"EvenPerfectBitScanner.ResultsParser"
|
"EvenPerfectBitScanner.ResultsParser",
|
||||||
|
"EvenPerfectBitScanner.Benchmarks"
|
||||||
],
|
],
|
||||||
"default": "EvenPerfectBitScanner"
|
"default": "EvenPerfectBitScanner"
|
||||||
}
|
}
|
||||||
@@ -20,7 +21,7 @@
|
|||||||
"preLaunchTask": "Build Debug",
|
"preLaunchTask": "Build Debug",
|
||||||
"program": "${workspaceFolder}/${input:projectName}/bin/Debug/net8.0/${input:projectName}.dll",
|
"program": "${workspaceFolder}/${input:projectName}/bin/Debug/net8.0/${input:projectName}.dll",
|
||||||
"args": [
|
"args": [
|
||||||
"--increment=add --mersenne=residue --threads=128 --gpu-scan-batch=512000 --primes-device=gpu --mersenne-device=gpu --mod-reduction=barrett128 --block-size=10000000 --gpu-prime-threads=32 --write-batch-size=10000 --divisor-cycles-device=gpu"
|
"--increment=add --mersenne=residue --threads=128 --gpu-scan-batch=512000 --primes-device=gpu --mersenne-device=gpu --mod-reduction=barrett128 --block-size=10000000 --gpu-prime-threads=32 --write-batch-size=10000 --divisor-cycles-device=gpu"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
@@ -93,6 +94,33 @@
|
|||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"internalConsoleOptions": "neverOpen",
|
"internalConsoleOptions": "neverOpen",
|
||||||
"justMyCode": false
|
"justMyCode": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Run EvenPerfectBitScanner.Benchmarks",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "launch",
|
||||||
|
"noDebug": true,
|
||||||
|
"preLaunchTask": "Build EvenPerfectBitScanner.Benchmarks Release",
|
||||||
|
"program": "${workspaceFolder}/EvenPerfectBitScanner.Benchmarks/bin/Release/net8.0/EvenPerfectBitScanner.Benchmarks.dll",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"internalConsoleOptions": "neverOpen",
|
||||||
|
"justMyCode": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Debug EvenPerfectBitScanner.Benchmarks",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "Build EvenPerfectBitScanner.Benchmarks Debug",
|
||||||
|
"program": "${workspaceFolder}/EvenPerfectBitScanner.Benchmarks/bin/Debug/net8.0/EvenPerfectBitScanner.Benchmarks.dll",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"internalConsoleOptions": "neverOpen",
|
||||||
|
"justMyCode": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Vendored
+123
-78
@@ -1,66 +1,66 @@
|
|||||||
{
|
{
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"label": "Build Debug",
|
"label": "Build Debug",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"${workspaceFolder}/EvenPerfectScanner.sln",
|
"${workspaceFolder}/EvenPerfectScanner.sln",
|
||||||
"--configuration",
|
"--configuration",
|
||||||
"Debug",
|
"Debug",
|
||||||
"--framework",
|
"--framework",
|
||||||
"net8.0"
|
"net8.0"
|
||||||
],
|
],
|
||||||
"group": {
|
"group": {
|
||||||
"kind": "build",
|
"kind": "build",
|
||||||
"isDefault": false
|
"isDefault": false
|
||||||
},
|
},
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Build Release",
|
"label": "Build Release",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"${workspaceFolder}/EvenPerfectScanner.sln",
|
"${workspaceFolder}/EvenPerfectScanner.sln",
|
||||||
"--configuration",
|
"--configuration",
|
||||||
"Release",
|
"Release",
|
||||||
"--framework",
|
"--framework",
|
||||||
"net8.0"
|
"net8.0"
|
||||||
],
|
],
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Build EvenPerfectBitScanner Debug",
|
"label": "Build EvenPerfectBitScanner Debug",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"${workspaceFolder}/EvenPerfectBitScanner/EvenPerfectBitScanner.csproj",
|
"${workspaceFolder}/EvenPerfectBitScanner/EvenPerfectBitScanner.csproj",
|
||||||
"--configuration",
|
"--configuration",
|
||||||
"Debug",
|
"Debug",
|
||||||
"--framework",
|
"--framework",
|
||||||
"net8.0"
|
"net8.0"
|
||||||
],
|
],
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Build EvenPerfectBitScanner Release",
|
"label": "Build EvenPerfectBitScanner Release",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"${workspaceFolder}/EvenPerfectBitScanner/EvenPerfectBitScanner.csproj",
|
"${workspaceFolder}/EvenPerfectBitScanner/EvenPerfectBitScanner.csproj",
|
||||||
"--configuration",
|
"--configuration",
|
||||||
"Release",
|
"Release",
|
||||||
"--framework",
|
"--framework",
|
||||||
"net8.0"
|
"net8.0"
|
||||||
],
|
],
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
},
|
},
|
||||||
@@ -97,16 +97,16 @@
|
|||||||
{
|
{
|
||||||
"label": "Run EvenPerfectBitScanner",
|
"label": "Run EvenPerfectBitScanner",
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
"--project",
|
"--project",
|
||||||
"${workspaceFolder}/EvenPerfectBitScanner/EvenPerfectBitScanner.csproj",
|
"${workspaceFolder}/EvenPerfectBitScanner/EvenPerfectBitScanner.csproj",
|
||||||
"--configuration",
|
"--configuration",
|
||||||
"Release",
|
"Release",
|
||||||
"--framework",
|
"--framework",
|
||||||
"net8.0"
|
"net8.0"
|
||||||
],
|
],
|
||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -124,18 +124,63 @@
|
|||||||
],
|
],
|
||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Run Release (no debug)",
|
"label": "Run Release (no debug)",
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"run",
|
"run",
|
||||||
"--configuration",
|
"--configuration",
|
||||||
"Release",
|
"Release",
|
||||||
"--framework",
|
"--framework",
|
||||||
"net8.0"
|
"net8.0"
|
||||||
],
|
],
|
||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
}
|
},
|
||||||
]
|
{
|
||||||
|
"label": "Build EvenPerfectBitScanner.Benchmarks Debug",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"${workspaceFolder}/EvenPerfectBitScanner.Benchmarks/EvenPerfectBitScanner.Benchmarks.csproj",
|
||||||
|
"--configuration",
|
||||||
|
"Debug",
|
||||||
|
"--framework",
|
||||||
|
"net8.0"
|
||||||
|
],
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build EvenPerfectBitScanner.Benchmarks Release",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"${workspaceFolder}/EvenPerfectBitScanner.Benchmarks/EvenPerfectBitScanner.Benchmarks.csproj",
|
||||||
|
"--configuration",
|
||||||
|
"Release",
|
||||||
|
"--framework",
|
||||||
|
"net8.0"
|
||||||
|
],
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Run EvenPerfectBitScanner.Benchmarks",
|
||||||
|
"type": "process",
|
||||||
|
"command": "dotnet",
|
||||||
|
"args": [
|
||||||
|
"run",
|
||||||
|
"--project",
|
||||||
|
"${workspaceFolder}/EvenPerfectBitScanner.Benchmarks/EvenPerfectBitScanner.Benchmarks.csproj",
|
||||||
|
"--configuration",
|
||||||
|
"Release",
|
||||||
|
"--framework",
|
||||||
|
"net8.0"
|
||||||
|
],
|
||||||
|
"problemMatcher": []
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="../PerfectNumbers.Core/PerfectNumbers.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="BenchmarkDotNet" Version="0.13.12" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using BenchmarkDotNet.Running;
|
||||||
|
|
||||||
|
namespace EvenPerfectBitScanner.Benchmarks;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using PerfectNumbers.Core;
|
||||||
|
|
||||||
|
namespace EvenPerfectBitScanner.Benchmarks;
|
||||||
|
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
public class ResidueComputationBenchmarks
|
||||||
|
{
|
||||||
|
[Params(3UL, 8191UL, 131071UL, 2147483647UL)]
|
||||||
|
public ulong Exponent { get; set; }
|
||||||
|
|
||||||
|
[Benchmark(Baseline = true)]
|
||||||
|
public (ulong Step10, ulong Step8, ulong Step3, ulong Step5) LegacyModulo()
|
||||||
|
{
|
||||||
|
ulong exponent = Exponent;
|
||||||
|
ulong step10 = ((exponent % 10UL) << 1) % 10UL;
|
||||||
|
ulong step8 = ((exponent & 7UL) << 1) & 7UL;
|
||||||
|
ulong step3 = ((exponent % 3UL) << 1) % 3UL;
|
||||||
|
ulong step5 = ((exponent % 5UL) << 1) % 5UL;
|
||||||
|
return (step10, step8, step3, step5);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public (ulong Step10, ulong Step8, ulong Step3, ulong Step5) ModMethodModulo()
|
||||||
|
{
|
||||||
|
UInt128 exponent128 = Exponent;
|
||||||
|
exponent128.Mod10_8_5_3(out ulong mod10, out ulong mod8, out ulong mod5, out ulong mod3);
|
||||||
|
ulong step10 = (mod10 << 1) % 10UL;
|
||||||
|
ulong step8 = (mod8 << 1) & 7UL;
|
||||||
|
ulong step3 = (mod3 << 1) % 3UL;
|
||||||
|
ulong step5 = (mod5 << 1) % 5UL;
|
||||||
|
return (step10, step8, step3, step5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -12,6 +12,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EvenPerfectBitScanner.Tests
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EvenPerfectBitScanner.ResultsParser", "EvenPerfectBitScanner.ResultsParser\EvenPerfectBitScanner.ResultsParser.csproj", "{B07A718C-A71C-410D-A0D7-FA1674CEB38F}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EvenPerfectBitScanner.ResultsParser", "EvenPerfectBitScanner.ResultsParser\EvenPerfectBitScanner.ResultsParser.csproj", "{B07A718C-A71C-410D-A0D7-FA1674CEB38F}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EvenPerfectBitScanner.Benchmarks", "EvenPerfectBitScanner.Benchmarks\EvenPerfectBitScanner.Benchmarks.csproj", "{83551FCC-41FA-4162-B541-AFCB5666A29F}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -41,5 +43,9 @@ Global
|
|||||||
{B07A718C-A71C-410D-A0D7-FA1674CEB38F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{B07A718C-A71C-410D-A0D7-FA1674CEB38F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{B07A718C-A71C-410D-A0D7-FA1674CEB38F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{B07A718C-A71C-410D-A0D7-FA1674CEB38F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{B07A718C-A71C-410D-A0D7-FA1674CEB38F}.Release|Any CPU.Build.0 = Release|Any CPU
|
{B07A718C-A71C-410D-A0D7-FA1674CEB38F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{83551FCC-41FA-4162-B541-AFCB5666A29F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{83551FCC-41FA-4162-B541-AFCB5666A29F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{83551FCC-41FA-4162-B541-AFCB5666A29F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{83551FCC-41FA-4162-B541-AFCB5666A29F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
@@ -158,7 +158,7 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<uint, Stride1D.Dense>> IncrementalOrderKernel
|
public readonly Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<uint, Stride1D.Dense>> IncrementalOrderKernel
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@@ -175,7 +175,7 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<uint, Stride1D.Dense>> Pow2ModOrderKernel
|
public readonly Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<uint, Stride1D.Dense>> Pow2ModOrderKernel
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@@ -486,7 +486,7 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void IncrementalOrderKernelScan(Index1D index, ulong exponent, GpuUInt128 twoP, GpuUInt128 kStart, byte lastIsSeven, ulong divMul,
|
private static void IncrementalOrderKernelScan(Index1D index, ulong exponent, GpuUInt128 twoP, GpuUInt128 kStart, byte lastIsSeven, ulong divMul,
|
||||||
ResidueAutomatonArgs ra, ArrayView<int> found, ArrayView1D<uint, Stride1D.Dense> smallCycles)
|
ResidueAutomatonArgs ra, ArrayView<int> found, ArrayView1D<uint, Stride1D.Dense> smallCycles)
|
||||||
{
|
{
|
||||||
ulong idx = (ulong)index.X;
|
ulong idx = (ulong)index.X;
|
||||||
ulong r10 = ra.Q0M10 + (ra.Step10 * idx) % 10UL; r10 -= (r10 >= 10UL) ? 10UL : 0UL;
|
ulong r10 = ra.Q0M10 + (ra.Step10 * idx) % 10UL; r10 -= (r10 >= 10UL) ? 10UL : 0UL;
|
||||||
@@ -570,7 +570,7 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void Pow2ModOrderKernelScan(Index1D index, ulong exponent, GpuUInt128 twoP, GpuUInt128 kStart, byte lastIsSeven, ulong _,
|
private static void Pow2ModOrderKernelScan(Index1D index, ulong exponent, GpuUInt128 twoP, GpuUInt128 kStart, byte lastIsSeven, ulong _,
|
||||||
ResidueAutomatonArgs ra, ArrayView<int> found, ArrayView1D<uint, Stride1D.Dense> smallCycles)
|
ResidueAutomatonArgs ra, ArrayView<int> found, ArrayView1D<uint, Stride1D.Dense> smallCycles)
|
||||||
{
|
{
|
||||||
ulong idx = (ulong)index.X;
|
ulong idx = (ulong)index.X;
|
||||||
ulong r10 = ra.Q0M10 + (ra.Step10 * idx) % 10UL; r10 -= (r10 >= 10UL) ? 10UL : 0UL;
|
ulong r10 = ra.Q0M10 + (ra.Step10 * idx) % 10UL; r10 -= (r10 >= 10UL) ? 10UL : 0UL;
|
||||||
|
|||||||
@@ -23,10 +23,12 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
|
|||||||
|
|
||||||
var pow2Kernel = gpuLease.Pow2ModKernel;
|
var pow2Kernel = gpuLease.Pow2ModKernel;
|
||||||
var incKernel = gpuLease.IncrementalKernel;
|
var incKernel = gpuLease.IncrementalKernel;
|
||||||
ulong step10 = ((exponent % 10UL) << 1) % 10UL;
|
UInt128 exponent128 = exponent;
|
||||||
ulong step8 = ((exponent & 7UL) << 1) & 7UL;
|
exponent128.Mod10_8_5_3(out ulong exponentMod10, out ulong exponentMod8, out ulong exponentMod5, out ulong exponentMod3);
|
||||||
ulong step3 = ((exponent % 3UL) << 1) % 3UL;
|
ulong step10 = (exponentMod10 << 1) % 10UL;
|
||||||
ulong step5 = ((exponent % 5UL) << 1) % 5UL;
|
ulong step8 = (exponentMod8 << 1) & 7UL;
|
||||||
|
ulong step3 = (exponentMod3 << 1) % 3UL;
|
||||||
|
ulong step5 = (exponentMod5 << 1) % 5UL;
|
||||||
GpuUInt128 twoPGpu = (GpuUInt128)twoP;
|
GpuUInt128 twoPGpu = (GpuUInt128)twoP;
|
||||||
var smallCyclesView = GpuKernelPool.EnsureSmallCyclesOnDevice(accelerator);
|
var smallCyclesView = GpuKernelPool.EnsureSmallCyclesOnDevice(accelerator);
|
||||||
ResiduePrimeViews primeViews = default;
|
ResiduePrimeViews primeViews = default;
|
||||||
@@ -55,9 +57,9 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
|
|||||||
if (_kernelType == GpuKernelType.Pow2Mod)
|
if (_kernelType == GpuKernelType.Pow2Mod)
|
||||||
{
|
{
|
||||||
q0.Mod10_8_5_3(out ulong q0m10, out ulong q0m8, out ulong q0m5, out ulong q0m3);
|
q0.Mod10_8_5_3(out ulong q0m10, out ulong q0m8, out ulong q0m5, out ulong q0m3);
|
||||||
var ra = new ResidueAutomatonArgs(q0m10, step10, q0m8, step8, q0m3, step3, q0m5, step5);
|
var kernelArgs = new ResidueAutomatonArgs(q0m10, step10, q0m8, step8, q0m3, step3, q0m5, step5);
|
||||||
pow2Kernel(stream, currentSize, exponent, twoPGpu, (GpuUInt128)kStart, last, divMul,
|
pow2Kernel(stream, currentSize, exponent, twoPGpu, (GpuUInt128)kStart, last, divMul,
|
||||||
ra, orderBuffer.View, smallCyclesView, primeViews.LastOne, primeViews.LastSeven,
|
kernelArgs, orderBuffer.View, smallCyclesView, primeViews.LastOne, primeViews.LastSeven,
|
||||||
primeViews.LastOnePow2, primeViews.LastSevenPow2);
|
primeViews.LastOnePow2, primeViews.LastSevenPow2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -25,6 +25,12 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
|
|||||||
};
|
};
|
||||||
|
|
||||||
var foundBuffer = accelerator.Allocate1D<int>(1);
|
var foundBuffer = accelerator.Allocate1D<int>(1);
|
||||||
|
UInt128 exponent128 = exponent;
|
||||||
|
exponent128.Mod10_8_5_3(out ulong exponentMod10, out ulong exponentMod8, out ulong exponentMod5, out ulong exponentMod3);
|
||||||
|
ulong step10 = (exponentMod10 << 1) % 10UL;
|
||||||
|
ulong step8 = (exponentMod8 << 1) & 7UL;
|
||||||
|
ulong step3 = (exponentMod3 << 1) % 3UL;
|
||||||
|
ulong step5 = (exponentMod5 << 1) % 5UL;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
UInt128 remaining;
|
UInt128 remaining;
|
||||||
@@ -37,21 +43,14 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO
|
|||||||
foundBuffer.MemSetToZero();
|
foundBuffer.MemSetToZero();
|
||||||
// Precompute residue automaton bases for this batch
|
// Precompute residue automaton bases for this batch
|
||||||
UInt128 q0 = twoP * kStart + 1UL;
|
UInt128 q0 = twoP * kStart + 1UL;
|
||||||
ulong q0m10 = q0.Mod10();
|
q0.Mod10_8_5_3(out ulong q0m10, out ulong q0m8, out ulong q0m5, out ulong q0m3);
|
||||||
ulong q0m8 = q0.Mod8();
|
var kernelArgs = new ResidueAutomatonArgs(q0m10, step10, q0m8, step8, q0m3, step3, q0m5, step5);
|
||||||
ulong q0m3 = q0.Mod3();
|
|
||||||
ulong q0m5 = q0.Mod5();
|
|
||||||
ulong step10 = ((exponent % 10UL) << 1) % 10UL;
|
|
||||||
ulong step8 = ((exponent & 7UL) << 1) & 7UL;
|
|
||||||
ulong step3 = ((exponent % 3UL) << 1) % 3UL;
|
|
||||||
ulong step5 = ((exponent % 5UL) << 1) % 5UL;
|
|
||||||
var ra = new ResidueAutomatonArgs(q0m10, step10, q0m8, step8, q0m3, step3, q0m5, step5);
|
|
||||||
|
|
||||||
|
|
||||||
// Ensure device has small cycles table for early rejections in order kernels
|
// Ensure device has small cycles table for early rejections in order kernels
|
||||||
var smallCyclesView = GpuKernelPool.EnsureSmallCyclesOnDevice(accelerator);
|
var smallCyclesView = GpuKernelPool.EnsureSmallCyclesOnDevice(accelerator);
|
||||||
kernel(stream, currentSize, exponent, (GpuUInt128)twoP, (GpuUInt128)kStart, last, divMul,
|
kernel(stream, currentSize, exponent, (GpuUInt128)twoP, (GpuUInt128)kStart, last, divMul,
|
||||||
ra, foundBuffer.View, smallCyclesView);
|
kernelArgs, foundBuffer.View, smallCyclesView);
|
||||||
|
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
foundBuffer.View.CopyToCPU(ref found, 1);
|
foundBuffer.View.CopyToCPU(ref found, 1);
|
||||||
|
|||||||
@@ -20,74 +20,89 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
|||||||
// Ensure device has small cycles and primes tables for in-kernel lookup
|
// Ensure device has small cycles and primes tables for in-kernel lookup
|
||||||
var smallCyclesView = GpuKernelPool.EnsureSmallCyclesOnDevice(accelerator);
|
var smallCyclesView = GpuKernelPool.EnsureSmallCyclesOnDevice(accelerator);
|
||||||
ResiduePrimeViews primeViews = GpuKernelPool.EnsureSmallPrimesOnDevice(accelerator);
|
ResiduePrimeViews primeViews = GpuKernelPool.EnsureSmallPrimesOnDevice(accelerator);
|
||||||
int batchSize = GpuConstants.ScanBatchSize;
|
int batchSize = GpuConstants.ScanBatchSize;
|
||||||
UInt128 kStart = 1UL;
|
UInt128 kStart = 1UL;
|
||||||
byte last = lastIsSeven ? (byte)1 : (byte)0;
|
byte last = lastIsSeven ? (byte)1 : (byte)0;
|
||||||
var kernel = gpuLease.Pow2ModKernel;
|
var kernel = gpuLease.Pow2ModKernel;
|
||||||
ulong step10 = ((exponent % 10UL) << 1) % 10UL;
|
UInt128 exponent128 = exponent;
|
||||||
ulong step8 = ((exponent & 7UL) << 1) & 7UL;
|
exponent128.Mod10_8_5_3(out ulong exponentMod10, out ulong exponentMod8, out ulong exponentMod5, out ulong exponentMod3);
|
||||||
ulong step3 = ((exponent % 3UL) << 1) % 3UL;
|
ulong step10 = (exponentMod10 << 1) % 10UL;
|
||||||
ulong step5 = ((exponent % 5UL) << 1) % 5UL;
|
ulong step8 = (exponentMod8 << 1) & 7UL;
|
||||||
GpuUInt128 twoPGpu = (GpuUInt128)twoP;
|
ulong step3 = (exponentMod3 << 1) % 3UL;
|
||||||
|
ulong step5 = (exponentMod5 << 1) % 5UL;
|
||||||
|
GpuUInt128 twoPGpu = (GpuUInt128)twoP;
|
||||||
|
|
||||||
var orderBuffer = accelerator.Allocate1D<ulong>(batchSize);
|
var orderBuffer = accelerator.Allocate1D<ulong>(batchSize);
|
||||||
// Device memory returned by Allocate1D is not guaranteed to be zeroed.
|
// Device memory returned by Allocate1D is not guaranteed to be zeroed.
|
||||||
// Ensure the buffer starts with a known state so that lanes skipped by the
|
// Ensure the buffer starts with a known state so that lanes skipped by the
|
||||||
// kernel (for example due to early rejections) do not leave stale garbage
|
// kernel (for example due to early rejections) do not leave stale garbage
|
||||||
// values that would be interpreted as composite witnesses when copied back
|
// values that would be interpreted as composite witnesses when copied back
|
||||||
// to the host. This mirrors the explicit zeroing performed by other GPU
|
// to the host. This mirrors the explicit zeroing performed by other GPU
|
||||||
// testers such as the order kernels.
|
// testers such as the order kernels.
|
||||||
orderBuffer.MemSetToZero();
|
orderBuffer.MemSetToZero();
|
||||||
ulong[] orderArray = ArrayPool<ulong>.Shared.Rent(batchSize);
|
ulong[] orderArray = ArrayPool<ulong>.Shared.Rent(batchSize);
|
||||||
UInt128 remaining;
|
UInt128 batchSize128 = (UInt128)batchSize;
|
||||||
int currentSize;
|
UInt128 fullBatchStep = twoP * batchSize128;
|
||||||
int i;
|
UInt128 q = twoP * kStart + UInt128.One;
|
||||||
UInt128 batchSize128 = (UInt128)batchSize, q;
|
|
||||||
Span<ulong> orders = orderArray.AsSpan(0, batchSize);
|
|
||||||
ref var ordersRef = ref MemoryMarshal.GetReference(orders);
|
|
||||||
while (kStart < maxK && Volatile.Read(ref isPrime))
|
|
||||||
{
|
|
||||||
remaining = maxK - kStart;
|
|
||||||
if (remaining > batchSize128)
|
|
||||||
{
|
|
||||||
currentSize = batchSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
currentSize = (int)remaining;
|
|
||||||
orders = orderArray.AsSpan(0, currentSize);
|
|
||||||
ordersRef = ref MemoryMarshal.GetReference(orders);
|
|
||||||
}
|
|
||||||
|
|
||||||
q = twoP * kStart + UInt128.One;
|
try
|
||||||
q.Mod10_8_5_3(out ulong q0m10, out ulong q0m8, out ulong q0m5, out ulong q0m3);
|
{
|
||||||
var ra = new ResidueAutomatonArgs(q0m10, step10, q0m8, step8, q0m3, step3, q0m5, step5);
|
while (kStart < maxK && Volatile.Read(ref isPrime))
|
||||||
|
{
|
||||||
|
UInt128 remaining = maxK - kStart;
|
||||||
|
int currentSize = remaining > batchSize128 ? batchSize : (int)remaining;
|
||||||
|
Span<ulong> orders = orderArray.AsSpan(0, currentSize);
|
||||||
|
ref ulong ordersRef = ref MemoryMarshal.GetReference(orders);
|
||||||
|
|
||||||
kernel(stream, currentSize, exponent, twoPGpu, (GpuUInt128)kStart, last, 0UL,
|
q.Mod10_8_5_3(out ulong q0m10, out ulong q0m8, out ulong q0m5, out ulong q0m3);
|
||||||
ra, orderBuffer.View, smallCyclesView, primeViews.LastOne, primeViews.LastSeven, primeViews.LastOnePow2, primeViews.LastSevenPow2);
|
var kernelArgs = new ResidueAutomatonArgs(q0m10, step10, q0m8, step8, q0m3, step3, q0m5, step5);
|
||||||
|
|
||||||
accelerator.Synchronize();
|
kernel(stream, currentSize, exponent, twoPGpu, (GpuUInt128)kStart, last, 0UL,
|
||||||
orderBuffer.View.CopyToCPU(ref ordersRef, currentSize);
|
kernelArgs, orderBuffer.View, smallCyclesView, primeViews.LastOne, primeViews.LastSeven, primeViews.LastOnePow2, primeViews.LastSevenPow2);
|
||||||
if (!Volatile.Read(ref isPrime))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < currentSize; i++)
|
accelerator.Synchronize();
|
||||||
{
|
orderBuffer.View.CopyToCPU(ref ordersRef, currentSize);
|
||||||
if (orders[i] != 0UL)
|
if (!Volatile.Read(ref isPrime))
|
||||||
{
|
{
|
||||||
Volatile.Write(ref isPrime, false);
|
break;
|
||||||
goto cleanup;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kStart += batchSize128;
|
bool compositeFound = false;
|
||||||
}
|
for (int i = 0; i < currentSize; i++)
|
||||||
|
{
|
||||||
|
if (orders[i] != 0UL)
|
||||||
|
{
|
||||||
|
Volatile.Write(ref isPrime, false);
|
||||||
|
compositeFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cleanup:
|
if (compositeFound)
|
||||||
ArrayPool<ulong>.Shared.Return(orderArray);
|
{
|
||||||
orderBuffer.Dispose();
|
break;
|
||||||
gpuLease.Dispose();
|
}
|
||||||
}
|
|
||||||
|
UInt128 processed = (UInt128)currentSize;
|
||||||
|
kStart += processed;
|
||||||
|
if (kStart < maxK)
|
||||||
|
{
|
||||||
|
if (processed == batchSize128)
|
||||||
|
{
|
||||||
|
q += fullBatchStep;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
q += twoP * processed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
ArrayPool<ulong>.Shared.Return(orderArray);
|
||||||
|
orderBuffer.Dispose();
|
||||||
|
gpuLease.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user