// sequential variant (deeper levels) void TopDownSplitMergeSeq(int *src, int begin, int end, int *dest) { if (end - begin < 2) return; int middle = (end + begin)/2; TopDownSplitMergeSeq(src, begin, middle, dest); TopDownSplitMergeSeq(src, middle, end, dest); TopDownMerge(src, begin, middle, end, dest); memcpy(src + begin, dest + begin, sizeof(int) * (end - begin)); }
TopDownSplitMerge(A[], iBegin, iEnd, B[]) { if(iEnd - iBegin < 2) // if run size == 1 return; // consider it sorted // recursively split runs into two halves until run size == 1, // then merge them and return back up the call chain iMiddle = (iEnd + iBegin) / 2; // iMiddle = mid point TopDownSplitMerge(A, iBegin, iMiddle, B); // split / merge left half TopDownSplitMerge(A, iMiddle, iEnd, B); // split / merge right half TopDownMerge(A, iBegin, iMiddle, iEnd, B); // merge the two half runs CopyArray(B, iBegin, iEnd, A); // copy the merged runs back to A }
// parallelized variant (highest levels) void TopDownSplitMerge(int *src, int begin, int end, int *dest, int depth) { if (end - begin < 2) return; // Once we've reached the desired depth, move to the sequential version. if (depth > max_depth) { TopDownSplitMergeSeq(src, begin, end, dest); return; } int middle = (end + begin)/2; #pragma omp parallel sections num_threads(2) { #pragma omp section TopDownSplitMerge(src, begin, middle, dest, depth + 1); #pragma omp section TopDownSplitMerge(src, middle, end, dest, depth + 1); } // Merge the two sorted array into a sorted section of the temporary buffer, // then copy that temporary buffer back to our main results array. TopDownMerge(src, begin, middle, end, dest); memcpy(src + begin, dest + begin, sizeof(int) * (end - begin)); }