Optimizations. Unnecessary variables removed.
This commit is contained in:
1 parent
15bc2686cc
commit
01bb731220
1 file changed
+140
-149
@@ -98,6 +98,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
|
|||||||
|
|
||||||
private bool CheckDivisors(ulong prime, ulong allowedMax, out ulong lastProcessed, out bool coveredRange)
|
private bool CheckDivisors(ulong prime, ulong allowedMax, out ulong lastProcessed, out bool coveredRange)
|
||||||
{
|
{
|
||||||
|
// TODO: We should be able to calculate allowedMax outside in the parent method, unless it depends from some changing value.
|
||||||
allowedMax = Math.Min(allowedMax, _divisorLimit);
|
allowedMax = Math.Min(allowedMax, _divisorLimit);
|
||||||
lastProcessed = 0UL;
|
lastProcessed = 0UL;
|
||||||
|
|
||||||
@@ -107,126 +108,126 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Rent these in the parent method before the loops - batch size doesn't change
|
||||||
var gpuLease = GpuContextPool.RentPreferred(preferCpu: false);
|
var gpuLease = GpuContextPool.RentPreferred(preferCpu: false);
|
||||||
var accelerator = gpuLease.Accelerator;
|
var accelerator = gpuLease.Accelerator;
|
||||||
var kernel = GetKernel(accelerator);
|
var kernel = GetKernel(accelerator);
|
||||||
|
|
||||||
int batchCapacity = _gpuBatchSize;
|
int batchCapacity = _gpuBatchSize;
|
||||||
|
// TODO: Rent buffers in the parent method before the loops - batch size doesn't change
|
||||||
var divisorsBuffer = accelerator.Allocate1D<MontgomeryDivisorData>(batchCapacity);
|
var divisorsBuffer = accelerator.Allocate1D<MontgomeryDivisorData>(batchCapacity);
|
||||||
var hitsBuffer = accelerator.Allocate1D<byte>(batchCapacity);
|
var hitsBuffer = accelerator.Allocate1D<byte>(batchCapacity);
|
||||||
|
|
||||||
ulong[] divisors = ArrayPool<ulong>.Shared.Rent(batchCapacity);
|
ulong[] divisors = ArrayPool<ulong>.Shared.Rent(batchCapacity);
|
||||||
byte[] hits = ArrayPool<byte>.Shared.Rent(batchCapacity);
|
byte[] hits = ArrayPool<byte>.Shared.Rent(batchCapacity);
|
||||||
MontgomeryDivisorData[] divisorData = ArrayPool<MontgomeryDivisorData>.Shared.Rent(batchCapacity);
|
MontgomeryDivisorData[] divisorData = ArrayPool<MontgomeryDivisorData>.Shared.Rent(batchCapacity);
|
||||||
|
|
||||||
bool composite = false;
|
bool composite = false;
|
||||||
bool processedAll = false;
|
bool processedAll = false;
|
||||||
ulong divisor = 3UL;
|
ulong cycle, divisor = 3UL, next;
|
||||||
|
int batchSize, i;
|
||||||
|
bool reachedEndInBatch, useCycles = _useDivisorCycles;
|
||||||
|
|
||||||
try
|
Span<MontgomeryDivisorData> divisorDataSpan;
|
||||||
|
Span<ulong> divisorSpan;
|
||||||
|
Span<byte> hitsSpan;
|
||||||
|
MersenneDivisorCycles divisorCycles = MersenneDivisorCycles.Shared;
|
||||||
|
ArrayView1D<MontgomeryDivisorData, Stride1D.Dense> divisorView;
|
||||||
|
ArrayView1D<byte, Stride1D.Dense> hitsView;
|
||||||
|
|
||||||
|
while (divisor <= allowedMax)
|
||||||
{
|
{
|
||||||
bool useCycles = _useDivisorCycles;
|
batchSize = 0;
|
||||||
MersenneDivisorCycles? divisorCycles = useCycles ? MersenneDivisorCycles.Shared : null;
|
reachedEndInBatch = false;
|
||||||
while (divisor <= allowedMax)
|
|
||||||
|
while (batchSize < batchCapacity && divisor <= allowedMax)
|
||||||
{
|
{
|
||||||
int batchSize = 0;
|
if (useCycles)
|
||||||
bool reachedEndInBatch = false;
|
|
||||||
|
|
||||||
while (batchSize < batchCapacity && divisor <= allowedMax)
|
|
||||||
{
|
{
|
||||||
ulong current = divisor;
|
cycle = divisorCycles!.GetCycle(divisor);
|
||||||
ulong next = current + 2UL;
|
if (cycle == 0UL || prime % cycle != 0UL)
|
||||||
bool include = true;
|
|
||||||
if (useCycles)
|
|
||||||
{
|
{
|
||||||
ulong cycle = divisorCycles!.GetCycle(current);
|
ReportStatus(divisor);
|
||||||
if (cycle == 0UL || prime % cycle != 0UL)
|
|
||||||
{
|
|
||||||
include = false;
|
|
||||||
lastProcessed = current;
|
|
||||||
ReportStatus(lastProcessed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (include)
|
|
||||||
{
|
{
|
||||||
divisors[batchSize++] = current;
|
divisors[batchSize++] = divisor;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
divisors[batchSize++] = divisor;
|
||||||
|
}
|
||||||
|
|
||||||
if (next <= current)
|
next = divisor + 2UL;
|
||||||
{
|
if (next <= divisor)
|
||||||
reachedEndInBatch = true;
|
{
|
||||||
break;
|
reachedEndInBatch = true;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
if (next > allowedMax)
|
|
||||||
{
|
|
||||||
divisor = next;
|
|
||||||
reachedEndInBatch = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (next > allowedMax)
|
||||||
|
{
|
||||||
divisor = next;
|
divisor = next;
|
||||||
}
|
reachedEndInBatch = true;
|
||||||
|
|
||||||
if (batchSize == 0)
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Span<MontgomeryDivisorData> divisorDataSpan = divisorData.AsSpan(0, batchSize);
|
divisor = next;
|
||||||
var divisorView = divisorsBuffer.View.SubView(0, batchSize);
|
}
|
||||||
var hitsView = hitsBuffer.View.SubView(0, batchSize);
|
|
||||||
|
|
||||||
Span<ulong> divisorSpan = divisors.AsSpan(0, batchSize);
|
if (batchSize == 0)
|
||||||
Span<byte> hitsSpan = hits.AsSpan(0, batchSize);
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < batchSize; i++)
|
divisorDataSpan = divisorData.AsSpan(0, batchSize);
|
||||||
|
divisorView = divisorsBuffer.View.SubView(0, batchSize);
|
||||||
|
hitsView = hitsBuffer.View.SubView(0, batchSize);
|
||||||
|
|
||||||
|
divisorSpan = divisors.AsSpan(0, batchSize);
|
||||||
|
hitsSpan = hits.AsSpan(0, batchSize);
|
||||||
|
|
||||||
|
for (i = 0; i < batchSize; i++)
|
||||||
|
{
|
||||||
|
divisorDataSpan[i] = CreateMontgomeryDivisorData(divisorSpan[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
divisorView.CopyFromCPU(ref MemoryMarshal.GetReference(divisorDataSpan), batchSize);
|
||||||
|
kernel(batchSize, prime, divisorView, hitsView);
|
||||||
|
accelerator.Synchronize();
|
||||||
|
hitsView.CopyToCPU(ref MemoryMarshal.GetReference(hitsSpan), batchSize);
|
||||||
|
|
||||||
|
for (i = 0; i < batchSize; i++)
|
||||||
|
{
|
||||||
|
if (hitsSpan[i] != 0)
|
||||||
{
|
{
|
||||||
divisorDataSpan[i] = CreateMontgomeryDivisorData(divisorSpan[i]);
|
composite = true;
|
||||||
}
|
|
||||||
|
|
||||||
divisorView.CopyFromCPU(ref MemoryMarshal.GetReference(divisorDataSpan), batchSize);
|
|
||||||
kernel(batchSize, prime, divisorView, hitsView);
|
|
||||||
accelerator.Synchronize();
|
|
||||||
|
|
||||||
hitsView.CopyToCPU(ref MemoryMarshal.GetReference(hitsSpan), batchSize);
|
|
||||||
|
|
||||||
for (int i = 0; i < batchSize; i++)
|
|
||||||
{
|
|
||||||
lastProcessed = divisorSpan[i];
|
|
||||||
if (hitsSpan[i] != 0)
|
|
||||||
{
|
|
||||||
composite = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReportStatus(lastProcessed);
|
|
||||||
if (composite)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reachedEndInBatch)
|
|
||||||
{
|
|
||||||
processedAll = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
coveredRange = composite || processedAll || divisor > allowedMax;
|
ReportStatus(divisorSpan[i < batchSize ? i : i - 1]);
|
||||||
}
|
if (composite)
|
||||||
finally
|
{
|
||||||
{
|
break;
|
||||||
ArrayPool<byte>.Shared.Return(hits, clearArray: true);
|
}
|
||||||
ArrayPool<ulong>.Shared.Return(divisors, clearArray: true);
|
|
||||||
ArrayPool<MontgomeryDivisorData>.Shared.Return(divisorData, clearArray: true);
|
if (reachedEndInBatch)
|
||||||
hitsBuffer.Dispose();
|
{
|
||||||
divisorsBuffer.Dispose();
|
processedAll = true;
|
||||||
gpuLease.Dispose();
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
coveredRange = composite || processedAll || divisor > allowedMax;
|
||||||
|
|
||||||
|
ArrayPool<byte>.Shared.Return(hits, clearArray: true);
|
||||||
|
ArrayPool<ulong>.Shared.Return(divisors, clearArray: true);
|
||||||
|
ArrayPool<MontgomeryDivisorData>.Shared.Return(divisorData, clearArray: true);
|
||||||
|
hitsBuffer.Dispose();
|
||||||
|
divisorsBuffer.Dispose();
|
||||||
|
gpuLease.Dispose();
|
||||||
|
|
||||||
return composite;
|
return composite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,7 +318,6 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
|
|||||||
}
|
}
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int consoleStatus = 0;
|
|
||||||
MersenneNumberDivisorByDivisorGpuTester owner = _owner;
|
MersenneNumberDivisorByDivisorGpuTester owner = _owner;
|
||||||
int gpuBatchSize = owner._gpuBatchSize;
|
int gpuBatchSize = owner._gpuBatchSize;
|
||||||
bool useCycles = owner._useDivisorCycles;
|
bool useCycles = owner._useDivisorCycles;
|
||||||
@@ -335,83 +335,74 @@ 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 = Span<ulong>.Empty;
|
Span<ulong> primeSpan = [];
|
||||||
Span<int> indexSpan = Span<int>.Empty;
|
ReadOnlySpan<ulong> primesSlice;
|
||||||
Span<byte> hitSpan = Span<byte>.Empty;
|
Span<int> indexSpan = [];
|
||||||
Span<byte> hitsSlice;
|
Span<byte> hitSpan = [];
|
||||||
int batchSize, currentSpanSize = -1, gpuCount, i, primesLength = primes.Length;
|
Span<byte> hitsSlice;
|
||||||
|
int batchSize, currentSpanSize = -1, gpuCount, i, primesLength = primes.Length;
|
||||||
|
|
||||||
while (offset < primesLength)
|
while (offset < primesLength)
|
||||||
{
|
{
|
||||||
batchSize = Math.Min(gpuBatchSize, primesLength - offset);
|
batchSize = Math.Min(gpuBatchSize, primesLength - offset);
|
||||||
ReadOnlySpan<ulong> primesSlice = primes.Slice(offset, batchSize);
|
primesSlice = primes.Slice(offset, batchSize);
|
||||||
|
hitsSlice = hits.Slice(offset, batchSize);
|
||||||
|
|
||||||
if (++consoleStatus == PerfectNumberConstants.ConsoleInterval)
|
if (useCycles)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"...processed by-divisor candidate = {primesSlice[0]}");
|
if (batchSize != currentSpanSize)
|
||||||
consoleStatus = 0;
|
{
|
||||||
}
|
primeSpan = primesHost.AsSpan(0, batchSize);
|
||||||
|
indexSpan = indexHost.AsSpan(0, batchSize);
|
||||||
|
hitSpan = hitsHost.AsSpan(0, batchSize);
|
||||||
|
currentSpanSize = batchSize;
|
||||||
|
}
|
||||||
|
|
||||||
hitsSlice = hits.Slice(offset, batchSize);
|
gpuCount = 0;
|
||||||
|
|
||||||
if (useCycles)
|
for (i = 0; i < batchSize; i++)
|
||||||
{
|
{
|
||||||
if (batchSize != currentSpanSize)
|
primeValue = primesSlice[i];
|
||||||
{
|
if (cycle == 0UL || primeValue % cycle != 0UL)
|
||||||
primeSpan = primesHost.AsSpan(0, batchSize);
|
{
|
||||||
indexSpan = indexHost.AsSpan(0, batchSize);
|
hitsSlice[i] = 0;
|
||||||
hitSpan = hitsHost.AsSpan(0, batchSize);
|
continue;
|
||||||
currentSpanSize = batchSize;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ref ulong primesSpanRef = ref MemoryMarshal.GetReference(primeSpan);
|
indexSpan[gpuCount] = i;
|
||||||
ref byte hitSpanRef = ref MemoryMarshal.GetReference(hitSpan);
|
primeSpan[gpuCount] = primeValue;
|
||||||
gpuCount = 0;
|
gpuCount++;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < batchSize; i++)
|
if (gpuCount > 0)
|
||||||
{
|
{
|
||||||
primeValue = primesSlice[i];
|
primesView = primesBufferView.SubView(0, gpuCount);
|
||||||
if (cycle == 0UL || primeValue % cycle != 0UL)
|
hitsView = hitsBufferView.SubView(0, gpuCount);
|
||||||
{
|
|
||||||
hitsSlice[i] = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
indexSpan[gpuCount] = i;
|
primesView.CopyFromCPU(ref MemoryMarshal.GetReference(primeSpan), gpuCount);
|
||||||
primeSpan[gpuCount] = primeValue;
|
kernel(gpuCount, divisorData, primesView, hitsView);
|
||||||
gpuCount++;
|
accelerator.Synchronize();
|
||||||
}
|
|
||||||
|
|
||||||
if (gpuCount > 0)
|
hitsView.CopyToCPU(ref MemoryMarshal.GetReference(hitSpan), gpuCount);
|
||||||
{
|
for (i = 0; i < gpuCount; i++)
|
||||||
primesView = primesBufferView.SubView(0, gpuCount);
|
{
|
||||||
hitsView = hitsBufferView.SubView(0, gpuCount);
|
hitsSlice[indexSpan[i]] = hitSpan[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
primesView = primesBufferView.SubView(0, batchSize);
|
||||||
|
hitsView = hitsBufferView.SubView(0, batchSize);
|
||||||
|
|
||||||
primesView.CopyFromCPU(ref primesSpanRef, gpuCount);
|
primesView.CopyFromCPU(ref MemoryMarshal.GetReference(primesSlice), batchSize);
|
||||||
kernel(gpuCount, divisorData, primesView, hitsView);
|
kernel(batchSize, divisorData, primesView, hitsView);
|
||||||
accelerator.Synchronize();
|
accelerator.Synchronize();
|
||||||
|
|
||||||
hitsView.CopyToCPU(ref hitSpanRef, gpuCount);
|
hitsView.CopyToCPU(ref MemoryMarshal.GetReference(hitsSlice), batchSize);
|
||||||
for (i = 0; i < gpuCount; i++)
|
}
|
||||||
{
|
|
||||||
hitsSlice[indexSpan[i]] = hitSpan[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
primesView = primesBufferView.SubView(0, batchSize);
|
|
||||||
hitsView = hitsBufferView.SubView(0, batchSize);
|
|
||||||
|
|
||||||
ref ulong primesSliceRef = ref MemoryMarshal.GetReference(primesSlice);
|
offset += batchSize;
|
||||||
primesView.CopyFromCPU(ref primesSliceRef, batchSize);
|
|
||||||
kernel(batchSize, divisorData, primesView, hitsView);
|
|
||||||
accelerator.Synchronize();
|
|
||||||
|
|
||||||
hitsView.CopyToCPU(ref MemoryMarshal.GetReference(hitsSlice), batchSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += batchSize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user