mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-29 01:30:22 +00:00
146 lines
3.8 KiB
Chapel
146 lines
3.8 KiB
Chapel
//
|
|
// An example of a parallel quick sort implementation that uses
|
|
// "cobegin" to make each recursive call in parallel and "serial" to
|
|
// limit the number of threads.
|
|
//
|
|
|
|
use Random, Time; // for random number generation and the Timer class
|
|
|
|
var timer: Timer; // to time the sort
|
|
|
|
config var n: int = 2**15; // the size of the array to be sorted
|
|
config var thresh: int = 1; // the recursive depth to serialize
|
|
config var verbose: int = 0; // print out this many elements in array
|
|
config var timing: bool = true; // set timing to false to disable timer
|
|
|
|
var A: [1..n] real; // array of real numbers
|
|
|
|
//
|
|
// initialize array with random numbers
|
|
//
|
|
fillRandom(A);
|
|
|
|
//
|
|
// print out front of array if verbose flag is set
|
|
//
|
|
if verbose > 0 then
|
|
writeln("A[1..", verbose, "] = ", A[1..verbose]);
|
|
|
|
//
|
|
// start timer, call parallel quick sort routine, stop timer
|
|
//
|
|
if timing then timer.start();
|
|
pqsort(A, thresh);
|
|
if timing then timer.stop();
|
|
|
|
//
|
|
// report sort time
|
|
//
|
|
if timing then writeln("sorted in ", timer.elapsed(), " seconds");
|
|
|
|
//
|
|
// print out front of array if verbose flag is set
|
|
// values should now be in sorted order
|
|
//
|
|
if verbose > 0 then
|
|
writeln("A[1..", verbose, "] = ", A[1..verbose]);
|
|
|
|
//
|
|
// verify that array is sorted or halt
|
|
//
|
|
for i in 2..n do
|
|
if A(i) < A(i-1) then
|
|
halt("A(", i-1, ") == ", A(i-1), " > A(", i, ") == ", A(i));
|
|
|
|
writeln("verification success");
|
|
|
|
//
|
|
// pqsort -- parallel quick sort
|
|
//
|
|
// arr: generic 1D array of values (real, int, ...)
|
|
// thresh: number of recursive calls to make before serializing
|
|
// low: lower bound of array to start sort at, defaults to whole array
|
|
// high: upper bound of array to stop sort at, defaults to whole array
|
|
//
|
|
proc pqsort(arr: [],
|
|
thresh: int,
|
|
low: int = arr.domain.low,
|
|
high: int = arr.domain.high) where arr.rank == 1 {
|
|
|
|
//
|
|
// base case: arr[low..high] is small enough to bubble sort
|
|
//
|
|
if high - low < 8 {
|
|
bubbleSort(arr, low, high);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// determine pivot and partition arr[low..high]
|
|
//
|
|
const pivotVal = findPivot();
|
|
const pivotLoc = partition(pivotVal);
|
|
|
|
//
|
|
// make recursive calls to parallel quick sort each unsorted half of
|
|
// the array; if thresh is 0 or less, start executing conquer tasks
|
|
// serially
|
|
//
|
|
serial thresh <= 0 do cobegin {
|
|
pqsort(arr, thresh-1, low, pivotLoc-1);
|
|
pqsort(arr, thresh-1, pivotLoc+1, high);
|
|
}
|
|
|
|
//
|
|
// findPivot -- helper routine to find pivot value using simple
|
|
// median-of-3 method, returns pivot value
|
|
//
|
|
proc findPivot() {
|
|
const mid = low + (high-low+1) / 2;
|
|
|
|
if arr(mid) < arr(low) then arr(mid) <=> arr(low);
|
|
if arr(high) < arr(low) then arr(high) <=> arr(low);
|
|
if arr(high) < arr(mid) then arr(high) <=> arr(mid);
|
|
|
|
const pivotVal = arr(mid);
|
|
arr(mid) = arr(high-1);
|
|
arr(high-1) = pivotVal;
|
|
|
|
return pivotVal;
|
|
}
|
|
|
|
//
|
|
// partition -- helper routine to partition array such that all
|
|
// values less than pivot are to its left and all
|
|
// values greater than pivot are to its right, returns
|
|
// pivot location
|
|
//
|
|
proc partition(pivotVal) {
|
|
var ilo = low, ihi = high-1;
|
|
while (ilo < ihi) {
|
|
do { ilo += 1; } while arr(ilo) < pivotVal;
|
|
do { ihi -= 1; } while pivotVal < arr(ihi);
|
|
if (ilo < ihi) {
|
|
arr(ilo) <=> arr(ihi);
|
|
}
|
|
}
|
|
arr(high-1) = arr(ilo);
|
|
arr(ilo) = pivotVal;
|
|
return ilo;
|
|
}
|
|
}
|
|
|
|
//
|
|
// bubbleSort -- bubble sort for base case of quick sort
|
|
//
|
|
// arr: generic 1D array of values (real, int, ...)
|
|
// low: lower bound of array to start sort at
|
|
// high: upper bound of array to stop sort at
|
|
//
|
|
proc bubbleSort(arr: [], low: int, high: int) where arr.rank == 1 {
|
|
for i in low..high do
|
|
for j in low..high-1 do
|
|
if arr(j) > arr(j+1) then
|
|
arr(j) <=> arr(j+1);
|
|
}
|