Example #1
0
        /// <summary>
        /// Creates a kernel to calculate the histogram on a supplied view
        /// (without overflow checking).
        /// </summary>
        /// <typeparam name="T">The input view element type.</typeparam>
        /// <typeparam name="TStride">The input view stride.</typeparam>
        /// <typeparam name="TBinType">The histogram bin type.</typeparam>
        /// <typeparam name="TIncrementor">
        /// The operation to increment the value of the bin.
        /// </typeparam>
        /// <typeparam name="TLocator">
        /// The operation to compute the bin location.
        /// </typeparam>
        /// <param name="accelerator">The accelerator.</param>
        /// <returns>The created histogram handler.</returns>
        public static HistogramUnchecked <T, TStride, TBinType> CreateHistogramUnchecked <
            T,
            TStride,
            TBinType,
            TIncrementor,
            TLocator>(
            this Accelerator accelerator)
            where T : unmanaged
            where TStride : unmanaged, IStride1D
            where TBinType : unmanaged
            where TIncrementor : struct, IIncrementOperation <TBinType>
            where TLocator : struct, IComputeMultiBinOperation <T, TBinType, TIncrementor>
        {
            var kernel = accelerator.LoadKernel <
                HistogramUncheckedDelegate <
                    T,
                    TStride,
                    TBinType,
                    TIncrementor,
                    TLocator> >(
                HistogramUncheckedKernelMethod.MakeGenericMethod(
                    typeof(T),
                    typeof(TStride),
                    typeof(TBinType),
                    typeof(TIncrementor),
                    typeof(TLocator)));

            return((stream, view, histogram) =>
            {
                if (!view.IsValid)
                {
                    throw new ArgumentNullException(nameof(view));
                }
                if (view.Length < 1)
                {
                    throw new ArgumentOutOfRangeException(nameof(view));
                }
                if (!histogram.IsValid)
                {
                    throw new ArgumentNullException(nameof(histogram));
                }
                if (histogram.Length < 1)
                {
                    throw new ArgumentOutOfRangeException(nameof(histogram));
                }
                if (view.Length > int.MaxValue || histogram.Length > int.MaxValue)
                {
                    throw new NotSupportedException(
                        ErrorMessages.NotSupportedArrayView64);
                }
                int numElements = view.IntExtent;
                var(gridDim, groupDim) = accelerator.ComputeGridStrideLoopExtent(
                    numElements,
                    out int numIterationsPerGroup);
                int lengthInformation =
                    XMath.DivRoundUp(numElements, groupDim) * groupDim;

                kernel(
                    stream,
                    (gridDim, groupDim),
                    view,
                    histogram,
                    lengthInformation);
            });
        }
Example #2
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();
        }
Example #3
0
        /// <summary>
        /// Creates a kernel to calculate the histogram on a supplied view.
        /// </summary>
        /// <typeparam name="T">The input view element type.</typeparam>
        /// <typeparam name="TIndex">The input view index type.</typeparam>
        /// <typeparam name="TBinType">The histogram bin type.</typeparam>
        /// <typeparam name="TIncrementor">
        /// The operation to increment the value of the bin.
        /// </typeparam>
        /// <typeparam name="TLocator">
        /// The operation to compute the bin location.
        /// </typeparam>
        /// <param name="accelerator">The accelerator.</param>
        /// <returns>The created histogram handler.</returns>
        public static Histogram <T, TIndex, TBinType> CreateHistogram <
            T,
            TIndex,
            TBinType,
            TIncrementor,
            TLocator>(
            this Accelerator accelerator)
            where T : unmanaged
            where TIndex : unmanaged, IIndex, IGenericIndex <TIndex>
            where TBinType : unmanaged
            where TIncrementor : struct, IIncrementOperation <TBinType>
            where TLocator : struct, IComputeMultiBinOperation <T, TBinType, TIncrementor>
        {
            var kernel = accelerator.LoadKernel <
                HistogramDelegate <
                    T,
                    TBinType,
                    TIncrementor,
                    TLocator> >(
                HistogramKernelMethod.MakeGenericMethod(
                    typeof(T),
                    typeof(TBinType),
                    typeof(TIncrementor),
                    typeof(TLocator)));

            return((stream, view, histogram, histogramOverflow) =>
            {
                if (!view.IsValid)
                {
                    throw new ArgumentNullException(nameof(view));
                }
                if (view.Length < 1)
                {
                    throw new ArgumentOutOfRangeException(nameof(view));
                }
                if (!histogram.IsValid)
                {
                    throw new ArgumentNullException(nameof(histogram));
                }
                if (histogram.Length < 1)
                {
                    throw new ArgumentOutOfRangeException(nameof(histogram));
                }
                if (!histogramOverflow.IsValid)
                {
                    throw new ArgumentNullException(nameof(histogramOverflow));
                }
                if (histogramOverflow.Length < 1)
                {
                    throw new ArgumentOutOfRangeException(nameof(histogramOverflow));
                }
                if (view.Length > int.MaxValue || histogram.Length > int.MaxValue)
                {
                    throw new NotSupportedException(
                        ErrorMessages.NotSupportedArrayView64);
                }
                var input = view.AsLinearView();
                var(gridDim, groupDim) = accelerator.ComputeGridStrideLoopExtent(
                    input.Length,
                    out int numIterationsPerGroup);
                int numVirtualGroups = gridDim * numIterationsPerGroup;
                int lengthInformation =
                    XMath.DivRoundUp(input.Length, groupDim) * groupDim;

                kernel(
                    stream,
                    (gridDim, groupDim),
                    input,
                    histogram,
                    histogramOverflow,
                    lengthInformation);
            });
        }