Add hybrid sorting with [HybridSortingNetwork] attribute#108
Open
jonathanpeppers wants to merge 8 commits into
Open
Add hybrid sorting with [HybridSortingNetwork] attribute#108jonathanpeppers wants to merge 8 commits into
jonathanpeppers wants to merge 8 commits into
Conversation
Implement a hybrid quicksort that uses 3-way partitioning for large arrays (n > 64) and sorting-network base cases for small sub-arrays (n <= 64). This allows sorting arrays of any size without requiring user-supplied OnFallback methods. New features: - [HybridSortingNetwork(typeof(T))] attribute for code generation - Sort(Span<T>) / Sort(T[]) for arbitrary-length arrays - PartialSort(Span<T>, int k) for top-k sorting - NthElement(Span<T>, int n) for quickselect - 3-way Dutch National Flag partition (handles duplicates well) - Embedded optimal sorting network data for sizes 2-64 - Support for int, byte, short, long, float, double types - HybridSortEmitter generates all code via source generator SIMD partition using AVX-512F Compress / AVX-512 VBMI2 Compress is scaffolded as a future optimization on top of the scalar partition. Resolves #34 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adds a new hybrid-sorting source-generation path alongside the existing fixed-size sorting-network generator. It introduces a [HybridSortingNetwork] attribute intended to generate Sort, PartialSort, and NthElement APIs for arbitrary-length inputs by combining quicksort-style partitioning with sorting-network base cases.
Changes:
- Adds a new public
[HybridSortingNetwork(typeof(T))]attribute in the runtime package. - Extends the incremental generator with a hybrid pipeline and a new
HybridSortEmitter. - Adds generator tests and end-to-end tests for generated hybrid sorters.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
SortingNetworks/HybridSortingNetworkAttribute.cs |
Adds the new public attribute that opts classes into hybrid sort code generation. |
SortingNetworks.Tests/HybridSorter.cs |
Declares a test partial class annotated with the new hybrid attribute for several primitive types. |
SortingNetworks.Tests/HybridSortTests.cs |
Adds functional tests for generated hybrid Sort, PartialSort, and NthElement APIs. |
SortingNetworks.Tests/GeneratorTests.cs |
Adds generator-compilation assertions for hybrid source emission. |
SortingNetworks.Generators/SortingNetworkGenerator.cs |
Registers and wires a second incremental pipeline for hybrid generation. |
SortingNetworks.Generators/HybridSortEmitter.cs |
Implements hybrid code emission, including quicksort/select logic and embedded network data. |
Add HybridIntSortingBenchmarks (sizes 32-10000, all InputKinds) and HybridLongSortingBenchmarks (sizes 32-10000, Random) to measure hybrid quicksort with sorting-network base cases against Array.Sort and Span.Sort baselines. - Add HybridSorters class with [HybridSortingNetwork] for int and long - Update CI benchmark summary to describe hybrid benchmarks correctly Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix PartialSort(span, 1) bug: k<=1 early return changed to k<=0 so k=1 correctly places the minimum element at index 0 - Fix network data allocation: use static readonly arrays instead of ReadOnlySpan property accessors that allocated per call - Add introsort depth limit (2*log2(n)) with fallback to span.Sort() to guarantee O(n log n) worst case - Deduplicate type requests in hybrid generator (HashSet<SpecialType>) - Use fully qualified hint name (namespace.class) to avoid collisions - Handle nested classes in hint name generation - Fix XML doc: remove AVX-512 SIMD claim (not yet implemented) - Add HybridSortingNetworkAttribute to PublicAPI.Unshipped.txt - Add PartialSort k=1 test - Add tests for sbyte, ushort, uint, ulong, char types - Add HybridSorter coverage for all supported primitive types - Merge main branch Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve merge conflicts in SortingNetworkGenerator.cs and GeneratorTests.cs, keeping both hybrid sort methods and IEquatable/incremental caching changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add decimal element size (16 bytes) in HybridSortEmitter.GetElementSize - Add [HybridSortingNetwork(typeof(decimal))] to test fixture - Add Sort_Decimal_200Elements functional test - Add decimal to HybridSort_GeneratesCode generator test Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve PublicAPI.Unshipped.txt conflict: keep only new HybridSortingNetworkAttribute entries since SortingNetworkAttribute was shipped to PublicAPI.Shipped.txt on main. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a new
[HybridSortingNetwork]attribute and source generator pipeline that generates hybrid quicksort methods (Sort,PartialSort,NthElement) for arbitrary-size arrays, using sorting networks as the base case for small sub-arrays.What's included
HybridSortingNetworkAttribute— new attribute (like[SortingNetwork]but for arbitrary sizes)HybridSortEmitter— source generator emitter producing:Sort(Span<T>)/Sort(T[])— full hybrid quicksortPartialSort(Span<T>, int k)— sort only first k elementsNthElement(Span<T>, int n)— quickselect for nth element2 * log2(n)) withMemoryExtensions.Sort()fallback for O(n log n) worst caseSortingNetworkGeneratorwith deduplication, fully-qualified hint namesintandlonghybrid sortBenchmark results (Ubuntu x64, .NET 10)
Hybrid sort vs
Array.Sortbaseline — the hybrid sort is a scalar quicksort (no SIMD partitioning yet), so it's expected to be slower than BCL for most sizes. The value is in the API surface and sorting network base case:At 10k elements with duplicates, hybrid sort wins (0.35x = ~3x faster) thanks to 3-way partitioning skipping equal elements.
Existing
[SortingNetwork]benchmarks show no regression — all ratios unchanged from main.What's NOT included (future work)
decimalsupport (issue Add decimal as a first-class supported element type #111)Review fixes addressed
PartialSort(span, 1)being a no-op (k <= 1changed tok <= 0)static readonlyarrays instead of property accessors)MemoryExtensions.Sort()fallbackHashSetdeduplication for type requests