Merge pull request #13 from mlemanczyk/codex/check-thread-initialization-in-evenperfectbitscanner

Assign contiguous p ranges to worker threads
This commit is contained in:
Marek Lemańczyk authored and GitHub committed 2025-09-11 02:36:41 +02:00
commit 40477eca5d
1 file changed
+65 -59
+65 -59
View File
@@ -589,46 +589,40 @@ internal static class Program
} }
Console.WriteLine("Starting scan..."); Console.WriteLine("Starting scan...");
_state = ((long)currentP << 3) | (long)remainder; _state = ((long)currentP << 3) | (long)remainder;
Task[] tasks = new Task[threadCount]; Task[] tasks = new Task[threadCount];
for (int i = 0; i < threadCount; i++) for (int i = 0; i < threadCount; i++)
{ {
tasks[i] = Task.Run(() => tasks[i] = Task.Run(() =>
{ {
ulong[] buffer = new ulong[blockSize]; ulong[] buffer = new ulong[blockSize];
while (!Volatile.Read(ref _limitReached)) while (!Volatile.Read(ref _limitReached))
{ {
int count = 0; int count = ReserveBlock(buffer, blockSize);
while (count < blockSize && !Volatile.Read(ref _limitReached)) if (count == 0)
{ {
buffer[count] = ReserveNextP(); break;
count++; }
}
if (count == 0) for (int j = 0; j < count && !Volatile.Read(ref _limitReached); j++)
{ {
break; ulong p = buffer[j];
} if (useFilter && !filter.Contains(p))
{
continue;
}
else if (useFilter)
{
Console.WriteLine($"Testing {p}");
}
for (int j = 0; j < count && !Volatile.Read(ref _limitReached); j++) bool isPerfect = IsEvenPerfectCandidate(p, divisorCyclesSearchLimit, out bool searchedMersenne, out bool detailedCheck);
{ PrintResult(p, searchedMersenne, detailedCheck, isPerfect);
ulong p = buffer[j]; }
if (useFilter && !filter.Contains(p)) }
{ });
continue; }
}
else if (useFilter)
{
Console.WriteLine($"Testing {p}");
}
bool isPerfect = IsEvenPerfectCandidate(p, out bool searchedMersenne, out bool detailedCheck);
PrintResult(p, searchedMersenne, detailedCheck, isPerfect);
}
}
});
}
Task.WaitAll(tasks); Task.WaitAll(tasks);
FlushBuffer(); FlushBuffer();
@@ -742,24 +736,36 @@ internal static class Program
return $"even_perfect_bit_scan_inc-{inc}_thr-{threads}_blk-{block}_mers-{mers}_mersdev-{mersenneDevice}_ntt-{ntt}_red-{red}_primesdev-{primesDevice}_{order}_orderdev-{orderDevice}_{gcd}_{work}_gputh-{gpuPrimeThreads}_llslice-{llSlice}_scanb-{gpuScanBatch}_warm-{warmupLimit}.csv"; return $"even_perfect_bit_scan_inc-{inc}_thr-{threads}_blk-{block}_mers-{mers}_mersdev-{mersenneDevice}_ntt-{ntt}_red-{red}_primesdev-{primesDevice}_{order}_orderdev-{orderDevice}_{gcd}_{work}_gputh-{gpuPrimeThreads}_llslice-{llSlice}_scanb-{gpuScanBatch}_warm-{warmupLimit}.csv";
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe ulong ReserveNextP() private static unsafe int ReserveBlock(ulong[] buffer, int blockSize)
{ {
while (true) while (true)
{ {
long state = Volatile.Read(ref _state); long state = Volatile.Read(ref _state);
ulong current = (ulong)state >> 3; ulong current = (ulong)state >> 3;
ulong remainder = ((ulong)state) & 7UL; ulong remainder = ((ulong)state) & 7UL;
ulong next = _transformP(current, ref remainder); ulong p = current;
long newState = ((long)next << 3) | (long)remainder; int count = 0;
long original = Interlocked.CompareExchange(ref _state, newState, state); while (count < blockSize && !Volatile.Read(ref _limitReached))
if (original == state) {
{ buffer[count++] = p;
return current; p = _transformP(p, ref remainder);
} }
}
} if (count == 0)
{
return 0;
}
long newState = ((long)p << 3) | (long)remainder;
long original = Interlocked.CompareExchange(ref _state, newState, state);
if (original == state)
{
return count;
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void PrintResult(ulong currentP, bool searchedMersenne, bool detailedCheck, bool isPerfect) private static void PrintResult(ulong currentP, bool searchedMersenne, bool detailedCheck, bool isPerfect)
@@ -948,11 +954,11 @@ internal static class Program
return remainder == 1UL; return remainder == 1UL;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool IsEvenPerfectCandidate(ulong p) internal static bool IsEvenPerfectCandidate(ulong p)
{ {
return IsEvenPerfectCandidate(p, out _, out _); return IsEvenPerfectCandidate(p, 0, out _, out _);
} }
internal static bool IsEvenPerfectCandidate(ulong p, int divisorCyclesSearchLimit, out bool searchedMersenne, out bool detailedCheck) internal static bool IsEvenPerfectCandidate(ulong p, int divisorCyclesSearchLimit, out bool searchedMersenne, out bool detailedCheck)
{ {