Merge pull request #71 from mlemanczyk/codex/review-changes-in-mersennenumberdivisorbydivisorgputester.cs

Fix Mod10 shortcut and restore Mod10_8_5_3Steps accuracy
This commit is contained in:
Marek Lemańczyk authored and GitHub committed 2025-09-24 00:32:29 +02:00
commit c1ad705a4a
2 files changed
+91 -88

No files matched your search

@@ -335,84 +335,83 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
MersenneDivisorCycles? divisorCycles = useCycles ? MersenneDivisorCycles.Shared : null; MersenneDivisorCycles? divisorCycles = useCycles ? MersenneDivisorCycles.Shared : null;
ulong cycle = useCycles ? divisorCycles!.GetCycle(divisor) : 0UL, primeValue; ulong cycle = useCycles ? divisorCycles!.GetCycle(divisor) : 0UL, primeValue;
MontgomeryDivisorData divisorData = CreateMontgomeryDivisorData(divisor); MontgomeryDivisorData divisorData = CreateMontgomeryDivisorData(divisor);
Span<ulong> primeSpan = primesHost.AsSpan(0, gpuBatchSize); Span<ulong> primeSpan = Span<ulong>.Empty;
ref ulong primesSpanRef = ref MemoryMarshal.GetReference(primeSpan); Span<int> indexSpan = Span<int>.Empty;
Span<int> indexSpan = indexHost.AsSpan(0, gpuBatchSize); Span<byte> hitSpan = Span<byte>.Empty;
Span<byte> hitsSlice, hitSpan = hitsHost.AsSpan(0, gpuBatchSize); Span<byte> hitsSlice;
ref byte hitSpanRef = ref MemoryMarshal.GetReference(hitSpan); int batchSize, currentSpanSize = -1, gpuCount, i, primesLength = primes.Length;
int batchSize, currentSpanSize = gpuBatchSize, gpuCount, i, primesLength = primes.Length;
while (offset < primesLength) while (offset < primesLength)
{ {
batchSize = Math.Min(gpuBatchSize, primesLength - offset); batchSize = Math.Min(gpuBatchSize, primesLength - offset);
if (batchSize != currentSpanSize) ReadOnlySpan<ulong> primesSlice = primes.Slice(offset, batchSize);
{
primeSpan = primesHost.AsSpan(0, batchSize);
primesSpanRef = ref MemoryMarshal.GetReference(primeSpan);
indexSpan = indexHost.AsSpan(0, batchSize);
hitSpan = hitsHost.AsSpan(0, batchSize);
hitSpanRef = ref MemoryMarshal.GetReference(hitSpan);
currentSpanSize = batchSize;
}
// We benefit from the constructor, because CopyTo will be called as static function if (++consoleStatus == PerfectNumberConstants.ConsoleInterval)
primes.Slice(offset, batchSize).CopyTo(primeSpan); {
Console.WriteLine($"...processed by-divisor candidate = {primesSlice[0]}");
consoleStatus = 0;
}
if (++consoleStatus == PerfectNumberConstants.ConsoleInterval) hitsSlice = hits.Slice(offset, batchSize);
{
Console.WriteLine($"...processed by-divisor candidate = {primes[0]}");
consoleStatus = 0;
}
hitsSlice = hits.Slice(offset, batchSize); if (useCycles)
gpuCount = 0; {
if (batchSize != currentSpanSize)
{
primeSpan = primesHost.AsSpan(0, batchSize);
indexSpan = indexHost.AsSpan(0, batchSize);
hitSpan = hitsHost.AsSpan(0, batchSize);
currentSpanSize = batchSize;
}
if (useCycles) ref ulong primesSpanRef = ref MemoryMarshal.GetReference(primeSpan);
{ ref byte hitSpanRef = ref MemoryMarshal.GetReference(hitSpan);
for (i = 0; i < batchSize; i++) gpuCount = 0;
{
primeValue = primeSpan[i];
if (cycle == 0UL || primeValue % cycle != 0UL)
{
hitsSlice[i] = 0;
continue;
}
indexSpan[gpuCount] = i; for (i = 0; i < batchSize; i++)
primeSpan[gpuCount] = primeValue; {
gpuCount++; primeValue = primesSlice[i];
} if (cycle == 0UL || primeValue % cycle != 0UL)
{
hitsSlice[i] = 0;
continue;
}
if (gpuCount > 0) indexSpan[gpuCount] = i;
{ primeSpan[gpuCount] = primeValue;
primesView = primesBufferView.SubView(0, gpuCount); gpuCount++;
hitsView = hitsBufferView.SubView(0, gpuCount); }
primesView.CopyFromCPU(ref primesSpanRef, gpuCount); if (gpuCount > 0)
kernel(gpuCount, divisorData, primesView, hitsView); {
accelerator.Synchronize(); primesView = primesBufferView.SubView(0, gpuCount);
hitsView = hitsBufferView.SubView(0, gpuCount);
hitsView.CopyToCPU(ref hitSpanRef, gpuCount); primesView.CopyFromCPU(ref primesSpanRef, gpuCount);
for (i = 0; i < gpuCount; i++) kernel(gpuCount, divisorData, primesView, hitsView);
{ accelerator.Synchronize();
hitsSlice[indexSpan[i]] = hitSpan[i];
}
}
}
else
{
primesView = primesBufferView.SubView(0, batchSize);
hitsView = hitsBufferView.SubView(0, batchSize);
primesView.CopyFromCPU(ref primesSpanRef, batchSize); hitsView.CopyToCPU(ref hitSpanRef, gpuCount);
kernel(batchSize, divisorData, primesView, hitsView); for (i = 0; i < gpuCount; i++)
accelerator.Synchronize(); {
hitsSlice[indexSpan[i]] = hitSpan[i];
}
}
}
else
{
primesView = primesBufferView.SubView(0, batchSize);
hitsView = hitsBufferView.SubView(0, batchSize);
hitsView.CopyToCPU(ref MemoryMarshal.GetReference(hitSpan), batchSize); ref ulong primesSliceRef = ref MemoryMarshal.GetReference(primesSlice);
hitSpan.CopyTo(hitsSlice); primesView.CopyFromCPU(ref primesSliceRef, batchSize);
} kernel(batchSize, divisorData, primesView, hitsView);
accelerator.Synchronize();
offset += batchSize; hitsView.CopyToCPU(ref MemoryMarshal.GetReference(hitsSlice), batchSize);
}
offset += batchSize;
} }
} }
+28 -24
View File
@@ -85,23 +85,27 @@ public static class ULongExtensions
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Mod10(this ulong value) => (value & 1UL) == 0UL public static ulong Mod10(this ulong value)
? value % 5UL switch {
{ ulong mod5 = value % 5UL;
0UL => 0UL, return (value & 1UL) == 0UL
1UL => 6UL, ? mod5 switch
2UL => 2UL, {
3UL => 8UL, 0UL => 0UL,
_ => 4UL, 1UL => 6UL,
} 2UL => 2UL,
: value % 5UL switch 3UL => 8UL,
{ _ => 4UL,
0UL => 5UL, }
1UL => 1UL, : mod5 switch
2UL => 7UL, {
3UL => 3UL, 0UL => 5UL,
_ => 9UL, 1UL => 1UL,
}; 2UL => 7UL,
3UL => 3UL,
_ => 9UL,
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Mod128(this ulong value) => value & 127UL; public static ulong Mod128(this ulong value) => value & 127UL;
@@ -143,14 +147,14 @@ public static class ULongExtensions
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Mod10_8_5_3Steps(this ulong value, out ulong step10, out ulong step8, out ulong step5, out ulong step3) public static void Mod10_8_5_3Steps(this ulong value, out ulong step10, out ulong step8, out ulong step5, out ulong step3)
{ {
value.Mod10_8_5_3(out step10, out step8, out step5, out step3); value.Mod10_8_5_3(out step10, out step8, out step5, out step3);
step10 = (step10 << 1).Mod10(); step10 = (step10 << 1).Mod10();
step8 = (step8 << 1) & 7UL; step8 = (step8 << 1) & 7UL;
step5 = (step5 << 1) % 5UL; step5 = (step5 << 1) % 5UL;
step3 = (step3 << 1) % 3UL; step3 = (step3 << 1) % 3UL;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]