DivisorSet scans added as EnumDependentTemplate to MersenneNumberDivisorByDivisorCpuTesterWithTemplate. New Pow2Groups scan implemented based on statistics for high divisors. MersenneNumberDivisorByDivisorPrimeScan sessions integrated into MersenneNumberDivisorByDivisorPrimeScanSessionWithTemplate. Various micro optimizations to eliminate variable, unnecessary struct creations and continue scans in higher divisor ranges, when lower ranges are exhausted. --bydivisor-k-increment command-line argument added.
This commit is contained in:
1 parent
759614de54
commit
87a66e4eca
13 files changed
+2539
-496
No files matched your search
@@ -2,6 +2,7 @@ using BenchmarkDotNet.Attributes;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using Open.Numeric.Primes;
|
||||
using PerfectNumbers.Core;
|
||||
using PerfectNumbers.Core.Gpu;
|
||||
using PerfectNumbers.Core.Gpu.Accelerators;
|
||||
|
||||
namespace EvenPerfectBitScanner.Benchmarks;
|
||||
@@ -18,6 +19,8 @@ public class PrimeTesterBenchmarks
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
EnvironmentConfiguration.RollingAccelerators = 1;
|
||||
|
||||
_candidates = BenchmarkCase.Candidates;
|
||||
|
||||
if (_candidates.Length == 0)
|
||||
@@ -25,7 +28,6 @@ public class PrimeTesterBenchmarks
|
||||
return;
|
||||
}
|
||||
|
||||
EnvironmentConfiguration.RollingAccelerators = 1;
|
||||
|
||||
PrimeOrderCalculatorAccelerator.WarmUp();
|
||||
// HeuristicGroupABPrimeTesterAccelerator.WarmUp();
|
||||
|
||||
@@ -5,8 +5,8 @@ using PerfectNumbers.Core.Gpu;
|
||||
|
||||
namespace EvenPerfectBitScanner;
|
||||
|
||||
internal readonly struct CliArguments
|
||||
{
|
||||
internal readonly struct CliArguments
|
||||
{
|
||||
private const string DefaultCyclesPath = "divisor_cycles.bin";
|
||||
|
||||
internal readonly ulong StartPrime;
|
||||
@@ -24,8 +24,10 @@ internal readonly struct CliArguments
|
||||
internal readonly bool UseLucas;
|
||||
internal readonly bool UseResidue;
|
||||
internal readonly bool UseDivisor;
|
||||
internal readonly bool UseByDivisor;
|
||||
internal readonly bool UseGcdFilter;
|
||||
internal readonly bool UseByDivisor;
|
||||
internal readonly bool UseDivisorPow2Increment;
|
||||
internal readonly int ByDivisorSpecialRange;
|
||||
internal readonly bool UseGcdFilter;
|
||||
internal readonly bool TestMode;
|
||||
internal readonly bool UseGpuCycles;
|
||||
internal readonly ComputationDevice MersenneDevice;
|
||||
@@ -72,6 +74,8 @@ internal readonly struct CliArguments
|
||||
bool useDivisor,
|
||||
bool useByDivisor,
|
||||
bool useGcdFilter,
|
||||
bool useDivisorPow2Increment,
|
||||
int byDivisorSpecialRange,
|
||||
bool testMode,
|
||||
bool useGpuCycles,
|
||||
ComputationDevice mersenneDevice,
|
||||
@@ -116,6 +120,8 @@ internal readonly struct CliArguments
|
||||
UseResidue = useResidue;
|
||||
UseDivisor = useDivisor;
|
||||
UseByDivisor = useByDivisor;
|
||||
UseDivisorPow2Increment = useDivisorPow2Increment;
|
||||
ByDivisorSpecialRange = byDivisorSpecialRange;
|
||||
UseGcdFilter = useGcdFilter;
|
||||
TestMode = testMode;
|
||||
UseGpuCycles = useGpuCycles;
|
||||
@@ -166,6 +172,8 @@ internal readonly struct CliArguments
|
||||
bool useResidue = false;
|
||||
bool useDivisor = false;
|
||||
bool useByDivisor = false;
|
||||
bool useDivisorPow2Increment = false;
|
||||
int byDivisorSpecialRange = 0;
|
||||
bool useGcdFilter = false;
|
||||
bool testMode = false;
|
||||
bool useGpuCycles = true;
|
||||
@@ -293,6 +301,41 @@ internal readonly struct CliArguments
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.StartsWith("--bydivisor-k-increment=", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string value = argument["--bydivisor-k-increment=".Length..].Trim();
|
||||
if (value.Equals("pow2groups", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
useDivisorPow2Increment = true;
|
||||
}
|
||||
else if (value.Equals("sequential", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
useDivisorPow2Increment = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid value for --bydivisor-k-increment. Use onebyone or pow2groups.");
|
||||
return default;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.StartsWith("--bydivisor-special-range=", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (Utf8CliParser.TryParseInt32(argument.AsSpan("--bydivisor-special-range=".Length), out int parsedRange) && parsedRange >= 0)
|
||||
{
|
||||
byDivisorSpecialRange = parsedRange;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid value for --bydivisor-special-range. Use a non-negative integer.");
|
||||
return default;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.StartsWith("--divisor-cycles-limit=", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (Utf8CliParser.TryParseUInt64(argument.AsSpan("--divisor-cycles-limit=".Length), out ulong parsedLimit))
|
||||
@@ -576,10 +619,10 @@ internal readonly struct CliArguments
|
||||
}
|
||||
|
||||
return new CliArguments(
|
||||
startPrime,
|
||||
startPrimeProvided,
|
||||
maxPrimeLimit,
|
||||
maxPrimeConfigured,
|
||||
startPrime,
|
||||
startPrimeProvided,
|
||||
maxPrimeLimit,
|
||||
maxPrimeConfigured,
|
||||
threadCount,
|
||||
blockSize,
|
||||
gpuPrimeThreads,
|
||||
@@ -589,37 +632,39 @@ internal readonly struct CliArguments
|
||||
showHelp,
|
||||
useBitTransform,
|
||||
useLucas,
|
||||
useResidue,
|
||||
useDivisor,
|
||||
useByDivisor,
|
||||
useGcdFilter,
|
||||
testMode,
|
||||
useGpuCycles,
|
||||
mersenneDevice,
|
||||
orderDevice,
|
||||
scanBatchSize,
|
||||
sliceSize,
|
||||
residueKMax,
|
||||
filterFile,
|
||||
forcePrimeKernelsOnCpu,
|
||||
modReductionMode,
|
||||
nttBackend,
|
||||
resultsDirectory,
|
||||
resultsPrefix,
|
||||
writeBatchSize,
|
||||
cyclesPath,
|
||||
continueCyclesGeneration,
|
||||
cyclesBatchSize,
|
||||
divisorCyclesSearchLimit,
|
||||
orderWarmupLimitOverride,
|
||||
rleBlacklistPath,
|
||||
rleHardMaxP,
|
||||
rleOnlyLast7,
|
||||
zeroFractionHard,
|
||||
zeroFractionConjecture,
|
||||
maxZeroConjecture,
|
||||
minK,
|
||||
gpuRatio);
|
||||
useResidue,
|
||||
useDivisor,
|
||||
useByDivisor,
|
||||
useGcdFilter,
|
||||
useDivisorPow2Increment,
|
||||
byDivisorSpecialRange,
|
||||
testMode,
|
||||
useGpuCycles,
|
||||
mersenneDevice,
|
||||
orderDevice,
|
||||
scanBatchSize,
|
||||
sliceSize,
|
||||
residueKMax,
|
||||
filterFile,
|
||||
forcePrimeKernelsOnCpu,
|
||||
modReductionMode,
|
||||
nttBackend,
|
||||
resultsDirectory,
|
||||
resultsPrefix,
|
||||
writeBatchSize,
|
||||
cyclesPath,
|
||||
continueCyclesGeneration,
|
||||
cyclesBatchSize,
|
||||
divisorCyclesSearchLimit,
|
||||
orderWarmupLimitOverride,
|
||||
rleBlacklistPath,
|
||||
rleHardMaxP,
|
||||
rleOnlyLast7,
|
||||
zeroFractionHard,
|
||||
zeroFractionConjecture,
|
||||
maxZeroConjecture,
|
||||
minK,
|
||||
gpuRatio);
|
||||
}
|
||||
|
||||
internal static void PrintHelp()
|
||||
@@ -632,7 +677,9 @@ internal readonly struct CliArguments
|
||||
Console.WriteLine(" --max-prime=<value> inclusive upper bound for primes from filter files");
|
||||
Console.WriteLine(" --increment=bit|add exponent increment method (default add)");
|
||||
Console.WriteLine(" --threads=<value> number of worker threads");
|
||||
Console.WriteLine(" --mersenne=pow2mod|incremental|lucas|residue|divisor|bydivisor Mersenne test method");
|
||||
S Console.WriteLine(" --mersenne=pow2mod|incremental|lucas|residue|divisor|bydivisor Mersenne test method");
|
||||
Console.WriteLine(" --bydivisor-k-increment=sequential|pow2groups k iteration strategy for --mersenne=bydivisor (default sequential)");
|
||||
Console.WriteLine(" --bydivisor-special-range=<n> widen pow2groups special values to +/- n percent (default 0 = points)");
|
||||
Console.WriteLine(" --residue-max-k=<value> max k for residue Mersenne test (q = 2*p*k + 1)");
|
||||
Console.WriteLine(" --mersenne-device=cpu|gpu|hybrid Device for Mersenne method (default gpu)");
|
||||
Console.WriteLine(" --primes-device=cpu|gpu device for prime-scan kernels (default gpu)");
|
||||
|
||||
@@ -8,6 +8,13 @@ using PerfectNumbers.Core;
|
||||
using PerfectNumbers.Core.Cpu;
|
||||
using PerfectNumbers.Core.Gpu;
|
||||
using PerfectNumbers.Core.Gpu.Accelerators;
|
||||
using MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForCpuOrder;
|
||||
using MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForHybridOrder;
|
||||
using MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForGpuOrder;
|
||||
using ByDivisorCpuOrderPow2 = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForCpuOrder;
|
||||
using ByDivisorHybridOrderPow2 = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForHybridOrder;
|
||||
using ByDivisorGpuOrderPow2 = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForGpuOrder;
|
||||
using System.Globalization;
|
||||
|
||||
namespace EvenPerfectBitScanner;
|
||||
|
||||
@@ -21,6 +28,9 @@ private static ThreadLocal<object>? MersenneTesters;
|
||||
private static MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder _byDivisorCpuOrderTester;
|
||||
private static MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder _byDivisorHybridOrderTester;
|
||||
private static MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder _byDivisorGpuOrderTester;
|
||||
private static ByDivisorCpuOrderPow2 _byDivisorCpuOrderTesterPow2;
|
||||
private static ByDivisorHybridOrderPow2 _byDivisorHybridOrderTesterPow2;
|
||||
private static ByDivisorGpuOrderPow2 _byDivisorGpuOrderTesterPow2;
|
||||
private static Dictionary<ulong, (bool DetailedCheck, bool PassedAllTests)>? _byDivisorPreviousResults;
|
||||
private static bool _limitReached;
|
||||
private static ulong _byDivisorStartPrime;
|
||||
@@ -56,16 +66,18 @@ private static ThreadLocal<object>? MersenneTesters;
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("Initializing");
|
||||
int gpuPrimeThreads = Math.Max(1, _cliArguments.GpuPrimeThreads);
|
||||
int threadCount = Math.Max(1, _cliArguments.ThreadCount);
|
||||
Console.WriteLine("Initializing");
|
||||
int gpuPrimeThreads = Math.Max(1, _cliArguments.GpuPrimeThreads);
|
||||
int threadCount = Math.Max(1, _cliArguments.ThreadCount);
|
||||
|
||||
EnvironmentConfiguration.MinK = _cliArguments.MinK;
|
||||
EnvironmentConfiguration.GpuBatchSize = Math.Max(1, _cliArguments.ScanBatchSize);
|
||||
EnvironmentConfiguration.GpuRatio = _cliArguments.GpuRatio;
|
||||
EnvironmentConfiguration.OrderDevice = _cliArguments.OrderDevice;
|
||||
EnvironmentConfiguration.RollingAccelerators = Math.Min(Math.Min(PerfectNumberConstants.RollingAccelerators, gpuPrimeThreads), threadCount);
|
||||
EnvironmentConfiguration.Initialize();
|
||||
EnvironmentConfiguration.MinK = _cliArguments.MinK;
|
||||
EnvironmentConfiguration.GpuBatchSize = Math.Max(1, _cliArguments.ScanBatchSize);
|
||||
EnvironmentConfiguration.GpuRatio = _cliArguments.GpuRatio;
|
||||
EnvironmentConfiguration.OrderDevice = _cliArguments.OrderDevice;
|
||||
EnvironmentConfiguration.UsePow2GroupDivisors = _cliArguments.UseDivisorPow2Increment;
|
||||
EnvironmentConfiguration.ByDivisorSpecialRange = _cliArguments.ByDivisorSpecialRange;
|
||||
EnvironmentConfiguration.RollingAccelerators = Math.Min(Math.Min(PerfectNumberConstants.RollingAccelerators, gpuPrimeThreads), threadCount);
|
||||
EnvironmentConfiguration.Initialize();
|
||||
|
||||
// NttGpuMath.GpuTransformBackend = _cliArguments.NttBackend;
|
||||
// NttGpuMath.ReductionMode = _cliArguments.ModReductionMode;
|
||||
@@ -257,17 +269,39 @@ private static ThreadLocal<object>? MersenneTesters;
|
||||
throw new NotSupportedException("--mersenne-device=gpu is not supported for --mersenne=bydivisor on this execution path.");
|
||||
}
|
||||
|
||||
bool usePow2Divisors = _cliArguments.UseDivisorPow2Increment;
|
||||
if (EnvironmentConfiguration.UseCpuOrder)
|
||||
{
|
||||
_byDivisorCpuOrderTester = new MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder();
|
||||
if (usePow2Divisors)
|
||||
{
|
||||
_byDivisorCpuOrderTesterPow2 = new ByDivisorCpuOrderPow2();
|
||||
}
|
||||
else
|
||||
{
|
||||
_byDivisorCpuOrderTester = new MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder();
|
||||
}
|
||||
}
|
||||
else if (EnvironmentConfiguration.UseHybridOrder)
|
||||
{
|
||||
_byDivisorHybridOrderTester = new MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder();
|
||||
if (usePow2Divisors)
|
||||
{
|
||||
_byDivisorHybridOrderTesterPow2 = new ByDivisorHybridOrderPow2();
|
||||
}
|
||||
else
|
||||
{
|
||||
_byDivisorHybridOrderTester = new MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_byDivisorGpuOrderTester = new MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder();
|
||||
if (usePow2Divisors)
|
||||
{
|
||||
_byDivisorGpuOrderTesterPow2 = new ByDivisorGpuOrderPow2();
|
||||
}
|
||||
else
|
||||
{
|
||||
_byDivisorGpuOrderTester = new MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,44 +517,96 @@ private static ThreadLocal<object>? MersenneTesters;
|
||||
if (useByDivisor)
|
||||
{
|
||||
int byDivisorPrimeRange = Math.Max(1, _cliArguments.BlockSize);
|
||||
bool usePow2Divisors = _cliArguments.UseDivisorPow2Increment;
|
||||
if (EnvironmentConfiguration.UseCpuOrder)
|
||||
{
|
||||
MersenneNumberDivisorByDivisorTester.Run(
|
||||
byDivisorCandidates,
|
||||
ref _byDivisorCpuOrderTester,
|
||||
_byDivisorPreviousResults,
|
||||
_byDivisorStartPrime,
|
||||
static () => _lastCompositeP = true,
|
||||
static () => _lastCompositeP = false,
|
||||
static (candidate, searchedMersenne, detailedCheck, passedAllTests, divisor) => CalculationResultHandler.HandleResult(candidate, divisor, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP),
|
||||
threadCount,
|
||||
byDivisorPrimeRange);
|
||||
if (usePow2Divisors)
|
||||
{
|
||||
Console.WriteLine("Using by-divisor pow2groups increment (CPU order).");
|
||||
MersenneNumberDivisorByDivisorTester.Run(
|
||||
byDivisorCandidates,
|
||||
ref _byDivisorCpuOrderTesterPow2,
|
||||
_byDivisorPreviousResults,
|
||||
_byDivisorStartPrime,
|
||||
static () => _lastCompositeP = true,
|
||||
static () => _lastCompositeP = false,
|
||||
static (candidate, searchedMersenne, detailedCheck, passedAllTests, divisor) => CalculationResultHandler.HandleResult(candidate, divisor, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP),
|
||||
threadCount,
|
||||
byDivisorPrimeRange);
|
||||
}
|
||||
else
|
||||
{
|
||||
MersenneNumberDivisorByDivisorTester.Run(
|
||||
byDivisorCandidates,
|
||||
ref _byDivisorCpuOrderTester,
|
||||
_byDivisorPreviousResults,
|
||||
_byDivisorStartPrime,
|
||||
static () => _lastCompositeP = true,
|
||||
static () => _lastCompositeP = false,
|
||||
static (candidate, searchedMersenne, detailedCheck, passedAllTests, divisor) => CalculationResultHandler.HandleResult(candidate, divisor, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP),
|
||||
threadCount,
|
||||
byDivisorPrimeRange);
|
||||
}
|
||||
}
|
||||
else if (EnvironmentConfiguration.UseHybridOrder)
|
||||
{
|
||||
MersenneNumberDivisorByDivisorTester.Run(
|
||||
byDivisorCandidates,
|
||||
ref _byDivisorHybridOrderTester,
|
||||
_byDivisorPreviousResults,
|
||||
_byDivisorStartPrime,
|
||||
static () => _lastCompositeP = true,
|
||||
static () => _lastCompositeP = false,
|
||||
static (candidate, searchedMersenne, detailedCheck, passedAllTests, divisor) => CalculationResultHandler.HandleResult(candidate, divisor, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP),
|
||||
threadCount,
|
||||
byDivisorPrimeRange);
|
||||
if (usePow2Divisors)
|
||||
{
|
||||
Console.WriteLine("Using by-divisor pow2groups increment (Hybrid order).");
|
||||
MersenneNumberDivisorByDivisorTester.Run(
|
||||
byDivisorCandidates,
|
||||
ref _byDivisorHybridOrderTesterPow2,
|
||||
_byDivisorPreviousResults,
|
||||
_byDivisorStartPrime,
|
||||
static () => _lastCompositeP = true,
|
||||
static () => _lastCompositeP = false,
|
||||
static (candidate, searchedMersenne, detailedCheck, passedAllTests, divisor) => CalculationResultHandler.HandleResult(candidate, divisor, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP),
|
||||
threadCount,
|
||||
byDivisorPrimeRange);
|
||||
}
|
||||
else
|
||||
{
|
||||
MersenneNumberDivisorByDivisorTester.Run(
|
||||
byDivisorCandidates,
|
||||
ref _byDivisorHybridOrderTester,
|
||||
_byDivisorPreviousResults,
|
||||
_byDivisorStartPrime,
|
||||
static () => _lastCompositeP = true,
|
||||
static () => _lastCompositeP = false,
|
||||
static (candidate, searchedMersenne, detailedCheck, passedAllTests, divisor) => CalculationResultHandler.HandleResult(candidate, divisor, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP),
|
||||
threadCount,
|
||||
byDivisorPrimeRange);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MersenneNumberDivisorByDivisorTester.Run(
|
||||
byDivisorCandidates,
|
||||
ref _byDivisorGpuOrderTester,
|
||||
_byDivisorPreviousResults,
|
||||
_byDivisorStartPrime,
|
||||
static () => _lastCompositeP = true,
|
||||
static () => _lastCompositeP = false,
|
||||
static (candidate, searchedMersenne, detailedCheck, passedAllTests, divisor) => CalculationResultHandler.HandleResult(candidate, divisor, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP),
|
||||
threadCount,
|
||||
byDivisorPrimeRange);
|
||||
if (usePow2Divisors)
|
||||
{
|
||||
Console.WriteLine("Using by-divisor pow2groups increment (GPU order).");
|
||||
MersenneNumberDivisorByDivisorTester.Run(
|
||||
byDivisorCandidates,
|
||||
ref _byDivisorGpuOrderTesterPow2,
|
||||
_byDivisorPreviousResults,
|
||||
_byDivisorStartPrime,
|
||||
static () => _lastCompositeP = true,
|
||||
static () => _lastCompositeP = false,
|
||||
static (candidate, searchedMersenne, detailedCheck, passedAllTests, divisor) => CalculationResultHandler.HandleResult(candidate, divisor, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP),
|
||||
threadCount,
|
||||
byDivisorPrimeRange);
|
||||
}
|
||||
else
|
||||
{
|
||||
MersenneNumberDivisorByDivisorTester.Run(
|
||||
byDivisorCandidates,
|
||||
ref _byDivisorGpuOrderTester,
|
||||
_byDivisorPreviousResults,
|
||||
_byDivisorStartPrime,
|
||||
static () => _lastCompositeP = true,
|
||||
static () => _lastCompositeP = false,
|
||||
static (candidate, searchedMersenne, detailedCheck, passedAllTests, divisor) => CalculationResultHandler.HandleResult(candidate, divisor, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP),
|
||||
threadCount,
|
||||
byDivisorPrimeRange);
|
||||
}
|
||||
}
|
||||
|
||||
CalculationResultHandler.FlushBuffer();
|
||||
@@ -907,17 +993,24 @@ private static ThreadLocal<object>? MersenneTesters;
|
||||
if (_cliArguments.UseByDivisor)
|
||||
{
|
||||
// Windowed pow2mod kernel handles by-divisor scans.
|
||||
bool usePow2Divisors = _cliArguments.UseDivisorPow2Increment;
|
||||
if (EnvironmentConfiguration.UseCpuOrder)
|
||||
{
|
||||
return _byDivisorCpuOrderTester.IsPrime(p, out detailedCheck, out _);
|
||||
return usePow2Divisors
|
||||
? _byDivisorCpuOrderTesterPow2.IsPrime(p, out detailedCheck, out _)
|
||||
: _byDivisorCpuOrderTester.IsPrime(p, out detailedCheck, out _);
|
||||
}
|
||||
|
||||
if (EnvironmentConfiguration.UseHybridOrder)
|
||||
{
|
||||
return _byDivisorHybridOrderTester.IsPrime(p, out detailedCheck, out _);
|
||||
return usePow2Divisors
|
||||
? _byDivisorHybridOrderTesterPow2.IsPrime(p, out detailedCheck, out _)
|
||||
: _byDivisorHybridOrderTester.IsPrime(p, out detailedCheck, out _);
|
||||
}
|
||||
|
||||
return _byDivisorGpuOrderTester.IsPrime(p, out detailedCheck, out _);
|
||||
return usePow2Divisors
|
||||
? _byDivisorGpuOrderTesterPow2.IsPrime(p, out detailedCheck, out _)
|
||||
: _byDivisorGpuOrderTester.IsPrime(p, out detailedCheck, out _);
|
||||
}
|
||||
|
||||
detailedCheck = IsMersennePrime(gpu, p);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Numerics;
|
||||
using FluentAssertions;
|
||||
using PerfectNumbers.Core.Cpu;
|
||||
using MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForCpuOrder;
|
||||
using Xunit;
|
||||
|
||||
namespace PerfectNumbers.Core.Tests;
|
||||
|
||||
@@ -8,27 +8,38 @@ namespace PerfectNumbers.Core;
|
||||
/// Mirrors <see cref="CycleRemainderStepper"/> for values that exceed 64 bits.
|
||||
/// </summary>
|
||||
[method: MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public struct BigIntegerCycleRemainderStepper(BigInteger cycleLength)
|
||||
public struct BigIntegerCycleRemainderStepper(byte cycleLength)
|
||||
{
|
||||
private readonly BigInteger _cycleLength = cycleLength;
|
||||
private readonly BigInteger _cycleLength = (BigInteger)cycleLength;
|
||||
private BigInteger _previousValue = BigInteger.Zero;
|
||||
private BigInteger _currentRemainder = BigInteger.Zero;
|
||||
private BigInteger _currentRemainder = 0;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public BigInteger Initialize(BigInteger value)
|
||||
public byte Initialize(BigInteger value)
|
||||
{
|
||||
_previousValue = value;
|
||||
_currentRemainder = value.ReduceCycleRemainder(_cycleLength);
|
||||
return _currentRemainder;
|
||||
_currentRemainder = value % _cycleLength;
|
||||
return (byte)_currentRemainder;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public BigInteger ComputeNext(BigInteger value)
|
||||
public bool NextIsNotDivisible(BigInteger value)
|
||||
{
|
||||
BigInteger delta = value - _previousValue;
|
||||
BigInteger delta = value - _previousValue;
|
||||
_previousValue = value;
|
||||
_currentRemainder = (_currentRemainder + delta).ReduceCycleRemainder(_cycleLength);
|
||||
delta = (_currentRemainder + delta) % _cycleLength;
|
||||
_currentRemainder = delta;
|
||||
return !delta.IsZero;
|
||||
}
|
||||
|
||||
return _currentRemainder;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public byte ComputeNext(BigInteger value)
|
||||
{
|
||||
BigInteger delta = value - _previousValue;
|
||||
_previousValue = value;
|
||||
delta = (_currentRemainder + delta) % _cycleLength;
|
||||
_currentRemainder = delta;
|
||||
|
||||
return (byte)delta;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
#define DIVISOR_SPECIALIZED
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PerfectNumbers.Core.Cpu;
|
||||
|
||||
public static class DivisorByDivisorConfig
|
||||
{
|
||||
|
||||
#if DIVISOR_SPECIALIZED
|
||||
public const int PercentScale = 10_000;
|
||||
|
||||
public static readonly (int Start, int End)[] PercentGroupsPromille =
|
||||
[
|
||||
(9998, 10000),
|
||||
(9844, 9845),
|
||||
(9561, 9562),
|
||||
(9402, 9403),
|
||||
(9307, 9308),
|
||||
(9127, 9128),
|
||||
(8900, 8901),
|
||||
(8682, 8683),
|
||||
(8546, 8547),
|
||||
(8381, 8382),
|
||||
(7988, 7989),
|
||||
(7693, 7694),
|
||||
(7426, 7427),
|
||||
(7184, 7185),
|
||||
(6705, 6706),
|
||||
(6473, 6474),
|
||||
(6218, 6219),
|
||||
(5944, 5945),
|
||||
(5791, 5792),
|
||||
(5530, 5531),
|
||||
(4902, 4903),
|
||||
(4657, 4658),
|
||||
(4388, 4389),
|
||||
(4119, 4120),
|
||||
(3844, 3845),
|
||||
(3602, 3603),
|
||||
(3477, 3478),
|
||||
(3112, 3113),
|
||||
(2901, 2902),
|
||||
(2742, 2743),
|
||||
(2358, 2359),
|
||||
(2134, 2135),
|
||||
(1827, 1828),
|
||||
(1611, 1612),
|
||||
(1439, 1440),
|
||||
(1354, 1355),
|
||||
(1281, 1284),
|
||||
(0906, 0907),
|
||||
(0847, 0848),
|
||||
(0706, 0707),
|
||||
(0694, 0695),
|
||||
(0569, 0570),
|
||||
(0244, 0245),
|
||||
(0204, 0205),
|
||||
(0143, 0144),
|
||||
(0095, 0096),
|
||||
(0070, 0071),
|
||||
];
|
||||
|
||||
public static readonly int[] SpecialPercentPromille = [
|
||||
0070,
|
||||
0143,
|
||||
0095,
|
||||
0204,
|
||||
0244,
|
||||
0569,
|
||||
0694,
|
||||
0706,
|
||||
0847,
|
||||
0906,
|
||||
0955,
|
||||
0958,
|
||||
1060,
|
||||
1018,
|
||||
1132,
|
||||
1308,
|
||||
1416,
|
||||
1782,
|
||||
1875,
|
||||
2026,
|
||||
2349,
|
||||
2451,
|
||||
2464,
|
||||
2782,
|
||||
3065,
|
||||
3088,
|
||||
3113,
|
||||
3257,
|
||||
3284,
|
||||
3304,
|
||||
3318,
|
||||
3343,
|
||||
3351,
|
||||
3383,
|
||||
3431,
|
||||
3566,
|
||||
3617,
|
||||
3938,
|
||||
3985,
|
||||
3994,
|
||||
4053,
|
||||
4166,
|
||||
4248,
|
||||
4337,
|
||||
4344,
|
||||
4467,
|
||||
4493,
|
||||
4866,
|
||||
5043,
|
||||
5189,
|
||||
5208,
|
||||
5510,
|
||||
5530,
|
||||
5925,
|
||||
6198,
|
||||
6281,
|
||||
6324,
|
||||
6363,
|
||||
6366,
|
||||
6387,
|
||||
6474,
|
||||
6477,
|
||||
6546,
|
||||
6548,
|
||||
6729,
|
||||
6741,
|
||||
6841,
|
||||
7203,
|
||||
7211,
|
||||
7234,
|
||||
7589,
|
||||
7593,
|
||||
7664,
|
||||
7775,
|
||||
8076,
|
||||
8203,
|
||||
8273,
|
||||
8331,
|
||||
8381,
|
||||
8546,
|
||||
8682,
|
||||
8900,
|
||||
9127,
|
||||
9307,
|
||||
9402,
|
||||
9561,
|
||||
9844,
|
||||
9998,
|
||||
1000,
|
||||
];
|
||||
#elif DIVISOR_SPECIALIZED_LOW_DIVISORS
|
||||
public const int PercentScale = 10_000;
|
||||
|
||||
public static readonly (int Start, int End)[] PercentGroupsPromille =
|
||||
[
|
||||
(4500, 5500),
|
||||
(7000, 8000),
|
||||
(9500, 9800),
|
||||
(9800, 10000),
|
||||
(3000, 4500),
|
||||
(0, 1000),
|
||||
];
|
||||
|
||||
public static readonly int[] SpecialPercentPromille = [9840, 10000, 7500, 5000, 3910, 0292, 0297, 0325, 0354, 0314, 0339, 0337, 0316, 0341, 0352, 0351, 0283, 0313, 0330, 0301, 0348, 0298, 0290, 0335, 0309, 0322, 0321, 0312, 0323, 0303, 0349, 0344, 0327, 0295, 0299, 0320, 0285, 0306, 0310, 0287, 0332, 0340, 0293, 0317, 0305, 0342, 0311, 0318, 0346, 0294, 0350, 0284, 0308, 0307, 0286, 0324, 0353, 0336, 0288, 0291, 0334, 0326, 0355, 0356, 0319, 0300, 0338, 0331, 0333, 0302, 0304, 0328, 0345, 0347, 0315, 0343, 0289, 0296, 0329, 5444, 0282, 5426, 5424, 5443, 5434, 5470, 5430, 5528, 5517, 5464, 5484, 5495, 5428, 5427, 5505, 5425, 5454, 5521, 5497, 5501, 5461, 5436, 5468, 5490, 5508, 5515, 5456, 5437, 5438, 5448, 5479, 5524, 5500, 5446, 5473, 5486, 5531, 5472, 5469, 5463, 5460, 5485, 5502, 5519, 5489, 5518, 5442, 5510, 5487, 5482, 5493, 5471, 5522, 5514, 1631, 5496, 1639, 5520, 1649, 5527, 5498, 5530, 5440, 5534, 5532, 5433, 5480, 5488, 5511, 5529, 5492, 5465, 5504, 5445, 5491, 1643, 5476, 5432, 5449, 5439, 5512, 5478, 5525, 1622, 5506, 5523, 5474, 5451, 5467, 5457, 5431, 5452, 5481, 1568, 1610, 5450, 1587, 1572, 1603, 5507, 1641, 1635, 5441, 5509, 5429, 5494, 5475, 5458, 5483, 5526, 5513, 1611, 1605, 1602, 1594, 5459, 1623, 1577, 1638, 1613, 1573, 6754, 1599, 1644, 3532, 1570, 5435, 1647, 7999, 1618, 1616, 3582, 5453, 4236, 1604, 1640, 1608, 3572, 1645, 1578, 1588, 5466, 8120, 1607, 1632, 1569, 1646, 8045, 9326, 1637, 3531, 3510, 1571, 5499, 1600, 1597, 8081, 3559, 0191, 5533, 5447, 9390, 1634, 8025, 9308, 1574, 0951, 1586, 4149, 1583, 8103, 2762, 5477, 8115, 5924, 1576, 1619, 8019, 3504, 2908, 1591, 0628, 5503, 1592, 2877, 3521, 1617, 0618, 2927, 8069, 0942, 1584, 2853, 3574, 8119, 1595, 0647, 2294, 1620, 0274, 1255, 1899, 1596, 8071, 2864, 1590, 3900, 2939, 1135, 9319, 1502, 1475, 8021, 0950, 0027, 8056, 1630, 0988, 7440, 0962, 3579, 9340, 9285, 2562, 3002, 8039, 1589, 4154, 8005, 4205, 6755, 9320, 4189, 9301, 4216, 9282, 4167, 8033, 1606, 3577, 3571, 8092, 5462, 1314, 5516, 3501, 2945, 3034, 0646, 3535, 1257, 0958, 1612, 1001, 1651, 1648, 8051, 1626, 8067, 1601, 7406, 3589, 4219, 4074, 9295, 1120, 2867, 9313, 2250, 2882, 7415, 9291, 3512, 4171, 9304, 8653, 1615, 2905, 8068, 9370, 4218, 1258, 5455, 8090, 3190, 0960, 7362, 8063, 1642, 9335, 9343, 9401, 9310, 2402, 9318, 8048, 9374, 3526, 9325, 3152, 8052, 2895, 5847, 3546, 1081, 9280, 2233, 1628, 6790, 2854, 4203, 9322, 4200, 0001, 6774, 4459, 7994, 6822, 1650, 3585, 3395, 1625, 3207, 6770, 4204, 2890, 8055, 9346, 0522, 4191, 9352, 0021, 8696, 3498, 6803, 9345, 3426, 7442, 3541, 9405, 9384, 0984, 2866, 3220, 0249, 0625, 1751, 2920, 2916, 0965, 2851, 7473, 9336, 9380, 2565, 0517, 2249, 4161, 0012, 0640, 9373, 1271, 8113, 2253, 2938, 2925, 4827, 0636, 1636, 3563, 2260, 0642, 0928, 1627, 3547, 2865, 8020, 1579, 9297, 0983, 9377, 0837, 8376, 0968, 0635, 1593, 3565, 9395, 8078, 0262, 0442, 0785, 2076, 9415, 3079, 9366, 1581, 0931, 8118, 8034, 8004, 4175, 5282, 1790, 7998, 3209, 2052, 9391, 0970, 0156, 0934, 4211, 9410, 9383, 7446, 2961, 0121, 3583, 1299, 4797, 2102, 2926, 4978, 8111, 7418, 9375, 9372, 7401, 1909, 6736, 0243, 2210, 8035, 3558, 9353, 9356, 9357, 3025, 9368, 1324, 2440, 6798, 2080, 2270, 2742, 1152, 4796, 8080, 0124, 6752, 8123, 6727, 2374, 3684, 9414, 0648, 1580, 2817, 5753, 1318, 0641, 6737, 2269, 2911, 8341, 6807, 9341, 6468, 9398, 1614, 4150, 8029, 9315, 2683, 2457, 3502, 6761, 3539, 4176, 2618, 1973, 2947, 3047, 9329, 9351, 8102, 6414, 8093, 1294, 0622, 0969, 2078, 2934, 4422, 2165, 3036, 8084, 0164, 0664, 0456, 6777, 6808, 4863, 3217, 3529, 4385, 5733, 2915, 9358, 3499, 2786, 0981, 5194, 3561, 1964, 2544, 0766, 8022, 1090, 7508, 5780, 0775, 2085, 8018, 3540, 7366, 1598, 4170, 5307, 0671, 3511, 1624, 9416, 3021, 0952, 3580, 3073, 5953, 1371, 8044, 4477, 0992, 0652, 9359, 0957, 8392, 3588, 4213, 4141, 9364, 1871, 3367, 8700, 4916, 8013, 5043, 4057, 7126, 1945, 3174, 3562, 0093, 3537, 3096, 0659, 7394, 0630, 3509, 5619, 2310, 0814, 1471, 0609, 8038, 1268, 0666, 0023, 3587, 4138, 0935, 4786, 8076, 9393, 9404, 6235, 1290, 0224, 2955, 0547, 8121, 4857, 4838, 2880, 1330, 6758, 3748, 2421, 0038, 8001, 6744, 7785, 0658, 6158, 8032, 1957, 0166, 0989, 1156, 0947, 2448, 3065, 2935, 2442, 2697, 6805, 6826, 3523, 7384, 2940, 1686, 2235, 1609, 8697, 3039, 4181, 2064, 4563, 1437, 1115, 0939, 5207, 4826, 8098, 0364, 3522, 9363, 0660, 2869, 4144, 1750, 8673, 1121, 2770, 7359, 2910, 9947, 0528, 0967, 3763, 9075, 3260, 5779, 1935, 1237, 1582, 2518, 0819, 3518, 1286, 1295, 0644, 1377, 8091, 3473, 8083, 9417, 2323, 1124, 0069, 0973, 0409, 0842, 0674, 6728, 4803, 0035, 1575, 2057, 2932, 2888, 9348, 4185, 8027, 3624, 0982, 1806, 1907, 8638, 4160, 0729, 1709, 8495, 4212, 0926, 8108, 1106, 6731, 0424, 8100, 1254, 5877, 2244, 5181, 2859, 1758, 2071, 3497, 2285, 4187, 5595, 3576, 2236, 9412, 6472, 6453, 6719, 3862, 4220, 4184, 2781, 8766, 4022, 2839, 6434, 1493, 0611, 9289, 5596, 2861, 6743, 8031, 1972, 8023, 8053, 0138, 4880, 2259, 4230, 2893, 2937, 9333, 3292, 7206, 5200Line truncated
|
||||
#else
|
||||
public const int PercentScale = 100_000;
|
||||
public static readonly (int Start, int End)[] PercentGroupsPromille =
|
||||
[
|
||||
(45000, 55000),
|
||||
(70000, 80000),
|
||||
(95000, 98000),
|
||||
(98000, 100000),
|
||||
(30000, 45000),
|
||||
(0, 10000),
|
||||
];
|
||||
|
||||
public static readonly int[] SpecialPercentPromille = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 10Line truncated
|
||||
#endif
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,88 +0,0 @@
|
||||
using System.Globalization;
|
||||
using System.Numerics;
|
||||
using PerfectNumbers.Core.Gpu;
|
||||
|
||||
namespace PerfectNumbers.Core.Cpu;
|
||||
|
||||
internal struct MersenneNumberDivisorByDivisorPrimeScanSessionWithCpuOrder(
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder prototype,
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult)
|
||||
{
|
||||
private MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder _tester = new()
|
||||
{
|
||||
DivisorLimit = prototype.DivisorLimit,
|
||||
MinK = EnvironmentConfiguration.MinK,
|
||||
};
|
||||
|
||||
private MersenneCpuDivisorScanSessionWithCpuOrder _divisorScanSession = new();
|
||||
|
||||
private readonly Action _markComposite = markComposite;
|
||||
private readonly Action _clearComposite = clearComposite;
|
||||
private readonly Action<ulong, bool, bool, bool, BigInteger> _printResult = printResult;
|
||||
|
||||
public void ProcessPrime(ulong prime)
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine($"Processing {prime}");
|
||||
string stateFile = Path.Combine(
|
||||
PerfectNumberConstants.ByDivisorStateDirectory,
|
||||
prime.ToString(CultureInfo.InvariantCulture) + ".bin");
|
||||
|
||||
ConfigureForPrime(stateFile);
|
||||
|
||||
bool isPrime = _tester.IsPrime(prime, out bool divisorsExhausted, out BigInteger divisor);
|
||||
|
||||
if (!isPrime)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(stateFile) && File.Exists(stateFile))
|
||||
{
|
||||
File.Delete(stateFile);
|
||||
}
|
||||
|
||||
_markComposite();
|
||||
_printResult(prime, true, true, false, divisor);
|
||||
Console.WriteLine($"Finished processing {prime}");
|
||||
return;
|
||||
}
|
||||
|
||||
_clearComposite();
|
||||
_printResult(prime, true, divisorsExhausted, true, divisor);
|
||||
Console.WriteLine($"Finished processing {prime}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error processing {ex.Message} {ex.StackTrace}");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigureForPrime(string stateFile)
|
||||
{
|
||||
BigInteger resumeK = EnvironmentConfiguration.MinK;
|
||||
if (File.Exists(stateFile))
|
||||
{
|
||||
if (MersenneNumberDivisorByDivisorTester.TryReadLastSavedK(stateFile, out BigInteger lastK))
|
||||
{
|
||||
resumeK = lastK + BigInteger.One;
|
||||
_tester.ResumeFromState(stateFile, lastK, resumeK);
|
||||
}
|
||||
else
|
||||
{
|
||||
_tester.ResumeFromState(stateFile, BigInteger.Zero, resumeK);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_tester.ResumeFromState(stateFile, BigInteger.Zero, resumeK);
|
||||
}
|
||||
|
||||
_tester.ResetStateTracking();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
-101
@@ -1,101 +0,0 @@
|
||||
using System.Globalization;
|
||||
using System.Numerics;
|
||||
using PerfectNumbers.Core.Gpu;
|
||||
using PerfectNumbers.Core.Gpu.Accelerators;
|
||||
|
||||
namespace PerfectNumbers.Core.Cpu;
|
||||
|
||||
internal struct MersenneNumberDivisorByDivisorPrimeScanSessionWithHybridOrder
|
||||
{
|
||||
private MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder _tester;
|
||||
private MersenneCpuDivisorScanSessionWithHybridOrder _divisorScanSession;
|
||||
|
||||
private readonly Action _markComposite;
|
||||
private readonly Action _clearComposite;
|
||||
private readonly Action<ulong, bool, bool, bool, BigInteger> _printResult;
|
||||
|
||||
public MersenneNumberDivisorByDivisorPrimeScanSessionWithHybridOrder(
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder prototype,
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult)
|
||||
{
|
||||
_tester = new MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder
|
||||
{
|
||||
DivisorLimit = prototype.DivisorLimit,
|
||||
MinK = EnvironmentConfiguration.MinK,
|
||||
};
|
||||
|
||||
_divisorScanSession = new MersenneCpuDivisorScanSessionWithHybridOrder();
|
||||
_divisorScanSession.Configure(_tester.Accelerator);
|
||||
|
||||
_markComposite = markComposite;
|
||||
_clearComposite = clearComposite;
|
||||
_printResult = printResult;
|
||||
}
|
||||
|
||||
public void ProcessPrime(ulong prime)
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine($"Processing {prime}");
|
||||
string stateFile = Path.Combine(
|
||||
PerfectNumberConstants.ByDivisorStateDirectory,
|
||||
prime.ToString(CultureInfo.InvariantCulture) + ".bin");
|
||||
|
||||
ConfigureForPrime(stateFile);
|
||||
|
||||
bool isPrime = _tester.IsPrime(prime, out bool divisorsExhausted, out BigInteger divisor);
|
||||
|
||||
if (!isPrime)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(stateFile) && File.Exists(stateFile))
|
||||
{
|
||||
File.Delete(stateFile);
|
||||
}
|
||||
|
||||
_markComposite();
|
||||
_printResult(prime, true, true, false, divisor);
|
||||
Console.WriteLine($"Finished processing {prime}");
|
||||
return;
|
||||
}
|
||||
|
||||
_clearComposite();
|
||||
_printResult(prime, true, divisorsExhausted, true, divisor);
|
||||
Console.WriteLine($"Finished processing {prime}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error processing {ex.Message} {ex.StackTrace}");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigureForPrime(string stateFile)
|
||||
{
|
||||
BigInteger resumeK = EnvironmentConfiguration.MinK;
|
||||
if (File.Exists(stateFile))
|
||||
{
|
||||
if (MersenneNumberDivisorByDivisorTester.TryReadLastSavedK(stateFile, out BigInteger lastK))
|
||||
{
|
||||
resumeK = lastK + BigInteger.One;
|
||||
_tester.ResumeFromState(stateFile, lastK, resumeK);
|
||||
}
|
||||
else
|
||||
{
|
||||
_tester.ResumeFromState(stateFile, BigInteger.Zero, resumeK);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_tester.ResumeFromState(stateFile, BigInteger.Zero, resumeK);
|
||||
}
|
||||
|
||||
_tester.ResetStateTracking();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
PrimeOrderCalculatorAccelerator.Return(_tester.Accelerator);
|
||||
}
|
||||
}
|
||||
+37
-9
@@ -1,34 +1,59 @@
|
||||
using System.Globalization;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using PerfectNumbers.Core.Gpu;
|
||||
using PerfectNumbers.Core.Gpu.Accelerators;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
|
||||
#if DivisorSet_Pow2Groups
|
||||
using TesterCpu = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForCpuOrder;
|
||||
using TesterHybrid = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForHybridOrder;
|
||||
using TesterGpu = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForGpuOrder;
|
||||
#else
|
||||
using TesterCpu = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForCpuOrder;
|
||||
using TesterHybrid = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForHybridOrder;
|
||||
using TesterGpu = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForGpuOrder;
|
||||
#endif
|
||||
|
||||
namespace PerfectNumbers.Core.Cpu;
|
||||
|
||||
internal struct MersenneNumberDivisorByDivisorPrimeScanSessionWithGpuOrder
|
||||
[EnumDependentTemplate(typeof(DivisorSet))]
|
||||
[DeviceDependentTemplate(typeof(ComputationDevice))]
|
||||
[NameSuffix("Order")]
|
||||
internal struct MersenneNumberDivisorByDivisorPrimeScanSessionWithTemplate
|
||||
{
|
||||
private MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder _tester;
|
||||
private MersenneCpuDivisorScanSessionWithGpuOrder _divisorScanSession;
|
||||
#if DEVICE_GPU
|
||||
private TesterGpu _tester;
|
||||
#elif DEVICE_HYBRID
|
||||
private TesterHybrid _tester;
|
||||
#else
|
||||
private TesterCpu _tester;
|
||||
#endif
|
||||
|
||||
private readonly Action _markComposite;
|
||||
private readonly Action _clearComposite;
|
||||
private readonly Action<ulong, bool, bool, bool, BigInteger> _printResult;
|
||||
|
||||
public MersenneNumberDivisorByDivisorPrimeScanSessionWithGpuOrder(
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder prototype,
|
||||
public MersenneNumberDivisorByDivisorPrimeScanSessionWithTemplate(
|
||||
#if DEVICE_GPU
|
||||
in TesterGpu prototype,
|
||||
#elif DEVICE_HYBRID
|
||||
in TesterHybrid prototype,
|
||||
#else
|
||||
in TesterCpu prototype,
|
||||
#endif
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult)
|
||||
{
|
||||
_tester = new MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder
|
||||
_tester = new()
|
||||
{
|
||||
DivisorLimit = prototype.DivisorLimit,
|
||||
MinK = EnvironmentConfiguration.MinK,
|
||||
};
|
||||
|
||||
_divisorScanSession = new MersenneCpuDivisorScanSessionWithGpuOrder();
|
||||
_divisorScanSession.Configure(_tester.Accelerator);
|
||||
|
||||
_markComposite = markComposite;
|
||||
_clearComposite = clearComposite;
|
||||
_printResult = printResult;
|
||||
@@ -94,8 +119,11 @@ internal struct MersenneNumberDivisorByDivisorPrimeScanSessionWithGpuOrder
|
||||
_tester.ResetStateTracking();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public void Dispose()
|
||||
{
|
||||
#if DEVICE_GPU || DEVICE_HYBRID
|
||||
PrimeOrderCalculatorAccelerator.Return(_tester.Accelerator);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,8 @@ public static class EnvironmentConfiguration
|
||||
public static bool UseGpuOrder;
|
||||
public static bool UseHybridOrder;
|
||||
public static bool UseCpuOrder;
|
||||
public static bool UsePow2GroupDivisors;
|
||||
public static int ByDivisorSpecialRange;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void Initialize()
|
||||
|
||||
@@ -6,6 +6,9 @@ using PerfectNumbers.Core.Gpu;
|
||||
using PerfectNumbers.Core.Gpu.Accelerators;
|
||||
using PerfectNumbers.Core.Cpu;
|
||||
using System.Runtime.CompilerServices;
|
||||
using MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForCpuOrder;
|
||||
using MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForHybridOrder;
|
||||
using MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForGpuOrder;
|
||||
|
||||
namespace PerfectNumbers.Core;
|
||||
|
||||
@@ -104,6 +107,99 @@ public static class MersenneNumberDivisorByDivisorTester
|
||||
Action<ulong, bool, bool, bool, BigInteger> pr) =>
|
||||
RunGpuOrderFiltered(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void Run(
|
||||
List<ulong> candidates,
|
||||
ref MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForCpuOrder tester,
|
||||
Dictionary<ulong, (bool DetailedCheck, bool PassedAllTests)>? previousResults,
|
||||
ulong startPrime,
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult,
|
||||
int threadCount,
|
||||
int primesPerTask)
|
||||
=> RunStructTester(
|
||||
candidates,
|
||||
ref tester,
|
||||
previousResults,
|
||||
startPrime,
|
||||
markComposite,
|
||||
clearComposite,
|
||||
printResult,
|
||||
threadCount,
|
||||
primesPerTask,
|
||||
static (
|
||||
List<ulong> filteredPrimes,
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForCpuOrder prototype,
|
||||
int workerCount,
|
||||
int partitionSize,
|
||||
Action mc,
|
||||
Action cc,
|
||||
Action<ulong, bool, bool, bool, BigInteger> pr) =>
|
||||
RunCpuOrderFilteredPow2(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void Run(
|
||||
List<ulong> candidates,
|
||||
ref MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForHybridOrder tester,
|
||||
Dictionary<ulong, (bool DetailedCheck, bool PassedAllTests)>? previousResults,
|
||||
ulong startPrime,
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult,
|
||||
int threadCount,
|
||||
int primesPerTask)
|
||||
=> RunStructTester(
|
||||
candidates,
|
||||
ref tester,
|
||||
previousResults,
|
||||
startPrime,
|
||||
markComposite,
|
||||
clearComposite,
|
||||
printResult,
|
||||
threadCount,
|
||||
primesPerTask,
|
||||
static (
|
||||
List<ulong> filteredPrimes,
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForHybridOrder prototype,
|
||||
int workerCount,
|
||||
int partitionSize,
|
||||
Action mc,
|
||||
Action cc,
|
||||
Action<ulong, bool, bool, bool, BigInteger> pr) =>
|
||||
RunHybridOrderFilteredPow2(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void Run(
|
||||
List<ulong> candidates,
|
||||
ref MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForGpuOrder tester,
|
||||
Dictionary<ulong, (bool DetailedCheck, bool PassedAllTests)>? previousResults,
|
||||
ulong startPrime,
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult,
|
||||
int threadCount,
|
||||
int primesPerTask)
|
||||
=> RunStructTester(
|
||||
candidates,
|
||||
ref tester,
|
||||
previousResults,
|
||||
startPrime,
|
||||
markComposite,
|
||||
clearComposite,
|
||||
printResult,
|
||||
threadCount,
|
||||
primesPerTask,
|
||||
static (
|
||||
List<ulong> filteredPrimes,
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForGpuOrder prototype,
|
||||
int workerCount,
|
||||
int partitionSize,
|
||||
Action mc,
|
||||
Action cc,
|
||||
Action<ulong, bool, bool, bool, BigInteger> pr) =>
|
||||
RunGpuOrderFilteredPow2(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr));
|
||||
|
||||
internal static bool TryReadLastSavedK(string stateFile, out BigInteger lastSavedK)
|
||||
{
|
||||
lastSavedK = BigInteger.Zero;
|
||||
@@ -224,7 +320,7 @@ public static class MersenneNumberDivisorByDivisorTester
|
||||
|
||||
if (maxPrime - 1UL >= 64UL)
|
||||
{
|
||||
return (BigInteger.One << 256) - BigInteger.One;
|
||||
return BigIntegerNumbers.OneShiftedLeft256MinusOne;
|
||||
}
|
||||
|
||||
return (BigInteger.One << (int)(maxPrime - 1UL)) - BigInteger.One;
|
||||
@@ -901,7 +997,7 @@ public static class MersenneNumberDivisorByDivisorTester
|
||||
if (workerCount == 1)
|
||||
{
|
||||
DeterministicRandomCpu.Initialize();
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithCpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForOneByOneDivisorSetForCpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
foreach (ulong prime in filteredPrimes)
|
||||
{
|
||||
session.ProcessPrime(prime);
|
||||
@@ -923,7 +1019,7 @@ public static class MersenneNumberDivisorByDivisorTester
|
||||
() =>
|
||||
{
|
||||
DeterministicRandomCpu.Initialize();
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithCpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForOneByOneDivisorSetForCpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
startGate.Wait();
|
||||
Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
|
||||
|
||||
@@ -986,7 +1082,7 @@ public static class MersenneNumberDivisorByDivisorTester
|
||||
if (workerCount == 1)
|
||||
{
|
||||
DeterministicRandomCpu.Initialize();
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithHybridOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForOneByOneDivisorSetForHybridOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
foreach (ulong prime in filteredPrimes)
|
||||
@@ -1012,7 +1108,7 @@ public static class MersenneNumberDivisorByDivisorTester
|
||||
() =>
|
||||
{
|
||||
DeterministicRandomCpu.Initialize();
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithHybridOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForOneByOneDivisorSetForHybridOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
startGate.Wait();
|
||||
Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
|
||||
|
||||
@@ -1077,7 +1173,7 @@ public static class MersenneNumberDivisorByDivisorTester
|
||||
if (workerCount == 1)
|
||||
{
|
||||
DeterministicRandomCpu.Initialize();
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithGpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForOneByOneDivisorSetForGpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
|
||||
GpuPrimeWorkLimiter.Acquire();
|
||||
foreach (ulong prime in filteredPrimes)
|
||||
@@ -1103,7 +1199,7 @@ public static class MersenneNumberDivisorByDivisorTester
|
||||
() =>
|
||||
{
|
||||
DeterministicRandomCpu.Initialize();
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithGpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForOneByOneDivisorSetForGpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
startGate.Wait();
|
||||
Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
|
||||
|
||||
@@ -1231,5 +1327,255 @@ public static class MersenneNumberDivisorByDivisorTester
|
||||
Task.WaitAll(tasks);
|
||||
startGate.Dispose();
|
||||
}
|
||||
|
||||
private static void RunCpuOrderFilteredPow2(
|
||||
List<ulong> filteredPrimes,
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForCpuOrder prototype,
|
||||
int workerCount,
|
||||
int partitionSize,
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult)
|
||||
{
|
||||
MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForCpuOrder prototypeCopy = prototype;
|
||||
int totalCount = filteredPrimes.Count;
|
||||
if (partitionSize > totalCount)
|
||||
{
|
||||
partitionSize = totalCount;
|
||||
}
|
||||
|
||||
if (workerCount == 1)
|
||||
{
|
||||
DeterministicRandomCpu.Initialize();
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForPow2GroupsDivisorSetForCpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
foreach (ulong prime in filteredPrimes)
|
||||
{
|
||||
session.ProcessPrime(prime);
|
||||
}
|
||||
|
||||
session.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
TaskScheduler scheduler = UnboundedTaskScheduler.Instance;
|
||||
int nextIndex = 0;
|
||||
Task[] tasks = new Task[workerCount];
|
||||
var startGate = new ManualResetEventSlim(initialState: false);
|
||||
|
||||
for (int taskIndex = 0; taskIndex < workerCount; taskIndex++)
|
||||
{
|
||||
int workerIndex = taskIndex;
|
||||
tasks[taskIndex] = Task.Factory.StartNew(
|
||||
() =>
|
||||
{
|
||||
DeterministicRandomCpu.Initialize();
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForPow2GroupsDivisorSetForCpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
startGate.Wait();
|
||||
Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
|
||||
|
||||
while (true)
|
||||
{
|
||||
int start = Interlocked.Add(ref nextIndex, partitionSize) - partitionSize;
|
||||
if (start >= totalCount)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
int end = start + partitionSize;
|
||||
if (end > totalCount)
|
||||
{
|
||||
end = totalCount;
|
||||
}
|
||||
|
||||
for (int index = start; index < end; index++)
|
||||
{
|
||||
ulong prime = filteredPrimes[index];
|
||||
if (prime > 1)
|
||||
{
|
||||
session.ProcessPrime(prime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
session.Dispose();
|
||||
Console.WriteLine($"Task finished for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
|
||||
},
|
||||
CancellationToken.None,
|
||||
TaskCreationOptions.None,
|
||||
scheduler);
|
||||
}
|
||||
|
||||
startGate.Set();
|
||||
Console.WriteLine("All tasks started");
|
||||
|
||||
for (int index = 0; index < tasks.Length; index++)
|
||||
{
|
||||
tasks[index].Wait();
|
||||
Console.WriteLine($"Task {index.ToString(CultureInfo.InvariantCulture)} finished");
|
||||
}
|
||||
}
|
||||
|
||||
private static void RunHybridOrderFilteredPow2(
|
||||
List<ulong> filteredPrimes,
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForHybridOrder prototype,
|
||||
int workerCount,
|
||||
int partitionSize,
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult)
|
||||
{
|
||||
MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForHybridOrder prototypeCopy = prototype;
|
||||
int totalCount = filteredPrimes.Count;
|
||||
if (partitionSize > totalCount)
|
||||
{
|
||||
partitionSize = totalCount;
|
||||
}
|
||||
|
||||
if (workerCount == 1)
|
||||
{
|
||||
DeterministicRandomCpu.Initialize();
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForPow2GroupsDivisorSetForHybridOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
foreach (ulong prime in filteredPrimes)
|
||||
{
|
||||
session.ProcessPrime(prime);
|
||||
}
|
||||
|
||||
session.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
TaskScheduler scheduler = UnboundedTaskScheduler.Instance;
|
||||
int nextIndex = 0;
|
||||
Task[] tasks = new Task[workerCount];
|
||||
var startGate = new ManualResetEventSlim(initialState: false);
|
||||
for (int taskIndex = 0; taskIndex < workerCount; taskIndex++)
|
||||
{
|
||||
int workerIndex = taskIndex;
|
||||
tasks[taskIndex] = Task.Factory.StartNew(
|
||||
() =>
|
||||
{
|
||||
DeterministicRandomCpu.Initialize();
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForPow2GroupsDivisorSetForHybridOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
startGate.Wait();
|
||||
Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
|
||||
while (true)
|
||||
{
|
||||
int start = Interlocked.Add(ref nextIndex, partitionSize) - partitionSize;
|
||||
if (start >= totalCount)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
int end = start + partitionSize;
|
||||
if (end > totalCount)
|
||||
{
|
||||
end = totalCount;
|
||||
}
|
||||
|
||||
for (int index = start; index < end; index++)
|
||||
{
|
||||
ulong prime = filteredPrimes[index];
|
||||
if (prime > 1)
|
||||
{
|
||||
session.ProcessPrime(prime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
session.Dispose();
|
||||
Console.WriteLine($"Task finished for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
|
||||
},
|
||||
CancellationToken.None,
|
||||
TaskCreationOptions.None,
|
||||
scheduler);
|
||||
}
|
||||
|
||||
startGate.Set();
|
||||
for (int index = 0; index < tasks.Length; index++)
|
||||
{
|
||||
tasks[index].Wait();
|
||||
Console.WriteLine($"Task finished {index.ToString(CultureInfo.InvariantCulture)}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void RunGpuOrderFilteredPow2(
|
||||
List<ulong> filteredPrimes,
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForGpuOrder prototype,
|
||||
int workerCount,
|
||||
int partitionSize,
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult)
|
||||
{
|
||||
MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForGpuOrder prototypeCopy = prototype;
|
||||
int totalCount = filteredPrimes.Count;
|
||||
if (partitionSize > totalCount)
|
||||
{
|
||||
partitionSize = totalCount;
|
||||
}
|
||||
|
||||
if (workerCount == 1)
|
||||
{
|
||||
DeterministicRandomCpu.Initialize();
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForPow2GroupsDivisorSetForGpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
foreach (ulong prime in filteredPrimes)
|
||||
{
|
||||
session.ProcessPrime(prime);
|
||||
}
|
||||
|
||||
session.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
TaskScheduler scheduler = UnboundedTaskScheduler.Instance;
|
||||
int nextIndex = 0;
|
||||
Task[] tasks = new Task[workerCount];
|
||||
var startGate = new ManualResetEventSlim(initialState: false);
|
||||
for (int taskIndex = 0; taskIndex < workerCount; taskIndex++)
|
||||
{
|
||||
int workerIndex = taskIndex;
|
||||
tasks[taskIndex] = Task.Factory.StartNew(
|
||||
() =>
|
||||
{
|
||||
DeterministicRandomCpu.Initialize();
|
||||
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForPow2GroupsDivisorSetForGpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
startGate.Wait();
|
||||
Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
|
||||
while (true)
|
||||
{
|
||||
int start = Interlocked.Add(ref nextIndex, partitionSize) - partitionSize;
|
||||
if (start >= totalCount)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
int end = start + partitionSize;
|
||||
if (end > totalCount)
|
||||
{
|
||||
end = totalCount;
|
||||
}
|
||||
|
||||
for (int index = start; index < end; index++)
|
||||
{
|
||||
ulong prime = filteredPrimes[index];
|
||||
if (prime > 1)
|
||||
{
|
||||
session.ProcessPrime(prime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
session.Dispose();
|
||||
Console.WriteLine($"Task finished for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
|
||||
},
|
||||
CancellationToken.None,
|
||||
TaskCreationOptions.DenyChildAttach,
|
||||
scheduler);
|
||||
}
|
||||
|
||||
startGate.Set();
|
||||
Task.WaitAll(tasks);
|
||||
startGate.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,20 +170,20 @@ public static partial class PrimeOrderCalculatorTemplate
|
||||
|
||||
private static int GetGroupWide(in UInt128 value, in UInt128 prime)
|
||||
{
|
||||
UInt128 threshold1 = prime >> 3;
|
||||
if (value <= threshold1)
|
||||
UInt128 threshold = prime >> 3;
|
||||
if (value <= threshold)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
UInt128 threshold2 = prime >> 2;
|
||||
if (value <= threshold2)
|
||||
threshold = prime >> 2;
|
||||
if (value <= threshold)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
UInt128 threshold3 = (UInt128)(((BigInteger)prime * 3) >> 3);
|
||||
if (value <= threshold3)
|
||||
threshold = (UInt128)(((BigInteger)prime * 3) >> 3);
|
||||
if (value <= threshold)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
@@ -306,6 +306,7 @@ public static partial class PrimeOrderCalculatorTemplate
|
||||
}
|
||||
|
||||
FactorEntry128 factor = factors[index];
|
||||
index++;
|
||||
UInt128 primeFactor = factor.Value;
|
||||
UInt128 contribution = UInt128.One;
|
||||
for (int exponent = 0; exponent <= factor.Exponent; exponent++)
|
||||
@@ -316,7 +317,7 @@ public static partial class PrimeOrderCalculatorTemplate
|
||||
break;
|
||||
}
|
||||
|
||||
BuildCandidatesRecursiveWide(order, factors, index + 1, nextDivisor, candidates, limit);
|
||||
BuildCandidatesRecursiveWide(order, factors, index, nextDivisor, candidates, limit);
|
||||
if (candidates.Count >= limit)
|
||||
{
|
||||
return;
|
||||
@@ -1267,48 +1268,49 @@ public static partial class PrimeOrderCalculatorTemplate
|
||||
private static int ExtractSmallPrimeExponent(ref ulong value, ulong primeValue, ulong quotient)
|
||||
{
|
||||
ulong dividend = quotient;
|
||||
int exponent = 1;
|
||||
|
||||
if (dividend < primeValue)
|
||||
{
|
||||
value = dividend;
|
||||
return exponent;
|
||||
return 1;
|
||||
}
|
||||
|
||||
quotient = dividend / primeValue;
|
||||
ulong product = quotient * primeValue;
|
||||
if (dividend - product != 0UL)
|
||||
if (dividend - quotient * primeValue != 0UL)
|
||||
{
|
||||
value = dividend;
|
||||
return exponent;
|
||||
return 1;
|
||||
}
|
||||
|
||||
dividend = quotient;
|
||||
exponent++;
|
||||
|
||||
if (dividend < primeValue)
|
||||
{
|
||||
value = dividend;
|
||||
return exponent;
|
||||
return 2;
|
||||
}
|
||||
|
||||
quotient = dividend / primeValue;
|
||||
product = quotient * primeValue;
|
||||
if (dividend - product != 0UL)
|
||||
if (dividend - quotient * primeValue != 0UL)
|
||||
{
|
||||
value = dividend;
|
||||
return exponent;
|
||||
return 2;
|
||||
}
|
||||
|
||||
dividend = quotient;
|
||||
exponent++;
|
||||
return ExtractSmallPrimeExponentWithLoop(ref value, primeValue, quotient);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
private static int ExtractSmallPrimeExponentWithLoop(ref ulong value, ulong primeValue, ulong quotient)
|
||||
{
|
||||
ulong dividend = quotient;
|
||||
int exponent = 3;
|
||||
|
||||
while (true)
|
||||
{
|
||||
quotient = dividend / primeValue;
|
||||
product = quotient * primeValue;
|
||||
|
||||
if (dividend - product != 0UL)
|
||||
if (dividend - quotient * primeValue != 0UL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -1319,7 +1321,8 @@ public static partial class PrimeOrderCalculatorTemplate
|
||||
|
||||
value = dividend;
|
||||
return exponent;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -1336,16 +1339,13 @@ public static partial class PrimeOrderCalculatorTemplate
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
private static ulong AdvancePolynomial(ulong x, ulong c, ulong modulus)
|
||||
{
|
||||
return unchecked((x * x) % modulus + c) % modulus;
|
||||
}
|
||||
private static ulong AdvancePolynomial(ulong x, ulong c, ulong modulus) => unchecked(x * x % modulus + c) % modulus;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
private static ulong AdvancePolynomialTwice(ulong x, ulong c, ulong modulus)
|
||||
{
|
||||
x = AdvancePolynomial(x, c, modulus);
|
||||
return AdvancePolynomial(x, c, modulus);
|
||||
x = unchecked(x * x % modulus + c) % modulus;
|
||||
return unchecked(x * x % modulus + c) % modulus;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -1911,14 +1911,29 @@ public static partial class PrimeOrderCalculatorTemplate
|
||||
|
||||
List<PartialFactorPendingEntry> pending = result.PendingFactors;
|
||||
pending.Clear();
|
||||
// #if DEVICE_HYBRID
|
||||
// bool pollardRhoDeadlineReached = false;
|
||||
// CollectSmallFactors(gpu, config, exponentSlots, primeSlots, ref value, ref pollardRhoDeadlineReached, out int factorCount);
|
||||
// if (factorCount == 0 && !pollardRhoDeadlineReached)
|
||||
// {
|
||||
// PopulateSmallPrimeFactors(
|
||||
// value,
|
||||
// config.SmallFactorLimit,
|
||||
// primeSlots,
|
||||
// exponentSlots,
|
||||
// out factorCount,
|
||||
// out value);
|
||||
// }
|
||||
// #elif DEVICE_CPU
|
||||
PopulateSmallPrimeFactors(
|
||||
value,
|
||||
config.SmallFactorLimit,
|
||||
primeSlots,
|
||||
exponentSlots,
|
||||
out int factorCount,
|
||||
out value);
|
||||
// #endif
|
||||
|
||||
PopulateSmallPrimeFactors(
|
||||
value,
|
||||
config.SmallFactorLimit,
|
||||
primeSlots,
|
||||
exponentSlots,
|
||||
out int factorCount,
|
||||
out value);
|
||||
|
||||
bool cofactorContainsComposite;
|
||||
if (value > 1UL)
|
||||
@@ -3051,7 +3066,7 @@ public static partial class PrimeOrderCalculatorTemplate
|
||||
return true;
|
||||
}
|
||||
|
||||
#if DEVICE_GPU
|
||||
#if DEVICE_GPU //|| DEVICE_HYBRID
|
||||
private const int GpuSmallPrimeFactorSlots = 64;
|
||||
|
||||
// GPU specific. It doesn't make sense to consolidate into one method.
|
||||
|
||||
Reference in new issue
Block a user