diff --git a/EvenPerfectBitScanner.Tests/ProgramTests.cs b/EvenPerfectBitScanner.Tests/ProgramTests.cs index ac76716..83f1d88 100644 --- a/EvenPerfectBitScanner.Tests/ProgramTests.cs +++ b/EvenPerfectBitScanner.Tests/ProgramTests.cs @@ -227,7 +227,7 @@ public class ProgramTests var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!; - mersenneField.SetValue(null, new ThreadLocal(() => new MersenneNumberTesterForResidueCalculationMethodForCpu( maxK: 1_000UL), trackAllValues: true)); + mersenneField.SetValue(null, new ThreadLocal(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu( maxK: 1_000UL), trackAllValues: true)); primeField.SetValue(null, new ThreadLocal(() => new PrimeTester(), trackAllValues: true)); CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal(() => new ModResidueTracker(ResidueModel.Identity, 2UL, true), trackAllValues: true)); @@ -260,7 +260,7 @@ public class ProgramTests var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!; - mersenneField.SetValue(null, new ThreadLocal(() => new MersenneNumberTesterForResidueCalculationMethodForCpu( + mersenneField.SetValue(null, new ThreadLocal(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu( maxK: 1_024UL), trackAllValues: true)); primeField.SetValue(null, new ThreadLocal(() => new PrimeTester(), trackAllValues: true)); @@ -296,7 +296,7 @@ public class ProgramTests var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!; - mersenneField.SetValue(null, new ThreadLocal(() => new MersenneNumberTesterForResidueCalculationMethodForCpu( + mersenneField.SetValue(null, new ThreadLocal(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu( maxK: 5_000_000UL), trackAllValues: true)); primeField.SetValue(null, new ThreadLocal(() => new PrimeTester(), trackAllValues: true)); @@ -331,7 +331,7 @@ public class ProgramTests var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!; - mersenneField.SetValue(null, new ThreadLocal(() => new MersenneNumberTesterForResidueCalculationMethodForCpu( + mersenneField.SetValue(null, new ThreadLocal(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu( maxK: 5_000_000UL), trackAllValues: true)); primeField.SetValue(null, new ThreadLocal(() => new PrimeTester(), trackAllValues: true)); @@ -367,10 +367,8 @@ public class ProgramTests var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!; - mersenneField.SetValue(null, new ThreadLocal(() => new MersenneNumberTesterForResidueCalculationMethodForCpu( + mersenneField.SetValue(null, new ThreadLocal(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu( - useGpuScan: false, - useGpuOrder: false, maxK: 1_024UL), trackAllValues: true)); primeField.SetValue(null, new ThreadLocal(() => new PrimeTester(), trackAllValues: true)); CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal(() => new ModResidueTracker(ResidueModel.Identity, exponent, true), trackAllValues: true)); @@ -402,12 +400,21 @@ public class ProgramTests var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!; - mersenneField.SetValue(null, new ThreadLocal(() => new MersenneNumberTesterForResidueCalculationMethodForCpu( - - kernelType: configuration.KernelType, - useGpuScan: true, - useGpuOrder: configuration.UseGpuOrder, - maxK: configuration.ResidueMaxK), trackAllValues: true)); + mersenneField.SetValue(null, new ThreadLocal(() => + { + if (configuration.UseGpuOrder) + { + return new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu( + + kernelType: configuration.KernelType, + maxK: configuration.ResidueMaxK); + } + + return new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu( + + kernelType: configuration.KernelType, + maxK: configuration.ResidueMaxK); + }, trackAllValues: true)); primeField.SetValue(null, new ThreadLocal(() => new PrimeTester(), trackAllValues: true)); CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal(() => new ModResidueTracker(ResidueModel.Identity, exponent, true), trackAllValues: true)); @@ -488,7 +495,7 @@ public class ProgramTests var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var compositeField = typeof(Program).GetField("_lastCompositeP", BindingFlags.NonPublic | BindingFlags.Static)!; - mersenneField.SetValue(null, new ThreadLocal(() => new MersenneNumberTesterForIncrementalCalculationMethodForCpu( maxK: 1_000UL), trackAllValues: true)); + mersenneField.SetValue(null, new ThreadLocal(() => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu( maxK: 1_000UL), trackAllValues: true)); primeField.SetValue(null, new ThreadLocal(() => new PrimeTester(), trackAllValues: true)); CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal(() => new ModResidueTracker(ResidueModel.Identity, 2UL, true), trackAllValues: true)); diff --git a/EvenPerfectBitScanner/Program.cs b/EvenPerfectBitScanner/Program.cs index 55a7adf..d9d17be 100644 --- a/EvenPerfectBitScanner/Program.cs +++ b/EvenPerfectBitScanner/Program.cs @@ -28,7 +28,8 @@ private static ThreadLocal? MersenneTesters; private static int _testTargetPrimeCount; private static int _testProcessedPrimeCount; private static ComputationDevice _mersenneDevice; - private static ComputationDevice _orderDevice; + private static OrderDevice _orderCalculationDevice; + private static CacheStatus _cacheStatus; private static CalculationMethod _calculationMethod; [ThreadStatic] @@ -99,17 +100,18 @@ private static ThreadLocal? MersenneTesters; : (useResidue ? PrimeTransformMode.Add : PrimeTransformMode.AddPrimes); CandidatesCalculator.Configure(transformMode); ComputationDevice mersenneDevice = _cliArguments.MersenneDevice; - ComputationDevice orderDevice = EnvironmentConfiguration.OrderDevice; _mersenneDevice = mersenneDevice; - _orderDevice = orderDevice; _calculationMethod = useResidue ? CalculationMethod.Residue - : (useLucas - ? CalculationMethod.LucasLehmer - : (useOrder ? CalculationMethod.Divisor : CalculationMethod.Incremental)); + : (useLucas + ? CalculationMethod.LucasLehmer + : (useOrder ? CalculationMethod.Divisor : CalculationMethod.Incremental)); bool mersenneOnGpu = mersenneDevice == ComputationDevice.Gpu; - bool orderOnGpu = EnvironmentConfiguration.UseGpuOrder; - bool orderOnHybrid = EnvironmentConfiguration.UseHybridOrder; + OrderDevice orderCalculationDevice = EnvironmentConfiguration.UseGpuOrder + ? OrderDevice.Gpu + : (EnvironmentConfiguration.UseHybridOrder ? OrderDevice.Hybrid : OrderDevice.Cpu); + _orderCalculationDevice = orderCalculationDevice; + _cacheStatus = CacheStatus.Disabled; int sliceSize = Math.Max(1, _cliArguments.SliceSize); ulong residueKMax = _cliArguments.ResidueKMax; string filterFile = _cliArguments.FilterFile; @@ -228,18 +230,15 @@ private static ThreadLocal? MersenneTesters; { object tester = CreateMersenneTester( _calculationMethod, - orderDevice, + _cacheStatus, + _orderCalculationDevice, + mersenneDevice, kernelType, - useLucas, - useOrder, - mersenneOnGpu, - orderOnGpu, - orderOnHybrid, residueKMax); if (!useLucas) { Console.WriteLine("Warming up orders"); - WarmUpOrders(tester, orderDevice, currentP, orderWarmupLimitOverride ?? 5_000_000UL); + WarmUpOrders(tester, _orderCalculationDevice, _mersenneDevice, currentP, orderWarmupLimitOverride ?? 5_000_000UL); } return tester; @@ -303,10 +302,10 @@ private static ThreadLocal? MersenneTesters; _ => "cpu", }; - string orderDeviceLabel = orderDevice switch + string orderDeviceLabel = _orderCalculationDevice switch { - ComputationDevice.Hybrid => "hybrid", - ComputationDevice.Gpu => "gpu", + OrderDevice.Hybrid => "hybrid", + OrderDevice.Gpu => "gpu", _ => "cpu", }; @@ -543,7 +542,7 @@ private static ThreadLocal? MersenneTesters; if (!useLucas) { Console.WriteLine("Warming up orders..."); - WarmUpOrders(MersenneTesters.Value!, orderDevice, currentP, orderWarmupLimitOverride ?? 5_000_000UL); + WarmUpOrders(MersenneTesters.Value!, _orderCalculationDevice, _mersenneDevice, currentP, orderWarmupLimitOverride ?? 5_000_000UL); } } @@ -653,299 +652,155 @@ private static ThreadLocal? MersenneTesters; private static bool IsMersennePrime(PrimeOrderCalculatorAccelerator gpu, ulong exponent) { object tester = MersenneTesters!.Value!; - return (_calculationMethod, _orderDevice) switch + return (_calculationMethod, _orderCalculationDevice, _mersenneDevice) switch { - (CalculationMethod.Residue, ComputationDevice.Gpu) => ((MersenneNumberTesterForResidueCalculationMethodForGpu)tester).IsMersennePrime(gpu, exponent), - (CalculationMethod.Residue, ComputationDevice.Hybrid) => ((MersenneNumberTesterForResidueCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent), - (CalculationMethod.Residue, _) => ((MersenneNumberTesterForResidueCalculationMethodForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Residue, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Residue, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Residue, OrderDevice.Gpu, _) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Residue, OrderDevice.Hybrid, ComputationDevice.Gpu) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Residue, OrderDevice.Hybrid, ComputationDevice.Hybrid) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Residue, OrderDevice.Hybrid, _) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Residue, _, ComputationDevice.Gpu) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Residue, _, ComputationDevice.Hybrid) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Residue, _, _) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), - (CalculationMethod.LucasLehmer, ComputationDevice.Gpu) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForGpu)tester).IsMersennePrime(gpu, exponent), - (CalculationMethod.LucasLehmer, ComputationDevice.Hybrid) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent), - (CalculationMethod.LucasLehmer, _) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.LucasLehmer, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.LucasLehmer, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.LucasLehmer, OrderDevice.Gpu, _) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.LucasLehmer, OrderDevice.Hybrid, ComputationDevice.Gpu) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.LucasLehmer, OrderDevice.Hybrid, ComputationDevice.Hybrid) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.LucasLehmer, OrderDevice.Hybrid, _) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.LucasLehmer, _, ComputationDevice.Gpu) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.LucasLehmer, _, ComputationDevice.Hybrid) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.LucasLehmer, _, _) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), - (CalculationMethod.Divisor, ComputationDevice.Gpu) => ((MersenneNumberTesterForDivisorCalculationMethodForGpu)tester).IsMersennePrime(gpu, exponent), - (CalculationMethod.Divisor, ComputationDevice.Hybrid) => ((MersenneNumberTesterForDivisorCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent), - (CalculationMethod.Divisor, _) => ((MersenneNumberTesterForDivisorCalculationMethodForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Divisor, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Divisor, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Divisor, OrderDevice.Gpu, _) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Divisor, OrderDevice.Hybrid, ComputationDevice.Gpu) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Divisor, OrderDevice.Hybrid, ComputationDevice.Hybrid) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Divisor, OrderDevice.Hybrid, _) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Divisor, _, ComputationDevice.Gpu) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Divisor, _, ComputationDevice.Hybrid) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Divisor, _, _) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), - (CalculationMethod.ByDivisor, ComputationDevice.Gpu) => ((MersenneNumberTesterForByDivisorCalculationMethodForGpu)tester).IsMersennePrime(gpu, exponent), - (CalculationMethod.ByDivisor, ComputationDevice.Hybrid) => ((MersenneNumberTesterForByDivisorCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent), - (CalculationMethod.ByDivisor, _) => ((MersenneNumberTesterForByDivisorCalculationMethodForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.ByDivisor, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.ByDivisor, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.ByDivisor, OrderDevice.Gpu, _) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.ByDivisor, OrderDevice.Hybrid, ComputationDevice.Gpu) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.ByDivisor, OrderDevice.Hybrid, ComputationDevice.Hybrid) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.ByDivisor, OrderDevice.Hybrid, _) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.ByDivisor, _, ComputationDevice.Gpu) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.ByDivisor, _, ComputationDevice.Hybrid) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.ByDivisor, _, _) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), - (CalculationMethod.Pow2Mod, ComputationDevice.Gpu) => ((MersenneNumberTesterForPow2ModCalculationMethodForGpu)tester).IsMersennePrime(gpu, exponent), - (CalculationMethod.Pow2Mod, ComputationDevice.Hybrid) => ((MersenneNumberTesterForPow2ModCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent), - (CalculationMethod.Pow2Mod, _) => ((MersenneNumberTesterForPow2ModCalculationMethodForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Pow2Mod, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Pow2Mod, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Pow2Mod, OrderDevice.Gpu, _) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Pow2Mod, OrderDevice.Hybrid, ComputationDevice.Gpu) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Pow2Mod, OrderDevice.Hybrid, ComputationDevice.Hybrid) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Pow2Mod, OrderDevice.Hybrid, _) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Pow2Mod, _, ComputationDevice.Gpu) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Pow2Mod, _, ComputationDevice.Hybrid) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (CalculationMethod.Pow2Mod, _, _) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), - (_, ComputationDevice.Gpu) => ((MersenneNumberTesterForIncrementalCalculationMethodForGpu)tester).IsMersennePrime(gpu, exponent), - (_, ComputationDevice.Hybrid) => ((MersenneNumberTesterForIncrementalCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent), - _ => ((MersenneNumberTesterForIncrementalCalculationMethodForCpu)tester).IsMersennePrime(gpu, exponent), + (_, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (_, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (_, OrderDevice.Gpu, _) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), + (_, OrderDevice.Hybrid, ComputationDevice.Gpu) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (_, OrderDevice.Hybrid, ComputationDevice.Hybrid) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + (_, OrderDevice.Hybrid, _) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), + (_, _, ComputationDevice.Gpu) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent), + (_, _, ComputationDevice.Hybrid) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent), + _ => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent), }; } private static object CreateMersenneTester( CalculationMethod method, - ComputationDevice device, + CacheStatus cacheStatus, + OrderDevice orderDevice, + ComputationDevice mersenneDevice, GpuKernelType kernelType, - bool useLucas, - bool useOrder, - bool mersenneOnGpu, - bool orderOnGpu, - bool orderOnHybrid, ulong residueKMax) { - return (method, device) switch + if (cacheStatus != CacheStatus.Disabled) { - (CalculationMethod.Residue, ComputationDevice.Gpu) => new MersenneNumberTesterForResidueCalculationMethodForGpu( + throw new NotSupportedException("CacheStatus.Enabled is not wired into Program.cs yet."); + } - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - (CalculationMethod.Residue, ComputationDevice.Hybrid) => new MersenneNumberTesterForResidueCalculationMethodForHybrid( + return (method, orderDevice, mersenneDevice) switch + { + (CalculationMethod.Residue, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Residue, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Residue, OrderDevice.Gpu, _) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Residue, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Residue, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Residue, OrderDevice.Hybrid, _) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Residue, _, ComputationDevice.Gpu) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Residue, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Residue, _, _) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - (CalculationMethod.Residue, _) => new MersenneNumberTesterForResidueCalculationMethodForCpu( + (CalculationMethod.LucasLehmer, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.LucasLehmer, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.LucasLehmer, OrderDevice.Gpu, _) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.LucasLehmer, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.LucasLehmer, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.LucasLehmer, OrderDevice.Hybrid, _) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.LucasLehmer, _, ComputationDevice.Gpu) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.LucasLehmer, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.LucasLehmer, _, _) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), + (CalculationMethod.Divisor, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Divisor, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Divisor, OrderDevice.Gpu, _) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Divisor, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Divisor, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Divisor, OrderDevice.Hybrid, _) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Divisor, _, ComputationDevice.Gpu) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Divisor, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Divisor, _, _) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), - (CalculationMethod.LucasLehmer, ComputationDevice.Gpu) => new MersenneNumberTesterForLucasLehmerCalculationMethodForGpu( + (CalculationMethod.ByDivisor, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.ByDivisor, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.ByDivisor, OrderDevice.Gpu, _) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.ByDivisor, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.ByDivisor, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.ByDivisor, OrderDevice.Hybrid, _) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.ByDivisor, _, ComputationDevice.Gpu) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.ByDivisor, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.ByDivisor, _, _) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - (CalculationMethod.LucasLehmer, ComputationDevice.Hybrid) => new MersenneNumberTesterForLucasLehmerCalculationMethodForHybrid( + (CalculationMethod.Pow2Mod, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Pow2Mod, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Pow2Mod, OrderDevice.Gpu, _) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Pow2Mod, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Pow2Mod, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Pow2Mod, OrderDevice.Hybrid, _) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Pow2Mod, _, ComputationDevice.Gpu) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Pow2Mod, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (CalculationMethod.Pow2Mod, _, _) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - (CalculationMethod.LucasLehmer, _) => new MersenneNumberTesterForLucasLehmerCalculationMethodForCpu( - - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - - (CalculationMethod.Divisor, ComputationDevice.Gpu) => new MersenneNumberTesterForDivisorCalculationMethodForGpu( - - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - (CalculationMethod.Divisor, ComputationDevice.Hybrid) => new MersenneNumberTesterForDivisorCalculationMethodForHybrid( - - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - (CalculationMethod.Divisor, _) => new MersenneNumberTesterForDivisorCalculationMethodForCpu( - - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - - (CalculationMethod.ByDivisor, ComputationDevice.Gpu) => new MersenneNumberTesterForByDivisorCalculationMethodForGpu( - - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - (CalculationMethod.ByDivisor, ComputationDevice.Hybrid) => new MersenneNumberTesterForByDivisorCalculationMethodForHybrid( - - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - (CalculationMethod.ByDivisor, _) => new MersenneNumberTesterForByDivisorCalculationMethodForCpu( - - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - - (CalculationMethod.Pow2Mod, ComputationDevice.Gpu) => new MersenneNumberTesterForPow2ModCalculationMethodForGpu( - - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - (CalculationMethod.Pow2Mod, ComputationDevice.Hybrid) => new MersenneNumberTesterForPow2ModCalculationMethodForHybrid( - - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - (CalculationMethod.Pow2Mod, _) => new MersenneNumberTesterForPow2ModCalculationMethodForCpu( - - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - - (_, ComputationDevice.Gpu) => new MersenneNumberTesterForIncrementalCalculationMethodForGpu( - - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - (_, ComputationDevice.Hybrid) => new MersenneNumberTesterForIncrementalCalculationMethodForHybrid( - - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), - _ => new MersenneNumberTesterForIncrementalCalculationMethodForCpu( - - useOrderCache: false, - kernelType: kernelType, - useOrder: useOrder, - useGpuLucas: mersenneOnGpu, - useGpuScan: mersenneOnGpu, - useGpuOrder: orderOnGpu || orderOnHybrid, - maxK: residueKMax, - orderDevice: device), + (_, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (_, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (_, OrderDevice.Gpu, _) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), + (_, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (_, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + (_, OrderDevice.Hybrid, _) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), + (_, _, ComputationDevice.Gpu) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax), + (_, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax), + _ => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax), }; } - private static void WarmUpOrders(object tester, ComputationDevice device, ulong exponent, ulong limit) + private static void WarmUpOrders(object tester, OrderDevice orderDevice, ComputationDevice device, ulong exponent, ulong limit) { - switch (_calculationMethod, device) + if (_cacheStatus == CacheStatus.Disabled) { - case (CalculationMethod.Residue, ComputationDevice.Gpu): - ((MersenneNumberTesterForResidueCalculationMethodForGpu)tester).WarmUpOrders(exponent, limit); - break; - case (CalculationMethod.Residue, ComputationDevice.Hybrid): - ((MersenneNumberTesterForResidueCalculationMethodForHybrid)tester).WarmUpOrders(exponent, limit); - break; - case (CalculationMethod.Residue, _): - ((MersenneNumberTesterForResidueCalculationMethodForCpu)tester).WarmUpOrders(exponent, limit); - break; - - case (CalculationMethod.LucasLehmer, ComputationDevice.Gpu): - ((MersenneNumberTesterForLucasLehmerCalculationMethodForGpu)tester).WarmUpOrders(exponent, limit); - break; - case (CalculationMethod.LucasLehmer, ComputationDevice.Hybrid): - ((MersenneNumberTesterForLucasLehmerCalculationMethodForHybrid)tester).WarmUpOrders(exponent, limit); - break; - case (CalculationMethod.LucasLehmer, _): - ((MersenneNumberTesterForLucasLehmerCalculationMethodForCpu)tester).WarmUpOrders(exponent, limit); - break; - - case (CalculationMethod.Divisor, ComputationDevice.Gpu): - ((MersenneNumberTesterForDivisorCalculationMethodForGpu)tester).WarmUpOrders(exponent, limit); - break; - case (CalculationMethod.Divisor, ComputationDevice.Hybrid): - ((MersenneNumberTesterForDivisorCalculationMethodForHybrid)tester).WarmUpOrders(exponent, limit); - break; - case (CalculationMethod.Divisor, _): - ((MersenneNumberTesterForDivisorCalculationMethodForCpu)tester).WarmUpOrders(exponent, limit); - break; - - case (CalculationMethod.ByDivisor, ComputationDevice.Gpu): - ((MersenneNumberTesterForByDivisorCalculationMethodForGpu)tester).WarmUpOrders(exponent, limit); - break; - case (CalculationMethod.ByDivisor, ComputationDevice.Hybrid): - ((MersenneNumberTesterForByDivisorCalculationMethodForHybrid)tester).WarmUpOrders(exponent, limit); - break; - case (CalculationMethod.ByDivisor, _): - ((MersenneNumberTesterForByDivisorCalculationMethodForCpu)tester).WarmUpOrders(exponent, limit); - break; - - case (CalculationMethod.Pow2Mod, ComputationDevice.Gpu): - ((MersenneNumberTesterForPow2ModCalculationMethodForGpu)tester).WarmUpOrders(exponent, limit); - break; - case (CalculationMethod.Pow2Mod, ComputationDevice.Hybrid): - ((MersenneNumberTesterForPow2ModCalculationMethodForHybrid)tester).WarmUpOrders(exponent, limit); - break; - case (CalculationMethod.Pow2Mod, _): - ((MersenneNumberTesterForPow2ModCalculationMethodForCpu)tester).WarmUpOrders(exponent, limit); - break; - - case (_, ComputationDevice.Gpu): - ((MersenneNumberTesterForIncrementalCalculationMethodForGpu)tester).WarmUpOrders(exponent, limit); - break; - case (_, ComputationDevice.Hybrid): - ((MersenneNumberTesterForIncrementalCalculationMethodForHybrid)tester).WarmUpOrders(exponent, limit); - break; - default: - ((MersenneNumberTesterForIncrementalCalculationMethodForCpu)tester).WarmUpOrders(exponent, limit); - break; + return; } + + // When cache warming is enabled, add calls for the generated classes keyed by orderDevice and device. } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/PerfectNumbers.Core.Tests/MersenneNumberTester/MersenneNumberTesterTests.cs b/PerfectNumbers.Core.Tests/MersenneNumberTester/MersenneNumberTesterTests.cs index 0000d41..d8fef2d 100644 --- a/PerfectNumbers.Core.Tests/MersenneNumberTester/MersenneNumberTesterTests.cs +++ b/PerfectNumbers.Core.Tests/MersenneNumberTester/MersenneNumberTesterTests.cs @@ -13,7 +13,7 @@ public class MersenneNumberTesterTests [InlineData(136_000_005UL)] public void IsMersennePrime_detects_small_prime_divisors_for_large_exponents(ulong p) { - var tester = new MersenneNumberTesterForIncrementalCalculationMethodForCpu(); + var tester = new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(); var gpu = PrimeOrderCalculatorAccelerator.Rent(1); try { @@ -29,7 +29,7 @@ public class MersenneNumberTesterTests [InlineData(125UL)] public void WarmUpOrdersCpu_populates_cache_without_affecting_results(ulong p) { - var tester = new MersenneNumberTesterForIncrementalCalculationMethodForCpu(useOrderCache: true, useGpuOrder: true); + var tester = new MersenneNumberTesterForIncrementalCalculationMethodForEnabledCacheStatusForGpuOrderDeviceForCpu(); tester.WarmUpOrders(p, 1_000UL); var gpu = PrimeOrderCalculatorAccelerator.Rent(1); try @@ -46,7 +46,7 @@ public class MersenneNumberTesterTests [InlineData(125UL)] public void WarmUpOrdersGpu_populates_cache_without_affecting_results(ulong p) { - var tester = new MersenneNumberTesterForIncrementalCalculationMethodForGpu(useOrderCache: true, useGpuOrder: true); + var tester = new MersenneNumberTesterForIncrementalCalculationMethodForEnabledCacheStatusForGpuOrderDeviceForGpu(); tester.WarmUpOrders(p, 1_000UL); var gpu = PrimeOrderCalculatorAccelerator.Rent(1); try diff --git a/PerfectNumbers.Core.Tests/MersenneNumberTester/MersenneResidueModeTests.cs b/PerfectNumbers.Core.Tests/MersenneNumberTester/MersenneResidueModeTests.cs index 60b61ca..7415860 100644 --- a/PerfectNumbers.Core.Tests/MersenneNumberTester/MersenneResidueModeTests.cs +++ b/PerfectNumbers.Core.Tests/MersenneNumberTester/MersenneResidueModeTests.cs @@ -10,10 +10,7 @@ public class MersenneResidueModeTests [Fact] public void IsMersennePrime_residue_mode_rejects_composite_exponent() { - var tester = new MersenneNumberTesterForResidueCalculationMethodForCpu( - - useGpuScan: false, - useGpuOrder: false); + var tester = new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(); var gpu = PrimeOrderCalculatorAccelerator.Rent(1); try { @@ -28,10 +25,7 @@ public class MersenneResidueModeTests [Fact] public void IsMersennePrime_residue_mode_accepts_prime_exponent() { - var tester = new MersenneNumberTesterForResidueCalculationMethodForCpu( - - useGpuScan: false, - useGpuOrder: false, + var tester = new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu( maxK: 1_000UL); var gpu = PrimeOrderCalculatorAccelerator.Rent(1); try diff --git a/PerfectNumbers.Core/MersenneNumberTesterTemplate.cs b/PerfectNumbers.Core/MersenneNumberTesterTemplate.cs index 50e8535..824b27c 100644 --- a/PerfectNumbers.Core/MersenneNumberTesterTemplate.cs +++ b/PerfectNumbers.Core/MersenneNumberTesterTemplate.cs @@ -1,3 +1,4 @@ +using System; using System.Runtime.CompilerServices; using System.Collections.Concurrent; using System.Buffers; @@ -26,32 +27,49 @@ public enum CalculationMethod Residue, } +public enum CacheStatus +{ + Disabled, + Enabled, +} + +public enum OrderDevice +{ + Cpu, + Hybrid, + Gpu, +} + [EnumDependentTemplate(typeof(CalculationMethod))] +[EnumDependentTemplate(typeof(CacheStatus))] +[EnumDependentTemplate(typeof(OrderDevice))] [DeviceDependentTemplate(typeof(ComputationDevice))] public sealed class MersenneNumberTesterTemplate( - bool useOrderCache = false, GpuKernelType kernelType = GpuKernelType.Incremental, - bool useOrder = false, - bool useGpuLucas = true, - bool useGpuScan = true, - bool useGpuOrder = true, - ulong maxK = 5_000_000UL, - ComputationDevice orderDevice = ComputationDevice.Gpu) + ulong maxK = 5_000_000UL) { +#if CacheStatus_Enabled private static readonly ConcurrentDictionary _orderCache = []; - // TODO: Swap this ConcurrentDictionary for the pooled dictionary variant highlighted in - // Pow2MontgomeryModBenchmarks once order warmups reuse deterministic divisor-cycle snapshots; the pooled approach removed - // the locking overhead when scanning p >= 138M in those benchmarks. +#endif + #if CalculationMethod_Residue #if DEVICE_GPU || DEVICE_HYBRID - private readonly MersenneNumberResidueGpuTester _residueTester = new(useGpuOrder); +#if OrderDevice_Gpu || OrderDevice_Hybrid + private readonly MersenneNumberResidueGpuTester _residueTester = new(true); +#else + private readonly MersenneNumberResidueGpuTester _residueTester = new(false); +#endif #else private readonly MersenneNumberResidueCpuTester _residueTester = new(); #endif private readonly ulong _maxK = maxK; #elif CalculationMethod_LucasLehmer #if DEVICE_GPU || DEVICE_HYBRID - private readonly MersenneNumberIncrementalGpuTester _incrementalTester = new(kernelType, useGpuOrder); +#if OrderDevice_Cpu + private readonly MersenneNumberIncrementalCpuTester _incrementalTester = new(kernelType); +#else + private readonly MersenneNumberIncrementalGpuTester _incrementalTester = new(kernelType, true); +#endif private readonly MersenneNumberLucasLehmerGpuTester _lucasLehmerTester = new(); #else private readonly MersenneNumberIncrementalCpuTester _incrementalTester = new(kernelType); @@ -59,13 +77,21 @@ public sealed class MersenneNumberTesterTemplate( #endif #elif CalculationMethod_Divisor || CalculationMethod_ByDivisor #if DEVICE_GPU || DEVICE_HYBRID - private readonly MersenneNumberOrderGpuTester _orderTester = new(kernelType, useGpuOrder); +#if OrderDevice_Cpu + private readonly MersenneNumberOrderCpuTester _orderTester = new(kernelType); +#else + private readonly MersenneNumberOrderGpuTester _orderTester = new(kernelType, true); +#endif #else private readonly MersenneNumberOrderCpuTester _orderTester = new(kernelType); #endif #else #if DEVICE_GPU || DEVICE_HYBRID - private readonly MersenneNumberIncrementalGpuTester _incrementalTester = new(kernelType, useGpuOrder); +#if OrderDevice_Cpu + private readonly MersenneNumberIncrementalCpuTester _incrementalTester = new(kernelType); +#else + private readonly MersenneNumberIncrementalGpuTester _incrementalTester = new(kernelType, true); +#endif #else private readonly MersenneNumberIncrementalCpuTester _incrementalTester = new(kernelType); #endif @@ -75,100 +101,83 @@ public sealed class MersenneNumberTesterTemplate( public void WarmUpOrders(ulong exponent, ulong limit = 5_000_000UL) { - if (!useOrderCache) - { - return; - } - - UInt128 k, q; +#if !CacheStatus_Enabled + return; +#else UInt128 twoP = (UInt128)exponent << 1; // 2 * p bool lastIsSeven = (exponent & 3UL) == 3UL; -#if DEVICE_GPU || DEVICE_HYBRID - var gpu = PrimeOrderCalculatorAccelerator.Rent(1); -#endif - if (!useGpuOrder) + +#if OrderDevice_Cpu + UInt128 k = UInt128.One; + for (; k <= limit; k++) { - k = UInt128.One; - for (; k <= limit; k++) + UInt128 q = twoP * k + UInt128.One; + ulong remainder = q.Mod10(); + bool shouldCheck = lastIsSeven + ? remainder == 7UL || remainder == 9UL || remainder == 3UL + : remainder == 1UL || remainder == 3UL || remainder == 9UL; + + if (shouldCheck) { - q = twoP * k + UInt128.One; - ulong remainder = q.Mod10(); - bool shouldCheck = lastIsSeven - ? remainder == 7UL || remainder == 9UL || remainder == 3UL - : remainder == 1UL || remainder == 3UL || remainder == 9UL; - - if (shouldCheck) - { - ulong mod8 = q.Mod8(); - if (mod8 != 1UL && mod8 != 7UL) - { - continue; - } - - if (q.Mod3() == 0UL || q.Mod5() == 0UL) - { - continue; - } - } - - if (!shouldCheck || _orderCache.ContainsKey(q)) + ulong mod8 = q.Mod8(); + if (mod8 != 1UL && mod8 != 7UL) { continue; } - _orderCache[q] = -#if DEVICE_GPU - q.CalculateOrderGpu(gpu); -#elif DEVICE_HYBRID - q.CalculateOrderHybrid(gpu); -#else - q.CalculateOrderCpu(); -#endif + if (q.Mod3() == 0UL || q.Mod5() == 0UL) + { + continue; + } } -#if DEVICE_GPU || DEVICE_HYBRID - PrimeOrderCalculatorAccelerator.Return(gpu); -#endif - return; - } + if (!shouldCheck || _orderCache.ContainsKey(q)) + { + continue; + } + + _orderCache[q] = q.CalculateOrderCpu(); + } + return; +#else +#if DEVICE_GPU || DEVICE_HYBRID + var gpu = PrimeOrderCalculatorAccelerator.Rent(1); ArrayPool uInt128Pool = ThreadStaticPools.UInt128Pool; UInt128[] qsBuffer = uInt128Pool.Rent((int)limit); int idx = 0; - k = UInt128.One; - for (; k <= limit; k++) + UInt128 k2 = 1UL; + for (; k2 <= limit; k2++) { - q = twoP * k + UInt128.One; - ulong remainder2 = q.Mod10(); + UInt128 q2 = twoP * k2 + 1UL; + ulong remainder2 = q2.Mod10(); bool shouldCheck2 = lastIsSeven ? remainder2 == 7UL || remainder2 == 9UL || remainder2 == 3UL : remainder2 == 1UL || remainder2 == 3UL || remainder2 == 9UL; if (shouldCheck2) { - ulong mod8 = q.Mod8(); + ulong mod8 = q2.Mod8(); if (mod8 != 1UL && mod8 != 7UL) { shouldCheck2 = false; } - else if (q.Mod3() == 0UL || q.Mod5() == 0UL) + else if (q2.Mod3() == 0UL || q2.Mod5() == 0UL) { shouldCheck2 = false; } } - if (!shouldCheck2 || _orderCache.ContainsKey(q)) + if (!shouldCheck2 || _orderCache.ContainsKey(q2)) { continue; } - qsBuffer[idx++] = q; + qsBuffer[idx++] = q2; } if (idx == 0) { -#if DEVICE_GPU || DEVICE_HYBRID PrimeOrderCalculatorAccelerator.Return(gpu); -#endif ThreadStaticPools.UInt128Pool.Return(qsBuffer); return; } @@ -210,20 +219,10 @@ public sealed class MersenneNumberTesterTemplate( ulong order = orders[i]; if (order == 0UL) { - order = -#if DEVICE_GPU - qs[offset + i].CalculateOrderGpu(gpu); -#elif DEVICE_HYBRID - qs[offset + i].CalculateOrderHybrid(gpu); -#else - qs[offset + i].CalculateOrderCpu(); -#endif + order = qs[offset + i].CalculateOrderGpu(gpu); } - if (useOrderCache) - { - _orderCache[qs[offset + i]] = order; - } + _orderCache[qs[offset + i]] = order; } offset += count; @@ -232,10 +231,42 @@ public sealed class MersenneNumberTesterTemplate( } AcceleratorStreamPool.Return(acceleratorIndex,stream); -#if DEVICE_GPU || DEVICE_HYBRID PrimeOrderCalculatorAccelerator.Return(gpu); -#endif uInt128Pool.Return(qs); +#else + UInt128 kFallback = UInt128.One; + for (; kFallback <= limit; kFallback++) + { + UInt128 qFallback = twoP * kFallback + UInt128.One; + ulong remainderFallback = qFallback.Mod10(); + bool shouldCheckFallback = lastIsSeven + ? remainderFallback == 7UL || remainderFallback == 9UL || remainderFallback == 3UL + : remainderFallback == 1UL || remainderFallback == 3UL || remainderFallback == 9UL; + + if (shouldCheckFallback) + { + ulong mod8Fallback = qFallback.Mod8(); + if (mod8Fallback != 1UL && mod8Fallback != 7UL) + { + continue; + } + + if (qFallback.Mod3() == 0UL || qFallback.Mod5() == 0UL) + { + continue; + } + } + + if (!shouldCheckFallback || _orderCache.ContainsKey(qFallback)) + { + continue; + } + + _orderCache[qFallback] = qFallback.CalculateOrderCpu(); + } +#endif +#endif +#endif } public bool IsMersennePrime(PrimeOrderCalculatorAccelerator gpu, ulong exponent) @@ -272,6 +303,10 @@ public sealed class MersenneNumberTesterTemplate( return false; } +#if CalculationMethod_Divisor || CalculationMethod_ByDivisor + // When using order/divisor scanning the theoretical maxK is huge; cache or GPU selection already fixed at compile time. +#endif + UInt128 twoP = (UInt128)exponent << 1; // 2 * p UInt128 maxK = UInt128Numbers.Two.Pow(exponent) / 2 + 1; LastDigit lastDigit = (exponent & 3UL) == 3UL ? LastDigit.Seven : LastDigit.One; @@ -296,7 +331,11 @@ public sealed class MersenneNumberTesterTemplate( UInt128 maxKPre = (UInt128)PreLucasPreScanK; LastDigit lastDigitPre = (exponent & 3UL) == 3UL ? LastDigit.Seven : LastDigit.One; #if DEVICE_GPU || DEVICE_HYBRID +#if OrderDevice_Cpu + _incrementalTester.Scan(gpu, exponent, twoPPre, lastDigitPre, maxKPre, ref prePrime); +#else _incrementalTester.Scan(exponent, twoPPre, lastDigitPre, maxKPre, ref prePrime); +#endif if (!prePrime) { return false; @@ -315,7 +354,11 @@ public sealed class MersenneNumberTesterTemplate( #elif CalculationMethod_Divisor || CalculationMethod_ByDivisor bool isPrime = true; #if DEVICE_GPU || DEVICE_HYBRID +#if OrderDevice_Cpu + _orderTester.Scan(gpu, exponent, twoP, lastDigit, maxK, ref isPrime); +#else _orderTester.Scan(exponent, twoP, lastDigit, maxK, ref isPrime); +#endif #else _orderTester.Scan(gpu, exponent, twoP, lastDigit, maxK, ref isPrime); #endif @@ -323,7 +366,11 @@ public sealed class MersenneNumberTesterTemplate( #else bool isPrime = true; #if DEVICE_GPU || DEVICE_HYBRID +#if OrderDevice_Cpu + _incrementalTester.Scan(gpu, exponent, twoP, lastDigit, maxK, ref isPrime); +#else _incrementalTester.Scan(exponent, twoP, lastDigit, maxK, ref isPrime); +#endif #else _incrementalTester.Scan(gpu, exponent, twoP, lastDigit, maxK, ref isPrime); #endif