MersenneNumberTesterTemplate extended to depend on new enums: CacheStatus & OrderDevice instead of constructor parameters to limit code branches during execution.
This commit is contained in:
1 parent
c5c42b0c19
commit
9147124ddf
5 files changed
+270
-367
No files matched your search
@@ -227,7 +227,7 @@ public class ProgramTests
|
|||||||
var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
|
|
||||||
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForCpu( maxK: 1_000UL), trackAllValues: true));
|
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu( maxK: 1_000UL), trackAllValues: true));
|
||||||
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
||||||
CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, 2UL, true), trackAllValues: true));
|
CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => 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 mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
|
|
||||||
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForCpu(
|
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(
|
||||||
|
|
||||||
maxK: 1_024UL), trackAllValues: true));
|
maxK: 1_024UL), trackAllValues: true));
|
||||||
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
||||||
@@ -296,7 +296,7 @@ public class ProgramTests
|
|||||||
var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
|
|
||||||
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForCpu(
|
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(
|
||||||
|
|
||||||
maxK: 5_000_000UL), trackAllValues: true));
|
maxK: 5_000_000UL), trackAllValues: true));
|
||||||
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
||||||
@@ -331,7 +331,7 @@ public class ProgramTests
|
|||||||
var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
|
|
||||||
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForCpu(
|
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(
|
||||||
|
|
||||||
maxK: 5_000_000UL), trackAllValues: true));
|
maxK: 5_000_000UL), trackAllValues: true));
|
||||||
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
||||||
@@ -367,10 +367,8 @@ public class ProgramTests
|
|||||||
var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
|
|
||||||
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForCpu(
|
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(
|
||||||
|
|
||||||
useGpuScan: false,
|
|
||||||
useGpuOrder: false,
|
|
||||||
maxK: 1_024UL), trackAllValues: true));
|
maxK: 1_024UL), trackAllValues: true));
|
||||||
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
||||||
CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, exponent, true), trackAllValues: true));
|
CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => 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 mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
|
|
||||||
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForCpu(
|
mersenneField.SetValue(null, new ThreadLocal<object>(() =>
|
||||||
|
{
|
||||||
|
if (configuration.UseGpuOrder)
|
||||||
|
{
|
||||||
|
return new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(
|
||||||
|
|
||||||
kernelType: configuration.KernelType,
|
kernelType: configuration.KernelType,
|
||||||
useGpuScan: true,
|
maxK: configuration.ResidueMaxK);
|
||||||
useGpuOrder: configuration.UseGpuOrder,
|
}
|
||||||
maxK: configuration.ResidueMaxK), trackAllValues: true));
|
|
||||||
|
return new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(
|
||||||
|
|
||||||
|
kernelType: configuration.KernelType,
|
||||||
|
maxK: configuration.ResidueMaxK);
|
||||||
|
}, trackAllValues: true));
|
||||||
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
||||||
CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, exponent, true), trackAllValues: true));
|
CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => 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 primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
var compositeField = typeof(Program).GetField("_lastCompositeP", BindingFlags.NonPublic | BindingFlags.Static)!;
|
var compositeField = typeof(Program).GetField("_lastCompositeP", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
|
|
||||||
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForIncrementalCalculationMethodForCpu( maxK: 1_000UL), trackAllValues: true));
|
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu( maxK: 1_000UL), trackAllValues: true));
|
||||||
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
||||||
CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, 2UL, true), trackAllValues: true));
|
CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, 2UL, true), trackAllValues: true));
|
||||||
|
|
||||||
|
|||||||
+137
-282
@@ -28,7 +28,8 @@ private static ThreadLocal<object>? MersenneTesters;
|
|||||||
private static int _testTargetPrimeCount;
|
private static int _testTargetPrimeCount;
|
||||||
private static int _testProcessedPrimeCount;
|
private static int _testProcessedPrimeCount;
|
||||||
private static ComputationDevice _mersenneDevice;
|
private static ComputationDevice _mersenneDevice;
|
||||||
private static ComputationDevice _orderDevice;
|
private static OrderDevice _orderCalculationDevice;
|
||||||
|
private static CacheStatus _cacheStatus;
|
||||||
private static CalculationMethod _calculationMethod;
|
private static CalculationMethod _calculationMethod;
|
||||||
|
|
||||||
[ThreadStatic]
|
[ThreadStatic]
|
||||||
@@ -99,17 +100,18 @@ private static ThreadLocal<object>? MersenneTesters;
|
|||||||
: (useResidue ? PrimeTransformMode.Add : PrimeTransformMode.AddPrimes);
|
: (useResidue ? PrimeTransformMode.Add : PrimeTransformMode.AddPrimes);
|
||||||
CandidatesCalculator.Configure(transformMode);
|
CandidatesCalculator.Configure(transformMode);
|
||||||
ComputationDevice mersenneDevice = _cliArguments.MersenneDevice;
|
ComputationDevice mersenneDevice = _cliArguments.MersenneDevice;
|
||||||
ComputationDevice orderDevice = EnvironmentConfiguration.OrderDevice;
|
|
||||||
_mersenneDevice = mersenneDevice;
|
_mersenneDevice = mersenneDevice;
|
||||||
_orderDevice = orderDevice;
|
|
||||||
_calculationMethod = useResidue
|
_calculationMethod = useResidue
|
||||||
? CalculationMethod.Residue
|
? CalculationMethod.Residue
|
||||||
: (useLucas
|
: (useLucas
|
||||||
? CalculationMethod.LucasLehmer
|
? CalculationMethod.LucasLehmer
|
||||||
: (useOrder ? CalculationMethod.Divisor : CalculationMethod.Incremental));
|
: (useOrder ? CalculationMethod.Divisor : CalculationMethod.Incremental));
|
||||||
bool mersenneOnGpu = mersenneDevice == ComputationDevice.Gpu;
|
bool mersenneOnGpu = mersenneDevice == ComputationDevice.Gpu;
|
||||||
bool orderOnGpu = EnvironmentConfiguration.UseGpuOrder;
|
OrderDevice orderCalculationDevice = EnvironmentConfiguration.UseGpuOrder
|
||||||
bool orderOnHybrid = EnvironmentConfiguration.UseHybridOrder;
|
? OrderDevice.Gpu
|
||||||
|
: (EnvironmentConfiguration.UseHybridOrder ? OrderDevice.Hybrid : OrderDevice.Cpu);
|
||||||
|
_orderCalculationDevice = orderCalculationDevice;
|
||||||
|
_cacheStatus = CacheStatus.Disabled;
|
||||||
int sliceSize = Math.Max(1, _cliArguments.SliceSize);
|
int sliceSize = Math.Max(1, _cliArguments.SliceSize);
|
||||||
ulong residueKMax = _cliArguments.ResidueKMax;
|
ulong residueKMax = _cliArguments.ResidueKMax;
|
||||||
string filterFile = _cliArguments.FilterFile;
|
string filterFile = _cliArguments.FilterFile;
|
||||||
@@ -228,18 +230,15 @@ private static ThreadLocal<object>? MersenneTesters;
|
|||||||
{
|
{
|
||||||
object tester = CreateMersenneTester(
|
object tester = CreateMersenneTester(
|
||||||
_calculationMethod,
|
_calculationMethod,
|
||||||
orderDevice,
|
_cacheStatus,
|
||||||
|
_orderCalculationDevice,
|
||||||
|
mersenneDevice,
|
||||||
kernelType,
|
kernelType,
|
||||||
useLucas,
|
|
||||||
useOrder,
|
|
||||||
mersenneOnGpu,
|
|
||||||
orderOnGpu,
|
|
||||||
orderOnHybrid,
|
|
||||||
residueKMax);
|
residueKMax);
|
||||||
if (!useLucas)
|
if (!useLucas)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Warming up orders");
|
Console.WriteLine("Warming up orders");
|
||||||
WarmUpOrders(tester, orderDevice, currentP, orderWarmupLimitOverride ?? 5_000_000UL);
|
WarmUpOrders(tester, _orderCalculationDevice, _mersenneDevice, currentP, orderWarmupLimitOverride ?? 5_000_000UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tester;
|
return tester;
|
||||||
@@ -303,10 +302,10 @@ private static ThreadLocal<object>? MersenneTesters;
|
|||||||
_ => "cpu",
|
_ => "cpu",
|
||||||
};
|
};
|
||||||
|
|
||||||
string orderDeviceLabel = orderDevice switch
|
string orderDeviceLabel = _orderCalculationDevice switch
|
||||||
{
|
{
|
||||||
ComputationDevice.Hybrid => "hybrid",
|
OrderDevice.Hybrid => "hybrid",
|
||||||
ComputationDevice.Gpu => "gpu",
|
OrderDevice.Gpu => "gpu",
|
||||||
_ => "cpu",
|
_ => "cpu",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -543,7 +542,7 @@ private static ThreadLocal<object>? MersenneTesters;
|
|||||||
if (!useLucas)
|
if (!useLucas)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Warming up orders...");
|
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<object>? MersenneTesters;
|
|||||||
private static bool IsMersennePrime(PrimeOrderCalculatorAccelerator gpu, ulong exponent)
|
private static bool IsMersennePrime(PrimeOrderCalculatorAccelerator gpu, ulong exponent)
|
||||||
{
|
{
|
||||||
object tester = MersenneTesters!.Value!;
|
object tester = MersenneTesters!.Value!;
|
||||||
return (_calculationMethod, _orderDevice) switch
|
return (_calculationMethod, _orderCalculationDevice, _mersenneDevice) switch
|
||||||
{
|
{
|
||||||
(CalculationMethod.Residue, ComputationDevice.Gpu) => ((MersenneNumberTesterForResidueCalculationMethodForGpu)tester).IsMersennePrime(gpu, exponent),
|
(CalculationMethod.Residue, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
|
||||||
(CalculationMethod.Residue, ComputationDevice.Hybrid) => ((MersenneNumberTesterForResidueCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent),
|
(CalculationMethod.Residue, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
|
||||||
(CalculationMethod.Residue, _) => ((MersenneNumberTesterForResidueCalculationMethodForCpu)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, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
|
||||||
(CalculationMethod.LucasLehmer, ComputationDevice.Hybrid) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent),
|
(CalculationMethod.LucasLehmer, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
|
||||||
(CalculationMethod.LucasLehmer, _) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForCpu)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, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
|
||||||
(CalculationMethod.Divisor, ComputationDevice.Hybrid) => ((MersenneNumberTesterForDivisorCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent),
|
(CalculationMethod.Divisor, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
|
||||||
(CalculationMethod.Divisor, _) => ((MersenneNumberTesterForDivisorCalculationMethodForCpu)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, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
|
||||||
(CalculationMethod.ByDivisor, ComputationDevice.Hybrid) => ((MersenneNumberTesterForByDivisorCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent),
|
(CalculationMethod.ByDivisor, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
|
||||||
(CalculationMethod.ByDivisor, _) => ((MersenneNumberTesterForByDivisorCalculationMethodForCpu)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, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
|
||||||
(CalculationMethod.Pow2Mod, ComputationDevice.Hybrid) => ((MersenneNumberTesterForPow2ModCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent),
|
(CalculationMethod.Pow2Mod, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
|
||||||
(CalculationMethod.Pow2Mod, _) => ((MersenneNumberTesterForPow2ModCalculationMethodForCpu)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),
|
(_, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
|
||||||
(_, ComputationDevice.Hybrid) => ((MersenneNumberTesterForIncrementalCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent),
|
(_, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
|
||||||
_ => ((MersenneNumberTesterForIncrementalCalculationMethodForCpu)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(
|
private static object CreateMersenneTester(
|
||||||
CalculationMethod method,
|
CalculationMethod method,
|
||||||
ComputationDevice device,
|
CacheStatus cacheStatus,
|
||||||
|
OrderDevice orderDevice,
|
||||||
|
ComputationDevice mersenneDevice,
|
||||||
GpuKernelType kernelType,
|
GpuKernelType kernelType,
|
||||||
bool useLucas,
|
|
||||||
bool useOrder,
|
|
||||||
bool mersenneOnGpu,
|
|
||||||
bool orderOnGpu,
|
|
||||||
bool orderOnHybrid,
|
|
||||||
ulong residueKMax)
|
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,
|
return (method, orderDevice, mersenneDevice) switch
|
||||||
kernelType: kernelType,
|
{
|
||||||
useOrder: useOrder,
|
(CalculationMethod.Residue, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuLucas: mersenneOnGpu,
|
(CalculationMethod.Residue, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuScan: mersenneOnGpu,
|
(CalculationMethod.Residue, OrderDevice.Gpu, _) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuOrder: orderOnGpu || orderOnHybrid,
|
(CalculationMethod.Residue, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
maxK: residueKMax,
|
(CalculationMethod.Residue, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
|
||||||
orderDevice: device),
|
(CalculationMethod.Residue, OrderDevice.Hybrid, _) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
(CalculationMethod.Residue, ComputationDevice.Hybrid) => new MersenneNumberTesterForResidueCalculationMethodForHybrid(
|
(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,
|
(CalculationMethod.LucasLehmer, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
kernelType: kernelType,
|
(CalculationMethod.LucasLehmer, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
|
||||||
useOrder: useOrder,
|
(CalculationMethod.LucasLehmer, OrderDevice.Gpu, _) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuLucas: mersenneOnGpu,
|
(CalculationMethod.LucasLehmer, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuScan: mersenneOnGpu,
|
(CalculationMethod.LucasLehmer, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuOrder: orderOnGpu || orderOnHybrid,
|
(CalculationMethod.LucasLehmer, OrderDevice.Hybrid, _) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
maxK: residueKMax,
|
(CalculationMethod.LucasLehmer, _, ComputationDevice.Gpu) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
orderDevice: device),
|
(CalculationMethod.LucasLehmer, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
|
||||||
(CalculationMethod.Residue, _) => new MersenneNumberTesterForResidueCalculationMethodForCpu(
|
(CalculationMethod.LucasLehmer, _, _) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
|
|
||||||
useOrderCache: false,
|
(CalculationMethod.Divisor, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
kernelType: kernelType,
|
(CalculationMethod.Divisor, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
|
||||||
useOrder: useOrder,
|
(CalculationMethod.Divisor, OrderDevice.Gpu, _) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuLucas: mersenneOnGpu,
|
(CalculationMethod.Divisor, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuScan: mersenneOnGpu,
|
(CalculationMethod.Divisor, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuOrder: orderOnGpu || orderOnHybrid,
|
(CalculationMethod.Divisor, OrderDevice.Hybrid, _) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
maxK: residueKMax,
|
(CalculationMethod.Divisor, _, ComputationDevice.Gpu) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
orderDevice: device),
|
(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,
|
(CalculationMethod.Pow2Mod, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
kernelType: kernelType,
|
(CalculationMethod.Pow2Mod, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
|
||||||
useOrder: useOrder,
|
(CalculationMethod.Pow2Mod, OrderDevice.Gpu, _) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuLucas: mersenneOnGpu,
|
(CalculationMethod.Pow2Mod, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuScan: mersenneOnGpu,
|
(CalculationMethod.Pow2Mod, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuOrder: orderOnGpu || orderOnHybrid,
|
(CalculationMethod.Pow2Mod, OrderDevice.Hybrid, _) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
maxK: residueKMax,
|
(CalculationMethod.Pow2Mod, _, ComputationDevice.Gpu) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
orderDevice: device),
|
(CalculationMethod.Pow2Mod, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
|
||||||
(CalculationMethod.LucasLehmer, ComputationDevice.Hybrid) => new MersenneNumberTesterForLucasLehmerCalculationMethodForHybrid(
|
(CalculationMethod.Pow2Mod, _, _) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
|
|
||||||
useOrderCache: false,
|
(_, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
kernelType: kernelType,
|
(_, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
|
||||||
useOrder: useOrder,
|
(_, OrderDevice.Gpu, _) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuLucas: mersenneOnGpu,
|
(_, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuScan: mersenneOnGpu,
|
(_, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
|
||||||
useGpuOrder: orderOnGpu || orderOnHybrid,
|
(_, OrderDevice.Hybrid, _) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
maxK: residueKMax,
|
(_, _, ComputationDevice.Gpu) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
orderDevice: device),
|
(_, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
|
||||||
(CalculationMethod.LucasLehmer, _) => new MersenneNumberTesterForLucasLehmerCalculationMethodForCpu(
|
_ => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
|
||||||
|
|
||||||
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),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
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):
|
return;
|
||||||
((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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When cache warming is enabled, add calls for the generated classes keyed by orderDevice and device.
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class MersenneNumberTesterTests
|
|||||||
[InlineData(136_000_005UL)]
|
[InlineData(136_000_005UL)]
|
||||||
public void IsMersennePrime_detects_small_prime_divisors_for_large_exponents(ulong p)
|
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);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -29,7 +29,7 @@ public class MersenneNumberTesterTests
|
|||||||
[InlineData(125UL)]
|
[InlineData(125UL)]
|
||||||
public void WarmUpOrdersCpu_populates_cache_without_affecting_results(ulong p)
|
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);
|
tester.WarmUpOrders(p, 1_000UL);
|
||||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
try
|
try
|
||||||
@@ -46,7 +46,7 @@ public class MersenneNumberTesterTests
|
|||||||
[InlineData(125UL)]
|
[InlineData(125UL)]
|
||||||
public void WarmUpOrdersGpu_populates_cache_without_affecting_results(ulong p)
|
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);
|
tester.WarmUpOrders(p, 1_000UL);
|
||||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -10,10 +10,7 @@ public class MersenneResidueModeTests
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void IsMersennePrime_residue_mode_rejects_composite_exponent()
|
public void IsMersennePrime_residue_mode_rejects_composite_exponent()
|
||||||
{
|
{
|
||||||
var tester = new MersenneNumberTesterForResidueCalculationMethodForCpu(
|
var tester = new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu();
|
||||||
|
|
||||||
useGpuScan: false,
|
|
||||||
useGpuOrder: false);
|
|
||||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -28,10 +25,7 @@ public class MersenneResidueModeTests
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void IsMersennePrime_residue_mode_accepts_prime_exponent()
|
public void IsMersennePrime_residue_mode_accepts_prime_exponent()
|
||||||
{
|
{
|
||||||
var tester = new MersenneNumberTesterForResidueCalculationMethodForCpu(
|
var tester = new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(
|
||||||
|
|
||||||
useGpuScan: false,
|
|
||||||
useGpuOrder: false,
|
|
||||||
maxK: 1_000UL);
|
maxK: 1_000UL);
|
||||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
@@ -26,32 +27,49 @@ public enum CalculationMethod
|
|||||||
Residue,
|
Residue,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum CacheStatus
|
||||||
|
{
|
||||||
|
Disabled,
|
||||||
|
Enabled,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum OrderDevice
|
||||||
|
{
|
||||||
|
Cpu,
|
||||||
|
Hybrid,
|
||||||
|
Gpu,
|
||||||
|
}
|
||||||
|
|
||||||
[EnumDependentTemplate(typeof(CalculationMethod))]
|
[EnumDependentTemplate(typeof(CalculationMethod))]
|
||||||
|
[EnumDependentTemplate(typeof(CacheStatus))]
|
||||||
|
[EnumDependentTemplate(typeof(OrderDevice))]
|
||||||
[DeviceDependentTemplate(typeof(ComputationDevice))]
|
[DeviceDependentTemplate(typeof(ComputationDevice))]
|
||||||
public sealed class MersenneNumberTesterTemplate(
|
public sealed class MersenneNumberTesterTemplate(
|
||||||
bool useOrderCache = false,
|
|
||||||
GpuKernelType kernelType = GpuKernelType.Incremental,
|
GpuKernelType kernelType = GpuKernelType.Incremental,
|
||||||
bool useOrder = false,
|
ulong maxK = 5_000_000UL)
|
||||||
bool useGpuLucas = true,
|
|
||||||
bool useGpuScan = true,
|
|
||||||
bool useGpuOrder = true,
|
|
||||||
ulong maxK = 5_000_000UL,
|
|
||||||
ComputationDevice orderDevice = ComputationDevice.Gpu)
|
|
||||||
{
|
{
|
||||||
|
#if CacheStatus_Enabled
|
||||||
private static readonly ConcurrentDictionary<UInt128, ulong> _orderCache = [];
|
private static readonly ConcurrentDictionary<UInt128, ulong> _orderCache = [];
|
||||||
// TODO: Swap this ConcurrentDictionary for the pooled dictionary variant highlighted in
|
#endif
|
||||||
// Pow2MontgomeryModBenchmarks once order warmups reuse deterministic divisor-cycle snapshots; the pooled approach removed
|
|
||||||
// the locking overhead when scanning p >= 138M in those benchmarks.
|
|
||||||
#if CalculationMethod_Residue
|
#if CalculationMethod_Residue
|
||||||
#if DEVICE_GPU || DEVICE_HYBRID
|
#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
|
#else
|
||||||
private readonly MersenneNumberResidueCpuTester _residueTester = new();
|
private readonly MersenneNumberResidueCpuTester _residueTester = new();
|
||||||
#endif
|
#endif
|
||||||
private readonly ulong _maxK = maxK;
|
private readonly ulong _maxK = maxK;
|
||||||
#elif CalculationMethod_LucasLehmer
|
#elif CalculationMethod_LucasLehmer
|
||||||
#if DEVICE_GPU || DEVICE_HYBRID
|
#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();
|
private readonly MersenneNumberLucasLehmerGpuTester _lucasLehmerTester = new();
|
||||||
#else
|
#else
|
||||||
private readonly MersenneNumberIncrementalCpuTester _incrementalTester = new(kernelType);
|
private readonly MersenneNumberIncrementalCpuTester _incrementalTester = new(kernelType);
|
||||||
@@ -59,13 +77,21 @@ public sealed class MersenneNumberTesterTemplate(
|
|||||||
#endif
|
#endif
|
||||||
#elif CalculationMethod_Divisor || CalculationMethod_ByDivisor
|
#elif CalculationMethod_Divisor || CalculationMethod_ByDivisor
|
||||||
#if DEVICE_GPU || DEVICE_HYBRID
|
#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
|
#else
|
||||||
private readonly MersenneNumberOrderCpuTester _orderTester = new(kernelType);
|
private readonly MersenneNumberOrderCpuTester _orderTester = new(kernelType);
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#if DEVICE_GPU || DEVICE_HYBRID
|
#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
|
#else
|
||||||
private readonly MersenneNumberIncrementalCpuTester _incrementalTester = new(kernelType);
|
private readonly MersenneNumberIncrementalCpuTester _incrementalTester = new(kernelType);
|
||||||
#endif
|
#endif
|
||||||
@@ -75,23 +101,17 @@ public sealed class MersenneNumberTesterTemplate(
|
|||||||
|
|
||||||
public void WarmUpOrders(ulong exponent, ulong limit = 5_000_000UL)
|
public void WarmUpOrders(ulong exponent, ulong limit = 5_000_000UL)
|
||||||
{
|
{
|
||||||
if (!useOrderCache)
|
#if !CacheStatus_Enabled
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
#else
|
||||||
|
|
||||||
UInt128 k, q;
|
|
||||||
UInt128 twoP = (UInt128)exponent << 1; // 2 * p
|
UInt128 twoP = (UInt128)exponent << 1; // 2 * p
|
||||||
bool lastIsSeven = (exponent & 3UL) == 3UL;
|
bool lastIsSeven = (exponent & 3UL) == 3UL;
|
||||||
#if DEVICE_GPU || DEVICE_HYBRID
|
|
||||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
#if OrderDevice_Cpu
|
||||||
#endif
|
UInt128 k = UInt128.One;
|
||||||
if (!useGpuOrder)
|
|
||||||
{
|
|
||||||
k = UInt128.One;
|
|
||||||
for (; k <= limit; k++)
|
for (; k <= limit; k++)
|
||||||
{
|
{
|
||||||
q = twoP * k + UInt128.One;
|
UInt128 q = twoP * k + UInt128.One;
|
||||||
ulong remainder = q.Mod10();
|
ulong remainder = q.Mod10();
|
||||||
bool shouldCheck = lastIsSeven
|
bool shouldCheck = lastIsSeven
|
||||||
? remainder == 7UL || remainder == 9UL || remainder == 3UL
|
? remainder == 7UL || remainder == 9UL || remainder == 3UL
|
||||||
@@ -116,59 +136,48 @@ public sealed class MersenneNumberTesterTemplate(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_orderCache[q] =
|
_orderCache[q] = q.CalculateOrderCpu();
|
||||||
#if DEVICE_GPU
|
|
||||||
q.CalculateOrderGpu(gpu);
|
|
||||||
#elif DEVICE_HYBRID
|
|
||||||
q.CalculateOrderHybrid(gpu);
|
|
||||||
#else
|
|
||||||
q.CalculateOrderCpu();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#if DEVICE_GPU || DEVICE_HYBRID
|
|
||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
#else
|
||||||
|
#if DEVICE_GPU || DEVICE_HYBRID
|
||||||
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
ArrayPool<UInt128> uInt128Pool = ThreadStaticPools.UInt128Pool;
|
ArrayPool<UInt128> uInt128Pool = ThreadStaticPools.UInt128Pool;
|
||||||
UInt128[] qsBuffer = uInt128Pool.Rent((int)limit);
|
UInt128[] qsBuffer = uInt128Pool.Rent((int)limit);
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
k = UInt128.One;
|
UInt128 k2 = 1UL;
|
||||||
for (; k <= limit; k++)
|
for (; k2 <= limit; k2++)
|
||||||
{
|
{
|
||||||
q = twoP * k + UInt128.One;
|
UInt128 q2 = twoP * k2 + 1UL;
|
||||||
ulong remainder2 = q.Mod10();
|
ulong remainder2 = q2.Mod10();
|
||||||
bool shouldCheck2 = lastIsSeven
|
bool shouldCheck2 = lastIsSeven
|
||||||
? remainder2 == 7UL || remainder2 == 9UL || remainder2 == 3UL
|
? remainder2 == 7UL || remainder2 == 9UL || remainder2 == 3UL
|
||||||
: remainder2 == 1UL || remainder2 == 3UL || remainder2 == 9UL;
|
: remainder2 == 1UL || remainder2 == 3UL || remainder2 == 9UL;
|
||||||
|
|
||||||
if (shouldCheck2)
|
if (shouldCheck2)
|
||||||
{
|
{
|
||||||
ulong mod8 = q.Mod8();
|
ulong mod8 = q2.Mod8();
|
||||||
if (mod8 != 1UL && mod8 != 7UL)
|
if (mod8 != 1UL && mod8 != 7UL)
|
||||||
{
|
{
|
||||||
shouldCheck2 = false;
|
shouldCheck2 = false;
|
||||||
}
|
}
|
||||||
else if (q.Mod3() == 0UL || q.Mod5() == 0UL)
|
else if (q2.Mod3() == 0UL || q2.Mod5() == 0UL)
|
||||||
{
|
{
|
||||||
shouldCheck2 = false;
|
shouldCheck2 = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shouldCheck2 || _orderCache.ContainsKey(q))
|
if (!shouldCheck2 || _orderCache.ContainsKey(q2))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
qsBuffer[idx++] = q;
|
qsBuffer[idx++] = q2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
{
|
{
|
||||||
#if DEVICE_GPU || DEVICE_HYBRID
|
|
||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
#endif
|
|
||||||
ThreadStaticPools.UInt128Pool.Return(qsBuffer);
|
ThreadStaticPools.UInt128Pool.Return(qsBuffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -210,21 +219,11 @@ public sealed class MersenneNumberTesterTemplate(
|
|||||||
ulong order = orders[i];
|
ulong order = orders[i];
|
||||||
if (order == 0UL)
|
if (order == 0UL)
|
||||||
{
|
{
|
||||||
order =
|
order = qs[offset + i].CalculateOrderGpu(gpu);
|
||||||
#if DEVICE_GPU
|
|
||||||
qs[offset + i].CalculateOrderGpu(gpu);
|
|
||||||
#elif DEVICE_HYBRID
|
|
||||||
qs[offset + i].CalculateOrderHybrid(gpu);
|
|
||||||
#else
|
|
||||||
qs[offset + i].CalculateOrderCpu();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useOrderCache)
|
|
||||||
{
|
|
||||||
_orderCache[qs[offset + i]] = order;
|
_orderCache[qs[offset + i]] = order;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
offset += count;
|
offset += count;
|
||||||
orderBuffer.Dispose();
|
orderBuffer.Dispose();
|
||||||
@@ -232,10 +231,42 @@ public sealed class MersenneNumberTesterTemplate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
AcceleratorStreamPool.Return(acceleratorIndex,stream);
|
AcceleratorStreamPool.Return(acceleratorIndex,stream);
|
||||||
#if DEVICE_GPU || DEVICE_HYBRID
|
|
||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
#endif
|
|
||||||
uInt128Pool.Return(qs);
|
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)
|
public bool IsMersennePrime(PrimeOrderCalculatorAccelerator gpu, ulong exponent)
|
||||||
@@ -272,6 +303,10 @@ public sealed class MersenneNumberTesterTemplate(
|
|||||||
return false;
|
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 twoP = (UInt128)exponent << 1; // 2 * p
|
||||||
UInt128 maxK = UInt128Numbers.Two.Pow(exponent) / 2 + 1;
|
UInt128 maxK = UInt128Numbers.Two.Pow(exponent) / 2 + 1;
|
||||||
LastDigit lastDigit = (exponent & 3UL) == 3UL ? LastDigit.Seven : LastDigit.One;
|
LastDigit lastDigit = (exponent & 3UL) == 3UL ? LastDigit.Seven : LastDigit.One;
|
||||||
@@ -296,7 +331,11 @@ public sealed class MersenneNumberTesterTemplate(
|
|||||||
UInt128 maxKPre = (UInt128)PreLucasPreScanK;
|
UInt128 maxKPre = (UInt128)PreLucasPreScanK;
|
||||||
LastDigit lastDigitPre = (exponent & 3UL) == 3UL ? LastDigit.Seven : LastDigit.One;
|
LastDigit lastDigitPre = (exponent & 3UL) == 3UL ? LastDigit.Seven : LastDigit.One;
|
||||||
#if DEVICE_GPU || DEVICE_HYBRID
|
#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);
|
_incrementalTester.Scan(exponent, twoPPre, lastDigitPre, maxKPre, ref prePrime);
|
||||||
|
#endif
|
||||||
if (!prePrime)
|
if (!prePrime)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -315,7 +354,11 @@ public sealed class MersenneNumberTesterTemplate(
|
|||||||
#elif CalculationMethod_Divisor || CalculationMethod_ByDivisor
|
#elif CalculationMethod_Divisor || CalculationMethod_ByDivisor
|
||||||
bool isPrime = true;
|
bool isPrime = true;
|
||||||
#if DEVICE_GPU || DEVICE_HYBRID
|
#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);
|
_orderTester.Scan(exponent, twoP, lastDigit, maxK, ref isPrime);
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
_orderTester.Scan(gpu, exponent, twoP, lastDigit, maxK, ref isPrime);
|
_orderTester.Scan(gpu, exponent, twoP, lastDigit, maxK, ref isPrime);
|
||||||
#endif
|
#endif
|
||||||
@@ -323,7 +366,11 @@ public sealed class MersenneNumberTesterTemplate(
|
|||||||
#else
|
#else
|
||||||
bool isPrime = true;
|
bool isPrime = true;
|
||||||
#if DEVICE_GPU || DEVICE_HYBRID
|
#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);
|
_incrementalTester.Scan(exponent, twoP, lastDigit, maxK, ref isPrime);
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
_incrementalTester.Scan(gpu, exponent, twoP, lastDigit, maxK, ref isPrime);
|
_incrementalTester.Scan(gpu, exponent, twoP, lastDigit, maxK, ref isPrime);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in new issue
Block a user