Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
497b1fcf89 | ||
|
|
df04ba601c | ||
|
|
9939c5d562 | ||
|
|
54fdff0a4e |
No files matched your search
@@ -28,8 +28,8 @@ public class PrimeTesterBenchmarks
|
|||||||
|
|
||||||
PrimeOrderCalculatorAccelerator.WarmUp();
|
PrimeOrderCalculatorAccelerator.WarmUp();
|
||||||
// HeuristicGroupABPrimeTesterAccelerator.WarmUp();
|
// HeuristicGroupABPrimeTesterAccelerator.WarmUp();
|
||||||
_ = _heuristicTester.IsPrimeCpu(_candidates[0]);
|
_ = HeuristicPrimeTester.IsPrimeCpu(_candidates[0]);
|
||||||
_ = _heuristicTester.IsPrimeGpu(_candidates[0]);
|
_ = HeuristicPrimeTester.IsPrimeGpu(_candidates[0]);
|
||||||
_ = Prime.Numbers.IsPrime(_candidates[0]);
|
_ = Prime.Numbers.IsPrime(_candidates[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ public class PrimeTesterBenchmarks
|
|||||||
|
|
||||||
for (int i = 0; i < values.Length; i++)
|
for (int i = 0; i < values.Length; i++)
|
||||||
{
|
{
|
||||||
if (tester.IsPrimeCpu(values[i]))
|
if (HeuristicPrimeTester.IsPrimeCpu(values[i]))
|
||||||
{
|
{
|
||||||
primeCount++;
|
primeCount++;
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ public class PrimeTesterBenchmarks
|
|||||||
|
|
||||||
for (int i = 0; i < values.Length; i++)
|
for (int i = 0; i < values.Length; i++)
|
||||||
{
|
{
|
||||||
if (tester.IsPrimeGpu(values[i]))
|
if (HeuristicPrimeTester.IsPrimeGpu(values[i]))
|
||||||
{
|
{
|
||||||
primeCount++;
|
primeCount++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ internal static class Program
|
|||||||
"/help"
|
"/help"
|
||||||
};
|
};
|
||||||
|
|
||||||
private const string DefaultHeader = "p,searchedMersenne,detailedCheck,passedAllTests";
|
private const string DefaultHeader = "p,divisor,searchedMersenne,detailedCheck,passedAllTests";
|
||||||
|
|
||||||
private static int Main(string[] args)
|
private static int Main(string[] args)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace EvenPerfectBitScanner;
|
|||||||
|
|
||||||
internal static class CalculationResultHandler
|
internal static class CalculationResultHandler
|
||||||
{
|
{
|
||||||
private const string ResultsHeader = "p,searchedMersenne,detailedCheck,passedAllTests";
|
private const string ResultsHeader = "p,divisor,searchedMersenne,detailedCheck,passedAllTests";
|
||||||
private const string PrimeFoundSuffix = " (FOUND VALID CANDIDATES)";
|
private const string PrimeFoundSuffix = " (FOUND VALID CANDIDATES)";
|
||||||
internal const int DefaultWriteBatchSize = 100;
|
internal const int DefaultWriteBatchSize = 100;
|
||||||
|
|
||||||
@@ -93,19 +93,19 @@ internal static class CalculationResultHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static void HandleResult(ulong currentP, bool searchedMersenne, bool detailedCheck, bool passedAllTests, bool lastWasComposite)
|
internal static void HandleResult(ulong currentP, ulong divisor, bool searchedMersenne, bool detailedCheck, bool passedAllTests, bool lastWasComposite)
|
||||||
{
|
{
|
||||||
// Program flow ensures Initialize(...) and InitializeOutputBuffer() ran before this call. Do not add initialization guards here.
|
// Program flow ensures Initialize(...) and InitializeOutputBuffer() ran before this call. Do not add initialization guards here.
|
||||||
|
|
||||||
Span<byte> stackBuffer = stackalloc byte[128];
|
Span<byte> stackBuffer = stackalloc byte[128];
|
||||||
byte[]? rentedBuffer = null;
|
byte[]? rentedBuffer = null;
|
||||||
Span<byte> utf8Span = stackBuffer;
|
Span<byte> utf8Span = stackBuffer;
|
||||||
int byteCount = TryFormatResultLine(utf8Span, currentP, searchedMersenne, detailedCheck, passedAllTests);
|
int byteCount = TryFormatResultLine(utf8Span, currentP, divisor, searchedMersenne, detailedCheck, passedAllTests);
|
||||||
if (byteCount < 0)
|
if (byteCount < 0)
|
||||||
{
|
{
|
||||||
rentedBuffer = ThreadStaticPools.BytePool.Rent(256);
|
rentedBuffer = ThreadStaticPools.BytePool.Rent(256);
|
||||||
utf8Span = rentedBuffer;
|
utf8Span = rentedBuffer;
|
||||||
byteCount = TryFormatResultLine(utf8Span, currentP, searchedMersenne, detailedCheck, passedAllTests);
|
byteCount = TryFormatResultLine(utf8Span, currentP, divisor, searchedMersenne, detailedCheck, passedAllTests);
|
||||||
if (byteCount < 0)
|
if (byteCount < 0)
|
||||||
{
|
{
|
||||||
ThreadStaticPools.BytePool.Return(rentedBuffer);
|
ThreadStaticPools.BytePool.Return(rentedBuffer);
|
||||||
@@ -229,7 +229,7 @@ internal static class CalculationResultHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static int TryFormatResultLine(Span<byte> destination, ulong currentP, bool searchedMersenne, bool detailedCheck, bool passedAllTests)
|
private static int TryFormatResultLine(Span<byte> destination, ulong currentP, ulong divisor, bool searchedMersenne, bool detailedCheck, bool passedAllTests)
|
||||||
{
|
{
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
@@ -246,6 +246,19 @@ internal static class CalculationResultHandler
|
|||||||
|
|
||||||
destination[offset++] = (byte)',';
|
destination[offset++] = (byte)',';
|
||||||
|
|
||||||
|
if (!Utf8Formatter.TryFormat(divisor, destination[offset..], out written))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += written;
|
||||||
|
if (offset >= destination.Length)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
destination[offset++] = (byte)',';
|
||||||
|
|
||||||
if (!Utf8Formatter.TryFormat(searchedMersenne, destination[offset..], out written))
|
if (!Utf8Formatter.TryFormat(searchedMersenne, destination[offset..], out written))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ internal static class CalculationResultsFile
|
|||||||
int first = 0;
|
int first = 0;
|
||||||
int second = 0;
|
int second = 0;
|
||||||
int third = 0;
|
int third = 0;
|
||||||
|
int fourth = 0;
|
||||||
ulong parsedP = 0UL;
|
ulong parsedP = 0UL;
|
||||||
ReadOnlySpan<char> detailedSpan = default;
|
ReadOnlySpan<char> detailedSpan = default;
|
||||||
ReadOnlySpan<char> passedAllTestsSpan = default;
|
ReadOnlySpan<char> passedAllTestsSpan = default;
|
||||||
@@ -139,8 +140,15 @@ internal static class CalculationResultsFile
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
detailedSpan = span[..third];
|
span = span[(third + 1)..];
|
||||||
passedAllTestsSpan = span[(third + 1)..];
|
fourth = span.IndexOf(',');
|
||||||
|
if (fourth < 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
detailedSpan = span[..fourth];
|
||||||
|
passedAllTestsSpan = span[(fourth + 1)..];
|
||||||
|
|
||||||
if (Utf8CliParser.TryParseBoolean(detailedSpan, out detailed) && Utf8CliParser.TryParseBoolean(passedAllTestsSpan, out passedAllTests))
|
if (Utf8CliParser.TryParseBoolean(detailedSpan, out detailed) && Utf8CliParser.TryParseBoolean(passedAllTestsSpan, out passedAllTests))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -422,7 +422,7 @@ internal static class Program
|
|||||||
_byDivisorStartPrime,
|
_byDivisorStartPrime,
|
||||||
static () => _lastCompositeP = true,
|
static () => _lastCompositeP = true,
|
||||||
static () => _lastCompositeP = false,
|
static () => _lastCompositeP = false,
|
||||||
static (candidate, searchedMersenne, detailedCheck, passedAllTests) => CalculationResultHandler.HandleResult(candidate, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP),
|
static (candidate, searchedMersenne, detailedCheck, passedAllTests, divisor) => CalculationResultHandler.HandleResult(candidate, divisor, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP),
|
||||||
threadCount,
|
threadCount,
|
||||||
byDivisorPrimeRange);
|
byDivisorPrimeRange);
|
||||||
|
|
||||||
@@ -483,7 +483,7 @@ internal static class Program
|
|||||||
{
|
{
|
||||||
p = buffer[j];
|
p = buffer[j];
|
||||||
passedAllTests = IsEvenPerfectCandidate(p, divisorCyclesSearchLimit, out searchedMersenne, out detailedCheck);
|
passedAllTests = IsEvenPerfectCandidate(p, divisorCyclesSearchLimit, out searchedMersenne, out detailedCheck);
|
||||||
CalculationResultHandler.HandleResult(p, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP);
|
CalculationResultHandler.HandleResult(p, 0UL, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -506,7 +506,7 @@ internal static class Program
|
|||||||
}
|
}
|
||||||
|
|
||||||
passedAllTests = IsEvenPerfectCandidate(p, divisorCyclesSearchLimit, out searchedMersenne, out detailedCheck);
|
passedAllTests = IsEvenPerfectCandidate(p, divisorCyclesSearchLimit, out searchedMersenne, out detailedCheck);
|
||||||
CalculationResultHandler.HandleResult(p, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP);
|
CalculationResultHandler.HandleResult(p, 0UL, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP);
|
||||||
|
|
||||||
if (p == maxP)
|
if (p == maxP)
|
||||||
{
|
{
|
||||||
@@ -649,7 +649,7 @@ internal static class Program
|
|||||||
if (_cliArguments.UseByDivisor)
|
if (_cliArguments.UseByDivisor)
|
||||||
{
|
{
|
||||||
// Windowed pow2mod kernel handles by-divisor scans.
|
// Windowed pow2mod kernel handles by-divisor scans.
|
||||||
return _byDivisorTester!.IsPrime(p, out detailedCheck);
|
return _byDivisorTester!.IsPrime(p, out detailedCheck, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
detailedCheck = MersenneTesters.Value!.IsMersennePrime(p);
|
detailedCheck = MersenneTesters.Value!.IsMersennePrime(p);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public class MersenneNumberDivisorByDivisorTesterTests
|
|||||||
{
|
{
|
||||||
var candidates = new List<ulong> { 5UL, 7UL, 11UL, 13UL };
|
var candidates = new List<ulong> { 5UL, 7UL, 11UL, 13UL };
|
||||||
var tester = new FakeTester();
|
var tester = new FakeTester();
|
||||||
var results = new List<(ulong Prime, bool Searched, bool Detailed, bool Passed)>();
|
var results = new List<(ulong Prime, bool Searched, bool Detailed, bool Passed, ulong Divisor)>();
|
||||||
int compositeMarks = 0;
|
int compositeMarks = 0;
|
||||||
int clearedMarks = 0;
|
int clearedMarks = 0;
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ public class MersenneNumberDivisorByDivisorTesterTests
|
|||||||
startPrime: 0UL,
|
startPrime: 0UL,
|
||||||
markComposite: () => compositeMarks++,
|
markComposite: () => compositeMarks++,
|
||||||
clearComposite: () => clearedMarks++,
|
clearComposite: () => clearedMarks++,
|
||||||
printResult: (prime, searched, detailed, passed) => results.Add((prime, searched, detailed, passed)),
|
printResult: (prime, searched, detailed, passed, divisor) => results.Add((prime, searched, detailed, passed, divisor)),
|
||||||
threadCount: 1,
|
threadCount: 1,
|
||||||
primesPerTask: 2);
|
primesPerTask: 2);
|
||||||
|
|
||||||
@@ -32,10 +32,10 @@ public class MersenneNumberDivisorByDivisorTesterTests
|
|||||||
results.Should().Equal(
|
results.Should().Equal(
|
||||||
new[]
|
new[]
|
||||||
{
|
{
|
||||||
(5UL, true, true, true),
|
(5UL, true, true, true, 0UL),
|
||||||
(7UL, true, true, false),
|
(7UL, true, true, false, 7UL),
|
||||||
(11UL, true, true, false),
|
(11UL, true, true, false, 11UL),
|
||||||
(13UL, true, true, true),
|
(13UL, true, true, true, 0UL),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,10 +57,23 @@ public class MersenneNumberDivisorByDivisorTesterTests
|
|||||||
return DivisorLimit;
|
return DivisorLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsPrime(ulong prime, out bool divisorsExhausted)
|
public bool IsPrime(ulong prime, out bool divisorsExhausted, out ulong divisor)
|
||||||
{
|
{
|
||||||
divisorsExhausted = true;
|
divisorsExhausted = true;
|
||||||
return prime % 7UL != 0UL && prime % 11UL != 0UL;
|
if (prime % 7UL == 0UL)
|
||||||
|
{
|
||||||
|
divisor = 7UL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prime % 11UL == 0UL)
|
||||||
|
{
|
||||||
|
divisor = 11UL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
divisor = 0UL;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMersenneNumberDivisorByDivisorTester.IDivisorScanSession CreateDivisorSession()
|
public IMersenneNumberDivisorByDivisorTester.IDivisorScanSession CreateDivisorSession()
|
||||||
|
|||||||
@@ -13,14 +13,17 @@ public class MersenneNumberDivisorCpuTesterTests
|
|||||||
var tester = new MersenneNumberDivisorByDivisorCpuTester();
|
var tester = new MersenneNumberDivisorByDivisorCpuTester();
|
||||||
tester.ConfigureFromMaxPrime(11UL);
|
tester.ConfigureFromMaxPrime(11UL);
|
||||||
|
|
||||||
tester.IsPrime(5UL, out bool divisorsExhausted).Should().BeTrue();
|
tester.IsPrime(5UL, out bool divisorsExhausted, out ulong divisor).Should().BeTrue();
|
||||||
divisorsExhausted.Should().BeTrue();
|
divisorsExhausted.Should().BeTrue();
|
||||||
|
divisor.Should().Be(0UL);
|
||||||
|
|
||||||
tester.IsPrime(7UL, out divisorsExhausted).Should().BeTrue();
|
tester.IsPrime(7UL, out divisorsExhausted, out divisor).Should().BeTrue();
|
||||||
divisorsExhausted.Should().BeTrue();
|
divisorsExhausted.Should().BeTrue();
|
||||||
|
divisor.Should().Be(0UL);
|
||||||
|
|
||||||
tester.IsPrime(11UL, out divisorsExhausted).Should().BeFalse();
|
tester.IsPrime(11UL, out divisorsExhausted, out divisor).Should().BeFalse();
|
||||||
divisorsExhausted.Should().BeTrue();
|
divisorsExhausted.Should().BeTrue();
|
||||||
|
divisor.Should().BeGreaterThan(0UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -73,14 +73,17 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
tester.ConfigureFromMaxPrime(43UL);
|
tester.ConfigureFromMaxPrime(43UL);
|
||||||
|
|
||||||
tester.IsPrime(31UL, out bool exhausted).Should().BeTrue();
|
tester.IsPrime(31UL, out bool exhausted, out ulong divisor).Should().BeTrue();
|
||||||
exhausted.Should().BeTrue();
|
exhausted.Should().BeTrue();
|
||||||
|
divisor.Should().Be(0UL);
|
||||||
|
|
||||||
tester.IsPrime(37UL, out exhausted).Should().BeFalse();
|
tester.IsPrime(37UL, out exhausted, out divisor).Should().BeFalse();
|
||||||
exhausted.Should().BeTrue();
|
exhausted.Should().BeTrue();
|
||||||
|
divisor.Should().BeGreaterThan(0UL);
|
||||||
|
|
||||||
tester.IsPrime(43UL, out exhausted).Should().BeFalse();
|
tester.IsPrime(43UL, out exhausted, out divisor).Should().BeFalse();
|
||||||
exhausted.Should().BeTrue();
|
exhausted.Should().BeTrue();
|
||||||
|
divisor.Should().BeGreaterThan(0UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -105,12 +108,15 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
tester.ConfigureFromMaxPrime(41UL);
|
tester.ConfigureFromMaxPrime(41UL);
|
||||||
|
|
||||||
tester.IsPrime(31UL, out _).Should().BeTrue();
|
tester.IsPrime(31UL, out _, out ulong divisor).Should().BeTrue();
|
||||||
tester.IsPrime(37UL, out bool exhausted).Should().BeFalse();
|
divisor.Should().Be(0UL);
|
||||||
|
tester.IsPrime(37UL, out bool exhausted, out divisor).Should().BeFalse();
|
||||||
exhausted.Should().BeTrue();
|
exhausted.Should().BeTrue();
|
||||||
|
divisor.Should().BeGreaterThan(0UL);
|
||||||
|
|
||||||
tester.IsPrime(41UL, out bool divisorsExhausted).Should().BeFalse();
|
tester.IsPrime(41UL, out bool divisorsExhausted, out divisor).Should().BeFalse();
|
||||||
divisorsExhausted.Should().BeTrue();
|
divisorsExhausted.Should().BeTrue();
|
||||||
|
divisor.Should().BeGreaterThan(0UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -124,8 +130,16 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
tester.ConfigureFromMaxPrime(exponent);
|
tester.ConfigureFromMaxPrime(exponent);
|
||||||
|
|
||||||
tester.IsPrime(exponent, out bool exhausted).Should().Be(expectedPrime);
|
tester.IsPrime(exponent, out bool exhausted, out ulong divisor).Should().Be(expectedPrime);
|
||||||
exhausted.Should().BeTrue();
|
exhausted.Should().BeTrue();
|
||||||
|
if (expectedPrime)
|
||||||
|
{
|
||||||
|
divisor.Should().Be(0UL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
divisor.Should().BeGreaterThan(0UL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Category", "Fast")]
|
[Trait("Category", "Fast")]
|
||||||
@@ -138,8 +152,9 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
|
|
||||||
tester.ConfigureFromMaxPrime(43UL);
|
tester.ConfigureFromMaxPrime(43UL);
|
||||||
|
|
||||||
tester.IsPrime(41UL, out bool divisorsExhausted).Should().BeFalse();
|
tester.IsPrime(41UL, out bool divisorsExhausted, out ulong divisor).Should().BeFalse();
|
||||||
divisorsExhausted.Should().BeTrue();
|
divisorsExhausted.Should().BeTrue();
|
||||||
|
divisor.Should().BeGreaterThan(0UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -309,8 +324,9 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
.GetField("_divisorLimit", BindingFlags.NonPublic | BindingFlags.Instance)!
|
.GetField("_divisorLimit", BindingFlags.NonPublic | BindingFlags.Instance)!
|
||||||
.SetValue(tester, 200UL);
|
.SetValue(tester, 200UL);
|
||||||
|
|
||||||
tester.IsPrime(19UL, out bool divisorsExhausted).Should().BeTrue();
|
tester.IsPrime(19UL, out bool divisorsExhausted, out ulong divisor).Should().BeTrue();
|
||||||
divisorsExhausted.Should().BeTrue();
|
divisorsExhausted.Should().BeTrue();
|
||||||
|
divisor.Should().Be(0UL);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public ulong GetAllowedMaxDivisor(ulong prime) => ComputeAllowedMaxDivisor(prime, _divisorLimit);
|
public ulong GetAllowedMaxDivisor(ulong prime) => ComputeAllowedMaxDivisor(prime, _divisorLimit);
|
||||||
|
|
||||||
public bool IsPrime(ulong prime, out bool divisorsExhausted)
|
public bool IsPrime(ulong prime, out bool divisorsExhausted, out ulong divisor)
|
||||||
{
|
{
|
||||||
ulong allowedMax = ComputeAllowedMaxDivisor(prime, _divisorLimit);
|
ulong allowedMax = ComputeAllowedMaxDivisor(prime, _divisorLimit);
|
||||||
|
|
||||||
@@ -60,7 +60,8 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
bool composite = CheckDivisors(
|
bool composite = CheckDivisors(
|
||||||
prime,
|
prime,
|
||||||
allowedMax,
|
allowedMax,
|
||||||
out processedAll);
|
out processedAll,
|
||||||
|
out divisor);
|
||||||
|
|
||||||
if (composite)
|
if (composite)
|
||||||
{
|
{
|
||||||
@@ -69,6 +70,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
}
|
}
|
||||||
|
|
||||||
divisorsExhausted = processedAll || composite;
|
divisorsExhausted = processedAll || composite;
|
||||||
|
divisor = 0UL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +98,10 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
private bool CheckDivisors(
|
private bool CheckDivisors(
|
||||||
ulong prime,
|
ulong prime,
|
||||||
ulong allowedMax,
|
ulong allowedMax,
|
||||||
out bool processedAll)
|
out bool processedAll,
|
||||||
|
out ulong foundDivisor)
|
||||||
{
|
{
|
||||||
|
foundDivisor = 0UL;
|
||||||
// The EvenPerfectBitScanner feeds primes >= 138,000,000 here, so allowedMax >= 3 in production runs.
|
// The EvenPerfectBitScanner feeds primes >= 138,000,000 here, so allowedMax >= 3 in production runs.
|
||||||
// Keeping the guard commented out documents the reasoning for benchmarks and tests.
|
// Keeping the guard commented out documents the reasoning for benchmarks and tests.
|
||||||
// if (allowedMax < 3UL)
|
// if (allowedMax < 3UL)
|
||||||
@@ -123,6 +127,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
if (divisor.CompareTo(limit) > 0)
|
if (divisor.CompareTo(limit) > 0)
|
||||||
{
|
{
|
||||||
processedAll = true;
|
processedAll = true;
|
||||||
|
foundDivisor = 0UL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +187,8 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
remainder3,
|
remainder3,
|
||||||
remainder7,
|
remainder7,
|
||||||
remainder11,
|
remainder11,
|
||||||
out processedAll);
|
out processedAll,
|
||||||
|
out foundDivisor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong divisorHigh = divisor.High;
|
ulong divisorHigh = divisor.High;
|
||||||
@@ -240,6 +246,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
{
|
{
|
||||||
// A cycle equal to the tested exponent (which is prime in this path) guarantees that the candidate divides
|
// A cycle equal to the tested exponent (which is prime in this path) guarantees that the candidate divides
|
||||||
// the corresponding Mersenne number because the order of 2 modulo the divisor is exactly p.
|
// the corresponding Mersenne number because the order of 2 modulo the divisor is exactly p.
|
||||||
|
foundDivisor = candidate;
|
||||||
processedAll = true;
|
processedAll = true;
|
||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
return true;
|
return true;
|
||||||
@@ -261,6 +268,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
|
|
||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
processedAll = true;
|
processedAll = true;
|
||||||
|
foundDivisor = 0UL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,9 +288,11 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
byte remainder3,
|
byte remainder3,
|
||||||
byte remainder7,
|
byte remainder7,
|
||||||
byte remainder11,
|
byte remainder11,
|
||||||
out bool processedAll)
|
out bool processedAll,
|
||||||
|
out ulong foundDivisor)
|
||||||
{
|
{
|
||||||
processedAll = false;
|
processedAll = false;
|
||||||
|
foundDivisor = 0UL;
|
||||||
|
|
||||||
bool canAdvance = step <= limit;
|
bool canAdvance = step <= limit;
|
||||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
@@ -314,6 +324,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
|
|
||||||
if (divisorCycle == prime)
|
if (divisorCycle == prime)
|
||||||
{
|
{
|
||||||
|
foundDivisor = divisor;
|
||||||
processedAll = true;
|
processedAll = true;
|
||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
return true;
|
return true;
|
||||||
@@ -327,12 +338,14 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
}
|
}
|
||||||
|
|
||||||
processedAll = true;
|
processedAll = true;
|
||||||
|
foundDivisor = 0UL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (divisor > limit)
|
if (divisor > limit)
|
||||||
{
|
{
|
||||||
processedAll = true;
|
processedAll = true;
|
||||||
|
foundDivisor = 0UL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,6 +378,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
|
|
||||||
if (divisorCycle == prime)
|
if (divisorCycle == prime)
|
||||||
{
|
{
|
||||||
|
foundDivisor = divisor;
|
||||||
processedAll = true;
|
processedAll = true;
|
||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
return true;
|
return true;
|
||||||
@@ -380,6 +394,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
if (remainingIterations == 0UL)
|
if (remainingIterations == 0UL)
|
||||||
{
|
{
|
||||||
processedAll = true;
|
processedAll = true;
|
||||||
|
foundDivisor = 0UL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,20 +115,18 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
|
|
||||||
public Dictionary<ulong, int> Pow2ModEntriesToTestOnHost = [];
|
public Dictionary<ulong, int> Pow2ModEntriesToTestOnHost = [];
|
||||||
|
|
||||||
public readonly Kernel CheckFactorsKernel;
|
public readonly Action<AcceleratorStream, int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>> CheckFactorsKernelLauncher;
|
||||||
public readonly Kernel ConvertToStandardKernel;
|
|
||||||
|
|
||||||
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>> ConvertToStandardKernelLauncher;
|
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>> ConvertToStandardKernelLauncher;
|
||||||
|
|
||||||
public readonly Kernel HeuristicCombinedTrialDivisionKernel;
|
|
||||||
public readonly Action<AcceleratorStream, Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicCombinedGpuViews> HeuristicCombinedTrialDivisionKernelLauncher;
|
public readonly Action<AcceleratorStream, Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicCombinedGpuViews> HeuristicCombinedTrialDivisionKernelLauncher;
|
||||||
public readonly Kernel KeepMontgomeryKernel;
|
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>> KeepMontgomeryKernelLauncher;
|
||||||
public readonly Kernel PollardRhoKernel;
|
public readonly Action<AcceleratorStream, ulong, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> PollardRhoKernelLauncher;
|
||||||
public readonly Kernel Pow2ModWideKernel;
|
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>> Pow2ModWideKernelLauncher;
|
||||||
public readonly Kernel SharesFactorKernel;
|
public readonly Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<byte>> SharesFactorKernelLauncher;
|
||||||
public readonly Kernel SmallPrimeFactorKernel;
|
public readonly Action<AcceleratorStream, Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> SmallPrimeFactorKernelLauncher;
|
||||||
public readonly Kernel SmallPrimeSieveKernel;
|
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 Kernel SpecialMaxKernel;
|
public readonly Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> SpecialMaxKernelLauncher;
|
||||||
|
|
||||||
public void EnsureCapacity(int factorsCount, int primeTesterCapacity)
|
public void EnsureCapacity(int factorsCount, int primeTesterCapacity)
|
||||||
{
|
{
|
||||||
@@ -262,31 +260,25 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
SmallPrimeFactorSquares = tables.Squares.View;
|
SmallPrimeFactorSquares = tables.Squares.View;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckFactorsKernel = KernelUtil.GetKernel(accelerator.LoadStreamKernel<int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.CheckFactorsKernel));
|
CheckFactorsKernelLauncher = KernelUtil.GetKernel(accelerator.LoadStreamKernel<int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.CheckFactorsKernel)).CreateLauncherDelegate<Action<AcceleratorStream, int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
|
|
||||||
Kernel convertToStandardKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelConvertToStandard));
|
ConvertToStandardKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelConvertToStandard)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
|
|
||||||
ConvertToStandardKernel = convertToStandardKernel;
|
HeuristicCombinedTrialDivisionKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicCombinedGpuViews>(PrimeTesterKernels.HeuristicTrialCombinedDivisionKernel)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicCombinedGpuViews>>();
|
||||||
ConvertToStandardKernelLauncher = convertToStandardKernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
|
|
||||||
|
|
||||||
var heuristicCombinedTrialDivisionKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicCombinedGpuViews>(PrimeTesterKernels.HeuristicTrialCombinedDivisionKernel));
|
KeepMontgomeryKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelKeepMontgomery)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
|
|
||||||
HeuristicCombinedTrialDivisionKernel = heuristicCombinedTrialDivisionKernel;
|
PollardRhoKernelLauncher = KernelUtil.GetKernel(accelerator.LoadStreamKernel<ulong, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.TryPollardRhoKernel)).CreateLauncherDelegate<Action<AcceleratorStream, ulong, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
HeuristicCombinedTrialDivisionKernelLauncher = heuristicCombinedTrialDivisionKernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicCombinedGpuViews>>();
|
|
||||||
|
|
||||||
KeepMontgomeryKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelKeepMontgomery));
|
Pow2ModWideKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>(PrimeOrderGpuHeuristics.Pow2ModKernelWide)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>>();
|
||||||
|
|
||||||
PollardRhoKernel = KernelUtil.GetKernel(accelerator.LoadStreamKernel<ulong, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.TryPollardRhoKernel));
|
SharesFactorKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SharesFactorKernel)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<byte>>>();
|
||||||
|
|
||||||
Pow2ModWideKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>(PrimeOrderGpuHeuristics.Pow2ModKernelWide));
|
SmallPrimeFactorKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(SmallPrimeFactorKernels.SmallPrimeFactorKernelScan)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
|
|
||||||
SharesFactorKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SharesFactorKernel));
|
SmallPrimeSieveKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SmallPrimeSieveKernel)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>>();
|
||||||
|
|
||||||
SmallPrimeFactorKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(SmallPrimeFactorKernels.SmallPrimeFactorKernelScan));
|
SpecialMaxKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.EvaluateSpecialMaxCandidatesKernel)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
||||||
|
|
||||||
SmallPrimeSieveKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterKernels.SmallPrimeSieveKernel));
|
|
||||||
|
|
||||||
SpecialMaxKernel = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderGpuHeuristics.EvaluateSpecialMaxCandidatesKernel));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
|
|
||||||
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
|
||||||
public bool IsPrime(ulong prime, out bool divisorsExhausted)
|
public bool IsPrime(ulong prime, out bool divisorsExhausted, out ulong divisor)
|
||||||
{
|
{
|
||||||
ulong allowedMax;
|
ulong allowedMax;
|
||||||
int batchCapacity;
|
int batchCapacity;
|
||||||
@@ -147,10 +147,12 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
|
|||||||
if (composite)
|
if (composite)
|
||||||
{
|
{
|
||||||
divisorsExhausted = true;
|
divisorsExhausted = true;
|
||||||
|
divisor = lastProcessed;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
divisorsExhausted = coveredRange;
|
divisorsExhausted = coveredRange;
|
||||||
|
divisor = 0UL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,16 +18,13 @@ public static class Pow2MontgomeryGpuCalculator
|
|||||||
Accelerator? accelerator = gpu.Accelerator;
|
Accelerator? accelerator = gpu.Accelerator;
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
|
MemoryBuffer1D<ulong, Stride1D.Dense> exponentBuffer = gpu.Input;
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
MemoryBuffer1D<ulong, Stride1D.Dense> resultBuffer = gpu.OutputUlong;
|
||||||
var kernel = gpu.KeepMontgomeryKernel;
|
|
||||||
|
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
|
|
||||||
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
|
exponentBuffer.View.CopyFromCPU(stream, ref exponent, 1);
|
||||||
// We don't need to worry about any left-overs here.
|
// We don't need to worry about any left-overs here.
|
||||||
// resultBuffer.MemSetToZero(stream);
|
// resultBuffer.MemSetToZero(stream);
|
||||||
|
|
||||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
|
var kernelLauncher = gpu.KeepMontgomeryKernelLauncher;
|
||||||
|
|
||||||
kernelLauncher(stream, 1, exponentBuffer.View, divisor, resultBuffer.View);
|
kernelLauncher(stream, 1, exponentBuffer.View, divisor, resultBuffer.View);
|
||||||
|
|
||||||
resultBuffer.View.CopyToCPU(stream, ref result, 1);
|
resultBuffer.View.CopyToCPU(stream, ref result, 1);
|
||||||
|
|||||||
@@ -604,7 +604,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
}
|
}
|
||||||
|
|
||||||
exponentBuffer.View.CopyFromCPU(stream, exponentSpan);
|
exponentBuffer.View.CopyFromCPU(stream, exponentSpan);
|
||||||
var kernelLauncher = gpu.Pow2ModWideKernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<GpuUInt128, Stride1D.Dense>, GpuUInt128, ArrayView1D<GpuUInt128, Stride1D.Dense>>>();
|
var kernelLauncher = gpu.Pow2ModWideKernelLauncher;
|
||||||
|
|
||||||
kernelLauncher(stream, length, exponentBuffer.View, modulus, remainderBuffer.View);
|
kernelLauncher(stream, length, exponentBuffer.View, modulus, remainderBuffer.View);
|
||||||
remainderBuffer.View.CopyToCPU(stream, ref MemoryMarshal.GetReference(resultSpan), length);
|
remainderBuffer.View.CopyToCPU(stream, ref MemoryMarshal.GetReference(resultSpan), length);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using ILGPU.Runtime;
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using PerfectNumbers.Core.Gpu;
|
using PerfectNumbers.Core.Gpu;
|
||||||
using PerfectNumbers.Core.Gpu.Accelerators;
|
using PerfectNumbers.Core.Gpu.Accelerators;
|
||||||
using ILGPU;
|
|
||||||
|
|
||||||
namespace PerfectNumbers.Core;
|
namespace PerfectNumbers.Core;
|
||||||
|
|
||||||
@@ -236,13 +235,12 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
private static bool HeuristicTrialDivisionGpuDetectsDivisor(PrimeOrderCalculatorAccelerator gpu, ulong n, ulong maxDivisorSquare, byte nMod10)
|
private static bool HeuristicTrialDivisionGpuDetectsDivisor(PrimeOrderCalculatorAccelerator gpu, ulong n, ulong maxDivisorSquare, byte nMod10)
|
||||||
{
|
{
|
||||||
var acceleratorIndex = gpu.AcceleratorIndex;
|
var acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
|
||||||
var kernel = gpu.HeuristicCombinedTrialDivisionKernel;
|
|
||||||
var flagView1D = gpu.OutputInt!.View;
|
var flagView1D = gpu.OutputInt!.View;
|
||||||
|
|
||||||
bool compositeDetected;
|
bool compositeDetected;
|
||||||
// int compositeFlag = 0;
|
|
||||||
Span<int> compositeFlag = stackalloc int[1];
|
Span<int> compositeFlag = stackalloc int[1];
|
||||||
|
// int compositeFlag = 0;
|
||||||
|
|
||||||
|
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
flagView1D.MemSetToZero(stream);
|
flagView1D.MemSetToZero(stream);
|
||||||
|
|
||||||
var kernelLauncher = gpu.HeuristicCombinedTrialDivisionKernelLauncher;
|
var kernelLauncher = gpu.HeuristicCombinedTrialDivisionKernelLauncher;
|
||||||
@@ -266,14 +264,10 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static bool EvaluateWithOpenNumericFallback(ulong n)
|
private static bool EvaluateWithOpenNumericFallback(ulong n) => Prime.Numbers.IsPrime(n);
|
||||||
{
|
|
||||||
return Prime.Numbers.IsPrime(n);
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
}
|
internal static ulong ComputeHeuristicDivisorSquareLimit(ulong n) => n;
|
||||||
internal static ulong ComputeHeuristicDivisorSquareLimit(ulong n)
|
|
||||||
{
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlySpan<ulong> GetCombinedDivisors(byte nMod10) => nMod10 switch
|
private static ReadOnlySpan<ulong> GetCombinedDivisors(byte nMod10) => nMod10 switch
|
||||||
{
|
{
|
||||||
@@ -470,9 +464,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static HeuristicDivisorEnumerator CreateHeuristicDivisorEnumerator(ulong maxDivisorSquare, byte nMod10, Span<HeuristicGroupBSequenceState> groupBBuffer)
|
internal static HeuristicDivisorEnumerator CreateHeuristicDivisorEnumerator(ulong maxDivisorSquare, byte nMod10, Span<HeuristicGroupBSequenceState> groupBBuffer)
|
||||||
{
|
=> new(maxDivisorSquare, nMod10, groupBBuffer);
|
||||||
return new HeuristicDivisorEnumerator(maxDivisorSquare, nMod10, groupBBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal struct HeuristicGroupBSequenceState
|
internal struct HeuristicGroupBSequenceState
|
||||||
{
|
{
|
||||||
@@ -480,9 +472,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static MersenneHeuristicDivisorEnumerator CreateMersenneDivisorEnumerator(ulong exponent, ulong maxDivisor)
|
internal static MersenneHeuristicDivisorEnumerator CreateMersenneDivisorEnumerator(ulong exponent, ulong maxDivisor)
|
||||||
{
|
=> new(exponent, maxDivisor);
|
||||||
return new MersenneHeuristicDivisorEnumerator(exponent, maxDivisor);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static HeuristicDivisorPreparation PrepareHeuristicDivisor(in HeuristicDivisorCandidate candidate)
|
internal static HeuristicDivisorPreparation PrepareHeuristicDivisor(in HeuristicDivisorCandidate candidate)
|
||||||
@@ -490,7 +480,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
ulong divisor = candidate.Value;
|
ulong divisor = candidate.Value;
|
||||||
MontgomeryDivisorData divisorData = MontgomeryDivisorData.FromModulus(divisor);
|
MontgomeryDivisorData divisorData = MontgomeryDivisorData.FromModulus(divisor);
|
||||||
bool hasCycleHint = TryGetCycleLengthHint(divisor, out ulong cycleLength);
|
bool hasCycleHint = TryGetCycleLengthHint(divisor, out ulong cycleLength);
|
||||||
return new HeuristicDivisorPreparation(candidate, divisorData, cycleLength, hasCycleHint);
|
return new(candidate, divisorData, cycleLength, hasCycleHint);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -588,7 +578,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
ulong value = entry;
|
ulong value = entry;
|
||||||
byte ending = (byte)(value % 10UL);
|
byte ending = (byte)(value % 10UL);
|
||||||
ushort residue = (ushort)(value % Wheel210);
|
ushort residue = (ushort)(value % Wheel210);
|
||||||
candidate = new HeuristicDivisorCandidate(value, group, ending, 0, residue);
|
candidate = new(value, group, ending, 0, residue);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -691,7 +681,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
}
|
}
|
||||||
|
|
||||||
ushort residue = (ushort)(value % Wheel210);
|
ushort residue = (ushort)(value % Wheel210);
|
||||||
return new HeuristicDivisorCandidate(value, group, ending, 0, residue);
|
return new(value, group, ending, 0, residue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,6 @@ using System.Runtime.CompilerServices;
|
|||||||
using ILGPU.Runtime;
|
using ILGPU.Runtime;
|
||||||
using PerfectNumbers.Core.Gpu;
|
using PerfectNumbers.Core.Gpu;
|
||||||
using PerfectNumbers.Core.Gpu.Accelerators;
|
using PerfectNumbers.Core.Gpu.Accelerators;
|
||||||
using ILGPU;
|
|
||||||
|
|
||||||
namespace PerfectNumbers.Core;
|
namespace PerfectNumbers.Core;
|
||||||
|
|
||||||
@@ -68,7 +67,8 @@ public sealed class HeuristicPrimeTester
|
|||||||
|
|
||||||
public static HeuristicPrimeTester Exclusive => _tester ??= new();
|
public static HeuristicPrimeTester Exclusive => _tester ??= new();
|
||||||
|
|
||||||
public bool IsPrimeCpu(ulong n)
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static bool IsPrimeCpu(ulong n)
|
||||||
{
|
{
|
||||||
byte nMod10 = (byte)n.Mod10();
|
byte nMod10 = (byte)n.Mod10();
|
||||||
ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n);
|
ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n);
|
||||||
@@ -82,19 +82,18 @@ public sealed class HeuristicPrimeTester
|
|||||||
return HeuristicTrialDivisionCpu(n, maxDivisorSquare, nMod10, includeGroupB);
|
return HeuristicTrialDivisionCpu(n, maxDivisorSquare, nMod10, includeGroupB);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsPrimeGpu(ulong n)
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static bool IsPrimeGpu(ulong n)
|
||||||
{
|
{
|
||||||
byte nMod10 = (byte)n.Mod10();
|
byte nMod10 = (byte)n.Mod10();
|
||||||
ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n);
|
ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n);
|
||||||
return IsPrimeGpu(n, maxDivisorSquare, nMod10);
|
return IsPrimeGpu(n, maxDivisorSquare, nMod10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsPrimeGpu(ulong n, ulong maxDivisorSquare, byte nMod10)
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
{
|
public static bool IsPrimeGpu(ulong n, ulong maxDivisorSquare, byte nMod10) => HeuristicIsPrimeGpuCore(n, maxDivisorSquare, nMod10);
|
||||||
return HeuristicIsPrimeGpuCore(n, maxDivisorSquare, nMod10);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool HeuristicIsPrimeGpuCore(ulong n, ulong maxDivisorSquare, byte nMod10)
|
private static bool HeuristicIsPrimeGpuCore(ulong n, ulong maxDivisorSquare, byte nMod10)
|
||||||
{
|
{
|
||||||
// TODO: Is this condition ever met on the execution path in EvenPerfectBitScanner?
|
// TODO: Is this condition ever met on the execution path in EvenPerfectBitScanner?
|
||||||
if (maxDivisorSquare < 9UL)
|
if (maxDivisorSquare < 9UL)
|
||||||
@@ -133,7 +132,7 @@ public sealed class HeuristicPrimeTester
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong divisor = (ulong)groupADivisors[groupAIndex];
|
ulong divisor = groupADivisors[groupAIndex];
|
||||||
if (n % divisor == 0UL)
|
if (n % divisor == 0UL)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -186,7 +185,7 @@ public sealed class HeuristicPrimeTester
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong divisor = (ulong)groupADivisors[groupAIndex];
|
ulong divisor = groupADivisors[groupAIndex];
|
||||||
if (n % divisor == 0UL)
|
if (n % divisor == 0UL)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -240,13 +239,12 @@ public sealed class HeuristicPrimeTester
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10)
|
private static bool HeuristicTrialDivisionGpuDetectsDivisor(ulong n, ulong maxDivisorSquare, byte nMod10)
|
||||||
{
|
{
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
var kernel = gpu.HeuristicCombinedTrialDivisionKernel;
|
|
||||||
var flagView1D = gpu.OutputInt!.View;
|
var flagView1D = gpu.OutputInt!.View;
|
||||||
|
|
||||||
bool compositeDetected;
|
bool compositeDetected;
|
||||||
@@ -261,7 +259,7 @@ public sealed class HeuristicPrimeTester
|
|||||||
// HeuristicGpuDivisorTableKind tableKind,
|
// HeuristicGpuDivisorTableKind tableKind,
|
||||||
// HeuristicGpuDivisorTables tables)
|
// HeuristicGpuDivisorTables tables)
|
||||||
|
|
||||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, byte, ArrayView<int>, ulong, ulong, HeuristicGpuDivisorTableKind, HeuristicCombinedGpuViews>>();
|
var kernelLauncher = gpu.HeuristicCombinedTrialDivisionKernelLauncher;
|
||||||
kernelLauncher(
|
kernelLauncher(
|
||||||
stream,
|
stream,
|
||||||
1,
|
1,
|
||||||
@@ -269,7 +267,6 @@ public sealed class HeuristicPrimeTester
|
|||||||
flagView1D,
|
flagView1D,
|
||||||
n,
|
n,
|
||||||
maxDivisorSquare,
|
maxDivisorSquare,
|
||||||
HeuristicGpuDivisorTableKind.GroupA,
|
|
||||||
gpu.DivisorTables);
|
gpu.DivisorTables);
|
||||||
|
|
||||||
flagView1D.CopyToCPU(stream, ref compositeFlag, 1);
|
flagView1D.CopyToCPU(stream, ref compositeFlag, 1);
|
||||||
@@ -321,17 +318,11 @@ public sealed class HeuristicPrimeTester
|
|||||||
return compositeDetected;
|
return compositeDetected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static bool EvaluateWithOpenNumericFallback(ulong n) => Prime.Numbers.IsPrime(n);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static bool EvaluateWithOpenNumericFallback(ulong n)
|
internal static ulong ComputeHeuristicDivisorSquareLimit(ulong n) => n;
|
||||||
{
|
|
||||||
return Prime.Numbers.IsPrime(n);
|
|
||||||
}
|
|
||||||
internal static ulong ComputeHeuristicDivisorSquareLimit(ulong n)
|
|
||||||
{
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReadOnlySpan<byte> GetGroupBEndingOrder(byte nMod10) => nMod10 switch
|
private static ReadOnlySpan<byte> GetGroupBEndingOrder(byte nMod10) => nMod10 switch
|
||||||
{
|
{
|
||||||
@@ -339,7 +330,7 @@ public sealed class HeuristicPrimeTester
|
|||||||
3 => GroupBEndingOrderMod3,
|
3 => GroupBEndingOrderMod3,
|
||||||
7 => GroupBEndingOrderMod7,
|
7 => GroupBEndingOrderMod7,
|
||||||
9 => GroupBEndingOrderMod9,
|
9 => GroupBEndingOrderMod9,
|
||||||
_ => ReadOnlySpan<byte>.Empty,
|
_ => [],
|
||||||
};
|
};
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -415,19 +406,19 @@ public sealed class HeuristicPrimeTester
|
|||||||
private static ReadOnlySpan<uint> GetGroupBDivisors(byte ending) => ending switch
|
private static ReadOnlySpan<uint> GetGroupBDivisors(byte ending) => ending switch
|
||||||
{
|
{
|
||||||
1 => DivisorGenerator.SmallPrimesLastOneWithoutLastThree,
|
1 => DivisorGenerator.SmallPrimesLastOneWithoutLastThree,
|
||||||
3 => ReadOnlySpan<uint>.Empty,
|
3 => [],
|
||||||
7 => DivisorGenerator.SmallPrimesLastSevenWithoutLastThree,
|
7 => DivisorGenerator.SmallPrimesLastSevenWithoutLastThree,
|
||||||
9 => DivisorGenerator.SmallPrimesLastNineWithoutLastThree,
|
9 => DivisorGenerator.SmallPrimesLastNineWithoutLastThree,
|
||||||
_ => ReadOnlySpan<uint>.Empty,
|
_ => [],
|
||||||
};
|
};
|
||||||
|
|
||||||
private static ReadOnlySpan<ulong> GetGroupBDivisorSquares(byte ending) => ending switch
|
private static ReadOnlySpan<ulong> GetGroupBDivisorSquares(byte ending) => ending switch
|
||||||
{
|
{
|
||||||
1 => DivisorGenerator.SmallPrimesPow2LastOneWithoutLastThree,
|
1 => DivisorGenerator.SmallPrimesPow2LastOneWithoutLastThree,
|
||||||
3 => ReadOnlySpan<ulong>.Empty,
|
3 => [],
|
||||||
7 => DivisorGenerator.SmallPrimesPow2LastSevenWithoutLastThree,
|
7 => DivisorGenerator.SmallPrimesPow2LastSevenWithoutLastThree,
|
||||||
9 => DivisorGenerator.SmallPrimesPow2LastNineWithoutLastThree,
|
9 => DivisorGenerator.SmallPrimesPow2LastNineWithoutLastThree,
|
||||||
_ => ReadOnlySpan<ulong>.Empty,
|
_ => [],
|
||||||
};
|
};
|
||||||
|
|
||||||
private static int InitializeGroupBStates(byte nMod10, Span<HeuristicGroupBSequenceState> buffer)
|
private static int InitializeGroupBStates(byte nMod10, Span<HeuristicGroupBSequenceState> buffer)
|
||||||
@@ -444,16 +435,11 @@ public sealed class HeuristicPrimeTester
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static HeuristicDivisorEnumerator CreateHeuristicDivisorEnumerator(ulong maxDivisorSquare, byte nMod10, Span<HeuristicGroupBSequenceState> groupBBuffer)
|
internal static HeuristicDivisorEnumerator CreateHeuristicDivisorEnumerator(ulong maxDivisorSquare, byte nMod10, Span<HeuristicGroupBSequenceState> groupBBuffer) => new(maxDivisorSquare, nMod10, groupBBuffer);
|
||||||
{
|
|
||||||
return new HeuristicDivisorEnumerator(maxDivisorSquare, nMod10, groupBBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static MersenneHeuristicDivisorEnumerator CreateMersenneDivisorEnumerator(ulong exponent, ulong maxDivisor)
|
internal static MersenneHeuristicDivisorEnumerator CreateMersenneDivisorEnumerator(ulong exponent, ulong maxDivisor)
|
||||||
{
|
=> new(exponent, maxDivisor);
|
||||||
return new MersenneHeuristicDivisorEnumerator(exponent, maxDivisor);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static HeuristicDivisorPreparation PrepareHeuristicDivisor(in HeuristicDivisorCandidate candidate)
|
internal static HeuristicDivisorPreparation PrepareHeuristicDivisor(in HeuristicDivisorCandidate candidate)
|
||||||
@@ -611,25 +597,18 @@ public sealed class HeuristicPrimeTester
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
internal struct HeuristicGroupBSequenceState
|
internal struct HeuristicGroupBSequenceState(byte ending, byte priorityIndex)
|
||||||
{
|
{
|
||||||
public byte Ending;
|
public byte Ending = ending;
|
||||||
public byte PriorityIndex;
|
public byte PriorityIndex = priorityIndex;
|
||||||
public int Index;
|
public int Index = 0;
|
||||||
|
|
||||||
public HeuristicGroupBSequenceState(byte ending, byte priorityIndex)
|
|
||||||
{
|
|
||||||
Ending = ending;
|
|
||||||
PriorityIndex = priorityIndex;
|
|
||||||
Index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryPeek(ulong maxDivisorSquare, out ulong divisor)
|
public bool TryPeek(ulong maxDivisorSquare, out ulong divisor)
|
||||||
{
|
{
|
||||||
ReadOnlySpan<uint> divisors = GetGroupBDivisors(Ending);
|
ReadOnlySpan<uint> divisors = GetGroupBDivisors(Ending);
|
||||||
ReadOnlySpan<ulong> squares = GetGroupBDivisorSquares(Ending);
|
ReadOnlySpan<ulong> squares = GetGroupBDivisorSquares(Ending);
|
||||||
int index = Index;
|
int index = Index;
|
||||||
if ((uint)index >= (uint)divisors.Length)
|
if (index >= divisors.Length)
|
||||||
{
|
{
|
||||||
divisor = 0UL;
|
divisor = 0UL;
|
||||||
return false;
|
return false;
|
||||||
@@ -642,7 +621,7 @@ public sealed class HeuristicPrimeTester
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
divisor = (ulong)divisors[index];
|
divisor = divisors[index];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,11 +710,11 @@ public sealed class HeuristicPrimeTester
|
|||||||
residueStepper.Advance();
|
residueStepper.Advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong ProcessedCount => processedCount;
|
public readonly ulong ProcessedCount => processedCount;
|
||||||
|
|
||||||
public ulong LastDivisor => lastDivisor;
|
public readonly ulong LastDivisor => lastDivisor;
|
||||||
|
|
||||||
public bool Exhausted => !active;
|
public readonly bool Exhausted => !active;
|
||||||
|
|
||||||
private static HeuristicDivisorCandidate CreateCandidate(ulong value)
|
private static HeuristicDivisorCandidate CreateCandidate(ulong value)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public interface IMersenneNumberDivisorByDivisorTester
|
|||||||
|
|
||||||
ulong GetAllowedMaxDivisor(ulong prime);
|
ulong GetAllowedMaxDivisor(ulong prime);
|
||||||
|
|
||||||
bool IsPrime(ulong prime, out bool divisorsExhausted);
|
bool IsPrime(ulong prime, out bool divisorsExhausted, out ulong divisor);
|
||||||
|
|
||||||
IDivisorScanSession CreateDivisorSession();
|
IDivisorScanSession CreateDivisorSession();
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public static class MersenneNumberDivisorByDivisorTester
|
|||||||
ulong startPrime,
|
ulong startPrime,
|
||||||
Action markComposite,
|
Action markComposite,
|
||||||
Action clearComposite,
|
Action clearComposite,
|
||||||
Action<ulong, bool, bool, bool> printResult,
|
Action<ulong, bool, bool, bool, ulong> printResult,
|
||||||
int threadCount,
|
int threadCount,
|
||||||
int primesPerTask)
|
int primesPerTask)
|
||||||
{
|
{
|
||||||
@@ -242,18 +242,18 @@ public static class MersenneNumberDivisorByDivisorTester
|
|||||||
void ProcessPrime(ulong prime)
|
void ProcessPrime(ulong prime)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Processing {prime}");
|
Console.WriteLine($"Processing {prime}");
|
||||||
bool isPrime = tester.IsPrime(prime, out bool divisorsExhausted);
|
bool isPrime = tester.IsPrime(prime, out bool divisorsExhausted, out ulong divisor);
|
||||||
|
|
||||||
if (!isPrime)
|
if (!isPrime)
|
||||||
{
|
{
|
||||||
markComposite();
|
markComposite();
|
||||||
printResult(prime, true, true, false);
|
printResult(prime, true, true, false, divisor);
|
||||||
Console.WriteLine($"Finished processing {prime}");
|
Console.WriteLine($"Finished processing {prime}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearComposite();
|
clearComposite();
|
||||||
printResult(prime, true, divisorsExhausted, true);
|
printResult(prime, true, divisorsExhausted, true, divisor);
|
||||||
Console.WriteLine($"Finished processing {prime}");
|
Console.WriteLine($"Finished processing {prime}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ public static class PerfectNumberConstants
|
|||||||
public const int DefaultSmallPrimeFactorSlotCount = 64;
|
public const int DefaultSmallPrimeFactorSlotCount = 64;
|
||||||
public const int DefaultSpecialMaxFactorCapacity = 1024;
|
public const int DefaultSpecialMaxFactorCapacity = 1024;
|
||||||
public const ulong ExtraDivisorCycleSearchLimit = 64UL;
|
public const ulong ExtraDivisorCycleSearchLimit = 64UL;
|
||||||
|
public const int GpuFrequency = 768 - 1;
|
||||||
public const int MaxQForDivisorCycles = 4_000_000;
|
public const int MaxQForDivisorCycles = 4_000_000;
|
||||||
public static readonly uint PrimesLimit = 1_000_000; //(ulong)Array.MaxLength;// 1_000_000;
|
public static readonly uint PrimesLimit = 1_000_000; //(ulong)Array.MaxLength;// 1_000_000;
|
||||||
public const int MaxOddPowersCount = 128;
|
public const int MaxOddPowersCount = 128;
|
||||||
|
|||||||
@@ -1177,7 +1177,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
// bool isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite);
|
// bool isPrime = HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite);
|
||||||
bool runOnGpu = RunOnGpu();
|
bool runOnGpu = RunOnGpu();
|
||||||
|
|
||||||
bool isPrime = runOnGpu ? PrimeTester.IsPrime(composite) : HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite);
|
bool isPrime = !runOnGpu ? PrimeTester.IsPrime(composite) : HeuristicCombinedPrimeTester.IsPrimeGpu(gpu, composite);
|
||||||
// bool isPrime = PrimeTester.IsPrime(composite);
|
// bool isPrime = PrimeTester.IsPrime(composite);
|
||||||
// bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite);
|
// bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite);
|
||||||
|
|
||||||
@@ -1375,19 +1375,19 @@ internal static partial class PrimeOrderCalculator
|
|||||||
|
|
||||||
private static bool RunOnGpu()
|
private static bool RunOnGpu()
|
||||||
{
|
{
|
||||||
const int GpuFrequency = 1024 - 1;
|
// return true;
|
||||||
|
int cpuCount = Atomic.Add(ref _cpuCount, 1);
|
||||||
int cpuCount = Atomic.Add(target: ref _cpuCount, 1);
|
// return (cpuCount % GpuFrequency) == 0;
|
||||||
if (cpuCount == GpuFrequency)
|
if (cpuCount == PerfectNumberConstants.GpuFrequency)
|
||||||
{
|
{
|
||||||
Atomic.Add(ref _cpuCount, -GpuFrequency);
|
Atomic.Add(ref _cpuCount, -PerfectNumberConstants.GpuFrequency);
|
||||||
}
|
}
|
||||||
else if (cpuCount > GpuFrequency)
|
else if (cpuCount > PerfectNumberConstants.GpuFrequency)
|
||||||
{
|
{
|
||||||
cpuCount -= GpuFrequency;
|
cpuCount -= PerfectNumberConstants.GpuFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cpuCount != GpuFrequency;
|
return cpuCount == PerfectNumberConstants.GpuFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void PopulateSmallPrimeFactorsCpu(
|
private static void PopulateSmallPrimeFactorsCpu(
|
||||||
|
|||||||
@@ -36,15 +36,13 @@ internal static partial class PrimeOrderCalculator
|
|||||||
|
|
||||||
ulong order = phi;
|
ulong order = phi;
|
||||||
var acceleratorIndex = gpu.AcceleratorIndex;
|
var acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
var kernel = gpu.CheckFactorsKernel;
|
|
||||||
gpu.EnsureCapacity(entryCount, 1);
|
gpu.EnsureCapacity(entryCount, 1);
|
||||||
|
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
gpu.Pow2ModEntriesToTestOnDevice.View.CopyFromCPU(stream, entries);
|
gpu.Pow2ModEntriesToTestOnDevice.View.CopyFromCPU(stream, entries);
|
||||||
|
|
||||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
|
var kernelLauncher = gpu.CheckFactorsKernelLauncher;
|
||||||
|
|
||||||
kernelLauncher(stream, entryCount, phi, gpu.Pow2ModEntriesToTestOnDevice.View, divisorData, gpu.OutputUlong.View);
|
kernelLauncher(stream, entryCount, phi, gpu.Pow2ModEntriesToTestOnDevice.View, divisorData, gpu.OutputUlong.View);
|
||||||
|
|
||||||
gpu.OutputUlong.View.CopyToCPU(stream, ref order, 1);
|
gpu.OutputUlong.View.CopyToCPU(stream, ref order, 1);
|
||||||
@@ -67,19 +65,16 @@ internal static partial class PrimeOrderCalculator
|
|||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
var accelerator = gpu.Accelerator;
|
var accelerator = gpu.Accelerator;
|
||||||
|
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
var kernelLauncher = gpu.SmallPrimeFactorKernelLauncher;
|
||||||
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
|
||||||
|
|
||||||
var kernel = gpu.SmallPrimeFactorKernel;
|
|
||||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, uint, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<int, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
|
||||||
|
|
||||||
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorCountSlotView = gpu.SmallPrimeFactorCountSlot.View;
|
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorCountSlotView = gpu.SmallPrimeFactorCountSlot.View;
|
||||||
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorRemainingSlotView = gpu.Input.View;
|
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorRemainingSlotView = gpu.Input.View;
|
||||||
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorPrimeSlotsView = gpu.OutputUlong.View;
|
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorPrimeSlotsView = gpu.OutputUlong.View;
|
||||||
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorExponentSlotsView = gpu.OutputInt.View;
|
ArrayView1D<int, Stride1D.Dense> smallPrimeFactorExponentSlotsView = gpu.OutputInt.View;
|
||||||
ArrayView1D<uint, Stride1D.Dense> smallPrimeFactorsPrimesView = gpu.SmallPrimeFactorPrimes;
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorsSquaresView = gpu.SmallPrimeFactorSquares;
|
ArrayView1D<ulong, Stride1D.Dense> smallPrimeFactorsSquaresView = gpu.SmallPrimeFactorSquares;
|
||||||
|
ArrayView1D<uint, Stride1D.Dense> smallPrimeFactorsPrimesView = gpu.SmallPrimeFactorPrimes;
|
||||||
|
|
||||||
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
|
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
kernelLauncher(
|
kernelLauncher(
|
||||||
stream,
|
stream,
|
||||||
1,
|
1,
|
||||||
@@ -136,17 +131,14 @@ internal static partial class PrimeOrderCalculator
|
|||||||
|
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
|
||||||
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> specialMaxFactorsView = gpu.Input.View;
|
ArrayView1D<ulong, Stride1D.Dense> specialMaxFactorsView = gpu.Input.View;
|
||||||
specialMaxFactorsView.SubView(0, factorCount).CopyFromCPU(stream, factors);
|
|
||||||
|
|
||||||
var kernel = gpu.SpecialMaxKernel;
|
var stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
|
specialMaxFactorsView.SubView(0, factorCount).CopyFromCPU(stream, factors);
|
||||||
|
|
||||||
ArrayView1D<ulong, Stride1D.Dense> specialMaxResultView = gpu.SpecialMaxResult.View;
|
ArrayView1D<ulong, Stride1D.Dense> specialMaxResultView = gpu.SpecialMaxResult.View;
|
||||||
|
|
||||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, ArrayView1D<ulong, Stride1D.Dense>, int, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
var kernelLauncher = gpu.SpecialMaxKernelLauncher;
|
||||||
|
|
||||||
kernelLauncher(
|
kernelLauncher(
|
||||||
stream,
|
stream,
|
||||||
1,
|
1,
|
||||||
@@ -178,7 +170,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
gpu.Input.View.CopyFromCPU(stream, randomStateSpan);
|
gpu.Input.View.CopyFromCPU(stream, randomStateSpan);
|
||||||
|
|
||||||
var kernelLauncher = gpu.PollardRhoKernel.CreateLauncherDelegate<Action<AcceleratorStream, ulong, int, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<byte, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>>();
|
var kernelLauncher = gpu.PollardRhoKernelLauncher;
|
||||||
|
|
||||||
kernelLauncher(stream, n, 1, gpu.Input.View, gpu.OutputByte.View, gpu.OutputUlong.View);
|
kernelLauncher(stream, n, 1, gpu.Input.View, gpu.OutputByte.View, gpu.OutputUlong.View);
|
||||||
|
|
||||||
|
|||||||
@@ -90,19 +90,17 @@ public sealed class PrimeTester
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool IsPrimeGpu(ulong n)
|
public static bool IsPrimeGpu(ulong n)
|
||||||
{
|
{
|
||||||
byte flag = 0;
|
|
||||||
|
|
||||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
var inputView = gpu.Input.View;
|
var inputView = gpu.Input.View;
|
||||||
var outputView = gpu.OutputByte.View;
|
var outputView = gpu.OutputByte.View;
|
||||||
var kernel = gpu.SmallPrimeSieveKernel!;
|
|
||||||
|
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
inputView.CopyFromCPU(stream, ref n, 1);
|
inputView.CopyFromCPU(stream, ref n, 1);
|
||||||
|
|
||||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>>();
|
var kernelLauncher = gpu.SmallPrimeSieveKernelLauncher;
|
||||||
|
|
||||||
kernelLauncher(
|
kernelLauncher(
|
||||||
stream,
|
stream,
|
||||||
@@ -118,6 +116,7 @@ public sealed class PrimeTester
|
|||||||
gpu.DevicePrimesPow2LastNine,
|
gpu.DevicePrimesPow2LastNine,
|
||||||
outputView);
|
outputView);
|
||||||
|
|
||||||
|
byte flag = 0;
|
||||||
outputView.CopyToCPU(stream, ref flag, 1);
|
outputView.CopyToCPU(stream, ref flag, 1);
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
@@ -136,13 +135,12 @@ public sealed class PrimeTester
|
|||||||
var inputView = input.View;
|
var inputView = input.View;
|
||||||
var output = gpu.OutputByte;
|
var output = gpu.OutputByte;
|
||||||
var outputView = output.View;
|
var outputView = output.View;
|
||||||
Kernel kernel = gpu.SmallPrimeSieveKernel!;
|
|
||||||
|
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
inputView.CopyFromCPU(stream, ref n, 1);
|
inputView.CopyFromCPU(stream, ref n, 1);
|
||||||
|
|
||||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>>();
|
var kernelLauncher = gpu.SmallPrimeSieveKernelLauncher;
|
||||||
|
|
||||||
kernelLauncher(
|
kernelLauncher(
|
||||||
stream,
|
stream,
|
||||||
@@ -196,7 +194,6 @@ public sealed class PrimeTester
|
|||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(GpuBatchSize);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(GpuBatchSize);
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
var kernel = gpu.SmallPrimeSieveKernel!;
|
|
||||||
int totalLength = values.Length;
|
int totalLength = values.Length;
|
||||||
int batchSize = GpuBatchSize;
|
int batchSize = GpuBatchSize;
|
||||||
|
|
||||||
@@ -207,7 +204,7 @@ public sealed class PrimeTester
|
|||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>>();
|
var kernelLauncher = gpu.SmallPrimeSieveKernelLauncher;
|
||||||
|
|
||||||
while (pos < totalLength)
|
while (pos < totalLength)
|
||||||
{
|
{
|
||||||
@@ -265,7 +262,7 @@ public sealed class PrimeTester
|
|||||||
// ResidueComputationBenchmarks so divisor-cycle metadata can short-circuit the test
|
// ResidueComputationBenchmarks so divisor-cycle metadata can short-circuit the test
|
||||||
// instead of recomputing binary GCD for every candidate.
|
// instead of recomputing binary GCD for every candidate.
|
||||||
ulong m = (ulong)BitOperations.Log2(n);
|
ulong m = (ulong)BitOperations.Log2(n);
|
||||||
return BinaryGcd(n, m) != 1UL;
|
return n.BinaryGcd(m) != 1UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SharesFactorWithMaxExponentBatch(ReadOnlySpan<ulong> values, Span<byte> results)
|
internal static void SharesFactorWithMaxExponentBatch(ReadOnlySpan<ulong> values, Span<byte> results)
|
||||||
@@ -280,15 +277,14 @@ public sealed class PrimeTester
|
|||||||
|
|
||||||
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
|
||||||
int acceleratorIndex = gpu.AcceleratorIndex;
|
int acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
var kernel = gpu.SharesFactorKernel;
|
|
||||||
gpu.EnsureCapacity(0, length);
|
gpu.EnsureCapacity(0, length);
|
||||||
MemoryBuffer1D<ulong, Stride1D.Dense>? inputBuffer = gpu.Input;
|
MemoryBuffer1D<ulong, Stride1D.Dense>? inputBuffer = gpu.Input;
|
||||||
MemoryBuffer1D<byte, Stride1D.Dense>? resultBuffer = gpu.OutputByte;
|
|
||||||
|
|
||||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||||
inputBuffer.View.CopyFromCPU(stream, values);
|
inputBuffer.View.CopyFromCPU(stream, values);
|
||||||
var kernelLauncher = kernel.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<byte>>>();
|
|
||||||
|
|
||||||
|
MemoryBuffer1D<byte, Stride1D.Dense>? resultBuffer = gpu.OutputByte;
|
||||||
|
var kernelLauncher = gpu.SharesFactorKernelLauncher;
|
||||||
kernelLauncher(stream, length, inputBuffer.View, resultBuffer.View);
|
kernelLauncher(stream, length, inputBuffer.View, resultBuffer.View);
|
||||||
|
|
||||||
resultBuffer.View.CopyToCPU(stream, in results);
|
resultBuffer.View.CopyToCPU(stream, in results);
|
||||||
@@ -298,39 +294,4 @@ public sealed class PrimeTester
|
|||||||
PrimeOrderCalculatorAccelerator.Return(gpu);
|
PrimeOrderCalculatorAccelerator.Return(gpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static ulong BinaryGcd(ulong u, ulong v)
|
|
||||||
{
|
|
||||||
// TODO: Swap this handwritten binary GCD for the optimized helper measured in
|
|
||||||
// GpuUInt128BinaryGcdBenchmarks so CPU callers share the faster subtract-less
|
|
||||||
// ladder once the common implementation is promoted into PerfectNumbers.Core.
|
|
||||||
// You have an example in the benchmarks and you already implemented it in
|
|
||||||
// GpuUInt128, iirc.
|
|
||||||
if (u == 0UL)
|
|
||||||
{
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v == 0UL)
|
|
||||||
{
|
|
||||||
return u;
|
|
||||||
}
|
|
||||||
|
|
||||||
int shift = BitOperations.TrailingZeroCount(u | v);
|
|
||||||
u >>= BitOperations.TrailingZeroCount(u);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
v >>= BitOperations.TrailingZeroCount(v);
|
|
||||||
if (u > v)
|
|
||||||
{
|
|
||||||
(u, v) = (v, u);
|
|
||||||
}
|
|
||||||
|
|
||||||
v -= u;
|
|
||||||
}
|
|
||||||
while (v != 0UL);
|
|
||||||
|
|
||||||
return u << shift;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user