From: Kuan-Wei Chiu <visitorckw@gmail.com>
To: akpm@linux-foundation.org
Cc: lkml@sdf.org, jserv@ccns.ncku.edu.tw,
linux-kernel@vger.kernel.org,
Kuan-Wei Chiu <visitorckw@gmail.com>
Subject: [PATCH 2/2] lib/sort: Optimize heapsort with double-pop variation
Date: Sat, 13 Jan 2024 11:13:52 +0800 [thread overview]
Message-ID: <20240113031352.2395118-3-visitorckw@gmail.com> (raw)
In-Reply-To: <20240113031352.2395118-1-visitorckw@gmail.com>
Instead of popping only the maximum element from the heap during each
iteration, we now pop the two largest elements at once. Although this
introduces an additional comparison to determine the second largest
element, it enables a reduction in the height of the tree by one during
the heapify operations starting from root's left/right child. This
reduction in tree height by one leads to a decrease of one comparison
and one swap.
This optimization results in saving approximately 0.5 * n swaps without
increasing the number of comparisons. Additionally, the heap size
during heapify is now one less than the original size, offering a
chance for further reduction in comparisons and swaps.
Signed-off-by: Kuan-Wei Chiu <visitorckw@gmail.com>
---
The following experimental data is based on the array generated using
get_random_u32().
| N | swaps (old) | swaps (new) | comparisons (old) | comparisons (new) |
|-------|-------------|-------------|-------------------|-------------------|
| 1000 | 9054 | 8569 | 10328 | 10320 |
| 2000 | 20137 | 19182 | 22634 | 22587 |
| 3000 | 32062 | 30623 | 35833 | 35752 |
| 4000 | 44274 | 42282 | 49332 | 49306 |
| 5000 | 57195 | 54676 | 63300 | 63294 |
| 6000 | 70205 | 67202 | 77599 | 77557 |
| 7000 | 83276 | 79831 | 92113 | 92032 |
| 8000 | 96630 | 92678 | 106635 | 106617 |
| 9000 | 110349 | 105883 | 121505 | 121404 |
| 10000 | 124165 | 119202 | 136628 | 136617 |
lib/sort.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/lib/sort.c b/lib/sort.c
index fe4efd4a1410..a0509088f82a 100644
--- a/lib/sort.c
+++ b/lib/sort.c
@@ -215,6 +215,7 @@ void sort_r(void *base, size_t num, size_t size,
/* pre-scale counters for performance */
size_t n = num * size, a = (num/2) * size;
const unsigned int lsbit = size & -size; /* Used to find parent */
+ size_t shift = 0;
if (!a) /* num < 2 || size == 0 */
return;
@@ -242,12 +243,21 @@ void sort_r(void *base, size_t num, size_t size,
for (;;) {
size_t b, c, d;
- if (a) /* Building heap: sift down --a */
- a -= size;
- else if (n -= size) /* Sorting: Extract root to --n */
+ if (a) /* Building heap: sift down a */
+ a -= size << shift;
+ else if (n > 3 * size) { /* Sorting: Extract two largest elements */
+ n -= size;
do_swap(base, base + n, size, swap_func, priv);
- else /* Sort complete */
+ shift = do_cmp(base + size, base + 2 * size, cmp_func, priv) <= 0;
+ a = size << shift;
+ n -= size;
+ do_swap(base + a, base + n, size, swap_func, priv);
+ } else if (n > size) { /* Sorting: Extract root */
+ n -= size;
+ do_swap(base, base + n, size, swap_func, priv);
+ } else { /* Sort complete */
break;
+ }
/*
* Sift element at "a" down into heap. This is the
--
2.25.1
next prev parent reply other threads:[~2024-01-13 3:14 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-13 3:13 [PATCH 0/2] lib/sort: Optimize the number of swaps and comparisons Kuan-Wei Chiu
2024-01-13 3:13 ` [PATCH 1/2] lib/sort: Optimize heapsort for equal elements in sift-down path Kuan-Wei Chiu
2024-01-13 3:13 ` Kuan-Wei Chiu [this message]
2024-06-20 15:36 ` [PATCH 2/2] lib/sort: Optimize heapsort with double-pop variation Julian Sikorski
2024-06-20 20:17 ` Mario Limonciello
2024-06-28 15:15 ` Linux regression tracking (Thorsten Leemhuis)
2024-06-28 17:10 ` Kuan-Wei Chiu
2024-06-29 5:03 ` Linux regression tracking (Thorsten Leemhuis)
[not found] ` <20240630210809.37550-1-visitorckw@gmail.com>
2024-06-30 21:13 ` [PATCH] ACPI: processor_idle: Fix invalid comparison with insertion sort for latency Kuan-Wei Chiu
2024-07-01 4:42 ` [PATCH v2] " Kuan-Wei Chiu
2024-07-01 5:06 ` Greg KH
2024-07-01 15:17 ` Mario Limonciello
2024-07-01 16:10 ` [PATCH v3] " Kuan-Wei Chiu
2024-07-01 17:36 ` Rafael J. Wysocki
2024-07-01 20:56 ` [PATCH v4] " Kuan-Wei Chiu
2024-07-02 7:28 ` Julian Sikorski
2024-07-02 12:59 ` Mario Limonciello
2024-07-02 18:38 ` Rafael J. Wysocki
2025-01-15 3:27 ` [PATCH 2/2] lib/sort: Optimize heapsort with double-pop variation Luke Jones
2025-01-15 12:49 ` Kuan-Wei Chiu
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=20240113031352.2395118-3-visitorckw@gmail.com \
--to=visitorckw@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=jserv@ccns.ncku.edu.tw \
--cc=linux-kernel@vger.kernel.org \
--cc=lkml@sdf.org \
/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.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox