/// <summary> /// Long-form of the kernel using existing comparison operation. /// </summary> static void UniqueKernel(Accelerator accelerator, long[] values) { Console.WriteLine("Unique Kernel"); var uniqueKernel = accelerator.CreateUnique <long, ComparisonInt64>(); using (var buffer = accelerator.Allocate1D(values)) { // Allocate buffer to hold the new length. using var newLengthBuffer = accelerator.Allocate1D <long>(Index1D.One); // Allocate buffer for temporary work area. var tempSize = accelerator.ComputeUniqueTempStorageSize <long>(buffer.Length); using var tempBuffer = accelerator.Allocate1D <int>(tempSize); uniqueKernel( accelerator.DefaultStream, buffer.View, newLengthBuffer.View, tempBuffer.View); // Reads data from the GPU buffer into a new CPU array. // Implicitly calls accelerator.DefaultStream.Synchronize() to ensure // that the kernel and memory copy are completed first. var newLengthArray = newLengthBuffer.GetAsArray1D(); var newLength = newLengthArray[0]; PrintResults(buffer.View, newLength); } Console.WriteLine(); }
/// <summary> /// Creates a kernel to remove consecutive duplicate elements in a given view. /// </summary> /// <typeparam name="T">The input view element type.</typeparam> /// <typeparam name="TComparisonOperation">The comparison operation.</typeparam> /// <param name="accelerator">The accelerator.</param> /// <returns>The created unique handler.</returns> public static Unique <T> CreateUnique <T, TComparisonOperation>( this Accelerator accelerator) where T : unmanaged where TComparisonOperation : struct, IComparisonOperation <T> { var initializer = accelerator.CreateInitializer <int, Stride1D.Dense>(); var kernel = accelerator.LoadKernel < ArrayView <T>, ArrayView <long>, SequentialGroupExecutor, SpecializedValue <int>, Index1D>( UniqueKernel <T, TComparisonOperation>); return((stream, input, output, temp) => { if (!input.IsValid) { throw new ArgumentNullException(nameof(input)); } if (!output.IsValid) { throw new ArgumentNullException(nameof(output)); } if (!temp.IsValid) { throw new ArgumentNullException(nameof(temp)); } if (output.Length < 1) { throw new ArgumentOutOfRangeException(nameof(output)); } if (temp.Length < accelerator.ComputeUniqueTempStorageSize <T>(input.Length)) { throw new ArgumentOutOfRangeException(nameof(temp)); } if (input.Length > int.MaxValue) { throw new NotSupportedException( ErrorMessages.NotSupportedArrayView64); } var viewManager = new TempViewManager(temp, nameof(temp)); var executorView = viewManager.Allocate <int>(); initializer(stream, temp.SubView(0, viewManager.NumInts), default); var(gridDim, groupDim) = accelerator.ComputeGridStrideLoopExtent( input.IntLength, out int numIterationsPerGroup); kernel( stream, (gridDim, groupDim), input, output, new SequentialGroupExecutor(executorView), new SpecializedValue <int>(groupDim * numIterationsPerGroup), numIterationsPerGroup); }); }
/// <summary> /// Removes consecutive duplicate elements in a supplied input view. /// </summary> /// <typeparam name="T">The input view element type.</typeparam> /// <typeparam name="TComparisonOperation">The comparison operation.</typeparam> /// <param name="accelerator">The accelerator.</param> /// <param name="stream">The accelerator stream.</param> /// <param name="input">The input view.</param> /// <returns>The new/valid length of the input view.</returns> public static long Unique <T, TComparisonOperation>( this Accelerator accelerator, AcceleratorStream stream, ArrayView <T> input) where T : unmanaged where TComparisonOperation : struct, IComparisonOperation <T> { using var output = accelerator.Allocate1D <long>(1); using var temp = accelerator.Allocate1D <int>( accelerator.ComputeUniqueTempStorageSize <T>(input.Length)); accelerator.CreateUnique <T, TComparisonOperation>()( stream, input, output.View, temp.View); output.View.CopyToCPU(stream, out long result, 1); return(result); }