mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Markus Wichmann <nullplan@gmx.net>
To: musl@lists.openwall.com
Subject: Re: [musl] Re:Re: [musl] qsort
Date: Wed, 1 Feb 2023 19:01:15 +0100	[thread overview]
Message-ID: <20230201180115.GB2626@voyager> (raw)
In-Reply-To: <4d290220.36d6.1860222ca46.Coremail.00107082@163.com>

On Mon, Jan 30, 2023 at 06:04:39PM +0800, David Wang wrote:
> WIth glibc,  average report is  "qsort:3351271634  vs   sort:4358412048"
> But on alpine,  it is "qsort:9585927992  vs   sort:4354856330"
>
> On average, qsort with musl is significantly slower than c++ sort,
> while with glibc the average performance of qsort is bettern than c++
> sort.
>

It seems to me as though smoothsort does not optimize for the number of
comparisons.

> Is there any story about the implementation of qsort in musl?  I feel
> it focused on performance improvement for some special kind of domain,
> but not clear what it is.
>

Smoothsort has the desirable property of being adaptive. Its runtime
gets closer to O(n) the more sorted the input already is. glibc uses
mergesort or quicksort (the latter as fallback) and neither of them has
that property. Plus, mergesort requires scratch storage and has a
significantly harder time sorting arrays with large elements, because
you end up constantly copying stuff. glibc tries to mitigate this by
indirectly sorting once the elements go above 32 bytes in size.

Basically, glibc is optimized for the comparisons, musl more for the
number of swaps. Although we really shouldn't loose sight of the
compares entirely, since those are indirect function calls, and current
processors seem to dislike those.

Anyway, there is an inefficiency in musl's smoothsort implementation,
namely in the sift() function:


| if(cmp(ar[0], lf, arg) >= 0 && cmp(ar[0], rt, arg) >= 0) {
| 	break;
| }
| if(cmp(lf, rt, arg) >= 0) {
| 	ar[i++] = lf;
| 	head = lf;
| 	pshift -= 1;
| } else {
| 	ar[i++] = rt;
| 	head = rt;
| 	pshift -= 2;
| }

As you can see, this does two or three comparisions, but actually needs
to do only two in any case: If we detect ar[0] >= lf && ar[0] < rt, then
by transitivity we have also detected rt > lf, so there is no need to
compare lf and rt directly anymore. I have not really found a good way
to formulate code that takes advantage of that, maybe something like
this?


		if(cmp(ar[0], lf, arg) < 0) {
			if(cmp(lf, rt, arg) >= 0) {
				ar[i++] = lf;
				head = lf;
				pshift -= 1;
			} else {
go_right:
				ar[i++] = rt;
				head = rt;
				pshift -= 2;
			}
		} else if (cmp(ar[0], rt, arg) < 0) {
			goto go_right;
		} else {
			break;
		}

Yeah, not great. But it does use only two compares ever. This ought to
lower the number of compares in your test somewhat.

HTH,
Markus

  reply	other threads:[~2023-02-01 18:01 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-20  1:49 Guy
2023-01-20 12:55 ` alice
2023-01-30 10:04   ` [musl] " David Wang
2023-02-01 18:01     ` Markus Wichmann [this message]
2023-02-02  2:12       ` [musl] " David Wang
2023-02-03  5:22         ` [musl] " David Wang
2023-02-03  8:03           ` Alexander Monakov
2023-02-03  9:01             ` [musl] " David Wang
2023-02-09 19:03       ` Rich Felker
2023-02-09 19:20         ` Alexander Monakov
2023-02-09 19:52           ` Rich Felker
2023-02-09 20:18             ` Rich Felker
2023-02-09 20:27               ` Pierpaolo Bernardi
2023-02-10  4:10             ` Markus Wichmann
2023-02-10 10:00         ` [musl] " David Wang
2023-02-10 13:10           ` Rich Felker
2023-02-10 13:45             ` [musl] " David Wang
2023-02-10 14:19               ` Rich Felker
2023-02-11  5:12                 ` [musl] " David Wang
2023-02-11  5:44                   ` alice
2023-02-11  8:39                     ` Joakim Sindholt
2023-02-11  9:06                       ` alice
2023-02-11  9:31                         ` [musl] " David Wang
2023-02-11 13:35                         ` Rich Felker
2023-02-11 17:18                           ` David Wang
2023-02-16 15:15       ` David Wang
2023-02-16 16:07         ` Rich Felker
2023-02-17  1:35           ` [musl] " David Wang
2023-02-17 13:17           ` Alexander Monakov
2023-02-17 15:07             ` Rich Felker
2023-02-11  9:22     ` [musl] " Markus Wichmann
2023-02-11  9:36       ` [musl] " David Wang
2023-02-11  9:51       ` David Wang
2023-01-20 13:32 ` [musl] qsort Valery Ushakov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230201180115.GB2626@voyager \
    --to=nullplan@gmx.net \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).