3 ms·
Yes, only your "10x" and "5-10x" numbers are overstated. Which is to say, all the quantitative comparison you've shared here, or in the vqsort README (aside fro
by mlochbaum 3y ago
Yes, only your "10x" and "5-10x" numbers are overstated. Which is to say, all the quantitative comparison you've shared here, or in the vqsort README (aside from the link to Lukas's measurements, which is linked with no indication it benchmarks against faster sorts). What you share is defensible in that it's technically correct, but it's not helpful.
As an example, consider an application that uses heapsort now, but ships a unified binary for x86. The programmers could easily switch to pdqsort, which is well-tested and available in many languages. If they read only material you publish, they may get the impression that SIMD support (at least SSE4) is required to get a substantial improvement, and stick with heapsort to avoid the need to ship multiple binaries or add architecture detection. All you need to correct this is one mention that you can do better than std::sort! By leaving this out, you instead reinforce the idea that it's a reasonable choice if you have to go scalar.
ipnsort has no explicit vectorization; some parts may be auto-vectorized. From a quick glance through perf results, I don't see any vector instructions used in the parts that take up time. I didn't see any anywhere, actually. Same story with other quicksorts, although I know fluxsort/crumsort's initial analyzer is designed to be auto-vectorized.
I don't get why you dismiss radix sort so quickly, when your own research shows that an MSD/LSD hybrid addresses the bandwidth problem well? Thanks for sharing that paper by the way, very elegant approach. The bandwidth problem is not one I've seen discussed although I see how it would arise. I just don't deal with big arrays that much—and it seems if you're going to market vqsort as general-purpose you should also care about this use case! However, a nice thing about radix sort is that it can be used as a base case for quicksort/samplesort, and any partitioning done so far allows fewer steps to be used. I have a case in SingeliSort to do 4-byte sorting that fits in 2-byte range nearly in-place[0]. It's only used on 2^16 elements or fewer to avoid possible cache associativity problems, so that should fit in L2 and not use system bandwidth.
Comparison-based algorithms I consider most relevant at the moment are fluxsort/crumsort/quadsort (all by the same author; they share many pieces), ipnsort (largely derived from those plus pdqsort but it may be easier to read), and glidesort somewhat (the gliding technique is cool but I think there are flaws to address, see [1]). For distribution sorting, there's radix, the version of counting sort where you reconstruct from counts instead of moving the data (output can be vectorized with a scan for large ranges!), and I've developed Robin Hood sort to take advantage of smooth-ish distributions such as uniform random. I keep notes at [2], which are pretty out of date. I should be writing there instead of here...
I of course don't think there's any requirement to know all this to contribute to sorting research. I take issue with making blanket claims like "I'd consider AVX2 to be table stakes for any sorting algorithm" and "anything as energy-inefficient as scalar code running on big OoO cores is a hard sell" without being familiar with the state of the art in scalar sorting.
[0] https://github.com/mlochbaum/SingeliSort/blob/master/src/radix.singeli#L120-L128 https://github.com/mlochbaum/SingeliSort/blob/master/src/rad...
[1] https://github.com/Voultapher/sort-research-rs/pull/6#issuecomment-1588172671 https://github.com/Voultapher/sort-research-rs/pull/6#issuec...
[2] https://mlochbaum.github.io/BQN/implementation/primitive/sort.html https://mlochbaum.github.io/BQN/implementation/primitive/sor...
- janwas 3y ago> Yes, only your "10x" and "5-10x" numbers are overstated. OK. I am curious: what is the desired outcome for you in this discussion? If we are arguing whether in some cases the speedup is 2x, I struggle to understand why anyone would use an 'only' 2x slower algorithm in a time-critical application. > they may [..] stick with heapsort to avoid the need to ship multiple binaries or add architecture detection. Huh, why would they do that? Calling VQSort() takes care of detection, and does not require multiple binaries. > All you need to correct this is one mention that you can do better than std::sort! By leaving this out, you instead reinforce the idea that it's a reasonable choice if you have to go scalar. When do people 'have to' go scalar? I suppose we can mention: "Note that other algorithms such as pdqsort can be about twice as fast as LLVM's std::sort as of 2023-06." > ipnsort has no explicit vectorization; some parts may be auto-vectorized Yes, Lukas mentioned it uses 128-bit SIMD so I am guessing it's via autovectorization. > I don't get why you dismiss radix sort so quickly, when your own research shows that an MSD/LSD hybrid > addresses the bandwidth problem well? Thanks for sharing that paper by the way, very elegant approach. :) Thanks. Unfortunately virtual memory is quite finite (the OS does not leave much for users, especially on Windows), so this approach is problematic for large arrays. Also, many of the use cases we see are 64 or even 128-bit elements, with varied and unpredictable distributions. Sure, radix sort can be suitable when there are smaller keys. > Comparison-based algorithms I consider most relevant at the moment are fluxsort/crumsort/quadsort .. > I keep notes at [2] Thanks. It's not clear to me how those ideas can interoperate with SIMD. For example, counting the range during partitioning turns out to be expensive, more so than it would be in scalar code (because fewer ports can run vector instructions than scalar instructions). An is-sorted check could be vectorized as you note, but it's not clear to me that that is a net win (extra cost if not alread sorted, and if it is, better to avoid the sort call in the first place). > I take issue with making blanket claims like "I'd consider AVX2 to be table stakes for any sorting algorithm" Here are some of my axioms: 1) all x86 CPUs we care about support AVX2 (which has been available since 10 years). 2) Lukas' measurements show that the fixed vqsort with AVX2 is the fastest starting at around 32 elements. (For less than that, I still struggle to understand how branchy insertion sorts can be worse than a single indirect branch to an AVX2 sorting network, and suspect this is due to remaining issues with measurement including lack of fences and an unusual attempt to 'poison' branch predictors/cache.) 3) It seems unlikely that anything using less SIMD hardware than vqsort (for example only SSE4) is going to outperform the AVX2 version. 4) we currently have no reason to use a slower sort. Do you disagree with any of those? I suppose there are some CPUs without AVX2, but it's an open question whether one would want to ship an entirely different algorithm for them.