Example #1
0
 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);
 }
Example #2
0
 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);
 }
Example #3
0
        /// <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();
        }