BitContradiction filtering changes to cut invalid divisors during checks.
This commit is contained in:
1 parent
b31aab4d89
commit
f1eaab8582
19 files changed
+3912
-2361
No files matched your search
@@ -5,18 +5,6 @@ using PerfectNumbers.Core.Gpu;
|
|||||||
|
|
||||||
namespace EvenPerfectBitScanner;
|
namespace EvenPerfectBitScanner;
|
||||||
|
|
||||||
internal enum ByDivisorKIncrementMode
|
|
||||||
{
|
|
||||||
Sequential,
|
|
||||||
Pow2Groups,
|
|
||||||
Predictive,
|
|
||||||
Percentile,
|
|
||||||
Additive,
|
|
||||||
TopDown,
|
|
||||||
BitContradiction,
|
|
||||||
BitTree,
|
|
||||||
}
|
|
||||||
|
|
||||||
internal readonly struct CliArguments
|
internal readonly struct CliArguments
|
||||||
{
|
{
|
||||||
private const string DefaultCyclesPath = "divisor_cycles.bin";
|
private const string DefaultCyclesPath = "divisor_cycles.bin";
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace EvenPerfectBitScanner;
|
|||||||
internal static class Program
|
internal static class Program
|
||||||
{
|
{
|
||||||
// private static ThreadLocal<PrimeTester> PrimeTesters = null!;
|
// private static ThreadLocal<PrimeTester> PrimeTesters = null!;
|
||||||
private static ThreadLocal<object>? MersenneTesters;
|
private static ThreadLocal<object>? MersenneTesters;
|
||||||
private const ulong InitialP = PerfectNumberConstants.BiggestKnownEvenPerfectP;
|
private const ulong InitialP = PerfectNumberConstants.BiggestKnownEvenPerfectP;
|
||||||
private static MersenneNumberDivisorGpuTester? _divisorTester;
|
private static MersenneNumberDivisorGpuTester? _divisorTester;
|
||||||
private static UInt128 _divisor;
|
private static UInt128 _divisor;
|
||||||
@@ -111,37 +111,31 @@ private static ThreadLocal<object>? MersenneTesters;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Initializing");
|
Console.WriteLine("Initializing");
|
||||||
int gpuPrimeThreads = Math.Max(1, _cliArguments.GpuPrimeThreads * PerfectNumberConstants.ThreadsByAccelerator);
|
|
||||||
int threadCount = Math.Max(1, _cliArguments.ThreadCount);
|
|
||||||
|
|
||||||
EnvironmentConfiguration.MinK = _cliArguments.MinK;
|
EnvironmentConfiguration.ByDivisorKIncrementMode = _cliArguments.ByDivisorKIncrementMode;
|
||||||
EnvironmentConfiguration.GpuBatchSize = Math.Max(1, _cliArguments.ScanBatchSize);
|
EnvironmentConfiguration.ByDivisorSpecialRange = _cliArguments.ByDivisorSpecialRange;
|
||||||
EnvironmentConfiguration.GpuRatio = _cliArguments.GpuRatio;
|
EnvironmentConfiguration.CalculationMethod =
|
||||||
EnvironmentConfiguration.MersenneDevice = _cliArguments.MersenneDevice;
|
_cliArguments.UseByDivisor ? CalculationMethod.ByDivisor
|
||||||
ComputationDevice orderDevice = _cliArguments.OrderDevice;
|
: _cliArguments.UseDivisor ? CalculationMethod.Divisor
|
||||||
if (_cliArguments.MersenneDevice == ComputationDevice.Gpu &&
|
: _cliArguments.UseResidue ? CalculationMethod.Residue
|
||||||
_cliArguments.ByDivisorKIncrementMode == ByDivisorKIncrementMode.BitContradiction)
|
: _cliArguments.UseLucas ? CalculationMethod.LucasLehmer
|
||||||
{
|
: _cliArguments.KernelType == GpuKernelType.Pow2Mod ? CalculationMethod.Pow2Mod
|
||||||
orderDevice = ComputationDevice.Gpu;
|
: CalculationMethod.Incremental;
|
||||||
}
|
EnvironmentConfiguration.GpuBatchSize = Math.Max(1, _cliArguments.ScanBatchSize);
|
||||||
|
EnvironmentConfiguration.GpuPrimeThreads = Math.Max(1, _cliArguments.GpuPrimeThreads * PerfectNumberConstants.ThreadsByAccelerator);
|
||||||
|
EnvironmentConfiguration.GpuRatio = _cliArguments.GpuRatio;
|
||||||
|
EnvironmentConfiguration.MersenneDevice = _cliArguments.MersenneDevice;
|
||||||
|
EnvironmentConfiguration.MinK = _cliArguments.MinK;
|
||||||
|
EnvironmentConfiguration.OrderDevice = _cliArguments.OrderDevice;
|
||||||
|
EnvironmentConfiguration.ThreadCount = Math.Max(1, _cliArguments.ThreadCount);
|
||||||
|
|
||||||
EnvironmentConfiguration.OrderDevice = orderDevice;
|
EnvironmentConfiguration.Initialize();
|
||||||
EnvironmentConfiguration.UsePow2GroupDivisors = _cliArguments.ByDivisorKIncrementMode == ByDivisorKIncrementMode.Pow2Groups;
|
|
||||||
EnvironmentConfiguration.ByDivisorSpecialRange = _cliArguments.ByDivisorSpecialRange;
|
|
||||||
|
|
||||||
bool useGpu = orderDevice == ComputationDevice.Hybrid || orderDevice == ComputationDevice.Gpu ||
|
PrimeOrderCalculatorAccelerator.SkipOrderTablesAndKernels =
|
||||||
_cliArguments.MersenneDevice == ComputationDevice.Hybrid || _cliArguments.MersenneDevice == ComputationDevice.Gpu;
|
EnvironmentConfiguration.MersenneDevice == ComputationDevice.Gpu &&
|
||||||
|
EnvironmentConfiguration.CalculationMethod == CalculationMethod.ByDivisor &&
|
||||||
EnvironmentConfiguration.RollingAccelerators = useGpu
|
EnvironmentConfiguration.ByDivisorKIncrementMode == ByDivisorKIncrementMode.BitContradiction;
|
||||||
? Math.Min(Math.Min(PerfectNumberConstants.RollingAccelerators, gpuPrimeThreads), threadCount)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
EnvironmentConfiguration.Initialize();
|
|
||||||
|
|
||||||
PrimeOrderCalculatorAccelerator.SkipOrderTablesAndKernels = _cliArguments.MersenneDevice == ComputationDevice.Gpu &&
|
|
||||||
_cliArguments.UseByDivisor &&
|
|
||||||
_cliArguments.ByDivisorKIncrementMode == ByDivisorKIncrementMode.BitContradiction;
|
|
||||||
|
|
||||||
// NttGpuMath.GpuTransformBackend = _cliArguments.NttBackend;
|
// NttGpuMath.GpuTransformBackend = _cliArguments.NttBackend;
|
||||||
// NttGpuMath.ReductionMode = _cliArguments.ModReductionMode;
|
// NttGpuMath.ReductionMode = _cliArguments.ModReductionMode;
|
||||||
@@ -151,6 +145,9 @@ private static ThreadLocal<object>? MersenneTesters;
|
|||||||
ulong remainder = currentP % 6UL;
|
ulong remainder = currentP % 6UL;
|
||||||
bool startPrimeProvided = _cliArguments.StartPrimeProvided;
|
bool startPrimeProvided = _cliArguments.StartPrimeProvided;
|
||||||
int gpuPrimeBatch = Math.Max(1, _cliArguments.GpuPrimeBatch);
|
int gpuPrimeBatch = Math.Max(1, _cliArguments.GpuPrimeBatch);
|
||||||
|
bool useGpu = EnvironmentConfiguration.UseGpu;
|
||||||
|
int threadCount = EnvironmentConfiguration.ThreadCount;
|
||||||
|
int gpuPrimeThreads = EnvironmentConfiguration.GpuPrimeThreads;
|
||||||
// int gpuPrimeThreads = SharedGpuContext.Device.MaxNumThreads;
|
// int gpuPrimeThreads = SharedGpuContext.Device.MaxNumThreads;
|
||||||
Console.WriteLine("Setting up parameters");
|
Console.WriteLine("Setting up parameters");
|
||||||
UnboundedTaskScheduler.ConfigureThreadCount(threadCount);
|
UnboundedTaskScheduler.ConfigureThreadCount(threadCount);
|
||||||
@@ -606,16 +603,16 @@ private static ThreadLocal<object>? MersenneTesters;
|
|||||||
EnvironmentConfiguration.ByDivisorPow2Minus1Repository ??= Pow2Minus1StateRepository.Open(Path.Combine(checksDir, "pow2minus1.faster"), pow2MinusLmdb, checksDir);
|
EnvironmentConfiguration.ByDivisorPow2Minus1Repository ??= Pow2Minus1StateRepository.Open(Path.Combine(checksDir, "pow2minus1.faster"), pow2MinusLmdb, checksDir);
|
||||||
EnvironmentConfiguration.BitContradictionStateRepository ??= BitContradictionStateRepository.Open(checksDir);
|
EnvironmentConfiguration.BitContradictionStateRepository ??= BitContradictionStateRepository.Open(checksDir);
|
||||||
|
|
||||||
if (kIncrementMode == ByDivisorKIncrementMode.Pow2Groups)
|
if (kIncrementMode == ByDivisorKIncrementMode.Pow2Groups)
|
||||||
{
|
{
|
||||||
EnvironmentConfiguration.ByDivisorSpecialStateRepository = KStateRepository.Open(checksDir, "pow2groups.special.kstate.faster", Path.Combine(checksDir, "pow2groups.special.kstate.lmdb"), checksDir);
|
EnvironmentConfiguration.ByDivisorSpecialStateRepository = KStateRepository.Open(checksDir, "pow2groups.special.kstate.faster", Path.Combine(checksDir, "pow2groups.special.kstate.lmdb"), checksDir);
|
||||||
EnvironmentConfiguration.ByDivisorGroupsStateRepository = KStateRepository.Open(checksDir, "pow2groups.groups.kstate.faster", Path.Combine(checksDir, "pow2groups.groups.kstate.lmdb"), checksDir);
|
EnvironmentConfiguration.ByDivisorGroupsStateRepository = KStateRepository.Open(checksDir, "pow2groups.groups.kstate.faster", Path.Combine(checksDir, "pow2groups.groups.kstate.lmdb"), checksDir);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EnvironmentConfiguration.ByDivisorSpecialStateRepository = null;
|
EnvironmentConfiguration.ByDivisorSpecialStateRepository = null;
|
||||||
EnvironmentConfiguration.ByDivisorGroupsStateRepository = null;
|
EnvironmentConfiguration.ByDivisorGroupsStateRepository = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool useFilter = !testMode && !string.IsNullOrEmpty(filterFile);
|
bool useFilter = !testMode && !string.IsNullOrEmpty(filterFile);
|
||||||
@@ -1409,48 +1406,48 @@ private static ThreadLocal<object>? MersenneTesters;
|
|||||||
// Windowed pow2mod kernel handles by-divisor scans.
|
// Windowed pow2mod kernel handles by-divisor scans.
|
||||||
ByDivisorKIncrementMode mode = _cliArguments.ByDivisorKIncrementMode;
|
ByDivisorKIncrementMode mode = _cliArguments.ByDivisorKIncrementMode;
|
||||||
if (EnvironmentConfiguration.UseCpuOrder)
|
if (EnvironmentConfiguration.UseCpuOrder)
|
||||||
{
|
{
|
||||||
return mode switch
|
|
||||||
{
|
|
||||||
ByDivisorKIncrementMode.Pow2Groups => _byDivisorCpuOrderTesterPow2.IsPrime(p, out detailedCheck, out _),
|
|
||||||
ByDivisorKIncrementMode.Predictive => _byDivisorCpuOrderTesterPredictive.IsPrime(p, out detailedCheck, out _),
|
|
||||||
ByDivisorKIncrementMode.Percentile => _byDivisorCpuOrderTesterPercentile.IsPrime(p, out detailedCheck, out _),
|
|
||||||
ByDivisorKIncrementMode.Additive => _byDivisorCpuOrderTesterAdditive.IsPrime(p, out detailedCheck, out _),
|
|
||||||
ByDivisorKIncrementMode.TopDown => _byDivisorCpuOrderTesterTopDown.IsPrime(p, out detailedCheck, out _),
|
|
||||||
ByDivisorKIncrementMode.BitContradiction => _byDivisorCpuOrderTesterBitContradiction.IsPrime(p, out detailedCheck, out _),
|
|
||||||
ByDivisorKIncrementMode.BitTree => _byDivisorCpuOrderTesterBitTree.IsPrime(p, out detailedCheck, out _),
|
|
||||||
_ => _byDivisorCpuOrderTester.IsPrime(p, out detailedCheck, out _),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EnvironmentConfiguration.UseHybridOrder)
|
|
||||||
{
|
|
||||||
return mode switch
|
|
||||||
{
|
|
||||||
ByDivisorKIncrementMode.Pow2Groups => _byDivisorHybridOrderTesterPow2.IsPrime(p, out detailedCheck, out _),
|
|
||||||
ByDivisorKIncrementMode.Predictive => _byDivisorHybridOrderTesterPredictive.IsPrime(p, out detailedCheck, out _),
|
|
||||||
ByDivisorKIncrementMode.Percentile => _byDivisorHybridOrderTesterPercentile.IsPrime(p, out detailedCheck, out _),
|
|
||||||
ByDivisorKIncrementMode.Additive => _byDivisorHybridOrderTesterAdditive.IsPrime(p, out detailedCheck, out _),
|
|
||||||
ByDivisorKIncrementMode.TopDown => _byDivisorHybridOrderTesterTopDown.IsPrime(p, out detailedCheck, out _),
|
|
||||||
ByDivisorKIncrementMode.BitContradiction => _byDivisorHybridOrderTesterBitContradiction.IsPrime(p, out detailedCheck, out _),
|
|
||||||
ByDivisorKIncrementMode.BitTree => _byDivisorHybridOrderTesterBitTree.IsPrime(p, out detailedCheck, out _),
|
|
||||||
_ => _byDivisorHybridOrderTester.IsPrime(p, out detailedCheck, out _),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return mode switch
|
return mode switch
|
||||||
{
|
{
|
||||||
ByDivisorKIncrementMode.Pow2Groups => _byDivisorGpuOrderTesterPow2.IsPrime(p, out detailedCheck, out _),
|
ByDivisorKIncrementMode.Pow2Groups => _byDivisorCpuOrderTesterPow2.IsPrime(p, out detailedCheck, out _),
|
||||||
ByDivisorKIncrementMode.Predictive => _byDivisorGpuOrderTesterPredictive.IsPrime(p, out detailedCheck, out _),
|
ByDivisorKIncrementMode.Predictive => _byDivisorCpuOrderTesterPredictive.IsPrime(p, out detailedCheck, out _),
|
||||||
ByDivisorKIncrementMode.Percentile => _byDivisorGpuOrderTesterPercentile.IsPrime(p, out detailedCheck, out _),
|
ByDivisorKIncrementMode.Percentile => _byDivisorCpuOrderTesterPercentile.IsPrime(p, out detailedCheck, out _),
|
||||||
ByDivisorKIncrementMode.Additive => _byDivisorGpuOrderTesterAdditive.IsPrime(p, out detailedCheck, out _),
|
ByDivisorKIncrementMode.Additive => _byDivisorCpuOrderTesterAdditive.IsPrime(p, out detailedCheck, out _),
|
||||||
ByDivisorKIncrementMode.TopDown => _byDivisorGpuOrderTesterTopDown.IsPrime(p, out detailedCheck, out _),
|
ByDivisorKIncrementMode.TopDown => _byDivisorCpuOrderTesterTopDown.IsPrime(p, out detailedCheck, out _),
|
||||||
ByDivisorKIncrementMode.BitContradiction => _byDivisorGpuOrderTesterBitContradiction.IsPrime(p, out detailedCheck, out _),
|
ByDivisorKIncrementMode.BitContradiction => _byDivisorCpuOrderTesterBitContradiction.IsPrime(p, out detailedCheck, out _),
|
||||||
ByDivisorKIncrementMode.BitTree => _byDivisorGpuOrderTesterBitTree.IsPrime(p, out detailedCheck, out _),
|
ByDivisorKIncrementMode.BitTree => _byDivisorCpuOrderTesterBitTree.IsPrime(p, out detailedCheck, out _),
|
||||||
_ => _byDivisorGpuOrderTester.IsPrime(p, out detailedCheck, out _),
|
_ => _byDivisorCpuOrderTester.IsPrime(p, out detailedCheck, out _),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (EnvironmentConfiguration.UseHybridOrder)
|
||||||
|
{
|
||||||
|
return mode switch
|
||||||
|
{
|
||||||
|
ByDivisorKIncrementMode.Pow2Groups => _byDivisorHybridOrderTesterPow2.IsPrime(p, out detailedCheck, out _),
|
||||||
|
ByDivisorKIncrementMode.Predictive => _byDivisorHybridOrderTesterPredictive.IsPrime(p, out detailedCheck, out _),
|
||||||
|
ByDivisorKIncrementMode.Percentile => _byDivisorHybridOrderTesterPercentile.IsPrime(p, out detailedCheck, out _),
|
||||||
|
ByDivisorKIncrementMode.Additive => _byDivisorHybridOrderTesterAdditive.IsPrime(p, out detailedCheck, out _),
|
||||||
|
ByDivisorKIncrementMode.TopDown => _byDivisorHybridOrderTesterTopDown.IsPrime(p, out detailedCheck, out _),
|
||||||
|
ByDivisorKIncrementMode.BitContradiction => _byDivisorHybridOrderTesterBitContradiction.IsPrime(p, out detailedCheck, out _),
|
||||||
|
ByDivisorKIncrementMode.BitTree => _byDivisorHybridOrderTesterBitTree.IsPrime(p, out detailedCheck, out _),
|
||||||
|
_ => _byDivisorHybridOrderTester.IsPrime(p, out detailedCheck, out _),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return mode switch
|
||||||
|
{
|
||||||
|
ByDivisorKIncrementMode.Pow2Groups => _byDivisorGpuOrderTesterPow2.IsPrime(p, out detailedCheck, out _),
|
||||||
|
ByDivisorKIncrementMode.Predictive => _byDivisorGpuOrderTesterPredictive.IsPrime(p, out detailedCheck, out _),
|
||||||
|
ByDivisorKIncrementMode.Percentile => _byDivisorGpuOrderTesterPercentile.IsPrime(p, out detailedCheck, out _),
|
||||||
|
ByDivisorKIncrementMode.Additive => _byDivisorGpuOrderTesterAdditive.IsPrime(p, out detailedCheck, out _),
|
||||||
|
ByDivisorKIncrementMode.TopDown => _byDivisorGpuOrderTesterTopDown.IsPrime(p, out detailedCheck, out _),
|
||||||
|
ByDivisorKIncrementMode.BitContradiction => _byDivisorGpuOrderTesterBitContradiction.IsPrime(p, out detailedCheck, out _),
|
||||||
|
ByDivisorKIncrementMode.BitTree => _byDivisorGpuOrderTesterBitTree.IsPrime(p, out detailedCheck, out _),
|
||||||
|
_ => _byDivisorGpuOrderTester.IsPrime(p, out detailedCheck, out _),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
detailedCheck = IsMersennePrime(gpu, p);
|
detailedCheck = IsMersennePrime(gpu, p);
|
||||||
return detailedCheck;
|
return detailedCheck;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -9,13 +9,19 @@ public readonly struct ColumnBounds(int forcedOnes, int possibleOnes)
|
|||||||
public readonly int PossibleOnes = possibleOnes;
|
public readonly int PossibleOnes = possibleOnes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly struct CarryRange(long min, long max)
|
public readonly struct CarryRange(long min, long max, byte mod4Mask = byte.MinValue)
|
||||||
{
|
{
|
||||||
public readonly long Min = min;
|
public readonly long Min = min;
|
||||||
public readonly long Max = max;
|
public readonly long Max = max;
|
||||||
|
public readonly byte Mod4Mask = mod4Mask;
|
||||||
|
|
||||||
public static CarryRange Single(long value) => new(value, value);
|
public static CarryRange Single(long value) => new(value, value, byte.MinValue);
|
||||||
public static readonly CarryRange Zero = Single(0);
|
public static CarryRange Single(long value, byte mod4Mask) => new(value, value, mod4Mask);
|
||||||
|
|
||||||
|
public static readonly CarryRange Zero = Single(0, 0);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool IsEmpty() => Min > Max || Mod4Mask == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ContradictionReason
|
public enum ContradictionReason
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
namespace PerfectNumbers.Core;
|
||||||
|
#pragma warning disable CA2211 // The fields are settable on purpose for the best performance
|
||||||
|
|
||||||
|
public enum ByDivisorKIncrementMode
|
||||||
|
{
|
||||||
|
Sequential,
|
||||||
|
Pow2Groups,
|
||||||
|
Predictive,
|
||||||
|
Percentile,
|
||||||
|
Additive,
|
||||||
|
TopDown,
|
||||||
|
BitContradiction,
|
||||||
|
BitTree,
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning restore CA2211 // Non-constant fields should not be visible
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace PerfectNumbers.Core;
|
||||||
|
|
||||||
|
public enum CacheStatus
|
||||||
|
{
|
||||||
|
Disabled,
|
||||||
|
Enabled,
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace PerfectNumbers.Core;
|
||||||
|
|
||||||
|
public enum CalculationMethod
|
||||||
|
{
|
||||||
|
ByDivisor,
|
||||||
|
Divisor,
|
||||||
|
Incremental,
|
||||||
|
LucasLehmer,
|
||||||
|
Pow2Mod,
|
||||||
|
Residue,
|
||||||
|
}
|
||||||
@@ -63,7 +63,7 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
private static readonly ConcurrentDictionary<ulong, byte> _checkedPow2MinusOne = new();
|
private static readonly ConcurrentDictionary<ulong, byte> _checkedPow2MinusOne = new();
|
||||||
private ulong _currentPrime;
|
private ulong _currentPrime;
|
||||||
|
|
||||||
#if DEVICE_GPU
|
#if DEVICE_GPU && DivisorSet_BitContradiction
|
||||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private bool CheckDivisorsBitContradictionGpu(
|
private bool CheckDivisorsBitContradictionGpu(
|
||||||
ulong prime,
|
ulong prime,
|
||||||
@@ -78,6 +78,17 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
foundDivisor = BigInteger.Zero;
|
foundDivisor = BigInteger.Zero;
|
||||||
|
|
||||||
BigInteger currentK = minK;
|
BigInteger currentK = minK;
|
||||||
|
|
||||||
|
#if OVERRIDE_MIN_K
|
||||||
|
// Regression test convenience: ensure we actually scan the range that contains the known divisor for p=138000001.
|
||||||
|
if (currentK > 1)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[GPU OVERRIDE] p={prime} forcing minK from {currentK} to 1 for known-divisor regression test.");
|
||||||
|
currentK = BigInteger.One;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
const int TargetBatchIndex = 273;
|
||||||
|
|
||||||
bool hasLimit = !allowedMax.IsZero;
|
bool hasLimit = !allowedMax.IsZero;
|
||||||
BigInteger maxK = hasLimit ? (allowedMax - BigInteger.One) / step : BigInteger.Zero;
|
BigInteger maxK = hasLimit ? (allowedMax - BigInteger.One) / step : BigInteger.Zero;
|
||||||
|
|
||||||
@@ -100,8 +111,7 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
BigInteger batchSizeBig = batchSize;
|
BigInteger batchSizeBig = batchSize;
|
||||||
int wordCount = BitContradictionKernels.MaxQWordCount;
|
int wordCount = BitContradictionKernels.MaxQWordCount;
|
||||||
int inputCapacity = maxThreadCount * wordCount;
|
int inputCapacity = maxThreadCount * wordCount;
|
||||||
gpu.EnsureCapacity(PerfectNumberConstants.DefaultFactorsBuffer, inputCapacity);
|
var buffers = gpu.EnsureBitContradictionCapacity(inputCapacity, inputCapacity, maxThreadCount);
|
||||||
gpu.EnsurePartialFactorCapacity(inputCapacity);
|
|
||||||
|
|
||||||
var stream = AcceleratorStreamPool.Rent(gpu.AcceleratorIndex);
|
var stream = AcceleratorStreamPool.Rent(gpu.AcceleratorIndex);
|
||||||
var kernels = GpuKernelPool.GetOrAddKernels(gpu.AcceleratorIndex, stream, KernelType.BitContradictionScan);
|
var kernels = GpuKernelPool.GetOrAddKernels(gpu.AcceleratorIndex, stream, KernelType.BitContradictionScan);
|
||||||
@@ -109,13 +119,158 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
|
|
||||||
int[] found = new int[maxThreadCount];
|
int[] found = new int[maxThreadCount];
|
||||||
ulong[] batchIndexWords = new ulong[inputCapacity];
|
ulong[] batchIndexWords = new ulong[inputCapacity];
|
||||||
using MemoryBuffer1D<int, Stride1D.Dense> delta8Keys = gpu.Accelerator.Allocate1D<int>(maxThreadCount * BitContradictionKernels.DeltaCacheSlots);
|
ArrayView1D<int, Stride1D.Dense> delta8KeysView = buffers.Delta8CacheKeysView;
|
||||||
using MemoryBuffer1D<int, Stride1D.Dense> delta8Cache = gpu.Accelerator.Allocate1D<int>(maxThreadCount * BitContradictionKernels.DeltaCacheSlots * 4194304);
|
ArrayView1D<int, Stride1D.Dense> delta8CacheView = buffers.Delta8CacheValuesView;
|
||||||
#if DETAILED_LOG
|
|
||||||
int debugWordsPerSlot = BitContradictionKernels.DebugWordCountPerSlot;
|
Span<int> temp = stackalloc int[(int)delta8KeysView.Length];
|
||||||
using MemoryBuffer1D<ulong, Stride1D.Dense> debugBuffer = gpu.Accelerator.Allocate1D<ulong>(maxThreadCount * debugWordsPerSlot);
|
temp.Fill(int.MinValue);
|
||||||
ArrayView1D<ulong, Stride1D.Dense> debugView = debugBuffer.View;
|
delta8KeysView.CopyFromCPU(stream, temp);
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#if INVERSION_VALIDATION
|
||||||
|
///
|
||||||
|
/// INVERSION VALIDATION
|
||||||
|
///
|
||||||
|
{
|
||||||
|
// --- Inputs (known test case)
|
||||||
|
ulong p = 138000001UL;
|
||||||
|
ulong k = 4383UL;
|
||||||
|
|
||||||
|
// --- ILGPU setup (minimal)
|
||||||
|
var accelerator = gpu.Accelerator;
|
||||||
|
|
||||||
|
// --- Compile kernel (Extent=1)
|
||||||
|
// Kernel signature must be: (Index1D, ulong p, ulong k, ArrayView1D<ulong, Stride1D.Dense> outBuf)
|
||||||
|
var kernel2 = accelerator.LoadAutoGroupedStreamKernel<
|
||||||
|
Index1D,
|
||||||
|
ulong,
|
||||||
|
ulong,
|
||||||
|
ArrayView1D<ulong, Stride1D.Dense>
|
||||||
|
>(BitContradictionKernels.BitContradictionKernelExportInverse1024);
|
||||||
|
|
||||||
|
// --- Output buffer (64 ulongs is enough: 16 qPrefix + 16 inv + 16 aLow + meta)
|
||||||
|
using var outBufGpu = accelerator.Allocate1D<ulong>(64);
|
||||||
|
var outCpu = new ulong[64];
|
||||||
|
|
||||||
|
// Optional: clear buffer
|
||||||
|
for (int i = 0; i < outCpu.Length; i++) outCpu[i] = 0;
|
||||||
|
outBufGpu.View.CopyFromCPU(stream, outCpu);
|
||||||
|
|
||||||
|
// --- Run kernel
|
||||||
|
kernel2(1, p, k, outBufGpu.View);
|
||||||
|
stream.Synchronize();
|
||||||
|
|
||||||
|
// --- Copy back
|
||||||
|
outBufGpu.View.CopyToCPU(stream, outCpu);
|
||||||
|
stream.Synchronize();
|
||||||
|
|
||||||
|
// --- Parse meta
|
||||||
|
ulong pOut = outCpu[48];
|
||||||
|
ulong kOut = outCpu[49];
|
||||||
|
ulong qOut = outCpu[50];
|
||||||
|
ulong marker = outCpu[51];
|
||||||
|
|
||||||
|
Console.WriteLine($"[GPU EXPORT] pOut={pOut} kOut={kOut} qOut={qOut} marker=0x{marker:X}");
|
||||||
|
|
||||||
|
// --- Helpers: build BigInteger from 16x ulong limbs (little-endian)
|
||||||
|
BigInteger FromU64Le(int startIndex)
|
||||||
|
{
|
||||||
|
// +1 byte to force positive sign for BigInteger ctor
|
||||||
|
byte[] bytes = new byte[16 * 8 + 1];
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
ulong w = outCpu[startIndex + i];
|
||||||
|
int o = i * 8;
|
||||||
|
bytes[o + 0] = (byte)(w);
|
||||||
|
bytes[o + 1] = (byte)(w >> 8);
|
||||||
|
bytes[o + 2] = (byte)(w >> 16);
|
||||||
|
bytes[o + 3] = (byte)(w >> 24);
|
||||||
|
bytes[o + 4] = (byte)(w >> 32);
|
||||||
|
bytes[o + 5] = (byte)(w >> 40);
|
||||||
|
bytes[o + 6] = (byte)(w >> 48);
|
||||||
|
bytes[o + 7] = (byte)(w >> 56);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BigInteger(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
var qPrefix = FromU64Le(0);
|
||||||
|
var inv = FromU64Le(16);
|
||||||
|
var aLow = FromU64Le(32);
|
||||||
|
|
||||||
|
var mask = (BigInteger.One << 1024) - 1;
|
||||||
|
|
||||||
|
// --- Validate inverse: (qPrefix * inv) mod 2^1024 == 1
|
||||||
|
var prod = (qPrefix * inv) & mask;
|
||||||
|
bool invOk = prod == BigInteger.One;
|
||||||
|
|
||||||
|
// --- Validate aLow: aLow == (-inv) mod 2^1024
|
||||||
|
var expectedALow = (mask + BigInteger.One - (inv & mask)) & mask;
|
||||||
|
bool aLowOk = ((aLow & mask) == expectedALow);
|
||||||
|
|
||||||
|
// --- Print concise diagnostics
|
||||||
|
Console.WriteLine($"[CPU VALIDATION] invOk={invOk} aLowOk={aLowOk}");
|
||||||
|
|
||||||
|
// Print low 64 bits (quick sanity)
|
||||||
|
ulong prodLow64 = (ulong)(prod & ((BigInteger.One << 64) - 1));
|
||||||
|
ulong invLow64 = (ulong)(inv & ((BigInteger.One << 64) - 1));
|
||||||
|
ulong aLowLow64 = (ulong)(aLow & ((BigInteger.One << 64) - 1));
|
||||||
|
|
||||||
|
Console.WriteLine($"[LOW64] qPrefix=0x{(ulong)(qPrefix & ((System.Numerics.BigInteger.One<<64)-1)):X}");
|
||||||
|
Console.WriteLine($"[LOW64] inv=0x{invLow64:X} aLow=0x{aLowLow64:X} prod=0x{prodLow64:X}");
|
||||||
|
|
||||||
|
// Optional: hard fail for CI/regression
|
||||||
|
if (!invOk || !aLowOk)
|
||||||
|
throw new System.InvalidOperationException($"Inverse export validation failed: invOk={invOk}, aLowOk={aLowOk}");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SELF_TEST
|
||||||
|
///
|
||||||
|
/// SELF-TEST
|
||||||
|
///
|
||||||
|
{
|
||||||
|
ulong p = 138000001UL;
|
||||||
|
ulong k = 4383UL;
|
||||||
|
|
||||||
|
var accelerator = gpu.Accelerator;
|
||||||
|
|
||||||
|
Console.WriteLine($"Compiling kernel for {prime}");
|
||||||
|
var kernel3 = accelerator.LoadAutoGroupedStreamKernel<
|
||||||
|
Index1D,
|
||||||
|
ulong,
|
||||||
|
ulong,
|
||||||
|
int,
|
||||||
|
ArrayView1D<ulong, Stride1D.Dense>
|
||||||
|
>(BitContradictionKernels.BitContradictionKernelDebugDpSingleQ);
|
||||||
|
|
||||||
|
var launcher3 = KernelUtil.GetKernel(kernel3).CreateLauncherDelegate<
|
||||||
|
Action<AcceleratorStream, Index1D, ulong, ulong, int, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
|
|
||||||
|
Console.WriteLine($"Preparing buffers for {prime}");
|
||||||
|
using var outGpu = accelerator.Allocate1D<ulong>(128);
|
||||||
|
var outCpu = new ulong[128];
|
||||||
|
Array.Clear(outCpu, 0, outCpu.Length);
|
||||||
|
outGpu.View.CopyFromCPU(stream, outCpu);
|
||||||
|
|
||||||
|
// First run: disable batching (scalar DP)
|
||||||
|
Console.WriteLine($"Launching GPU kernel for {prime}");
|
||||||
|
launcher3(stream, 1, p, k, 1, outGpu.View);
|
||||||
|
outGpu.View.CopyToCPU(stream, outCpu);
|
||||||
|
stream.Synchronize();
|
||||||
|
|
||||||
|
Console.WriteLine($"[DP DEBUG] marker=0x{outCpu[0]:X} p={outCpu[1]} k={outCpu[2]} q={outCpu[3]} qBitLen={outCpu[4]} offsetCount={outCpu[6]} ok={outCpu[9]} carryMin={outCpu[10]} carryMax={outCpu[11]}");
|
||||||
|
|
||||||
|
// Print first 10 step records
|
||||||
|
Console.WriteLine($"[DP DEBUG] marker=0x{outCpu[0]:X} p={outCpu[1]} k={outCpu[2]} q={outCpu[3]} qBitLen={outCpu[4]} offsetCount={outCpu[6]} ok={outCpu[9]} carryMin={outCpu[10]} carryMax={outCpu[11]} disableBatching={outCpu[12]}");
|
||||||
|
Console.WriteLine($"[DP EXTRA] maxAllowedA={outCpu[14]} maxFixed={outCpu[15]} windowSize={outCpu[16]} aWordCount={outCpu[17]}");
|
||||||
|
Console.WriteLine($"[DP FIRST] firstForced={unchecked((long)outCpu[18])} firstRemaining={unchecked((long)outCpu[19])} firstQWordsEff={outCpu[20]} firstQLastEff=0x{outCpu[21]:X} firstCarryMin={unchecked((long)outCpu[22])} firstCarryMax={unchecked((long)outCpu[23])}");
|
||||||
|
Console.WriteLine($"[DP SNAP] aLow0=0x{outCpu[24]:X} knownOne0=0x{outCpu[25]:X} knownZero0=0x{outCpu[26]:X} aOneWin0=0x{outCpu[27]:X} aZeroWin0=0x{outCpu[28]:X} qMask0=0x{outCpu[29]:X} lastMask=0x{outCpu[30]:X} off0={outCpu[31]} offLast={outCpu[32]}");
|
||||||
|
|
||||||
|
if (outCpu[0] != 0xD00DF00DUL)
|
||||||
|
throw new Exception("DP debug kernel did not run as expected.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
BigInteger currentBatch = (currentK - BigInteger.One) / batchSizeBig;
|
BigInteger currentBatch = (currentK - BigInteger.One) / batchSizeBig;
|
||||||
currentK = (currentBatch * batchSizeBig) + BigInteger.One;
|
currentK = (currentBatch * batchSizeBig) + BigInteger.One;
|
||||||
@@ -123,7 +278,6 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (hasLimit && currentBatch > maxBatch)
|
if (hasLimit && currentBatch > maxBatch)
|
||||||
{
|
{
|
||||||
processedAll = true;
|
processedAll = true;
|
||||||
@@ -137,6 +291,7 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"Preparing data for{prime}, batch {currentBatch}");
|
||||||
int threadCount = maxThreadCount;
|
int threadCount = maxThreadCount;
|
||||||
if (remainingBatches < threadCount)
|
if (remainingBatches < threadCount)
|
||||||
{
|
{
|
||||||
@@ -162,15 +317,28 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
WriteBigIntegerToWords(batchIndex, batchIndexWords.AsSpan(t * wordCount, wordCount));
|
WriteBigIntegerToWords(batchIndex, batchIndexWords.AsSpan(t * wordCount, wordCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu.InputView.CopyFromCPU(stream, batchIndexWords.AsSpan(0, threadCount * wordCount));
|
Console.WriteLine($"Copying data to GPU for {prime}, batch {currentBatch}");
|
||||||
kernel(stream, threadCount, prime, gpu.InputView, countQ, gpu.OutputIntView,
|
buffers.BatchIndexWordsView.CopyFromCPU(stream, batchIndexWords.AsSpan(0, threadCount * wordCount));
|
||||||
#if DETAILED_LOG
|
// #if DETAILED_LOG
|
||||||
debugView,
|
Console.WriteLine($"Launching GPU kernel for {prime}, batch {currentBatch}");
|
||||||
#endif
|
// #endif
|
||||||
delta8Keys.View, delta8Cache.View);
|
kernel(stream, 1, prime, buffers.BatchIndexWordsView, countQ, buffers.FoundQWordsView,
|
||||||
|
// kernel(stream, threadCount, prime, buffers.BatchIndexWords, countQ, buffers.FoundQWords,
|
||||||
|
delta8KeysView, delta8CacheView);
|
||||||
|
buffers.FoundQWordsView.CopyToCPU(stream, found.AsSpan(0, threadCount));
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
gpu.OutputIntView.CopyToCPU(stream, found.AsSpan(0, threadCount));
|
|
||||||
|
|
||||||
|
_consolePrintOut++;
|
||||||
|
if (_consolePrintOut >= PerfectNumberConstants.ConsoleInterval)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"GPU kernel for {prime} complete, batch {currentBatch}");
|
||||||
|
Console.WriteLine($"[GPU FOUND RAW] batch={currentBatch} found[0]={found[0]}");
|
||||||
|
_consolePrintOut = 0;
|
||||||
|
}
|
||||||
|
#if DETAILED_LOG || SELF_TEST
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TODO: This loop is incorrect. We have a loop over the threads outside from here
|
||||||
for (int i = 0; i < threadCount; i++)
|
for (int i = 0; i < threadCount; i++)
|
||||||
{
|
{
|
||||||
int foundIndex = found[i];
|
int foundIndex = found[i];
|
||||||
@@ -217,49 +385,92 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
// if (!dividesExact)
|
// if (!dividesExact)
|
||||||
// {
|
// {
|
||||||
// throw new InvalidOperationException($"BitContradiction CPU/GPU false positive for p={prime}, q={candidateQ}, k={candidateK}, batch={batchIndex}");
|
// throw new InvalidOperationException($"BitContradiction CPU/GPU false positive for p={prime}, q={candidateQ}, k={candidateK}, batch={batchIndex}");
|
||||||
#if DETAILED_LOG
|
#if DETAILED_LOG
|
||||||
if (prime == 138000001UL)
|
if (prime == 138000001UL)
|
||||||
|
// --- Fast self-check for known divisor: run scan kernel with ONE thread and SMALL countQ.
|
||||||
|
// This avoids waiting for other threads that would scan huge ranges and never hit the target.
|
||||||
{
|
{
|
||||||
ulong[] debugWords = new ulong[debugWordsPerSlot];
|
const int expectedFoundIndex = 4382; // k=4383 => index=k-1 in batch 0
|
||||||
debugView.SubView(i * debugWordsPerSlot, debugWordsPerSlot).CopyToCPU(stream, debugWords);
|
countQ = 6000; // must be > 4382, keep small to finish quickly
|
||||||
BigInteger gpuQ = ReadBigIntegerFromWords(debugWords.AsSpan(0, 16));
|
|
||||||
BigInteger gpuInv = ReadBigIntegerFromWords(debugWords.AsSpan(16, 16));
|
Array.Clear(found, 0, found.Length);
|
||||||
BigInteger gpuALow = ReadBigIntegerFromWords(debugWords.AsSpan(32, 16));
|
Array.Clear(batchIndexWords, 0, batchIndexWords.Length);
|
||||||
ulong gpuQBits = debugWords[48];
|
|
||||||
ulong gpuQWordCount = debugWords[49];
|
// batchIndex = 0
|
||||||
ulong gpuQMask0 = debugWords[50];
|
WriteBigIntegerToWords(BigInteger.Zero, batchIndexWords.AsSpan(0, wordCount));
|
||||||
ulong gpuQMask1 = debugWords[51];
|
buffers.BatchIndexWords.CopyFromCPU(stream, batchIndexWords.AsSpan(0, threadCount * wordCount));
|
||||||
ulong gpuKnownOne0 = debugWords[52];
|
|
||||||
ulong gpuKnownZero0 = debugWords[53];
|
Console.WriteLine($"[GPU SELFTEST] launching scan kernel (threads={threadCount}, countQ={countQ})");
|
||||||
ulong gpuAOneWin0 = debugWords[54];
|
kernel(
|
||||||
ulong gpuAZeroWin0 = debugWords[55];
|
stream,
|
||||||
long gpuCarryMin = unchecked((long)debugWords[56]);
|
threadCount,
|
||||||
long gpuCarryMax = unchecked((long)debugWords[57]);
|
prime,
|
||||||
long gpuMaxAllowedA = unchecked((long)debugWords[58]);
|
buffers.BatchIndexWords,
|
||||||
long gpuMaxFixed = unchecked((long)debugWords[59]);
|
countQ,
|
||||||
long gpuWindowSize = unchecked((long)debugWords[60]);
|
buffers.FoundQWords,
|
||||||
long gpuAWordCount = unchecked((long)debugWords[61]);
|
#if DETAILED_LOG
|
||||||
long gpuMaxKnownA = unchecked((long)debugWords[62]);
|
debugView,
|
||||||
long gpuMaxFixedPrefilter = unchecked((long)debugWords[63]);
|
#endif
|
||||||
ulong preKnownOne0 = debugWords[64];
|
delta8Keys.View,
|
||||||
ulong preKnownZero0 = debugWords[65];
|
delta8Cache.View);
|
||||||
ulong preAOneWin0 = debugWords[66];
|
|
||||||
ulong preAZeroWin0 = debugWords[67];
|
stream.Synchronize();
|
||||||
long preCarryMin = unchecked((long)debugWords[68]);
|
buffers.FoundQWords.CopyToCPU(stream, found.AsSpan(0, threadCount));
|
||||||
long preCarryMax = unchecked((long)debugWords[69]);
|
stream.Synchronize();
|
||||||
long preSegmentBase = unchecked((long)debugWords[70]);
|
|
||||||
long preWindowColumn = unchecked((long)debugWords[71]);
|
Console.WriteLine($"[GPU SELFTEST] found[0]={found[0]} (expected {expectedFoundIndex})");
|
||||||
long gpuOffsetCount = unchecked((long)debugWords[72]);
|
if (found[0] != expectedFoundIndex)
|
||||||
long gpuMaxOffset = unchecked((long)debugWords[73]);
|
{
|
||||||
long gpuFirstForced = unchecked((long)debugWords[74]);
|
throw new InvalidOperationException($"[GPU SELFTEST FAILED] got={found[0]} expected={expectedFoundIndex}");
|
||||||
long gpuFirstRemaining = unchecked((long)debugWords[75]);
|
}
|
||||||
long gpuFirstQWordsEff = unchecked((long)debugWords[76]);
|
|
||||||
ulong gpuFirstQLastEff = debugWords[77];
|
// Self-test succeeded => stop here (do not start full scan which may hit TDR during debugging).
|
||||||
long gpuFirstCarryMin = unchecked((long)debugWords[78]);
|
processedAll = false;
|
||||||
long gpuFirstCarryMax = unchecked((long)debugWords[79]);
|
foundDivisor = BigInteger.Zero;
|
||||||
throw new InvalidOperationException($"BitContradiction GPU debug for p={prime}, q={candidateQ}, k={candidateK}, qBits={gpuQBits}, qWordCount={gpuQWordCount}, qMask0=0x{gpuQMask0:X16}, qMask1=0x{gpuQMask1:X16}, knownOne0=0x{gpuKnownOne0:X16}, knownZero0=0x{gpuKnownZero0:X16}, aOneWin0=0x{gpuAOneWin0:X16}, aZeroWin0=0x{gpuAZeroWin0:X16}, carryMin={gpuCarryMin}, carryMax={gpuCarryMax}, maxAllowedA={gpuMaxAllowedA}, maxFixed={gpuMaxFixed}, windowSize={gpuWindowSize}, aWordCount={gpuAWordCount}, maxKnownA={gpuMaxKnownA}, maxFixedPrefilter={gpuMaxFixedPrefilter}, preKnownOne0=0x{preKnownOne0:X16}, preKnownZero0=0x{preKnownZero0:X16}, preAOneWin0=0x{preAOneWin0:X16}, preAZeroWin0=0x{preAZeroWin0:X16}, preCarryMin={preCarryMin}, preCarryMax={preCarryMax}, preSegmentBase={preSegmentBase}, preWindowColumn={preWindowColumn}, offsetCount={gpuOffsetCount}, maxOffset={gpuMaxOffset}, firstForced={gpuFirstForced}, firstRemaining={gpuFirstRemaining}, firstQWordsEff={gpuFirstQWordsEff}, firstQLastEff=0x{gpuFirstQLastEff:X16}, firstCarryMin={gpuFirstCarryMin}, firstCarryMax={gpuFirstCarryMax}, gpuQ={gpuQ}, gpuInv={gpuInv}, gpuALow={gpuALow}");
|
AcceleratorStreamPool.Return(gpu.AcceleratorIndex, stream);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
// {
|
||||||
|
// ulong[] debugWords = new ulong[debugWordsPerSlot];
|
||||||
|
// debugView.SubView(i * debugWordsPerSlot, debugWordsPerSlot).CopyToCPU(stream, debugWords);
|
||||||
|
// BigInteger gpuQ = ReadBigIntegerFromWords(debugWords.AsSpan(0, 16));
|
||||||
|
// BigInteger gpuInv = ReadBigIntegerFromWords(debugWords.AsSpan(16, 16));
|
||||||
|
// BigInteger gpuALow = ReadBigIntegerFromWords(debugWords.AsSpan(32, 16));
|
||||||
|
// ulong gpuQBits = debugWords[48];
|
||||||
|
// ulong gpuQWordCount = debugWords[49];
|
||||||
|
// ulong gpuQMask0 = debugWords[50];
|
||||||
|
// ulong gpuQMask1 = debugWords[51];
|
||||||
|
// ulong gpuKnownOne0 = debugWords[52];
|
||||||
|
// ulong gpuKnownZero0 = debugWords[53];
|
||||||
|
// ulong gpuAOneWin0 = debugWords[54];
|
||||||
|
// ulong gpuAZeroWin0 = debugWords[55];
|
||||||
|
// long gpuCarryMin = unchecked((long)debugWords[56]);
|
||||||
|
// long gpuCarryMax = unchecked((long)debugWords[57]);
|
||||||
|
// long gpuMaxAllowedA = unchecked((long)debugWords[58]);
|
||||||
|
// long gpuMaxFixed = unchecked((long)debugWords[59]);
|
||||||
|
// long gpuWindowSize = unchecked((long)debugWords[60]);
|
||||||
|
// long gpuAWordCount = unchecked((long)debugWords[61]);
|
||||||
|
// long gpuMaxKnownA = unchecked((long)debugWords[62]);
|
||||||
|
// long gpuMaxFixedPrefilter = unchecked((long)debugWords[63]);
|
||||||
|
// ulong preKnownOne0 = debugWords[64];
|
||||||
|
// ulong preKnownZero0 = debugWords[65];
|
||||||
|
// ulong preAOneWin0 = debugWords[66];
|
||||||
|
// ulong preAZeroWin0 = debugWords[67];
|
||||||
|
// long preCarryMin = unchecked((long)debugWords[68]);
|
||||||
|
// long preCarryMax = unchecked((long)debugWords[69]);
|
||||||
|
// long preSegmentBase = unchecked((long)debugWords[70]);
|
||||||
|
// long preWindowColumn = unchecked((long)debugWords[71]);
|
||||||
|
// long gpuOffsetCount = unchecked((long)debugWords[72]);
|
||||||
|
// long gpuMaxOffset = unchecked((long)debugWords[73]);
|
||||||
|
// long gpuFirstForced = unchecked((long)debugWords[74]);
|
||||||
|
// long gpuFirstRemaining = unchecked((long)debugWords[75]);
|
||||||
|
// long gpuFirstQWordsEff = unchecked((long)debugWords[76]);
|
||||||
|
// ulong gpuFirstQLastEff = debugWords[77];
|
||||||
|
// long gpuFirstCarryMin = unchecked((long)debugWords[78]);
|
||||||
|
// long gpuFirstCarryMax = unchecked((long)debugWords[79]);
|
||||||
|
// throw new InvalidOperationException($"BitContradiction GPU debug for p={prime}, q={candidateQ}, k={candidateK}, qBits={gpuQBits}, qWordCount={gpuQWordCount}, qMask0=0x{gpuQMask0:X16}, qMask1=0x{gpuQMask1:X16}, knownOne0=0x{gpuKnownOne0:X16}, knownZero0=0x{gpuKnownZero0:X16}, aOneWin0=0x{gpuAOneWin0:X16}, aZeroWin0=0x{gpuAZeroWin0:X16}, carryMin={gpuCarryMin}, carryMax={gpuCarryMax}, maxAllowedA={gpuMaxAllowedA}, maxFixed={gpuMaxFixed}, windowSize={gpuWindowSize}, aWordCount={gpuAWordCount}, maxKnownA={gpuMaxKnownA}, maxFixedPrefilter={gpuMaxFixedPrefilter}, preKnownOne0=0x{preKnownOne0:X16}, preKnownZero0=0x{preKnownZero0:X16}, preAOneWin0=0x{preAOneWin0:X16}, preAZeroWin0=0x{preAZeroWin0:X16}, preCarryMin={preCarryMin}, preCarryMax={preCarryMax}, preSegmentBase={preSegmentBase}, preWindowColumn={preWindowColumn}, offsetCount={gpuOffsetCount}, maxOffset={gpuMaxOffset}, firstForced={gpuFirstForced}, firstRemaining={gpuFirstRemaining}, firstQWordsEff={gpuFirstQWordsEff}, firstQLastEff=0x{gpuFirstQLastEff:X16}, firstCarryMin={gpuFirstCarryMin}, firstCarryMax={gpuFirstCarryMax}, gpuQ={gpuQ}, gpuInv={gpuInv}, gpuALow={gpuALow}");
|
||||||
|
// }
|
||||||
|
#endif
|
||||||
|
|
||||||
foundDivisor = candidateQ;
|
foundDivisor = candidateQ;
|
||||||
AcceleratorStreamPool.Return(gpu.AcceleratorIndex, stream);
|
AcceleratorStreamPool.Return(gpu.AcceleratorIndex, stream);
|
||||||
@@ -267,6 +478,12 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentBatch == TargetBatchIndex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"No divisor found up to batch index = {currentBatch}, with the target batch index = {TargetBatchIndex}");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
ContinueOuter:
|
ContinueOuter:
|
||||||
RecordState(currentK);
|
RecordState(currentK);
|
||||||
if (hasLimit && currentK > maxK)
|
if (hasLimit && currentK > maxK)
|
||||||
@@ -3039,7 +3256,7 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
}
|
}
|
||||||
|
|
||||||
ContinueOuter:
|
ContinueOuter:
|
||||||
RecordState(currentK);
|
RecordState(currentK);
|
||||||
// if (divisorCycle == prime && !IsMersenneValue(prime, candidate))
|
// if (divisorCycle == prime && !IsMersenneValue(prime, candidate))
|
||||||
if (divisorCycle == prime)
|
if (divisorCycle == prime)
|
||||||
{
|
{
|
||||||
@@ -3160,7 +3377,7 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
{
|
{
|
||||||
// Stopwatch sw = Stopwatch.StartNew();
|
// Stopwatch sw = Stopwatch.StartNew();
|
||||||
ContinueOuter:
|
ContinueOuter:
|
||||||
RecordState(currentK);
|
RecordState(currentK);
|
||||||
ulong powMod;
|
ulong powMod;
|
||||||
bool isPow2 = IsPowerOfTwo(currentK);
|
bool isPow2 = IsPowerOfTwo(currentK);
|
||||||
#if DETAILED_LOG
|
#if DETAILED_LOG
|
||||||
@@ -3262,7 +3479,7 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
if (remainder8 == 1 || remainder8 == 7)
|
if (remainder8 == 1 || remainder8 == 7)
|
||||||
{
|
{
|
||||||
ContinueOuter:
|
ContinueOuter:
|
||||||
RecordState(currentK);
|
RecordState(currentK);
|
||||||
BigInteger powResult = BigInteger.ModPow(BigIntegerNumbers.Two, primeBig, divisor);
|
BigInteger powResult = BigInteger.ModPow(BigIntegerNumbers.Two, primeBig, divisor);
|
||||||
if (powResult.IsOne)
|
if (powResult.IsOne)
|
||||||
{
|
{
|
||||||
@@ -3962,7 +4179,7 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
if (remainder8 == 1 || remainder8 == 7)
|
if (remainder8 == 1 || remainder8 == 7)
|
||||||
{
|
{
|
||||||
ContinueOuter:
|
ContinueOuter:
|
||||||
RecordState(currentK);
|
RecordState(currentK);
|
||||||
BigInteger powResult = BigInteger.ModPow(BigIntegerNumbers.Two, primeBig, divisor);
|
BigInteger powResult = BigInteger.ModPow(BigIntegerNumbers.Two, primeBig, divisor);
|
||||||
// if (powResult.IsOne && !IsMersenneValue(prime, divisor))
|
// if (powResult.IsOne && !IsMersenneValue(prime, divisor))
|
||||||
if (powResult.IsOne)
|
if (powResult.IsOne)
|
||||||
@@ -4317,7 +4534,7 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
}
|
}
|
||||||
|
|
||||||
ContinueOuter:
|
ContinueOuter:
|
||||||
RecordState(currentK);
|
RecordState(currentK);
|
||||||
if (divisorCycle == prime && !IsMersenneValue(prime, divisor))
|
if (divisorCycle == prime && !IsMersenneValue(prime, divisor))
|
||||||
{
|
{
|
||||||
foundDivisor = divisor;
|
foundDivisor = divisor;
|
||||||
@@ -4891,6 +5108,9 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
int remainder8 = (stepMod8 * kRem8 + 1) & 7;
|
int remainder8 = (stepMod8 * kRem8 + 1) & 7;
|
||||||
|
if (prime == 138000001UL && divisor == 1209708008767)
|
||||||
|
Console.WriteLine("[HIT] enumerated target q before remainder8 check");
|
||||||
|
|
||||||
if (remainder8 != 1 && remainder8 != 7)
|
if (remainder8 != 1 && remainder8 != 7)
|
||||||
{
|
{
|
||||||
goto MOVE_NEXT;
|
goto MOVE_NEXT;
|
||||||
@@ -4932,6 +5152,12 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prime == 138000001UL && divisor == 1209708008767)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[HIT] processed target q. Stopping.");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
MOVE_NEXT:
|
MOVE_NEXT:
|
||||||
ContinueOuter:
|
ContinueOuter:
|
||||||
RecordState(currentK);
|
RecordState(currentK);
|
||||||
@@ -5090,6 +5316,7 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
{
|
{
|
||||||
oneOffsets[i + 1] = pow2Offsets[i] + 1;
|
oneOffsets[i + 1] = pow2Offsets[i] + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
oneCount = needed;
|
oneCount = needed;
|
||||||
usedPow2Offsets = true;
|
usedPow2Offsets = true;
|
||||||
}
|
}
|
||||||
@@ -5114,6 +5341,7 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
pow2OffsetsTarget = new int[oneCount];
|
pow2OffsetsTarget = new int[oneCount];
|
||||||
_pow2Offsets = pow2OffsetsTarget;
|
_pow2Offsets = pow2OffsetsTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array.Copy(oneOffsets, pow2OffsetsTarget, oneCount);
|
Array.Copy(oneOffsets, pow2OffsetsTarget, oneCount);
|
||||||
_pow2OffsetCount = oneCount;
|
_pow2OffsetCount = oneCount;
|
||||||
_pow2K = currentK;
|
_pow2K = currentK;
|
||||||
@@ -5128,23 +5356,25 @@ public struct MersenneNumberDivisorByDivisorCpuTesterWithTemplate() : IMersenneN
|
|||||||
|
|
||||||
ReadOnlySpan<int> oneOffsetsSlice = oneOffsets[..oneCount];
|
ReadOnlySpan<int> oneOffsetsSlice = oneOffsets[..oneCount];
|
||||||
// BitContradictionSolverWithQMultiplier.SetDebugEnabled(true);
|
// BitContradictionSolverWithQMultiplier.SetDebugEnabled(true);
|
||||||
#if DETAILED_LOG
|
#if DETAILED_LOG
|
||||||
bool decided = BitContradictionSolverWithAMultiplier.TryCheckDivisibilityFromOneOffsets(oneOffsetsSlice, prime, currentK, isPowerOfTwo, out divides, out var reason);
|
bool decided = BitContradictionSolverWithAMultiplier.TryCheckDivisibilityFromOneOffsets(oneOffsetsSlice, prime, currentK, isPowerOfTwo, out divides, out var reason);
|
||||||
#else
|
#else
|
||||||
bool decided = BitContradictionSolverWithAMultiplier.TryCheckDivisibilityFromOneOffsets(oneOffsetsSlice, prime, currentK, isPowerOfTwo, out divides);
|
bool decided = BitContradictionSolverWithAMultiplier.TryCheckDivisibilityFromOneOffsets(oneOffsetsSlice, prime, currentK, isPowerOfTwo, out divides);
|
||||||
#endif
|
#endif
|
||||||
// BitContradictionSolverWithQMultiplier.SetDebugEnabled(false);
|
// BitContradictionSolverWithQMultiplier.SetDebugEnabled(false);
|
||||||
if (decided && divides)
|
if (decided && divides)
|
||||||
{
|
{
|
||||||
// Verify to avoid false positives on structurally admissible but non-dividing q.
|
// Verify to avoid false positives on structurally admissible but non-dividing q.
|
||||||
bool structuralOk = ((divisor - BigInteger.One) % (((BigInteger)prime) << 1)) == BigInteger.Zero;
|
bool structuralOk = ((divisor - BigInteger.One) % (((BigInteger)prime) << 1)) == BigInteger.Zero;
|
||||||
bool dividesExact = structuralOk && BigInteger.ModPow(2, prime, divisor) == BigInteger.One;
|
bool dividesExact = structuralOk && BigInteger.ModPow(2, prime, divisor) == BigInteger.One;
|
||||||
if (!dividesExact)
|
if (!dividesExact)
|
||||||
{
|
{
|
||||||
|
throw new InvalidOperationException($"We reported divisor q={divisor} as dividing {prime} but it doesn't divide it");
|
||||||
|
|
||||||
divides = false;
|
divides = false;
|
||||||
#if DETAILED_LOG
|
#if DETAILED_LOG
|
||||||
reason = ContradictionReason.ParityUnreachable;
|
reason = ContradictionReason.ParityUnreachable;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (decided && !divides)
|
if (decided && !divides)
|
||||||
|
|||||||
@@ -4,18 +4,21 @@ using PerfectNumbers.Core.Gpu;
|
|||||||
|
|
||||||
namespace PerfectNumbers.Core;
|
namespace PerfectNumbers.Core;
|
||||||
|
|
||||||
#pragma warning disable CA2211 // The fields are settable on purpose for the best performance
|
#pragma warning disable CA2211 // Non-constant fields should not be visible
|
||||||
|
|
||||||
public static class EnvironmentConfiguration
|
public static class EnvironmentConfiguration
|
||||||
{
|
{
|
||||||
public static ulong DivisorLimit = ulong.MaxValue;
|
public static ulong DivisorLimit = ulong.MaxValue;
|
||||||
public static int GpuBatchSize = GpuConstants.ScanBatchSize;
|
public static int GpuBatchSize = GpuConstants.ScanBatchSize;
|
||||||
|
public static int GpuPrimeThreads = 1;
|
||||||
public static int GpuRatio = PerfectNumberConstants.GpuRatio;
|
public static int GpuRatio = PerfectNumberConstants.GpuRatio;
|
||||||
public static ComputationDevice MersenneDevice = ComputationDevice.Cpu;
|
public static ComputationDevice MersenneDevice = ComputationDevice.Cpu;
|
||||||
public static BigInteger MinK = BigInteger.One;
|
public static BigInteger MinK = BigInteger.One;
|
||||||
public static ComputationDevice OrderDevice = ComputationDevice.Cpu;
|
public static ComputationDevice OrderDevice = ComputationDevice.Cpu;
|
||||||
public static int RollingAccelerators = PerfectNumberConstants.RollingAccelerators;
|
public static int RollingAccelerators = PerfectNumberConstants.RollingAccelerators;
|
||||||
public static string? StateFilePath;
|
public static string? StateFilePath;
|
||||||
|
public static int ThreadCount;
|
||||||
|
public static bool UseGpu;
|
||||||
public static bool UseGpuOrder;
|
public static bool UseGpuOrder;
|
||||||
public static bool UseHybridOrder;
|
public static bool UseHybridOrder;
|
||||||
public static bool UseCpuOrder;
|
public static bool UseCpuOrder;
|
||||||
@@ -24,6 +27,7 @@ public static class EnvironmentConfiguration
|
|||||||
public static ByDivisor.ByDivisorClassModel? ByDivisorClassModel;
|
public static ByDivisor.ByDivisorClassModel? ByDivisorClassModel;
|
||||||
public static ByDivisor.ByDivisorScanTuning ByDivisorScanTuning = ByDivisor.ByDivisorScanTuning.Default;
|
public static ByDivisor.ByDivisorScanTuning ByDivisorScanTuning = ByDivisor.ByDivisorScanTuning.Default;
|
||||||
public static double ByDivisorCheapKLimit = 10_000d;
|
public static double ByDivisorCheapKLimit = 10_000d;
|
||||||
|
public static ByDivisorKIncrementMode ByDivisorKIncrementMode = ByDivisorKIncrementMode.Sequential;
|
||||||
public static Persistence.ByDivisorClassModelRepository? ByDivisorClassModelRepository;
|
public static Persistence.ByDivisorClassModelRepository? ByDivisorClassModelRepository;
|
||||||
public static Persistence.KStateRepository? ByDivisorKStateRepository;
|
public static Persistence.KStateRepository? ByDivisorKStateRepository;
|
||||||
public static Persistence.KStateRepository? ByDivisorCheapKStateRepository;
|
public static Persistence.KStateRepository? ByDivisorCheapKStateRepository;
|
||||||
@@ -31,13 +35,31 @@ public static class EnvironmentConfiguration
|
|||||||
public static Persistence.KStateRepository? ByDivisorGroupsStateRepository;
|
public static Persistence.KStateRepository? ByDivisorGroupsStateRepository;
|
||||||
public static Persistence.Pow2Minus1StateRepository? ByDivisorPow2Minus1Repository;
|
public static Persistence.Pow2Minus1StateRepository? ByDivisorPow2Minus1Repository;
|
||||||
public static Persistence.BitContradictionStateRepository? BitContradictionStateRepository;
|
public static Persistence.BitContradictionStateRepository? BitContradictionStateRepository;
|
||||||
|
public static CalculationMethod CalculationMethod = CalculationMethod.Residue;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static void Initialize()
|
public static void Initialize()
|
||||||
{
|
{
|
||||||
|
if (MersenneDevice == ComputationDevice.Gpu &&
|
||||||
|
ByDivisorKIncrementMode == ByDivisorKIncrementMode.BitContradiction)
|
||||||
|
{
|
||||||
|
OrderDevice = ComputationDevice.Gpu;
|
||||||
|
}
|
||||||
|
|
||||||
UseGpuOrder = OrderDevice == ComputationDevice.Gpu;
|
UseGpuOrder = OrderDevice == ComputationDevice.Gpu;
|
||||||
UseHybridOrder = OrderDevice == ComputationDevice.Hybrid;
|
UseHybridOrder = OrderDevice == ComputationDevice.Hybrid;
|
||||||
UseCpuOrder = OrderDevice == ComputationDevice.Cpu;
|
UseCpuOrder = OrderDevice == ComputationDevice.Cpu;
|
||||||
|
|
||||||
|
UseGpu =
|
||||||
|
UseGpuOrder || UseHybridOrder ||
|
||||||
|
MersenneDevice is ComputationDevice.Hybrid or ComputationDevice.Gpu;
|
||||||
|
|
||||||
|
RollingAccelerators = UseGpu
|
||||||
|
? Math.Min(Math.Min(
|
||||||
|
PerfectNumberConstants.RollingAccelerators, GpuPrimeThreads), ThreadCount)
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
UsePow2GroupDivisors = ByDivisorKIncrementMode == ByDivisorKIncrementMode.Pow2Groups;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,238 @@ using PerfectNumbers.Core.Gpu.Kernels;
|
|||||||
|
|
||||||
namespace PerfectNumbers.Core.Gpu.Accelerators;
|
namespace PerfectNumbers.Core.Gpu.Accelerators;
|
||||||
|
|
||||||
|
public static class PrimeOrderCalculatorAcceleratorCapacityProviders
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
|
public static void EnsureCalculateOrderWideCapacity(this PrimeOrderCalculatorAccelerator gpu, int newSize)
|
||||||
|
{
|
||||||
|
if (newSize > gpu.Input.Length)
|
||||||
|
{
|
||||||
|
gpu.CalculateOrderWideExponentBuffer.Dispose();
|
||||||
|
gpu.CalculateOrderWideRemainderBuffer.Dispose();
|
||||||
|
|
||||||
|
var accelerator = gpu.Accelerator;
|
||||||
|
// lock (accelerator)
|
||||||
|
// {
|
||||||
|
gpu.CalculateOrderWideExponentBuffer = accelerator.Allocate1D<GpuUInt128>(newSize);
|
||||||
|
gpu.CalculateOrderWideRemainderBuffer = accelerator.Allocate1D<GpuUInt128>(newSize);
|
||||||
|
gpu.CalculateOrderWideExponentBufferView = gpu.CalculateOrderWideExponentBuffer.View;
|
||||||
|
gpu.CalculateOrderWideRemainderBufferView = gpu.CalculateOrderWideRemainderBuffer.View;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
|
public static void EnsurePrimeOrderCalculatorCapacity(this PrimeOrderCalculatorAccelerator gpu, int factorsCount, int primeTesterCapacity)
|
||||||
|
{
|
||||||
|
Accelerator accelerator = gpu.Accelerator;
|
||||||
|
|
||||||
|
MemoryBuffer1D<KeyValuePair<ulong, int>, Stride1D.Dense> pow2ModEntriesToTestOnDevice = gpu.Pow2ModEntriesToTestOnDevice;
|
||||||
|
if (pow2ModEntriesToTestOnDevice.Length < factorsCount)
|
||||||
|
{
|
||||||
|
// lock (accelerator)
|
||||||
|
// {
|
||||||
|
pow2ModEntriesToTestOnDevice.Dispose();
|
||||||
|
pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount);
|
||||||
|
gpu.Pow2ModEntriesToTestOnDevice = pow2ModEntriesToTestOnDevice;
|
||||||
|
gpu.Pow2ModEntriesToTestOnDeviceView = pow2ModEntriesToTestOnDevice.View;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryBuffer1D<ulong, Stride1D.Dense> input = gpu.Input;
|
||||||
|
if (input.Length < primeTesterCapacity)
|
||||||
|
{
|
||||||
|
// lock (accelerator)
|
||||||
|
// {
|
||||||
|
input.Dispose();
|
||||||
|
|
||||||
|
input = accelerator.Allocate1D<ulong>(primeTesterCapacity);
|
||||||
|
gpu.Input = input;
|
||||||
|
gpu.InputView = input.View;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryBuffer1D<byte, Stride1D.Dense> outputByte = gpu.OutputByte;
|
||||||
|
if (outputByte.Length < primeTesterCapacity)
|
||||||
|
{
|
||||||
|
// lock (accelerator)
|
||||||
|
// {
|
||||||
|
outputByte.Dispose();
|
||||||
|
|
||||||
|
outputByte = accelerator.Allocate1D<byte>(primeTesterCapacity);
|
||||||
|
gpu.OutputByte = outputByte;
|
||||||
|
gpu.OutputByteView = outputByte.View;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryBuffer1D<int, Stride1D.Dense> outputInt = gpu.OutputInt;
|
||||||
|
if (outputInt.Length < primeTesterCapacity)
|
||||||
|
{
|
||||||
|
// lock (accelerator)
|
||||||
|
// {
|
||||||
|
outputInt.Dispose();
|
||||||
|
|
||||||
|
outputInt = accelerator.Allocate1D<int>(primeTesterCapacity);
|
||||||
|
gpu.OutputInt = outputInt;
|
||||||
|
gpu.OutputIntView = outputInt.View;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EnsurePartialFactorCapacity(this PrimeOrderCalculatorAccelerator gpu, int newSize)
|
||||||
|
{
|
||||||
|
var accelerator = gpu.Accelerator;
|
||||||
|
|
||||||
|
var outputUlong = gpu.OutputUlong;
|
||||||
|
if (newSize > outputUlong.Length)
|
||||||
|
{
|
||||||
|
outputUlong.Dispose();
|
||||||
|
|
||||||
|
outputUlong = accelerator.Allocate1D<ulong>(newSize);
|
||||||
|
gpu.OutputUlong = outputUlong;
|
||||||
|
gpu.OutputUlongView = outputUlong.View;
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputInt = gpu.OutputInt;
|
||||||
|
if (newSize > outputInt.Length)
|
||||||
|
{
|
||||||
|
outputInt.Dispose();
|
||||||
|
|
||||||
|
outputInt = accelerator.Allocate1D<int>(newSize);
|
||||||
|
gpu.OutputInt = outputInt;
|
||||||
|
gpu.OutputIntView = outputInt.View;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EnsureSmallPrimeFactorSlotsCapacity(this PrimeOrderCalculatorAccelerator gpu, int newSize)
|
||||||
|
{
|
||||||
|
// Console.WriteLine($"Resizing GPU scratch buffer from pool ({buffer.SmallPrimeFactorPrimeSlots.Length} / {smallPrimeFactorSlotCount}), ({buffer.SpecialMaxFactors.Length}/{specialMaxFactorCapacity})");
|
||||||
|
var accelerator = gpu.Accelerator;
|
||||||
|
MemoryBuffer1D<ulong, Stride1D.Dense> outputUlong = gpu.OutputUlong;
|
||||||
|
if (outputUlong.Length < newSize)
|
||||||
|
{
|
||||||
|
// lock (accelerator)
|
||||||
|
// {
|
||||||
|
outputUlong.Dispose();
|
||||||
|
|
||||||
|
outputUlong = accelerator.Allocate1D<ulong>(newSize);
|
||||||
|
gpu.OutputUlong = outputUlong;
|
||||||
|
gpu.OutputUlongView = outputUlong.View;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryBuffer1D<int, Stride1D.Dense> outputInt = gpu.OutputInt;
|
||||||
|
if (outputInt.Length < newSize)
|
||||||
|
{
|
||||||
|
// lock (accelerator)
|
||||||
|
// {
|
||||||
|
outputInt.Dispose();
|
||||||
|
|
||||||
|
outputInt = accelerator.Allocate1D<int>(newSize);
|
||||||
|
gpu.OutputInt = outputInt;
|
||||||
|
gpu.OutputIntView = outputInt.View;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
|
public static void EnsureUlongInputOutputCapacity(this PrimeOrderCalculatorAccelerator gpu, int newSize)
|
||||||
|
{
|
||||||
|
var accelerator = gpu.Accelerator;
|
||||||
|
MemoryBuffer1D<ulong, Stride1D.Dense> buffer = gpu.Input;
|
||||||
|
if (buffer.Length < newSize)
|
||||||
|
{
|
||||||
|
// lock (accelerator)
|
||||||
|
// {
|
||||||
|
buffer.Dispose();
|
||||||
|
|
||||||
|
buffer = accelerator.Allocate1D<ulong>(newSize);
|
||||||
|
gpu.Input = buffer;
|
||||||
|
gpu.InputView = buffer.View;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = gpu.OutputUlong;
|
||||||
|
if (buffer.Length < newSize)
|
||||||
|
{
|
||||||
|
// lock (accelerator)
|
||||||
|
// {
|
||||||
|
buffer.Dispose();
|
||||||
|
|
||||||
|
buffer = accelerator.Allocate1D<ulong>(newSize);
|
||||||
|
gpu.OutputUlong = buffer;
|
||||||
|
gpu.OutputUlongView = buffer.View;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
|
public static BitContradictionBuffers EnsureBitContradictionCapacity(this PrimeOrderCalculatorAccelerator gpu, int maxBatchIndexWords, int maxQWords, int delta8CacheConcurrentThreads)
|
||||||
|
{
|
||||||
|
var accelerator = gpu.Accelerator;
|
||||||
|
|
||||||
|
MemoryBuffer1D<ulong, Stride1D.Dense> bufferUlong = gpu.Input;
|
||||||
|
if (bufferUlong.Length < maxBatchIndexWords)
|
||||||
|
{
|
||||||
|
// lock (accelerator)
|
||||||
|
// {
|
||||||
|
bufferUlong.Dispose();
|
||||||
|
|
||||||
|
bufferUlong = accelerator.Allocate1D<ulong>(maxBatchIndexWords);
|
||||||
|
gpu.Input = bufferUlong;
|
||||||
|
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryBuffer1D<int, Stride1D.Dense> bufferInt = gpu.OutputInt;
|
||||||
|
maxQWords <<= 1;
|
||||||
|
if (bufferUlong.Length < maxQWords)
|
||||||
|
{
|
||||||
|
// lock (accelerator)
|
||||||
|
// {
|
||||||
|
bufferInt.Dispose();
|
||||||
|
|
||||||
|
bufferInt = accelerator.Allocate1D<int>(maxQWords);
|
||||||
|
gpu.OutputInt = bufferInt;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferInt = gpu.StackIndexBuffer;
|
||||||
|
int requiredCapacity = BitContradictionKernels.GetDeltaCacheKeyLength(delta8CacheConcurrentThreads);
|
||||||
|
if (bufferInt.Length < requiredCapacity)
|
||||||
|
{
|
||||||
|
bufferInt.Dispose();
|
||||||
|
bufferInt = accelerator.Allocate1D<int>(requiredCapacity);
|
||||||
|
gpu.StackIndexBuffer = bufferInt;
|
||||||
|
|
||||||
|
bufferInt = gpu.StackExponentBuffer;
|
||||||
|
bufferInt.Dispose();
|
||||||
|
bufferInt = accelerator.Allocate1D<int>(BitContradictionKernels.GetDeltaCacheIntLength(delta8CacheConcurrentThreads));
|
||||||
|
gpu.StackExponentBuffer = bufferInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new(
|
||||||
|
gpu.Input.View,
|
||||||
|
gpu.OutputInt.View,
|
||||||
|
gpu.StackIndexBuffer.View,
|
||||||
|
gpu.StackExponentBuffer.View
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct BitContradictionBuffers(
|
||||||
|
in ArrayView1D<ulong, Stride1D.Dense> batchIndexWords,
|
||||||
|
in ArrayView1D<int, Stride1D.Dense> foundQWords,
|
||||||
|
in ArrayView1D<int, Stride1D.Dense> delta8CacheKeys,
|
||||||
|
in ArrayView1D<int, Stride1D.Dense> delta8CacheValues
|
||||||
|
)
|
||||||
|
{
|
||||||
|
public readonly ArrayView1D<ulong, Stride1D.Dense> BatchIndexWordsView = batchIndexWords;
|
||||||
|
public readonly ArrayView1D<int, Stride1D.Dense> FoundQWordsView = foundQWords;
|
||||||
|
public readonly ArrayView1D<int, Stride1D.Dense> Delta8CacheKeysView = delta8CacheKeys;
|
||||||
|
public readonly ArrayView1D<int, Stride1D.Dense> Delta8CacheValuesView = delta8CacheValues;
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class PrimeOrderCalculatorAccelerator
|
public sealed class PrimeOrderCalculatorAccelerator
|
||||||
{
|
{
|
||||||
#region Pool
|
#region Pool
|
||||||
@@ -18,7 +250,7 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
var pool = _pool ??= new(PerfectNumberConstants.DefaultThreadPoolCapacity);
|
var pool = _pool ??= new(PerfectNumberConstants.DefaultThreadPoolCapacity);
|
||||||
if (pool.TryPop(out var gpu))
|
if (pool.TryPop(out var gpu))
|
||||||
{
|
{
|
||||||
gpu.EnsureCapacity(PerfectNumberConstants.DefaultFactorsBuffer, primeTesterCapacity);
|
gpu.EnsurePrimeOrderCalculatorCapacity(PerfectNumberConstants.DefaultFactorsBuffer, primeTesterCapacity);
|
||||||
return gpu;
|
return gpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,8 +369,8 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
|
|
||||||
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> WorkFactorBuffer;
|
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> WorkFactorBuffer;
|
||||||
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> CandidateBuffer;
|
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> CandidateBuffer;
|
||||||
public readonly MemoryBuffer1D<int, Stride1D.Dense> StackIndexBuffer;
|
public MemoryBuffer1D<int, Stride1D.Dense> StackIndexBuffer;
|
||||||
public readonly MemoryBuffer1D<int, Stride1D.Dense> StackExponentBuffer;
|
public MemoryBuffer1D<int, Stride1D.Dense> StackExponentBuffer;
|
||||||
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> StackProductBuffer;
|
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> StackProductBuffer;
|
||||||
|
|
||||||
public OrderKernelBuffers CalculateOrderKernelBuffers;
|
public OrderKernelBuffers CalculateOrderKernelBuffers;
|
||||||
@@ -148,15 +380,11 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
public readonly ArrayView1D<int, Stride1D.Dense> StackExponentBufferView;
|
public readonly ArrayView1D<int, Stride1D.Dense> StackExponentBufferView;
|
||||||
public readonly ArrayView1D<ulong, Stride1D.Dense> StackProductBufferView;
|
public readonly ArrayView1D<ulong, Stride1D.Dense> StackProductBufferView;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public MemoryBuffer1D<GpuUInt128, Stride1D.Dense> CalculateOrderWideExponentBuffer;
|
public MemoryBuffer1D<GpuUInt128, Stride1D.Dense> CalculateOrderWideExponentBuffer;
|
||||||
public MemoryBuffer1D<GpuUInt128, Stride1D.Dense> CalculateOrderWideRemainderBuffer;
|
public MemoryBuffer1D<GpuUInt128, Stride1D.Dense> CalculateOrderWideRemainderBuffer;
|
||||||
public ArrayView1D<GpuUInt128, Stride1D.Dense> CalculateOrderWideExponentBufferView;
|
public ArrayView1D<GpuUInt128, Stride1D.Dense> CalculateOrderWideExponentBufferView;
|
||||||
public ArrayView1D<GpuUInt128, Stride1D.Dense> CalculateOrderWideRemainderBufferView;
|
public ArrayView1D<GpuUInt128, Stride1D.Dense> CalculateOrderWideRemainderBufferView;
|
||||||
|
|
||||||
|
|
||||||
public Dictionary<ulong, int> Pow2ModEntriesToTestOnHost = [];
|
public Dictionary<ulong, int> Pow2ModEntriesToTestOnHost = [];
|
||||||
|
|
||||||
private static readonly CalculatorKernels[] _kernels = new CalculatorKernels[_accelerators.Length];
|
private static readonly CalculatorKernels[] _kernels = new CalculatorKernels[_accelerators.Length];
|
||||||
@@ -205,169 +433,6 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
public readonly Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>> SmallPrimeSieveKernelLauncher;
|
public readonly Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>> SmallPrimeSieveKernelLauncher;
|
||||||
public readonly Action<AcceleratorStream, Index1D, ulong, ArrayView<ulong>, int, ulong, ArrayView<ulong>> SpecialMaxKernelLauncher;
|
public readonly Action<AcceleratorStream, Index1D, ulong, ArrayView<ulong>, int, ulong, ArrayView<ulong>> SpecialMaxKernelLauncher;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
|
||||||
public void EnsureCalculateOrderWideCapacity(int newSize)
|
|
||||||
{
|
|
||||||
if (newSize > Input.Length)
|
|
||||||
{
|
|
||||||
CalculateOrderWideExponentBuffer.Dispose();
|
|
||||||
CalculateOrderWideRemainderBuffer.Dispose();
|
|
||||||
|
|
||||||
var accelerator = Accelerator;
|
|
||||||
// lock (accelerator)
|
|
||||||
// {
|
|
||||||
CalculateOrderWideExponentBuffer = accelerator.Allocate1D<GpuUInt128>(newSize);
|
|
||||||
CalculateOrderWideRemainderBuffer = accelerator.Allocate1D<GpuUInt128>(newSize);
|
|
||||||
CalculateOrderWideExponentBufferView = CalculateOrderWideExponentBuffer.View;
|
|
||||||
CalculateOrderWideRemainderBufferView = CalculateOrderWideRemainderBuffer.View;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
|
||||||
public void EnsureCapacity(int factorsCount, int primeTesterCapacity)
|
|
||||||
{
|
|
||||||
Accelerator accelerator = Accelerator;
|
|
||||||
|
|
||||||
MemoryBuffer1D<KeyValuePair<ulong, int>, Stride1D.Dense> pow2ModEntriesToTestOnDevice = Pow2ModEntriesToTestOnDevice;
|
|
||||||
if (pow2ModEntriesToTestOnDevice.Length < factorsCount)
|
|
||||||
{
|
|
||||||
// lock (accelerator)
|
|
||||||
// {
|
|
||||||
pow2ModEntriesToTestOnDevice.Dispose();
|
|
||||||
pow2ModEntriesToTestOnDevice = accelerator.Allocate1D<KeyValuePair<ulong, int>>(factorsCount);
|
|
||||||
Pow2ModEntriesToTestOnDevice = pow2ModEntriesToTestOnDevice;
|
|
||||||
Pow2ModEntriesToTestOnDeviceView = pow2ModEntriesToTestOnDevice.View;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> input = Input;
|
|
||||||
if (input.Length < primeTesterCapacity)
|
|
||||||
{
|
|
||||||
// lock (accelerator)
|
|
||||||
// {
|
|
||||||
input.Dispose();
|
|
||||||
|
|
||||||
input = accelerator.Allocate1D<ulong>(primeTesterCapacity);
|
|
||||||
Input = input;
|
|
||||||
InputView = input.View;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryBuffer1D<byte, Stride1D.Dense> outputByte = OutputByte;
|
|
||||||
if (outputByte.Length < primeTesterCapacity)
|
|
||||||
{
|
|
||||||
// lock (accelerator)
|
|
||||||
// {
|
|
||||||
outputByte.Dispose();
|
|
||||||
|
|
||||||
outputByte = accelerator.Allocate1D<byte>(primeTesterCapacity);
|
|
||||||
OutputByte = outputByte;
|
|
||||||
OutputByteView = outputByte.View;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryBuffer1D<int, Stride1D.Dense> outputInt = OutputInt;
|
|
||||||
if (outputInt.Length < primeTesterCapacity)
|
|
||||||
{
|
|
||||||
// lock (accelerator)
|
|
||||||
// {
|
|
||||||
outputInt.Dispose();
|
|
||||||
|
|
||||||
outputInt = accelerator.Allocate1D<int>(primeTesterCapacity);
|
|
||||||
OutputInt = outputInt;
|
|
||||||
OutputIntView = outputInt.View;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EnsurePartialFactorCapacity(int newSize)
|
|
||||||
{
|
|
||||||
var accelerator = Accelerator;
|
|
||||||
|
|
||||||
var outputUlong = OutputUlong;
|
|
||||||
if (newSize > outputUlong.Length)
|
|
||||||
{
|
|
||||||
outputUlong.Dispose();
|
|
||||||
|
|
||||||
outputUlong = accelerator.Allocate1D<ulong>(newSize);
|
|
||||||
OutputUlong = outputUlong;
|
|
||||||
OutputUlongView = outputUlong.View;
|
|
||||||
}
|
|
||||||
|
|
||||||
var outputInt = OutputInt;
|
|
||||||
if (newSize > outputInt.Length)
|
|
||||||
{
|
|
||||||
outputInt.Dispose();
|
|
||||||
|
|
||||||
outputInt = accelerator.Allocate1D<int>(newSize);
|
|
||||||
OutputInt = outputInt;
|
|
||||||
OutputIntView = outputInt.View;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EnsureSmallPrimeFactorSlotsCapacity(int newSize)
|
|
||||||
{
|
|
||||||
// Console.WriteLine($"Resizing GPU scratch buffer from pool ({buffer.SmallPrimeFactorPrimeSlots.Length} / {smallPrimeFactorSlotCount}), ({buffer.SpecialMaxFactors.Length}/{specialMaxFactorCapacity})");
|
|
||||||
var accelerator = Accelerator;
|
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> outputUlong = OutputUlong;
|
|
||||||
if (outputUlong.Length < newSize)
|
|
||||||
{
|
|
||||||
// lock (accelerator)
|
|
||||||
// {
|
|
||||||
outputUlong.Dispose();
|
|
||||||
|
|
||||||
outputUlong = accelerator.Allocate1D<ulong>(newSize);
|
|
||||||
OutputUlong = outputUlong;
|
|
||||||
OutputUlongView = outputUlong.View;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryBuffer1D<int, Stride1D.Dense> outputInt = OutputInt;
|
|
||||||
if (outputInt.Length < newSize)
|
|
||||||
{
|
|
||||||
// lock (accelerator)
|
|
||||||
// {
|
|
||||||
outputInt.Dispose();
|
|
||||||
|
|
||||||
outputInt = accelerator.Allocate1D<int>(newSize);
|
|
||||||
OutputInt = outputInt;
|
|
||||||
OutputIntView = outputInt.View;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
|
||||||
public void EnsureUlongInputOutputCapacity(int newSize)
|
|
||||||
{
|
|
||||||
var accelerator = Accelerator;
|
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> buffer = Input;
|
|
||||||
if (buffer.Length < newSize)
|
|
||||||
{
|
|
||||||
// lock (accelerator)
|
|
||||||
// {
|
|
||||||
buffer.Dispose();
|
|
||||||
|
|
||||||
buffer = accelerator.Allocate1D<ulong>(newSize);
|
|
||||||
Input = buffer;
|
|
||||||
InputView = buffer.View;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = OutputUlong;
|
|
||||||
if (buffer.Length < newSize)
|
|
||||||
{
|
|
||||||
// lock (accelerator)
|
|
||||||
// {
|
|
||||||
buffer.Dispose();
|
|
||||||
|
|
||||||
buffer = accelerator.Allocate1D<ulong>(newSize);
|
|
||||||
OutputUlong = buffer;
|
|
||||||
OutputUlongView = buffer.View;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PrimeOrderCalculatorAccelerator(int acceleratorIndex, int factorsCount, int primeTesterCapacity, int smallPrimeFactorSlotCount, int specialMaxFactorCapacity)
|
public PrimeOrderCalculatorAccelerator(int acceleratorIndex, int factorsCount, int primeTesterCapacity, int smallPrimeFactorSlotCount, int specialMaxFactorCapacity)
|
||||||
{
|
{
|
||||||
var accelerator = _accelerators[acceleratorIndex];
|
var accelerator = _accelerators[acceleratorIndex];
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ public class GpuKernelPool
|
|||||||
{
|
{
|
||||||
var loaded = accelerator.LoadAutoGroupedStreamKernel<
|
var loaded = accelerator.LoadAutoGroupedStreamKernel<
|
||||||
Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<int, Stride1D.Dense>,
|
Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<int, Stride1D.Dense>,
|
||||||
#if DETAILED_LOG
|
#if DETAILED_LOG || SELF_TEST
|
||||||
ArrayView1D<ulong, Stride1D.Dense>,
|
ArrayView1D<ulong, Stride1D.Dense>,
|
||||||
#endif
|
#endif
|
||||||
ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>
|
ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>
|
||||||
@@ -135,7 +135,7 @@ public class GpuKernelPool
|
|||||||
|
|
||||||
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int,
|
return kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int,
|
||||||
ArrayView1D<int, Stride1D.Dense>,
|
ArrayView1D<int, Stride1D.Dense>,
|
||||||
#if DETAILED_LOG
|
#if DETAILED_LOG || SELF_TEST
|
||||||
ArrayView1D<ulong, Stride1D.Dense>,
|
ArrayView1D<ulong, Stride1D.Dense>,
|
||||||
#endif
|
#endif
|
||||||
ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>>>();
|
ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>>>();
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public sealed class KernelContainer
|
|||||||
ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>? Pow2ModOrder;
|
ResidueAutomatonArgs, ArrayView<int>, ArrayView1D<ulong, Stride1D.Dense>>? Pow2ModOrder;
|
||||||
|
|
||||||
public Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<int, Stride1D.Dense>,
|
public Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<int, Stride1D.Dense>,
|
||||||
#if DETAILED_LOG
|
#if DETAILED_LOG || SELF_TEST
|
||||||
ArrayView1D<ulong, Stride1D.Dense>,
|
ArrayView1D<ulong, Stride1D.Dense>,
|
||||||
#endif
|
#endif
|
||||||
ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>>? BitContradiction;
|
ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>>? BitContradiction;
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,7 @@
|
|||||||
|
namespace PerfectNumbers.Core;
|
||||||
|
|
||||||
|
public enum GpuKernelType
|
||||||
|
{
|
||||||
|
Incremental,
|
||||||
|
Pow2Mod,
|
||||||
|
}
|
||||||
@@ -11,35 +11,6 @@ using PerfectNumbers.Core.Gpu.Accelerators;
|
|||||||
|
|
||||||
namespace PerfectNumbers.Core;
|
namespace PerfectNumbers.Core;
|
||||||
|
|
||||||
public enum GpuKernelType
|
|
||||||
{
|
|
||||||
Incremental,
|
|
||||||
Pow2Mod,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum CalculationMethod
|
|
||||||
{
|
|
||||||
ByDivisor,
|
|
||||||
Divisor,
|
|
||||||
Incremental,
|
|
||||||
LucasLehmer,
|
|
||||||
Pow2Mod,
|
|
||||||
Residue,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum CacheStatus
|
|
||||||
{
|
|
||||||
Disabled,
|
|
||||||
Enabled,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum OrderDevice
|
|
||||||
{
|
|
||||||
Cpu,
|
|
||||||
Hybrid,
|
|
||||||
Gpu,
|
|
||||||
}
|
|
||||||
|
|
||||||
[EnumDependentTemplate(typeof(CalculationMethod))]
|
[EnumDependentTemplate(typeof(CalculationMethod))]
|
||||||
[EnumDependentTemplate(typeof(CacheStatus))]
|
[EnumDependentTemplate(typeof(CacheStatus))]
|
||||||
[EnumDependentTemplate(typeof(OrderDevice))]
|
[EnumDependentTemplate(typeof(OrderDevice))]
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace PerfectNumbers.Core;
|
||||||
|
|
||||||
|
public enum OrderDevice
|
||||||
|
{
|
||||||
|
Cpu,
|
||||||
|
Hybrid,
|
||||||
|
Gpu,
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ namespace PerfectNumbers.Core;
|
|||||||
public static class PerfectNumberConstants
|
public static class PerfectNumberConstants
|
||||||
{
|
{
|
||||||
public const ulong BiggestKnownEvenPerfectP = 136279841UL;
|
public const ulong BiggestKnownEvenPerfectP = 136279841UL;
|
||||||
|
// public const int ConsoleInterval = 1;
|
||||||
public const int ConsoleInterval = 100_000;
|
public const int ConsoleInterval = 100_000;
|
||||||
public const int DefaultFactorsBuffer = 32;
|
public const int DefaultFactorsBuffer = 32;
|
||||||
public const int DefaultPoolCapacity = 10_240;
|
public const int DefaultPoolCapacity = 10_240;
|
||||||
@@ -26,7 +27,10 @@ public static class PerfectNumberConstants
|
|||||||
public const int PollardRhoMilliseconds = 100;
|
public const int PollardRhoMilliseconds = 100;
|
||||||
public const int ByDivisorMersenneTailCount = 8;
|
public const int ByDivisorMersenneTailCount = 8;
|
||||||
public const int ByDivisorMersenneBitLimit = 4096;
|
public const int ByDivisorMersenneBitLimit = 4096;
|
||||||
public const int BitContradictionGpuBatchCount = 134217728;
|
public const int BitContradictionGpuBatchCount = 16;
|
||||||
|
// public const int BitContradictionGpuBatchCount = 512;
|
||||||
|
// public const int BitContradictionGpuBatchCount = 131_072;
|
||||||
|
// public const int BitContradictionGpuBatchCount = 2_097_152;
|
||||||
public const int BitContradictionGpuThreads = 1;
|
public const int BitContradictionGpuThreads = 1;
|
||||||
// TODO: Load these limits from the benchmark-driven configuration so CPU and GPU scans stay aligned with the optimal
|
// TODO: Load these limits from the benchmark-driven configuration so CPU and GPU scans stay aligned with the optimal
|
||||||
// divisor-cycle datasets we generate offline.
|
// divisor-cycle datasets we generate offline.
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ public sealed class PrimeTester
|
|||||||
int length = values.Length;
|
int length = values.Length;
|
||||||
|
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
gpu.EnsureCapacity(0, length);
|
gpu.EnsurePrimeOrderCalculatorCapacity(0, length);
|
||||||
var inputBufferView = gpu.InputView;
|
var inputBufferView = gpu.InputView;
|
||||||
var resultBufferView = gpu.OutputByteView;
|
var resultBufferView = gpu.OutputByteView;
|
||||||
var kernelLauncher = gpu.SharesFactorKernelLauncher;
|
var kernelLauncher = gpu.SharesFactorKernelLauncher;
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ public sealed class PrimeTesterSeverOrOthers
|
|||||||
int length = values.Length;
|
int length = values.Length;
|
||||||
|
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
gpu.EnsureCapacity(0, length);
|
gpu.EnsurePrimeOrderCalculatorCapacity(0, length);
|
||||||
var inputBufferView = gpu.InputView;
|
var inputBufferView = gpu.InputView;
|
||||||
var resultBufferView = gpu.OutputByteView;
|
var resultBufferView = gpu.OutputByteView;
|
||||||
var kernelLauncher = gpu.SharesFactorKernelLauncher;
|
var kernelLauncher = gpu.SharesFactorKernelLauncher;
|
||||||
|
|||||||
Reference in new issue
Block a user