Initial BitTree implementation added.
This commit is contained in:
1 parent
45e3455ff3
commit
d88ad25476
11 files changed
+3817
-367
No files matched your search
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -27,6 +27,10 @@ using TesterGpu = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTeste
|
||||
using TesterCpu = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForBitContradictionDivisorSetForCpuOrder;
|
||||
using TesterHybrid = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForBitContradictionDivisorSetForHybridOrder;
|
||||
using TesterGpu = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForBitContradictionDivisorSetForGpuOrder;
|
||||
#elif DivisorSet_BitTree
|
||||
using TesterCpu = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForBitTreeDivisorSetForCpuOrder;
|
||||
using TesterHybrid = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForBitTreeDivisorSetForHybridOrder;
|
||||
using TesterGpu = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForBitTreeDivisorSetForGpuOrder;
|
||||
#else
|
||||
using TesterCpu = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForSequentialDivisorSetForCpuOrder;
|
||||
using TesterHybrid = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForSequentialDivisorSetForHybridOrder;
|
||||
@@ -91,6 +95,8 @@ internal struct MersenneNumberDivisorByDivisorPrimeScanSessionWithTemplate
|
||||
extension = ".topdown";
|
||||
#elif DivisorSet_BitContradiction
|
||||
extension = ".bitcontradiction";
|
||||
#elif DivisorSet_BitTree
|
||||
extension = ".bittree";
|
||||
#endif
|
||||
string stateFile = prime.ToString(CultureInfo.InvariantCulture) + extension;
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ public sealed class PrimeOrderCalculatorAccelerator
|
||||
|
||||
private sealed class CalculatorKernels(Accelerator accelerator)
|
||||
{
|
||||
public readonly Action<AcceleratorStream, Index1D, ulong, CalculateOrderKernelConfig, ulong, ulong, ulong, ulong, ulong, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers> CalculateOrderKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, CalculateOrderKernelConfig, ulong, ulong, ulong, ulong, ulong, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers>(PrimeOrderKernels.CalculateOrderKernel)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, CalculateOrderKernelConfig, ulong, ulong, ulong, ulong, ulong, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers>>();
|
||||
// public readonly Action<AcceleratorStream, Index1D, ulong, CalculateOrderKernelConfig, ulong, ulong, ulong, ulong, ulong, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers> CalculateOrderKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, CalculateOrderKernelConfig, ulong, ulong, ulong, ulong, ulong, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers>(PrimeOrderKernels.CalculateOrderKernel)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, CalculateOrderKernelConfig, ulong, ulong, ulong, ulong, ulong, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers>>();
|
||||
|
||||
public readonly Kernel CheckFactorsKernel = KernelUtil.GetKernel(accelerator.LoadStreamKernel<int, ulong, ArrayView1D<KeyValuePair<ulong, int>, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>>(PrimeOrderKernels.CheckFactorsKernel));
|
||||
|
||||
@@ -177,7 +177,7 @@ public sealed class PrimeOrderCalculatorAccelerator
|
||||
public readonly Action<AcceleratorStream, Index1D, ulong, ArrayView<ulong>, int, ulong, ArrayView<ulong>> SpecialMaxKernelLauncher = KernelUtil.GetKernel(accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView<ulong>, int, ulong, ArrayView<ulong>>(PrimeOrderGpuHeuristics.EvaluateSpecialMaxCandidatesKernel)).CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ulong, ArrayView<ulong>, int, ulong, ArrayView<ulong>>>();
|
||||
}
|
||||
|
||||
public readonly Action<AcceleratorStream, Index1D, ulong, CalculateOrderKernelConfig, ulong, ulong, ulong, ulong, ulong, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers> CalculateOrderKernelLauncher;
|
||||
// public readonly Action<AcceleratorStream, Index1D, ulong, CalculateOrderKernelConfig, ulong, ulong, ulong, ulong, ulong, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, int, OrderKernelBuffers> CalculateOrderKernelLauncher;
|
||||
public readonly Kernel CheckFactorsKernel;
|
||||
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, ulong, ulong, ulong, ulong, ulong, ArrayView1D<ulong, Stride1D.Dense>> ConvertToStandardKernelLauncher;
|
||||
public readonly Action<AcceleratorStream, Index1D, ArrayView<int>, ulong, ulong, ArrayView<ulong>, ArrayView<ulong>> HeuristicCombinedTrialDivisionKernelLauncher;
|
||||
@@ -421,9 +421,9 @@ public sealed class PrimeOrderCalculatorAccelerator
|
||||
DevicePrimesPow2LastThree = lastDigitSharedTables.DevicePrimesPow2LastThree.View;
|
||||
DevicePrimesPow2LastNine = lastDigitSharedTables.DevicePrimesPow2LastNine.View;
|
||||
|
||||
DivisorTables = HeuristicCombinedGpuTables
|
||||
.GetStaticTables(acceleratorIndex)
|
||||
.CreateViews();
|
||||
// DivisorTables = HeuristicCombinedGpuTables
|
||||
// .GetStaticTables(acceleratorIndex)
|
||||
// .CreateViews();
|
||||
|
||||
var smallPrimeFactorTables = SmallPrimeFactorGpuTables.GetStaticTables(acceleratorIndex);
|
||||
|
||||
@@ -436,7 +436,7 @@ public sealed class PrimeOrderCalculatorAccelerator
|
||||
|
||||
var kernels = _kernels[acceleratorIndex];
|
||||
|
||||
CalculateOrderKernelLauncher = kernels.CalculateOrderKernelLauncher;
|
||||
// CalculateOrderKernelLauncher = kernels.CalculateOrderKernelLauncher;
|
||||
CheckFactorsKernel = kernels.CheckFactorsKernel;
|
||||
ConvertToStandardKernelLauncher = kernels.ConvertToStandardKernelLauncher;
|
||||
HeuristicCombinedTrialDivisionKernelLauncher = kernels.HeuristicCombinedTrialDivisionKernelLauncher;
|
||||
|
||||
@@ -272,27 +272,27 @@ internal static partial class PrimeOrderGpuHeuristics
|
||||
var kernelConfig = new CalculateOrderKernelConfig(previousValue, hasPrevious, limit, config.MaxPowChecks, config.StrictMode);
|
||||
ref var buffers = ref gpu.CalculateOrderKernelBuffers;
|
||||
|
||||
var kernelLauncher = gpu.CalculateOrderKernelLauncher;
|
||||
// var kernelLauncher = gpu.CalculateOrderKernelLauncher;
|
||||
|
||||
AcceleratorStream stream = AcceleratorStreamPool.Rent(acceleratorIndex);
|
||||
// TODO: Remove the cleaning after the order kernel is modified to always set the result.
|
||||
resultBufferView.MemSetToZero(stream);
|
||||
statusBufferView.MemSetToZero(stream);
|
||||
|
||||
kernelLauncher(
|
||||
stream,
|
||||
1,
|
||||
prime,
|
||||
kernelConfig,
|
||||
divisorData.Modulus,
|
||||
divisorData.NPrime,
|
||||
divisorData.MontgomeryOne,
|
||||
divisorData.MontgomeryTwo,
|
||||
divisorData.MontgomeryTwoSquared,
|
||||
smallPrimesView,
|
||||
smallSquaresView,
|
||||
(int)smallPrimesView.Length,
|
||||
buffers);
|
||||
// kernelLauncher(
|
||||
// stream,
|
||||
// 1,
|
||||
// prime,
|
||||
// kernelConfig,
|
||||
// divisorData.Modulus,
|
||||
// divisorData.NPrime,
|
||||
// divisorData.MontgomeryOne,
|
||||
// divisorData.MontgomeryTwo,
|
||||
// divisorData.MontgomeryTwoSquared,
|
||||
// smallPrimesView,
|
||||
// smallSquaresView,
|
||||
// (int)smallPrimesView.Length,
|
||||
// buffers);
|
||||
|
||||
|
||||
byte status = 0;
|
||||
|
||||
@@ -21,6 +21,9 @@ using MersenneNumberDivisorByDivisorCpuTesterWithAdditiveGpuOrder = PerfectNumbe
|
||||
using MersenneNumberDivisorByDivisorCpuTesterWithBitContradictionCpuOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForBitContradictionDivisorSetForCpuOrder;
|
||||
using MersenneNumberDivisorByDivisorCpuTesterWithBitContradictionHybridOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForBitContradictionDivisorSetForHybridOrder;
|
||||
using MersenneNumberDivisorByDivisorCpuTesterWithBitContradictionGpuOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForBitContradictionDivisorSetForGpuOrder;
|
||||
using MersenneNumberDivisorByDivisorCpuTesterWithBitTreeCpuOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForBitTreeDivisorSetForCpuOrder;
|
||||
using MersenneNumberDivisorByDivisorCpuTesterWithBitTreeHybridOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForBitTreeDivisorSetForHybridOrder;
|
||||
using MersenneNumberDivisorByDivisorCpuTesterWithBitTreeGpuOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForBitTreeDivisorSetForGpuOrder;
|
||||
|
||||
namespace PerfectNumbers.Core;
|
||||
|
||||
@@ -88,6 +91,37 @@ public static class MersenneNumberDivisorByDivisorTester
|
||||
Action<ulong, bool, bool, bool, BigInteger> pr) =>
|
||||
RunBitContradictionCpuOrderFiltered(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void Run(
|
||||
List<ulong> candidates,
|
||||
ref MersenneNumberDivisorByDivisorCpuTesterWithBitTreeCpuOrder tester,
|
||||
Dictionary<ulong, (bool DetailedCheck, bool PassedAllTests)>? previousResults,
|
||||
ulong startPrime,
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult,
|
||||
int threadCount,
|
||||
int primesPerTask)
|
||||
=> RunStructTester(
|
||||
candidates,
|
||||
ref tester,
|
||||
previousResults,
|
||||
startPrime,
|
||||
markComposite,
|
||||
clearComposite,
|
||||
printResult,
|
||||
threadCount,
|
||||
primesPerTask,
|
||||
static (
|
||||
List<ulong> filteredPrimes,
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithBitTreeCpuOrder prototype,
|
||||
int workerCount,
|
||||
int partitionSize,
|
||||
Action mc,
|
||||
Action cc,
|
||||
Action<ulong, bool, bool, bool, BigInteger> pr) =>
|
||||
RunBitTreeCpuOrderFiltered(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void Run(
|
||||
List<ulong> candidates,
|
||||
@@ -243,6 +277,37 @@ public static class MersenneNumberDivisorByDivisorTester
|
||||
Action<ulong, bool, bool, bool, BigInteger> pr) =>
|
||||
RunBitContradictionHybridOrderFiltered(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void Run(
|
||||
List<ulong> candidates,
|
||||
ref MersenneNumberDivisorByDivisorCpuTesterWithBitTreeHybridOrder tester,
|
||||
Dictionary<ulong, (bool DetailedCheck, bool PassedAllTests)>? previousResults,
|
||||
ulong startPrime,
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult,
|
||||
int threadCount,
|
||||
int primesPerTask)
|
||||
=> RunStructTester(
|
||||
candidates,
|
||||
ref tester,
|
||||
previousResults,
|
||||
startPrime,
|
||||
markComposite,
|
||||
clearComposite,
|
||||
printResult,
|
||||
threadCount,
|
||||
primesPerTask,
|
||||
static (
|
||||
List<ulong> filteredPrimes,
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithBitTreeHybridOrder prototype,
|
||||
int workerCount,
|
||||
int partitionSize,
|
||||
Action mc,
|
||||
Action cc,
|
||||
Action<ulong, bool, bool, bool, BigInteger> pr) =>
|
||||
RunBitTreeHybridOrderFiltered(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void Run(
|
||||
List<ulong> candidates,
|
||||
@@ -398,6 +463,37 @@ public static class MersenneNumberDivisorByDivisorTester
|
||||
Action<ulong, bool, bool, bool, BigInteger> pr) =>
|
||||
RunBitContradictionGpuOrderFiltered(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void Run(
|
||||
List<ulong> candidates,
|
||||
ref MersenneNumberDivisorByDivisorCpuTesterWithBitTreeGpuOrder tester,
|
||||
Dictionary<ulong, (bool DetailedCheck, bool PassedAllTests)>? previousResults,
|
||||
ulong startPrime,
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult,
|
||||
int threadCount,
|
||||
int primesPerTask)
|
||||
=> RunStructTester(
|
||||
candidates,
|
||||
ref tester,
|
||||
previousResults,
|
||||
startPrime,
|
||||
markComposite,
|
||||
clearComposite,
|
||||
printResult,
|
||||
threadCount,
|
||||
primesPerTask,
|
||||
static (
|
||||
List<ulong> filteredPrimes,
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithBitTreeGpuOrder prototype,
|
||||
int workerCount,
|
||||
int partitionSize,
|
||||
Action mc,
|
||||
Action cc,
|
||||
Action<ulong, bool, bool, bool, BigInteger> pr) =>
|
||||
RunBitTreeGpuOrderFiltered(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void Run(
|
||||
List<ulong> candidates,
|
||||
@@ -2575,6 +2671,150 @@ public static class MersenneNumberDivisorByDivisorTester
|
||||
}));
|
||||
}
|
||||
|
||||
private static void RunBitTreeCpuOrderFiltered(
|
||||
List<ulong> filteredPrimes,
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithBitTreeCpuOrder prototype,
|
||||
int workerCount,
|
||||
int partitionSize,
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult)
|
||||
{
|
||||
MersenneNumberDivisorByDivisorCpuTesterWithBitTreeCpuOrder prototypeCopy = prototype;
|
||||
int totalCount = filteredPrimes.Count;
|
||||
if (partitionSize > totalCount)
|
||||
{
|
||||
partitionSize = totalCount;
|
||||
}
|
||||
|
||||
if (workerCount <= 1 || totalCount <= partitionSize)
|
||||
{
|
||||
var session = new Cpu.MersenneNumberDivisorByDivisorPrimeScanSessionWithForBitTreeDivisorSetForCpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
for (int i = 0; i < totalCount; i++)
|
||||
{
|
||||
session.ProcessPrime(filteredPrimes[i]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var options = new ParallelOptions
|
||||
{
|
||||
MaxDegreeOfParallelism = workerCount,
|
||||
};
|
||||
|
||||
Parallel.For(
|
||||
0,
|
||||
(int)Math.Ceiling((double)totalCount / partitionSize),
|
||||
options,
|
||||
new Action<int>(partitionIndex =>
|
||||
{
|
||||
int startIndex = partitionIndex * partitionSize;
|
||||
int count = Math.Min(partitionSize, totalCount - startIndex);
|
||||
var session = new Cpu.MersenneNumberDivisorByDivisorPrimeScanSessionWithForBitTreeDivisorSetForCpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
session.ProcessPrime(filteredPrimes[startIndex + i]);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private static void RunBitTreeHybridOrderFiltered(
|
||||
List<ulong> filteredPrimes,
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithBitTreeHybridOrder prototype,
|
||||
int workerCount,
|
||||
int partitionSize,
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult)
|
||||
{
|
||||
MersenneNumberDivisorByDivisorCpuTesterWithBitTreeHybridOrder prototypeCopy = prototype;
|
||||
int totalCount = filteredPrimes.Count;
|
||||
if (partitionSize > totalCount)
|
||||
{
|
||||
partitionSize = totalCount;
|
||||
}
|
||||
|
||||
if (workerCount <= 1 || totalCount <= partitionSize)
|
||||
{
|
||||
var session = new Cpu.MersenneNumberDivisorByDivisorPrimeScanSessionWithForBitTreeDivisorSetForHybridOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
for (int i = 0; i < totalCount; i++)
|
||||
{
|
||||
session.ProcessPrime(filteredPrimes[i]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var options = new ParallelOptions
|
||||
{
|
||||
MaxDegreeOfParallelism = workerCount,
|
||||
};
|
||||
|
||||
Parallel.For(
|
||||
0,
|
||||
(int)Math.Ceiling((double)totalCount / partitionSize),
|
||||
options,
|
||||
new Action<int>(partitionIndex =>
|
||||
{
|
||||
int startIndex = partitionIndex * partitionSize;
|
||||
int count = Math.Min(partitionSize, totalCount - startIndex);
|
||||
var session = new Cpu.MersenneNumberDivisorByDivisorPrimeScanSessionWithForBitTreeDivisorSetForHybridOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
session.ProcessPrime(filteredPrimes[startIndex + i]);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private static void RunBitTreeGpuOrderFiltered(
|
||||
List<ulong> filteredPrimes,
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithBitTreeGpuOrder prototype,
|
||||
int workerCount,
|
||||
int partitionSize,
|
||||
Action markComposite,
|
||||
Action clearComposite,
|
||||
Action<ulong, bool, bool, bool, BigInteger> printResult)
|
||||
{
|
||||
MersenneNumberDivisorByDivisorCpuTesterWithBitTreeGpuOrder prototypeCopy = prototype;
|
||||
int totalCount = filteredPrimes.Count;
|
||||
if (partitionSize > totalCount)
|
||||
{
|
||||
partitionSize = totalCount;
|
||||
}
|
||||
|
||||
if (workerCount <= 1 || totalCount <= partitionSize)
|
||||
{
|
||||
var session = new Cpu.MersenneNumberDivisorByDivisorPrimeScanSessionWithForBitTreeDivisorSetForGpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
for (int i = 0; i < totalCount; i++)
|
||||
{
|
||||
session.ProcessPrime(filteredPrimes[i]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var options = new ParallelOptions
|
||||
{
|
||||
MaxDegreeOfParallelism = workerCount,
|
||||
};
|
||||
|
||||
Parallel.For(
|
||||
0,
|
||||
(int)Math.Ceiling((double)totalCount / partitionSize),
|
||||
options,
|
||||
new Action<int>(partitionIndex =>
|
||||
{
|
||||
int startIndex = partitionIndex * partitionSize;
|
||||
int count = Math.Min(partitionSize, totalCount - startIndex);
|
||||
var session = new Cpu.MersenneNumberDivisorByDivisorPrimeScanSessionWithForBitTreeDivisorSetForGpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
session.ProcessPrime(filteredPrimes[startIndex + i]);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private static void RunBitContradictionHybridOrderFiltered(
|
||||
List<ulong> filteredPrimes,
|
||||
in MersenneNumberDivisorByDivisorCpuTesterWithBitContradictionHybridOrder prototype,
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using FASTER.core;
|
||||
|
||||
namespace PerfectNumbers.Core.Persistence;
|
||||
|
||||
/// <summary>
|
||||
/// Stores BitTree frontier batches using Microsoft.FASTER.Core.
|
||||
/// Each batch is a byte[] payload containing a sequence of serialized states.
|
||||
/// Maintains a simple head/tail cursor stored inside the KV store.
|
||||
/// </summary>
|
||||
public sealed class BitTreeFrontierRepository : IDisposable
|
||||
{
|
||||
private readonly FasterKV<string, byte[]> _store;
|
||||
private readonly IDevice _logDevice;
|
||||
private readonly IDevice _objectLogDevice;
|
||||
private long _headIndex;
|
||||
private long _tailIndex;
|
||||
private const string HeadKey = "__head__";
|
||||
private const string TailKey = "__tail__";
|
||||
|
||||
public string DatabasePath { get; }
|
||||
|
||||
public static BitTreeFrontierRepository Open(string directory, string repositoryFileName = "bittree.frontier.faster")
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
string dbPath = Path.Combine(directory, repositoryFileName);
|
||||
return new BitTreeFrontierRepository(dbPath);
|
||||
}
|
||||
|
||||
private BitTreeFrontierRepository(string path)
|
||||
{
|
||||
DatabasePath = path;
|
||||
_logDevice = Devices.CreateLogDevice(path + ".log");
|
||||
_objectLogDevice = Devices.CreateLogDevice(path + ".obj.log");
|
||||
_store = new FasterKV<string, byte[]>(
|
||||
1L << 20,
|
||||
new LogSettings
|
||||
{
|
||||
LogDevice = _logDevice,
|
||||
ObjectLogDevice = _objectLogDevice,
|
||||
});
|
||||
|
||||
LoadCursors();
|
||||
}
|
||||
|
||||
public void AppendBatch(ReadOnlySpan<byte> batch)
|
||||
{
|
||||
using var session = _store.For(new SimpleFunctions<string, byte[]>()).NewSession<SimpleFunctions<string, byte[]>>();
|
||||
string key = BuildChunkKey(_tailIndex);
|
||||
session.Upsert(key, batch.ToArray());
|
||||
_tailIndex++;
|
||||
PersistCursors(session);
|
||||
session.CompletePending(true);
|
||||
_store.Log.FlushAndEvict(true);
|
||||
}
|
||||
|
||||
public bool TryDequeueBatch(int maxCount, out List<byte[]> batches)
|
||||
{
|
||||
batches = new List<byte[]>();
|
||||
using var session = _store.For(new SimpleFunctions<string, byte[]>()).NewSession<SimpleFunctions<string, byte[]>>();
|
||||
|
||||
while (_headIndex < _tailIndex && batches.Count < maxCount)
|
||||
{
|
||||
string key = BuildChunkKey(_headIndex);
|
||||
if (session.Read(key, out byte[]? stored).Found && stored is not null)
|
||||
{
|
||||
batches.Add(stored);
|
||||
session.Delete(key);
|
||||
}
|
||||
|
||||
_headIndex++;
|
||||
}
|
||||
|
||||
|
||||
if (batches.Count > 0)
|
||||
{
|
||||
PersistCursors(session);
|
||||
session.CompletePending(true);
|
||||
_store.Log.FlushAndEvict(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
session.CompletePending(true);
|
||||
_store.Log.FlushAndEvict(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_store.Dispose();
|
||||
_logDevice.Dispose();
|
||||
_objectLogDevice.Dispose();
|
||||
}
|
||||
|
||||
private void LoadCursors()
|
||||
{
|
||||
using var session = _store.For(new SimpleFunctions<string, byte[]>()).NewSession<SimpleFunctions<string, byte[]>>();
|
||||
_headIndex = ReadCursor(session, HeadKey);
|
||||
_tailIndex = ReadCursor(session, TailKey);
|
||||
session.CompletePending(true);
|
||||
}
|
||||
|
||||
private static long ReadCursor(ClientSession<string, byte[], byte[], byte[], Empty, SimpleFunctions<string, byte[]>> session, string key)
|
||||
{
|
||||
if (session.Read(key, out byte[]? stored).Found && stored is not null)
|
||||
{
|
||||
string text = Encoding.UTF8.GetString(stored);
|
||||
if (long.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out long value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void PersistCursors(ClientSession<string, byte[], byte[], byte[], Empty, SimpleFunctions<string, byte[]>> session)
|
||||
{
|
||||
session.Upsert(HeadKey, Encoding.UTF8.GetBytes(_headIndex.ToString(CultureInfo.InvariantCulture)));
|
||||
session.Upsert(TailKey, Encoding.UTF8.GetBytes(_tailIndex.ToString(CultureInfo.InvariantCulture)));
|
||||
}
|
||||
|
||||
private static string BuildChunkKey(long index) => $"chunk-{index}";
|
||||
}
|
||||
Reference in new issue
Block a user