Files
even-perfect-numbers-scanner/PerfectNumbers.Core/Gpu/Accelerators/Pow2MontgomeryAccelerator.cs
T

75 lines
2.7 KiB
C#

using System.Runtime.CompilerServices;
using ILGPU;
using ILGPU.Runtime;
using PerfectNumbers.Core.Gpu.Kernels;
namespace PerfectNumbers.Core.Gpu.Accelerators;
public sealed class Pow2MontgomeryAccelerator
{
#region Pool
[ThreadStatic]
private static Queue<Pow2MontgomeryAccelerator>? _pool;
private static AcceleratorPool _accelerators = new(PerfectNumberConstants.RollingAccelerators);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Pow2MontgomeryAccelerator Rent()
{
var pool = _pool ??= [];
if (!pool.TryDequeue(out var gpu))
{
Accelerator accelerator = _accelerators.Rent();
gpu = new(accelerator);
}
return gpu;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Return(Pow2MontgomeryAccelerator gpu)
{
gpu.Stream!.Dispose();
gpu.Stream = null;
_pool!.Enqueue(gpu);
}
#endregion
public readonly Accelerator Accelerator;
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> Input;
public readonly MemoryBuffer1D<ulong, Stride1D.Dense> Output;
public AcceleratorStream? Stream;
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>> ConvertToStandardKernel;
public readonly Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>> KeepMontgomeryKernel;
public Pow2MontgomeryAccelerator(Accelerator accelerator)
{
Accelerator = accelerator;
Input = accelerator.Allocate1D<ulong>(1);
Output = accelerator.Allocate1D<ulong>(1);
Stream = accelerator.CreateStream();
var keepKernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelKeepMontgomery);
var keepLauncher = KernelUtil.GetKernel(keepKernel);
KeepMontgomeryKernel = keepLauncher.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
var convertKernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>(Pow2MontgomeryKernels.Pow2MontgomeryKernelConvertToStandard);
var convertLauncher = KernelUtil.GetKernel(convertKernel);
ConvertToStandardKernel = convertLauncher.CreateLauncherDelegate<Action<AcceleratorStream, Index1D, ArrayView1D<ulong, Stride1D.Dense>, MontgomeryDivisorData, ArrayView1D<ulong, Stride1D.Dense>>>();
}
public void Dispose()
{
Input.Dispose();
Output.Dispose();
Stream?.Dispose();
// Accelerator is shared with other threads
// Accelerator.Dispose();
}
}