Draft:Powersort
Submission declined on 6 November 2024 by CFA (talk). This submission is not adequately supported by reliable sources. Reliable sources are required so that information can be verified. If you need help with referencing, please see Referencing for beginners and Citing sources. This draft's references do not show that the subject qualifies for a Wikipedia article. In summary, the draft needs multiple published sources that are:
Where to get help
How to improve a draft
You can also browse Wikipedia:Featured articles and Wikipedia:Good articles to find examples of Wikipedia's best writing on topics similar to your proposed article. Improving your odds of a speedy review To improve your odds of a faster review, tag your draft with relevant WikiProject tags using the button below. This will let reviewers know a new draft has been submitted in their area of interest. For instance, if you wrote about a female astronomer, you would want to add the Biography, Astronomy, and Women scientists tags. Editor resources
|
The following Wikipedia contributor has declared a personal or professional connection to the subject of this page. Relevant policies and guidelines may include conflict of interest, autobiography, and neutral point of view. |
Powersort
[edit]Class | Sorting Algorithm |
---|---|
Data structure | Array |
Worst-case performance | O(nlogn) |
Worst-case space complexity | O(n) |
Powersort is an adaptive sorting algorithm designed to optimally exploit existing order in the input data with minimal overhead. Since version 3.11, Powersort is the default list sorting algorithm in CPython.[1] and is also used in PyPy and AssemblyScript. Powersort belongs to the family of merge sort algorithms. More specifically, Powersort builds on Timsort; it is a drop-in replacement for Timsort's suboptimal heuristic merge policy. Unlike the latter, it is derived from first principles (see connection to nearly optimal binary search trees) and offers strong performance guarantees.
Like Timsort, Powersort is a stable sort and comparison-based. This property is essential for many applications[2]. Powersort was proposed by J. Ian Munro and Sebastian Wild[3]
Algorithm Overview
[edit]Powersort is a stable mergesort variant that adapts to existing runs in the input data, i.e., ranges in the input that are already in order. It maintains a stack of runs yet to be merged and alternates between finding the next run and merging adjacent runs near the top of the run stack.
This non-recursive mode of operation is particularly cache-friendly.
Like Timsort, it enforces a minimal run length by “filling up” short runs using insertion sort up to a chosen minimal run length. Each merge step combines two adjacent runs into a single one using a “galloping strategy”: exponential search is used to find the prefix of one run that precedes the minimum in the other run. This can save comparisons compared to a traditional linear merge.
Powersort improves Timsort in terms of the merge policy, i.e., the rule(s) that decides which runs on the run stack are merged before proceeding. Timsort's original policy used a suboptimal heuristic based solely on the lengths of runs; Powersort replaces this with a rule simulating Mehlhorn's algorithm for computing nearly optimal binary search trees with low overhead[3], thereby achieving optimal adaptivity up to an additive linear term.
The pseudocode below shows a simplified Powersort implementation.
algorithm PowerSort(A[0..n)) S := stack of runs // capacity ⌈lg(n)⌉ + 1 b1 := 0; e1 := FirstRunOf(A[b1..n)) // A[s1..e1) is leftmost run while e1 < n b2 := e1 + 1; e2 := FirstRunOf(A[b2..n)) // A[s2..e2) next run P := NodePower(n, b1, e1, b2, e2) while S.top().power > P (b1, e1) := Merge(S.pop(), A[b1..e1)) end while S.push((A[b1, e1), P)); b1 := b2; e1 := e2 end while // Now A[b1..e1) is the rightmost run while ¬S.empty() (b1, e1) := Merge(S.pop(), A[b1..e1)) end while
algorithm NodePower(n, b1, e1, b2, e2, n) n1 := e1 − b1; n2 := e2 − b2; a := (b1 + n1/2)/n; b := (b2 + n2/2)/n p := 0 while ⌊a · 2p⌋ == ⌊b · 2p⌋ p := p + 1 end while return p
Adoption
[edit]The implementation of Powersort in CPython began with version 3.11, replacing the older Timsort algorithm. The change was motivated by Powersort's superior performance and stability. The core implementation can be found in the CPython source code within the listobject.c file, where the list sorting functions are defined. The detailed merge policies and algorithm are described in listsort.txt..[5][6] The transition to Powersort involved addressing issue #78742 in the CPython repository.[7]
The PyPy project, known for its high-performance Just-In-Time (JIT) compiler for Python, also integrated Powersort. The relevant commit, identified as `ab2269f3c0ca0265b4ff462f1bda29442182de11`, details the inclusion of Powersort into PyPy's list sorting functions.[8]
In AssemblyScript, Powersort was integrated to enhance the performance of WebAssembly applications. The relevant pull request, #1904, and the implementation details can be found in the sort.ts file within the AssemblyScript standard library.[9][10] These implementations across different platforms highlight the adaptability and efficiency of Powersort in various programming environments.
Comparison with Timsort
[edit]Timsort's original merge policy caused several problems before being replaced by Powersort.
First, as accidentally observed during the formal verification of Timsort, Tim Peters's original formulation did not guarantee the desired height bound for the run stack, leaving both CPython and OpenJDK vulnerable to a stack overflow. This was eventually fixed by adding a forth rule to Timsort, but required two major patches of OpenJDK[11]. While eventually successful, the correctness proof of Timsort's stack height and the running-time analysis are very complicated.
Further, it was discovered that Timsort's merge policy also has a performance blind spot: specific patterns of run lengths cause Timsort to repeatedly perform very unbalanced merges, resulting in asymptotically 50% overhead[12]
Powersort simultaneously removes all of these limitations. Despite its advanced theoretical foundation, it's analysis is much easier[13] and it provably never uses more than comparisons, where , for the lengths of the runs in the input.
Powersort has been shown to outperform Timsort by up to 30% on certain types of input data that contain long runs of sorted elements.[3] Powersort has further been extended to multiway merging, something that was not possible with Timsort.
Multiway Powersort
[edit]Multiway Powersort[13] is an extension of Powersort that generalizes the binary merging process to k-way merging. This approach can reduce the number of merge operations and hence reduces the amount of memory transfer. It was proposed by William Cawley Gelling, Markus E. Nebel, Benjamin Smith, and Sebastian Wild in 2023.
Multiway Powersort retains the stability and adaptiveness of the original Powersort algorithm[13], and is just as easy to analyze.
The key differences to normal Powersort are:
- The computation of powers uses the basis k instead of 2.
- When merging runs, we have to pop all runs from the stack that are tied in power with the topmost run.
Details are shown in the pseudocode below.
algorithms k-wayPowerSort(A[0..n)) S := empty stack // capacity (k − 1)⌈logk(n) + 1⌉ b1 := 0; e1 = FirstRunOf(A[b1..n)) while e1 < n b2 := e1; e2 := FirstRunOf(A[b2..n)) P := Powerk(n, b1, e1, b2, e2) while S.top().power > P P':= S.top().power L := empty list; L.append(S.pop()) while S.top().power == P′ L.append(S.pop()) end while // merge runs in L with A[b1..e1) (b1, e1) := Merge(L, A[b1..e1)) end while S.push((A[b1, e1), P)) b1 := b2; e1 := e2 end while // Now A[b1..e1) is the rightmost run while ¬S.empty() // pop (up to) k − 1 runs, merge with A[b1..e1) (b1, e1) := Merge(S.pop(k − 1), A[b1..e1)) end while
algorithm Powerk(n, b1, e1, b2, e2) n1 := e1 − b1; n2 := e2 − b2; p := 0 a := (b1 + n1/2)/n; b := (b2 + n2/2)/n while ⌊a · kp⌋ == ⌊b · kp⌋ p := p + 1 end while return p
Further Resources
[edit]- Practical hands-on experience with Powersort can be gained by playing Powersort's Pursuit.
- A more graphical approach to explaining Powersort is used in Sebastian Wild's PyCon US 2023 talk.
References
[edit]- ^ James, Mike. "Python Now Uses Powersort". I Programmer. Retrieved 2024-06-21.
- ^ Peters, Tim (2002). "Timsort". Python Mailing List.
- ^ a b c Munro, J. Ian; Wild, Sebastian (2018). "Nearly-Optimal Mergesorts: Fast, Practical Sorting Methods That Optimally Adapt to Existing Runs". 26th Annual European Symposium on Algorithms (ESA): 63:1–63:16. arXiv:1805.04154. doi:10.4230/lipics.esa.2018.63.
- ^ Wild, Sebastian (19 June 2023). "Quicksort, Timsort, Powersort (PyCon US 2023 talk)". YouTube. Retrieved 2024-10-17.
- ^ "CPython Implementation Details". GitHub. Retrieved 2024-07-30.
- ^ "CPython List Sort". GitHub. Retrieved 2024-07-30.
- ^ "Issue #78742: Integrate Powersort". GitHub. Retrieved 2024-07-30.
- ^ "PyPy Implementation of Powersort". Heptapod. Retrieved 2024-07-30.
- ^ "AssemblyScript Pull Request #1904". GitHub. Retrieved 2024-07-30.
- ^ "AssemblyScript Sort Implementation". GitHub. Retrieved 2024-07-30.
- ^ Auger, Nicolas; Jugé, Vincent; Nicaud, Cyril; Pivoteau, Carine (2018). [DROPS]. doi:10.4230/LIPIcs.ESA.2018.4. ISBN 9783959770811. S2CID 44091254. Retrieved 1 September 2018.
- ^ Buss, Sam; Knop, Alexander (2019). "Strategies for Stable Merge Sorting". "Strategies for Stable Merge Sorting.". pp. 1272–1290. arXiv:1801.04641. doi:10.1137/1.9781611975482.78. ISBN 978-1-61197-548-2.
{{cite book}}
: Unknown parameter|DUPLICATE_title=
ignored (help) - ^ a b c Gelling, William Cawley; Nebel, Markus E.; Smith, Benjamin; Wild, Sebastian (2023). "Multiway Powersort". Symposium on Algorithm Engineering and Experiments (ALENEX 2023): 190–200. arXiv:2209.06909. doi:10.1137/1.9781611977561.ch16. ISBN 978-1-61197-756-1.