public TileInfo(ArrayView <T> input, Index1 numIterationsPerGroup) { TileSize = Group.DimX * numIterationsPerGroup; StartIndex = Grid.IdxX * TileSize + Group.IdxX; EndIndex = (Grid.IdxX + Index1.One) * TileSize; MaxLength = XMath.Min(input.Length, EndIndex); }
public TileInfo(int inputLength, Index1D numIterationsPerGroup) { TileSize = Group.DimX * numIterationsPerGroup; StartIndex = Grid.IdxX * TileSize + Group.IdxX; EndIndex = (Grid.IdxX + Index1D.One) * TileSize; MaxLength = XMath.Min(inputLength, EndIndex); }
/// <summary> /// The actual unique kernel implementation. /// </summary> /// <typeparam name="T">The element type.</typeparam> /// <typeparam name="TComparisonOperation">The comparison operation.</typeparam> /// <param name="input">The input view.</param> /// <param name="output">The output view to store the new length.</param> /// <param name="sequentialGroupExecutor"> /// The sequential group executor to use. /// </param> /// <param name="tileSize">The tile size.</param> /// <param name="numIterationsPerGroup"> /// The number of iterations per group. /// </param> internal static void UniqueKernel <T, TComparisonOperation>( ArrayView <T> input, ArrayView <long> output, SequentialGroupExecutor sequentialGroupExecutor, SpecializedValue <int> tileSize, Index1D numIterationsPerGroup) where T : unmanaged where TComparisonOperation : struct, IComparisonOperation <T> { TComparisonOperation comparison = default; var isFirstGrid = Grid.IdxX == 0; var tileInfo = new TileInfo(input.IntLength, numIterationsPerGroup); // Sync groups and wait for the current one to become active sequentialGroupExecutor.Wait(); var temp = SharedMemory.Allocate <bool>(tileSize); var startIdx = Grid.ComputeGlobalIndex(Grid.IdxX, 0); for ( int i = tileInfo.StartIndex; i < tileInfo.MaxLength; i += Group.DimX) { if (Group.IsFirstThread && i == tileInfo.StartIndex && isFirstGrid) { temp[0] = true; } else { var currIdx = i; var prevIdx = Group.IsFirstThread && i == tileInfo.StartIndex ? output[0] - 1 : currIdx - 1; temp[currIdx - startIdx] = comparison.Compare(input[currIdx], input[prevIdx]) != 0; } } Group.Barrier(); if (Group.IsFirstThread) { var offset = isFirstGrid ? 0 : output[0]; var maxLength = XMath.Min(startIdx + temp.IntLength, tileInfo.MaxLength) - startIdx; for (var i = 0; i < maxLength; i++) { if (temp[i]) { input[offset++] = input[startIdx + i]; } } output[0] = offset; } MemoryFence.DeviceLevel(); Group.Barrier(); sequentialGroupExecutor.Release(); }