diff --git a/PerfectNumbers.Core/Gpu/Kernels/PrimeTesterKernels.cs b/PerfectNumbers.Core/Gpu/Kernels/PrimeTesterKernels.cs index b17f7bb..5b9bf5c 100644 --- a/PerfectNumbers.Core/Gpu/Kernels/PrimeTesterKernels.cs +++ b/PerfectNumbers.Core/Gpu/Kernels/PrimeTesterKernels.cs @@ -68,18 +68,10 @@ internal static class PrimeTesterKernels results[index] = result; } - public static void HeuristicTrialDivisionKernel(Index1D index, ArrayView divisors, ulong n, ArrayView resultFlag) + public static void HeuristicTrialDivisionKernel(Index1D index, ArrayView divisors, ulong n, ArrayView resultFlag) { ulong divisor = divisors[index]; - if (divisor <= 1UL) - { - return; - } - - if (n % divisor == 0UL) - { - resultFlag[0] = 1; - } + Atomic.Or(ref resultFlag[0], divisor <= 1UL ? 0 : (n % divisor == 0UL ? 1 : 0)); } public static void SharesFactorKernel(Index1D index, ArrayView numbers, ArrayView results) diff --git a/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs b/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs index 5aea0f8..72add2f 100644 --- a/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs +++ b/PerfectNumbers.Core/HeuristicCombinedPrimeTester.cs @@ -221,16 +221,16 @@ public sealed class HeuristicCombinedPrimeTester int count = 0; var inputView = gpu.Input.View; - var outputView = gpu.Output.View; + var flagView = gpu.HeuristicFlag.View; bool ProcessBatch(int length) { inputView.CopyFromCPU(ref divisorArray[0], length); - byte compositeFlag = 0; - outputView.CopyFromCPU(ref compositeFlag, 1); - kernel(length, inputView, n, outputView); + int compositeFlag = 0; + flagView.CopyFromCPU(ref compositeFlag, 1); + kernel(length, inputView, n, flagView); accelerator.Synchronize(); - outputView.CopyToCPU(ref compositeFlag, 1); + flagView.CopyToCPU(ref compositeFlag, 1); return compositeFlag != 0; } diff --git a/PerfectNumbers.Core/HeuristicPrimeTester.cs b/PerfectNumbers.Core/HeuristicPrimeTester.cs index a2abb2f..5d91856 100644 --- a/PerfectNumbers.Core/HeuristicPrimeTester.cs +++ b/PerfectNumbers.Core/HeuristicPrimeTester.cs @@ -279,7 +279,7 @@ public sealed class HeuristicPrimeTester int count = 0; var inputView = gpu.Input.View; - var outputView = gpu.Output.View; + var flagView = gpu.HeuristicFlag.View; bool ProcessBatch(int length) { @@ -289,11 +289,11 @@ public sealed class HeuristicPrimeTester } inputView.CopyFromCPU(ref divisorArray[0], length); - byte compositeFlag = 0; - outputView.CopyFromCPU(ref compositeFlag, 1); - kernel(length, inputView, n, outputView); + int compositeFlag = 0; + flagView.CopyFromCPU(ref compositeFlag, 1); + kernel(length, inputView, n, flagView); accelerator.Synchronize(); - outputView.CopyToCPU(ref compositeFlag, 1); + flagView.CopyToCPU(ref compositeFlag, 1); return compositeFlag != 0; } diff --git a/PerfectNumbers.Core/PrimeTester.cs b/PerfectNumbers.Core/PrimeTester.cs index 3832125..f18ca71 100644 --- a/PerfectNumbers.Core/PrimeTester.cs +++ b/PerfectNumbers.Core/PrimeTester.cs @@ -272,7 +272,7 @@ public static bool IsPrimeCpu(ulong n, CancellationToken ct) internal readonly Context AcceleratorContext; public readonly Accelerator Accelerator; public readonly Action, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView> Kernel; - public readonly Action, ulong, ArrayView> HeuristicTrialDivisionKernel; + public readonly Action, ulong, ArrayView> HeuristicTrialDivisionKernel; public readonly MemoryBuffer1D DevicePrimesDefault; public readonly MemoryBuffer1D DevicePrimesLastOne; public readonly MemoryBuffer1D DevicePrimesLastSeven; @@ -285,6 +285,7 @@ public static bool IsPrimeCpu(ulong n, CancellationToken ct) public readonly MemoryBuffer1D DevicePrimesPow2LastNine; public MemoryBuffer1D Input; public MemoryBuffer1D Output; + public MemoryBuffer1D HeuristicFlag; public int BufferCapacity; internal PrimeTesterGpuContextLease(int minBufferCapacity) @@ -292,7 +293,7 @@ public static bool IsPrimeCpu(ulong n, CancellationToken ct) AcceleratorContext = Context.CreateDefault(); Accelerator = AcceleratorContext.GetPreferredDevice(false).CreateAccelerator(AcceleratorContext); Kernel = Accelerator.LoadAutoGroupedStreamKernel, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView, ArrayView>(PrimeTesterKernels.SmallPrimeSieveKernel); - HeuristicTrialDivisionKernel = Accelerator.LoadAutoGroupedStreamKernel, ulong, ArrayView>(PrimeTesterKernels.HeuristicTrialDivisionKernel); + HeuristicTrialDivisionKernel = Accelerator.LoadAutoGroupedStreamKernel, ulong, ArrayView>(PrimeTesterKernels.HeuristicTrialDivisionKernel); var primesDefault = DivisorGenerator.SmallPrimes; DevicePrimesDefault = Accelerator.Allocate1D(primesDefault.Length); @@ -337,6 +338,7 @@ public static bool IsPrimeCpu(ulong n, CancellationToken ct) BufferCapacity = minBufferCapacity < 1 ? 1 : minBufferCapacity; Input = Accelerator.Allocate1D(BufferCapacity); Output = Accelerator.Allocate1D(BufferCapacity); + HeuristicFlag = Accelerator.Allocate1D(BufferCapacity); _returned = false; } @@ -350,8 +352,10 @@ public static bool IsPrimeCpu(ulong n, CancellationToken ct) Input.Dispose(); Output.Dispose(); + HeuristicFlag.Dispose(); Input = Accelerator.Allocate1D(required); Output = Accelerator.Allocate1D(required); + HeuristicFlag = Accelerator.Allocate1D(required); BufferCapacity = required; } @@ -375,6 +379,7 @@ public static bool IsPrimeCpu(ulong n, CancellationToken ct) { Input.Dispose(); Output.Dispose(); + HeuristicFlag.Dispose(); DevicePrimesDefault.Dispose(); DevicePrimesLastOne.Dispose(); DevicePrimesLastSeven.Dispose();