Merge pull request #46 from mlemanczyk/codex/investigate-evenperfectbitscanner-calculation-errors
Harden GPU divisor scan buffer handling
This commit is contained in:
1 file changed
+20
-10
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using ILGPU;
|
using ILGPU;
|
||||||
@@ -31,7 +32,7 @@ public sealed class MersenneNumberDivisorGpuTester
|
|||||||
list[count++] = ((ulong)i, cycle);
|
list[count++] = ((ulong)i, cycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
_divisorCandidates = list[..count].ToArray();
|
_divisorCandidates = count == 0 ? Array.Empty<(ulong divisor, uint cycle)>() : list[..count].ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsDivisible(ulong exponent, UInt128 divisor)
|
public bool IsDivisible(ulong exponent, UInt128 divisor)
|
||||||
@@ -40,14 +41,20 @@ public sealed class MersenneNumberDivisorGpuTester
|
|||||||
var accelerator = gpu.Accelerator;
|
var accelerator = gpu.Accelerator;
|
||||||
var kernel = GetKernel(accelerator);
|
var kernel = GetKernel(accelerator);
|
||||||
var resultBuffer = _resultBuffers.GetOrAdd(accelerator, acc => acc.Allocate1D<byte>(1));
|
var resultBuffer = _resultBuffers.GetOrAdd(accelerator, acc => acc.Allocate1D<byte>(1));
|
||||||
|
resultBuffer.MemSetToZero();
|
||||||
kernel(1, exponent, (GpuUInt128)divisor, resultBuffer.View);
|
kernel(1, exponent, (GpuUInt128)divisor, resultBuffer.View);
|
||||||
accelerator.Synchronize();
|
accelerator.Synchronize();
|
||||||
bool divisible = resultBuffer.GetAsArray1D()[0] != 0;
|
Span<byte> result = stackalloc byte[1];
|
||||||
|
resultBuffer.View.CopyToCPU(ref result[0], 1);
|
||||||
|
bool divisible = result[0] != 0;
|
||||||
|
result[0] = 0;
|
||||||
|
resultBuffer.View.CopyFromCPU(ref result[0], 1);
|
||||||
|
accelerator.Synchronize();
|
||||||
gpu.Dispose();
|
gpu.Dispose();
|
||||||
return divisible;
|
return divisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (ulong divisor, uint cycle)[]? _divisorCandidates;
|
private static (ulong divisor, uint cycle)[]? _divisorCandidates = Array.Empty<(ulong divisor, uint cycle)>();
|
||||||
|
|
||||||
public bool IsPrime(ulong p, UInt128 d, ulong divisorCyclesSearchLimit, out bool divisorsExhausted)
|
public bool IsPrime(ulong p, UInt128 d, ulong divisorCyclesSearchLimit, out bool divisorsExhausted)
|
||||||
{
|
{
|
||||||
@@ -63,11 +70,11 @@ public sealed class MersenneNumberDivisorGpuTester
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var candidates = _divisorCandidates!;
|
if (_divisorCandidates is { Length: > 0 } candidates)
|
||||||
int k, len = candidates.Length;
|
{
|
||||||
|
int len = candidates.Length;
|
||||||
uint cycle;
|
uint cycle;
|
||||||
|
for (int k = 0; k < len; k++)
|
||||||
for (k = 0; k < len; k++)
|
|
||||||
{
|
{
|
||||||
(ulong dSmall, cycle) = candidates[k];
|
(ulong dSmall, cycle) = candidates[k];
|
||||||
if (p % cycle != 0UL)
|
if (p % cycle != 0UL)
|
||||||
@@ -81,6 +88,7 @@ public sealed class MersenneNumberDivisorGpuTester
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UInt128 kMul2;
|
UInt128 kMul2;
|
||||||
var divisorCycles = MersenneDivisorCycles.Shared;
|
var divisorCycles = MersenneDivisorCycles.Shared;
|
||||||
@@ -149,10 +157,12 @@ public sealed class MersenneNumberDivisorGpuTester
|
|||||||
baseVal = new GpuUInt128(0UL, 1UL << x);
|
baseVal = new GpuUInt128(0UL, 1UL << x);
|
||||||
}
|
}
|
||||||
|
|
||||||
baseVal.ModPow(exponent / ux, mod);
|
GpuUInt128 pow = baseVal;
|
||||||
|
pow.ModPow(exponent / ux, mod);
|
||||||
var part2 = GpuUInt128.Pow2Mod(exponent % ux, mod);
|
var part2 = GpuUInt128.Pow2Mod(exponent % ux, mod);
|
||||||
baseVal.MulMod(part2, mod);
|
GpuUInt128 product = pow;
|
||||||
result[0] = baseVal.High == 0UL && baseVal.Low == 1UL ? (byte)1 : (byte)0;
|
product.MulMod(part2, mod);
|
||||||
|
result[0] = product.High == 0UL && product.Low == 1UL ? (byte)1 : (byte)0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user