Exemplo n.º 1
0
        /// <summary>
        /// Divide-and-Conquer Merge of two ranges of source array src[ p1 .. r1 ] and src[ p2 .. r2 ] into destination array starting at index p3.
        /// </summary>
        /// <typeparam name="T">data type of each array element</typeparam>
        /// <param name="src">source array</param>
        /// <param name="p1">starting index of the first  segment, inclusive</param>
        /// <param name="r1">ending   index of the first  segment, inclusive</param>
        /// <param name="p2">starting index of the second segment, inclusive</param>
        /// <param name="r2">ending   index of the second segment, inclusive</param>
        /// <param name="dst">destination array</param>
        /// <param name="p3">starting index of the result</param>
        /// <param name="comparer">method to compare array elements</param>
        internal static void MergeInnerPar <T>(T[] src, Int32 p1, Int32 r1, Int32 p2, Int32 r2, T[] dst, Int32 p3, IComparer <T> comparer = null)
        {
            //Console.WriteLine("#1 " + p1 + " " + r1 + " " + p2 + " " + r2);
            Int32 length1 = r1 - p1 + 1;
            Int32 length2 = r2 - p2 + 1;

            if (length1 < length2)
            {
                Algorithm.Swap(ref p1, ref p2);
                Algorithm.Swap(ref r1, ref r2);
                Algorithm.Swap(ref length1, ref length2);
            }
            if (length1 == 0)
            {
                return;
            }
            if ((length1 + length2) <= MergeParallelArrayThreshold)
            {   // 8192 threshold is much better than 16 (is it for C#)
                //Console.WriteLine("#3 " + p1 + " " + length1 + " " + p2 + " " + length2 + " " + p3);
                HPCsharp.Algorithm.Merge <T>(src, p1, length1,
                                             src, p2, length2,
                                             dst, p3, comparer); // in Dr. Dobb's Journal paper
            }
            else
            {
                Int32 q1 = (p1 + r1) / 2;
                Int32 q2 = Algorithm.BinarySearch(src[q1], src, p2, r2, comparer);
                Int32 q3 = p3 + (q1 - p1) + (q2 - p2);
                dst[q3] = src[q1];
                Parallel.Invoke(
                    () => { MergeInnerPar <T>(src, p1, q1 - 1, p2, q2 - 1, dst, p3, comparer); },
                    () => { MergeInnerPar <T>(src, q1 + 1, r1, q2, r2, dst, q3 + 1, comparer); }
                    );
            }
        }
Exemplo n.º 2
0
        // TODO: Figure out why this is so slow and does not accelerate
        /// <summary>
        /// Divide-and-Conquer Merge of two ranges of source List src[ p1 .. r1 ] and src[ p2 .. r2 ] into destination List starting at index p3.
        /// </summary>
        /// <typeparam name="T">data type of each List element</typeparam>
        /// <param name="src">source List</param>
        /// <param name="p1">starting index of the first  segment, inclusive</param>
        /// <param name="r1">ending   index of the first  segment, inclusive</param>
        /// <param name="p2">starting index of the second segment, inclusive</param>
        /// <param name="r2">ending   index of the second segment, inclusive</param>
        /// <param name="dst">destination List</param>
        /// <param name="p3">starting index of the result</param>
        /// <param name="comparer">method to compare array elements</param>
        public static void MergeParallel <T>(List <T> src, Int32 p1, Int32 r1, Int32 p2, Int32 r2, List <T> dst, Int32 p3, Comparer <T> comparer = null)
        {
            Int32 length1 = r1 - p1 + 1;
            Int32 length2 = r2 - p2 + 1;

            if (length1 < length2)
            {
                Exchange(ref p1, ref p2);
                Exchange(ref r1, ref r2);
                Exchange(ref length1, ref length2);
            }
            if (length1 == 0)
            {
                return;
            }
            if ((length1 + length2) <= MergeParallelListThreshold)
            {                                                                                                  // 8192 threshold is much better than 16 (is it for C#)
                HPCsharp.Algorithm.Merge <T>(src, p1, p1 + length1, src, p2, p2 + length2, dst, p3, comparer); // in DDJ paper
            }
            else
            {
                Int32 q1 = (p1 + r1) / 2;
                Int32 q2 = Algorithm.BinarySearch(src[q1], src, p2, r2);
                Int32 q3 = p3 + (q1 - p1) + (q2 - p2);
                dst[q3] = src[q1];
                Parallel.Invoke(
                    () => { MergeParallel <T>(src, p1, q1 - 1, p2, q2 - 1, dst, p3, comparer); },
                    () => { MergeParallel <T>(src, q1 + 1, r1, q2, r2, dst, q3 + 1, comparer); }
                    );
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Divide-and-Conquer Merge of two ranges of source array src[ p1 .. r1 ] and src[ p2 .. r2 ] into destination array starting at index p3.
        /// This merge is not stable.
        /// </summary>
        /// <typeparam name="T">data type of each array element</typeparam>
        /// <param name="src">source array</param>
        /// <param name="aStart">starting index of the first  segment, inclusive</param>
        /// <param name="aEnd">ending   index of the first  segment, inclusive</param>
        /// <param name="bStart">starting index of the second segment, inclusive</param>
        /// <param name="bEnd">ending   index of the second segment, inclusive</param>
        /// <param name="dst">destination array</param>
        /// <param name="p3">starting index of the result</param>
        /// <param name="comparer">method to compare array elements</param>
        public static void MergeDivideAndConquer <T>(T[] src, Int32 aStart, Int32 aEnd, Int32 bStart, Int32 bEnd, T[] dst, Int32 p3, IComparer <T> comparer = null)
        {
            //Console.WriteLine("#1 " + aStart + " " + aEnd + " " + bStart + " " + bEnd);
            Int32 length1 = aEnd - aStart + 1;
            Int32 length2 = bEnd - bStart + 1;

            if (length1 < length2)
            {
                HPCsharp.ParallelAlgorithm.Exchange(ref aStart, ref bStart);
                HPCsharp.ParallelAlgorithm.Exchange(ref aEnd, ref bEnd);
                HPCsharp.ParallelAlgorithm.Exchange(ref length1, ref length2);
            }
            if (length1 == 0)
            {
                return;
            }
            if ((length1 + length2) <= MergeArrayThreshold)
            {
                //Console.WriteLine("Merge: aStart = {0} length1 = {1} bStart = {2} length2 = {3} p3 = {2}", aStart, length1, bStart, length2, p3);
                Merge <T>(src, aStart, length1,
                          src, bStart, length2,
                          dst, p3, comparer);           // in Dr. Dobb's Journal paper
            }
            else
            {
                Int32 q1 = (aStart + aEnd) / 2;
                Int32 q2 = Algorithm.BinarySearch(src[q1], src, bStart, bEnd, comparer);
                Int32 q3 = p3 + (q1 - aStart) + (q2 - bStart);
                dst[q3] = src[q1];
                MergeDivideAndConquer(src, aStart, q1 - 1, bStart, q2 - 1, dst, p3, comparer); // lower half
                MergeDivideAndConquer(src, q1 + 1, aEnd, q2, bEnd, dst, q3 + 1, comparer);     // upper half
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Divide-and-Conquer Merge of two ranges of source array src[ p1 .. r1 ] and src[ p2 .. r2 ] into destination array starting at index p3.
        /// </summary>
        /// <typeparam name="T">data type of each array element</typeparam>
        /// <param name="src">source array</param>
        /// <param name="p1">starting index of the first  segment, inclusive</param>
        /// <param name="r1">ending   index of the first  segment, inclusive</param>
        /// <param name="p2">starting index of the second segment, inclusive</param>
        /// <param name="r2">ending   index of the second segment, inclusive</param>
        /// <param name="dst">destination array</param>
        /// <param name="p3">starting index of the result</param>
        /// <param name="comparer">method to compare array elements</param>
        internal static void MergeInnerFasterPar <T>(T[] src, Int32 p1, Int32 r1, Int32 p2, Int32 r2, T[] dst, Int32 p3, IComparer <T> comparer = null, Int32 mergeParallelThreshold = 128 * 1024)
        {
            //Console.WriteLine("#1 " + p1 + " " + r1 + " " + p2 + " " + r2);
            Int32 length1 = r1 - p1 + 1;
            Int32 length2 = r2 - p2 + 1;

            if (length1 < length2)
            {
                Algorithm.Swap(ref p1, ref p2);
                Algorithm.Swap(ref r1, ref r2);
                Algorithm.Swap(ref length1, ref length2);
            }
            if (length1 == 0)
            {
                return;
            }
            if ((length1 + length2) <= mergeParallelThreshold)
            {
                //Console.WriteLine("#3 " + p1 + " " + length1 + " " + p2 + " " + length2 + " " + p3);
                HPCsharp.Algorithm.MergeFaster <T>(src, p1, length1,
                                                   src, p2, length2,
                                                   dst, p3, comparer);
            }
            else
            {
                Int32 q1 = (p1 + r1) / 2;
                Int32 q2 = Algorithm.BinarySearch(src[q1], src, p2, r2, comparer);
                Int32 q3 = p3 + (q1 - p1) + (q2 - p2);
                dst[q3] = src[q1];
                Parallel.Invoke(
                    () => { MergeInnerFasterPar <T>(src, p1, q1 - 1, p2, q2 - 1, dst, p3, comparer, mergeParallelThreshold); },
                    () => { MergeInnerFasterPar <T>(src, q1 + 1, r1, q2, r2, dst, q3 + 1, comparer, mergeParallelThreshold); }
                    );
            }
        }
Exemplo n.º 5
0
        // Merge two ranges of source array T[ l .. m, m+1 .. r ] in-place.
        // Based on not-in-place algorithm in 3rd ed. of "Introduction to Algorithms" p. 798-802, extending it to be in-place
        // and my Dr. Dobb's paper https://www.drdobbs.com/parallel/parallel-in-place-merge/240008783
        public static void MergeDivideAndConquerInPlacePar <T>(T[] arr, int startIndex, int midIndex, int endIndex, IComparer <T> comparer = null, int threshold0 = 16 * 1024, int threshold1 = 16 * 1024)
        {
            //Console.WriteLine("MergeDivideAndConquerInPlacePar: start = {0}, mid = {1}, end = {2}", startIndex, midIndex, endIndex);
            int length1 = midIndex - startIndex + 1;
            int length2 = endIndex - midIndex;

            if (length1 >= length2)
            {
                if (length2 <= 0)
                {
                    return;                                                                      // if the smaller segment has zero elements, then nothing to merge
                }
                int q1 = (startIndex + midIndex) / 2;                                            // q1 is mid-point of the larger segment. length1 >= length2 > 0
                int q2 = Algorithm.BinarySearch(arr[q1], arr, midIndex + 1, endIndex, comparer); // q2 is q1 partitioning element within the smaller sub-array (and q2 itself is part of the sub-array that does not move)
                int q3 = q1 + (q2 - midIndex - 1);
                //BlockSwapReversalPar(arr, q1, midIndex, q2 - 1, threshold0);
                //Algorithm.BlockSwapReversal(arr, q1, midIndex, q2 - 1);
                Algorithm.BlockSwapGriesMills(arr, q1, midIndex, q2 - 1);

                if (length1 < threshold1)
                {
                    MergeDivideAndConquerInPlacePar(arr, startIndex, q1 - 1, q3 - 1, comparer);
                    MergeDivideAndConquerInPlacePar(arr, q3 + 1, q2 - 1, endIndex, comparer);
                }
                else
                {
                    Parallel.Invoke(
                        () => { MergeDivideAndConquerInPlacePar(arr, startIndex, q1 - 1, q3 - 1, comparer); },     // note that q3 is now in its final place and no longer participates in further processing
                        () => { MergeDivideAndConquerInPlacePar(arr, q3 + 1, q2 - 1, endIndex, comparer); }
                        );
                }
            }
            else
            {   // length1 < length2
                if (length1 <= 0)
                {
                    return;                                                                    // if the smaller segment has zero elements, then nothing to merge
                }
                int q1 = (midIndex + 1 + endIndex) / 2;                                        // q1 is mid-point of the larger segment.  length2 > length1 > 0
                int q2 = Algorithm.BinarySearch(arr[q1], arr, startIndex, midIndex, comparer); // q2 is q1 partitioning element within the smaller sub-array (and q2 itself is part of the sub-array that does not move)
                int q3 = q2 + (q1 - midIndex - 1);
                //BlockSwapReversalPar(arr, q2, midIndex, q1, threshold0);
                //Algorithm.BlockSwapReversal(arr, q2, midIndex, q1);
                Algorithm.BlockSwapGriesMills(arr, q2, midIndex, q1);

                if (length1 < threshold1)
                {
                    MergeDivideAndConquerInPlacePar(arr, startIndex, q2 - 1, q3 - 1, comparer);
                    MergeDivideAndConquerInPlacePar(arr, q3 + 1, q1, endIndex, comparer);
                }
                else
                {
                    Parallel.Invoke(
                        () => { MergeDivideAndConquerInPlacePar(arr, startIndex, q2 - 1, q3 - 1, comparer); },     // note that q3 is now in its final place and no longer participates in further processing
                        () => { MergeDivideAndConquerInPlacePar(arr, q3 + 1, q1, endIndex, comparer); }
                        );
                }
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Divide-and-Conquer Merge of two ranges of source array src[ p1 .. r1 ] and src[ p2 .. r2 ] into destination array starting at index p3.
        /// </summary>
        /// <typeparam name="T">data type of each array element</typeparam>
        /// <param name="srcKeys">source array of keys used for sorting</param>
        /// <param name="srcItems">source array of items that will be sorted along with keys</param>
        /// <param name="p1">starting index of the first  segment, inclusive</param>
        /// <param name="r1">ending   index of the first  segment, inclusive</param>
        /// <param name="p2">starting index of the second segment, inclusive</param>
        /// <param name="r2">ending   index of the second segment, inclusive</param>
        /// <param name="dstKeys">destination array of sorted keys</param>
        /// <param name="dstItems">destination array of sorted items</param>
        /// <param name="p3">starting index of the result</param>
        /// <param name="comparer">method to compare array elements</param>
        internal static void MergeInnerPar <T1, T2>(T1[] srcKeys, T2[] srcItems, Int32 p1, Int32 r1, Int32 p2, Int32 r2, T1[] dstKeys, T2[] dstItems, Int32 p3, IComparer <T1> comparer = null)
        {
            //Console.WriteLine("merge: #1 " + p1 + " " + r1 + " " + p2 + " " + r2);
            Int32 length1 = r1 - p1 + 1;
            Int32 length2 = r2 - p2 + 1;

            if (length1 < length2)
            {
                Algorithm.Swap(ref p1, ref p2);
                Algorithm.Swap(ref r1, ref r2);
                Algorithm.Swap(ref length1, ref length2);
            }
            if (length1 == 0)
            {
                return;
            }
            if ((length1 + length2) <= MergeParallelArrayThreshold)
            {
                //Console.WriteLine("merge: #3 " + p1 + " " + length1 + " " + p2 + " " + length2 + " " + p3);
                HPCsharp.Algorithm.Merge <T1, T2>(srcKeys, srcItems, p1, length1,
                                                  srcKeys, srcItems, p2, length2,
                                                  dstKeys, dstItems, p3, comparer);
            }
            else
            {
                Int32 q1 = (p1 + r1) / 2;
                Int32 q2 = Algorithm.BinarySearch(srcKeys[q1], srcKeys, p2, r2, comparer);
                Int32 q3 = p3 + (q1 - p1) + (q2 - p2);
                dstKeys[q3]  = srcKeys[q1];
                dstItems[q3] = srcItems[q1];
                Parallel.Invoke(
                    () => { MergeInnerPar <T1, T2>(srcKeys, srcItems, p1, q1 - 1, p2, q2 - 1, dstKeys, dstItems, p3, comparer); },
                    () => { MergeInnerPar <T1, T2>(srcKeys, srcItems, q1 + 1, r1, q2, r2, dstKeys, dstItems, q3 + 1, comparer); }
                    );
            }
        }