Small primes array type changed to uint[] to avoid excessive memory use, especially on GPU
This commit is contained in:
1 parent
dafdc3d6b6
commit
2be49020a9
6 files changed
+29
-56
No files matched your search
@@ -12,9 +12,9 @@ public class PrimesGeneratorTests
|
|||||||
var primes = PrimesGenerator.SmallPrimes;
|
var primes = PrimesGenerator.SmallPrimes;
|
||||||
var squares = PrimesGenerator.SmallPrimesPow2;
|
var squares = PrimesGenerator.SmallPrimesPow2;
|
||||||
|
|
||||||
primes[..5].Should().Equal(new ulong[] { 2UL, 3UL, 5UL, 7UL, 11UL });
|
primes[..5].Should().Equal([2, 3, 5, 7, 11]);
|
||||||
|
|
||||||
squares[..5].Should().Equal(new ulong[] { 4UL, 9UL, 25UL, 49UL, 121UL });
|
squares[..5].Should().Equal([4UL, 9UL, 25UL, 49UL, 121UL]);
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++)
|
for (int i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ namespace PerfectNumbers.Core;
|
|||||||
public static class PerfectNumberConstants
|
public static class PerfectNumberConstants
|
||||||
{
|
{
|
||||||
public const ulong BiggestKnownEvenPerfectP = 136279841UL;
|
public const ulong BiggestKnownEvenPerfectP = 136279841UL;
|
||||||
public static readonly ulong PrimesLimit = 1_000_000; //(ulong)Array.MaxLength;// 1_000_000;
|
public static readonly uint PrimesLimit = 1_000_000; //(ulong)Array.MaxLength;// 1_000_000;
|
||||||
|
|
||||||
// Maximum K for residue-based Mersenne test (q = 2*p*k + 1 up to this k)
|
// Maximum K for residue-based Mersenne test (q = 2*p*k + 1 up to this k)
|
||||||
public static readonly UInt128 ResidueMaxK = 5_000_000UL;
|
public static readonly UInt128 ResidueMaxK = 5_000_000UL;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public sealed class PrimeTester(bool useInternal = false)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var smallPrimeDivisorsLength = PrimesGenerator.SmallPrimes.Length;
|
var smallPrimeDivisorsLength = PrimesGenerator.SmallPrimes.Length;
|
||||||
ulong[] smallPrimeDivisors = PrimesGenerator.SmallPrimes;
|
uint[] smallPrimeDivisors = PrimesGenerator.SmallPrimes;
|
||||||
ulong[] smallPrimeDivisorsMul = PrimesGenerator.SmallPrimesPow2;
|
ulong[] smallPrimeDivisorsMul = PrimesGenerator.SmallPrimesPow2;
|
||||||
for (int i = 0; i < smallPrimeDivisorsLength; i++)
|
for (int i = 0; i < smallPrimeDivisorsLength; i++)
|
||||||
{
|
{
|
||||||
@@ -128,8 +128,8 @@ public sealed class PrimeTester(bool useInternal = false)
|
|||||||
// Per-accelerator GPU state for prime sieve (kernel + uploaded primes).
|
// Per-accelerator GPU state for prime sieve (kernel + uploaded primes).
|
||||||
private sealed class KernelState
|
private sealed class KernelState
|
||||||
{
|
{
|
||||||
public Action<Index1D, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>> Kernel { get; }
|
public Action<Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<byte>> Kernel { get; }
|
||||||
public MemoryBuffer1D<ulong, Stride1D.Dense> DevicePrimes { get; }
|
public MemoryBuffer1D<uint, Stride1D.Dense> DevicePrimes { get; }
|
||||||
private readonly Accelerator _accel;
|
private readonly Accelerator _accel;
|
||||||
private readonly System.Collections.Concurrent.ConcurrentBag<ScratchBuffers> _scratchPool = new();
|
private readonly System.Collections.Concurrent.ConcurrentBag<ScratchBuffers> _scratchPool = new();
|
||||||
|
|
||||||
@@ -137,10 +137,10 @@ public sealed class PrimeTester(bool useInternal = false)
|
|||||||
{
|
{
|
||||||
_accel = accelerator;
|
_accel = accelerator;
|
||||||
// Compile once per accelerator and upload primes once.
|
// Compile once per accelerator and upload primes once.
|
||||||
Kernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>(SmallPrimeSieveKernel);
|
Kernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<byte>>(SmallPrimeSieveKernel);
|
||||||
|
|
||||||
var primes = PrimesGenerator.SmallPrimes;
|
var primes = PrimesGenerator.SmallPrimes;
|
||||||
DevicePrimes = accelerator.Allocate1D<ulong>(primes.Length);
|
DevicePrimes = accelerator.Allocate1D<uint>(primes.Length);
|
||||||
DevicePrimes.View.CopyFromCPU(primes);
|
DevicePrimes.View.CopyFromCPU(primes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,7 +232,7 @@ public sealed class PrimeTester(bool useInternal = false)
|
|||||||
|
|
||||||
// GPU kernel: small-prime sieve only. Returns 1 if passes sieve (probable prime), 0 otherwise.
|
// GPU kernel: small-prime sieve only. Returns 1 if passes sieve (probable prime), 0 otherwise.
|
||||||
// TODO: Follow-up: consider integration with MR rounds for bases {2,3,5,7,11,13} to make it deterministic for 64-bit.
|
// TODO: Follow-up: consider integration with MR rounds for bases {2,3,5,7,11,13} to make it deterministic for 64-bit.
|
||||||
private static void SmallPrimeSieveKernel(Index1D index, ArrayView<ulong> numbers, ArrayView<ulong> smallPrimes, ArrayView<byte> results)
|
private static void SmallPrimeSieveKernel(Index1D index, ArrayView<ulong> numbers, ArrayView<uint> smallPrimes, ArrayView<byte> results)
|
||||||
{
|
{
|
||||||
ulong n = numbers[index];
|
ulong n = numbers[index];
|
||||||
if (n <= 3UL)
|
if (n <= 3UL)
|
||||||
@@ -256,9 +256,9 @@ public sealed class PrimeTester(bool useInternal = false)
|
|||||||
}
|
}
|
||||||
|
|
||||||
long len = smallPrimes.Length;
|
long len = smallPrimes.Length;
|
||||||
for (long i = 0; i < len; i++)
|
for (int i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
ulong p = smallPrimes[(int)i];
|
ulong p = smallPrimes[i];
|
||||||
if (p * p > n)
|
if (p * p > n)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -2,18 +2,14 @@ namespace PerfectNumbers.Core;
|
|||||||
|
|
||||||
public static class PrimesGenerator
|
public static class PrimesGenerator
|
||||||
{
|
{
|
||||||
private static ulong[]? _primes;
|
private static uint[]? _primes;
|
||||||
private static ulong[]? _primesPow2;
|
private static ulong[]? _primesPow2;
|
||||||
// private static UInt128[]? _primes128;
|
|
||||||
// private static UInt128[]? _primesPow2_128;
|
|
||||||
|
|
||||||
public static readonly ulong[] SmallPrimes = BuildSmallPrimesInternal();
|
public static readonly uint[] SmallPrimes = BuildSmallPrimesInternal();
|
||||||
public static readonly ulong[] SmallPrimesPow2 = BuildSmallPrimesPow2Internal();
|
public static readonly ulong[] SmallPrimesPow2 = BuildSmallPrimesPow2Internal();
|
||||||
// public static readonly UInt128[] SmallPrimes128 = BuildSmallPrimes128Internal();
|
|
||||||
// public static readonly UInt128[] SmallPrimesPow2_128 = BuildSmallPrimesPow2_128Internal();
|
|
||||||
|
|
||||||
|
|
||||||
private static ulong[] BuildSmallPrimesInternal()
|
private static uint[] BuildSmallPrimesInternal()
|
||||||
{
|
{
|
||||||
if (_primes == null)
|
if (_primes == null)
|
||||||
{
|
{
|
||||||
@@ -33,43 +29,23 @@ public static class PrimesGenerator
|
|||||||
return _primesPow2!;
|
return _primesPow2!;
|
||||||
}
|
}
|
||||||
|
|
||||||
// private static UInt128[] BuildSmallPrimes128Internal()
|
|
||||||
// {
|
|
||||||
// if (_primes == null)
|
|
||||||
// {
|
|
||||||
// BuildSmallPrimes();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return _primes128!;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private static UInt128[] BuildSmallPrimesPow2_128Internal()
|
|
||||||
// {
|
|
||||||
// if (_primesPow2 == null)
|
|
||||||
// {
|
|
||||||
// BuildSmallPrimes();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return _primesPow2_128!;
|
|
||||||
// }
|
|
||||||
|
|
||||||
private static void BuildSmallPrimes()
|
private static void BuildSmallPrimes()
|
||||||
{
|
{
|
||||||
ulong limit = PerfectNumberConstants.PrimesLimit;
|
uint limit = PerfectNumberConstants.PrimesLimit;
|
||||||
var primes = new ulong[limit];
|
var primes = new uint[limit];
|
||||||
primes[0] = 2UL;
|
primes[0] = 2;
|
||||||
var primesPow2 = new ulong[limit];
|
var primesPow2 = new ulong[limit];
|
||||||
primesPow2[0] = 4UL;
|
primesPow2[0] = 4;
|
||||||
|
|
||||||
int j;
|
int j;
|
||||||
ulong i = 3UL, p, sqrt;
|
uint i = 3, p, sqrt;
|
||||||
bool isPrime;
|
bool isPrime;
|
||||||
int primeIndex = 1;
|
int primeIndex = 1;
|
||||||
|
|
||||||
for (; i <= limit; i += 2UL)
|
for (; i <= limit; i += 2)
|
||||||
{
|
{
|
||||||
isPrime = true;
|
isPrime = true;
|
||||||
sqrt = (ulong)Math.Sqrt(i);
|
sqrt = (uint)Math.Sqrt(i);
|
||||||
for (j = 0; j < primeIndex; j++)
|
for (j = 0; j < primeIndex; j++)
|
||||||
{
|
{
|
||||||
p = primes[j];
|
p = primes[j];
|
||||||
@@ -98,8 +74,6 @@ public static class PrimesGenerator
|
|||||||
|
|
||||||
_primes = primes;
|
_primes = primes;
|
||||||
_primesPow2 = primesPow2;
|
_primesPow2 = primesPow2;
|
||||||
// _primes128 = Array.ConvertAll(_primes, p => (UInt128)p);
|
|
||||||
// _primesPow2_128 = Array.ConvertAll(_primesPow2, p => (UInt128)p);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ public static class UInt128Extensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
ulong order = (ulong)phi;
|
ulong order = (ulong)phi;
|
||||||
ulong[] smallPrimes = PrimesGenerator.SmallPrimes,
|
uint[] smallPrimes = PrimesGenerator.SmallPrimes;
|
||||||
smallPrimesPow2 = PrimesGenerator.SmallPrimesPow2;
|
ulong[] smallPrimesPow2 = PrimesGenerator.SmallPrimesPow2;
|
||||||
|
|
||||||
int i = 0, primesLength = smallPrimes.Length;
|
int i = 0, primesLength = smallPrimes.Length;
|
||||||
UInt128 cycle = MersenneDivisorCycles.GetCycle(q);
|
UInt128 cycle = MersenneDivisorCycles.GetCycle(q);
|
||||||
@@ -100,7 +100,7 @@ public static class UInt128Extensions
|
|||||||
{
|
{
|
||||||
UInt128 p, zero = UInt128.Zero;
|
UInt128 p, zero = UInt128.Zero;
|
||||||
|
|
||||||
ulong[] smallPrimes = PrimesGenerator.SmallPrimes;
|
uint[] smallPrimes = PrimesGenerator.SmallPrimes;
|
||||||
ulong[] smallPrimesPow2 = PrimesGenerator.SmallPrimesPow2;
|
ulong[] smallPrimesPow2 = PrimesGenerator.SmallPrimesPow2;
|
||||||
ulong i, smallPrimesCount = (ulong)smallPrimes.Length;
|
ulong i, smallPrimesCount = (ulong)smallPrimes.Length;
|
||||||
for (i = 0UL; i < smallPrimesCount; i++)
|
for (i = 0UL; i < smallPrimesCount; i++)
|
||||||
|
|||||||
@@ -12,23 +12,22 @@ public static class ULongExtensions
|
|||||||
return 0UL;
|
return 0UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong order = q - 1UL;
|
ulong order = q - 1UL, prime, temp;
|
||||||
ulong[] smallPrimes = PrimesGenerator.SmallPrimes;
|
uint[] smallPrimes = PrimesGenerator.SmallPrimes;
|
||||||
ulong[] smallPrimesPow2 = PrimesGenerator.SmallPrimesPow2;
|
ulong[] smallPrimesPow2 = PrimesGenerator.SmallPrimesPow2;
|
||||||
|
|
||||||
int i = 0, primesLength = smallPrimes.Length;
|
int i = 0, primesLength = smallPrimes.Length;
|
||||||
ulong prime, temp;
|
|
||||||
UInt128 q128 = q,
|
UInt128 q128 = q,
|
||||||
cycle = MersenneDivisorCycles.GetCycle(q128);
|
cycle = MersenneDivisorCycles.GetCycle(q128);
|
||||||
|
|
||||||
for (; i < primesLength; i++)
|
for (; i < primesLength; i++)
|
||||||
{
|
{
|
||||||
prime = smallPrimes[i];
|
|
||||||
if (smallPrimesPow2[i] > order)
|
if (smallPrimesPow2[i] > order)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prime = smallPrimes[i];
|
||||||
while (order % prime == 0UL)
|
while (order % prime == 0UL)
|
||||||
{
|
{
|
||||||
temp = order / prime;
|
temp = order / prime;
|
||||||
@@ -63,7 +62,7 @@ public static class ULongExtensions
|
|||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
ulong p;
|
ulong p;
|
||||||
ulong[] smallPrimes = PrimesGenerator.SmallPrimes;
|
uint[] smallPrimes = PrimesGenerator.SmallPrimes;
|
||||||
ulong[] smallPrimesPow2 = PrimesGenerator.SmallPrimesPow2;
|
ulong[] smallPrimesPow2 = PrimesGenerator.SmallPrimesPow2;
|
||||||
int len = smallPrimes.Length;
|
int len = smallPrimes.Length;
|
||||||
for (; i < len; i++)
|
for (; i < len; i++)
|
||||||
@@ -388,7 +387,7 @@ public static class ULongExtensions
|
|||||||
{
|
{
|
||||||
ulong value = exponent - 1UL;
|
ulong value = exponent - 1UL;
|
||||||
value >>= BitOperations.TrailingZeroCount(value);
|
value >>= BitOperations.TrailingZeroCount(value);
|
||||||
ulong[] smallPrimes = PrimesGenerator.SmallPrimes;
|
uint[] smallPrimes = PrimesGenerator.SmallPrimes;
|
||||||
ulong[] smallPrimesPow2 = PrimesGenerator.SmallPrimesPow2;
|
ulong[] smallPrimesPow2 = PrimesGenerator.SmallPrimesPow2;
|
||||||
int i = 1, smallPrimesLength = smallPrimes.Length;
|
int i = 1, smallPrimesLength = smallPrimes.Length;
|
||||||
ulong prime;
|
ulong prime;
|
||||||
|
|||||||
Reference in new issue
Block a user