Sample Sort: Mechanism, Complexity Analysis & Interactive Visualizer
Sample Sort
A parallel divide-and-conquer distribution sort: selects a small sample of elements to extract multiple splitters, partitioning the array into many buckets that can be sorted concurrently.
How it works
Sample Sort is a generalization of Quicksort designed for distributed-memory parallel systems. While Quicksort uses a single pivot to partition elements into 2 sub-problems, Sample Sort partitions elements into \(P\) sub-problems (where \(P\) is the number of processors) using \(P - 1\) pivots called "splitters":
- Sampling: Select a small, representative sample of elements from the input array.
- Splitter Selection: Sort the sample. Pick \(P - 1\) splitter values at uniform intervals in the sorted sample (e.g. if \(P = 3\), we extract 2 splitters). These splitters define the boundary ranges of \(P\) buckets.
- Local Distribution: Distribute the remaining elements into the \(P\) buckets based on the splitters. On a parallel system, each processor performs this distribution locally.
- Parallel Sort: Sort each bucket independently (often using a fast comparison sort like Insertion Sort or Quicksort). Because the buckets represent disjoint value ranges, they can be processed concurrently with zero inter-processor communication.
- Recombination: Concatenate the sorted buckets back together to form the final sorted array.
Complexity
Interactive visualization
Pseudocode
procedure sampleSort(A, P): n ← length(A) sampleSize ← P * 5 sample ← chooseRandomSamples(A, sampleSize) sort(sample) splitters ← array of size P - 1 for i from 0 to P - 2: splitters[i] ← sample[(i + 1) * 5] buckets ← array of P empty lists for each x in A: bucketIdx ← findBucket(x, splitters) buckets[bucketIdx].append(x) A ← empty for each bucket in buckets: sort(bucket) A.appendAll(bucket)
JavaScript implementation
function sampleSort(arr, P = 3) { const n = arr.length; if (n <= 1) return arr; // 1. Select sample indices const sampleIdxs = [arr[0], arr[Math.floor(n/4)], arr[Math.floor(n/2)], arr[Math.floor(n*3/4)], arr[n - 1]]; sampleIdxs.sort((x, y) => x - y); // 2. Pick splitters const s1 = sampleIdxs[1]; const s2 = sampleIdxs[3]; // 3. Distribute into buckets const buckets = Array.from({ length: P }, () => []); for (let x of arr) { if (x < s1) { buckets[0].push(x); } else if (x < s2) { buckets[1].push(x); } else; { buckets[2].push(x); } } // 4. Sort buckets and combine let current = 0; for (let b = 0; b < P; b++) { buckets[b].sort((x, y) => x - y); for (let x of buckets[b]) { arr[current++] = x; } } return arr; }
Pros and cons
Pros
- Stunning performance speedups on multi-core GPU/CPU systems.
- Highly effective load-balancing across processors.
- Minimizes inter-processor communication during execution.
Cons
- Requires O(n) auxiliary buffer memory.
- Highly dependent on sample size quality (poor samples can cause unequal bucket loading).
- Higher overhead for small inputs.
- Unstable sorting order.
When (not) to use it
- Distributed computing networks: Standard choice for parallel database processing, MPI clusters, and map-reduce frameworks.
- Single-threaded systems: Avoid; Quicksort or Timsort have lower constant factors on single-core platforms.
Related reading
Sleep Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A unique concurrency-based sorting algorithm: spawns a separate thread for each element, sleeping for a duration proportional to the element value before writing it to the output.
By Md. Harun-Or-Roshid
Cube Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A parallel dimension sorting algorithm: organizes elements in a 3D coordinate cube and sorts vectors along the height, width, and depth axes sequentially to achieve sorted order.
By Md. Harun-Or-Roshid
Patience Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A card-game inspired sorting algorithm: distributes elements onto a series of piles such that each pile's top is \(\ge\) the incoming value, then performs a multi-way merge across pile tops.
By Md. Harun-Or-Roshid
Library Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A gapped variation of Insertion Sort: leaves empty slots (gaps) in the array, allowing elements to be inserted in \(O(1)\) shift time on average by avoiding massive shifts.
By Md. Harun-Or-Roshid