Skip to main content
QUICK REVIEW

[论文解读] BlockQuicksort: How Branch Mispredictions don't affect Quicksort

Stefan Edelkamp, A. Weiss|arXiv (Cornell University)|Apr 22, 2016
Advanced Data Storage Technologies参考文献 13被引用 8
一句话总结

BlockQuicksort 是一种新颖的原地排序算法,通过将数据按固定大小的块(例如 128 个元素)进行分区,并在重新排列元素前将比较结果存储在缓冲区中,从而消除快速排序中的分支预测错误。该方法将平均分支预测错误次数减少至最多 $\epsilon n\log n + \mathcal{O}(n)$,在随机整数数据上比 GCC 的 std::sort 快 80% 以上,并在某些工作负载下优于 Super Scalar Sample Sort。

ABSTRACT

Since the work of Kaligosi and Sanders (2006), it is well-known that Quicksort -- which is commonly considered as one of the fastest in-place sorting algorithms -- suffers in an essential way from branch mispredictions. We present a novel approach to address this problem by partially decoupling control from data flow: in order to perform the partitioning, we split the input in blocks of constant size (we propose 128 data elements); then, all elements in one block are compared with the pivot and the outcomes of the comparisons are stored in a buffer. In a second pass, the respective elements are rearranged. By doing so, we avoid conditional branches based on outcomes of comparisons at all (except for the final Insertionsort). Moreover, we prove that for a static branch predictor the average total number of branch mispredictions is at most $εn \log n + O(n)$ for some small $ε$ depending on the block size when sorting $n$ elements. Our experimental results are promising: when sorting random integer data, we achieve an increase in speed of 80% over the GCC implementation of C++ std::sort. Also for many other types of data and non-random inputs, there is still a significant speedup over std::sort. Only in few special cases like sorted or almost sorted inputs, std::sort can beat out implementation. Moreover, even on random input permutations, our implementation is even slightly faster than an implementation of the highly tuned Super Scalar Sample Sort, which uses a linear amount of additional space.

研究动机与目标

  • 解决现代流水线处理器中因分支预测错误导致的快速排序性能下降问题。
  • 设计一种原地排序算法,通过避免复杂枢纽选择或外部内存,最小化分支预测错误。
  • 在包括随机、近乎有序和重复元素较多的多种数据类型上保持高性能。
  • 在保持原地特性的同时,实现与高度优化的算法(如 Super Scalar Sample Sort)相当或更优的性能。

提出的方法

  • 将输入数组划分为固定大小的块(例如 128 个元素),以解耦控制流与数据依赖的比较决策。
  • 对每个块,将所有元素与枢纽进行比较,并将比较结果(例如“小于”或“大于”)存储在缓冲区中,避免比较过程中的条件分支。
  • 在完成所有比较后,进行第二轮遍历,根据存储的比较结果重新排列元素,从而在分区过程中消除数据依赖的分支。
  • 使用插入排序作为递归的基例,但通过优化缓冲区使用和块处理方式,进一步减少整体分支预测错误。
  • 应用静态分支预测模型,理论上将分支预测错误次数限制在 $\epsilon n\log n + \mathcal{O}(n)$ 以内,其中 $\epsilon$ 取决于块大小。
  • 采用中位数- $\sqrt{n}$ 或中位数-5 的枢纽选择策略,以在性能与可预测性之间取得平衡。

实验结果

研究问题

  • RQ1通过将比较结果与控制流决策解耦,能否显著减少快速排序中的分支预测错误?
  • RQ2在具有深流水线的现代处理器上,分块缓冲比较结果是否能带来可测量的性能提升?
  • RQ3一种原地排序算法能否在避免动态内存分配的前提下,实现与高度优化的算法(如 Super Scalar Sample Sort)相当或更优的性能?
  • RQ4该基于块的方法在包括随机、近乎有序和重复元素较多的数据在内的多种输入类型上表现如何?
  • RQ5分支预测错误的理论上限是否能在实际中实现?其性能随块大小如何变化?

主要发现

  • 在静态分支预测模型下,BlockQuicksort 将平均分支预测错误次数减少至最多 $\epsilon n\log n + \mathcal{O}(n)$,其中 $\epsilon$ 很小且取决于块大小。
  • 在随机整数数据上,BlockQuicksort 的吞吐量(每秒排序元素数)比 GCC 的 std::sort 高出 80% 以上。
  • 在所有测试的数据类型中,包括随机排列、近乎有序数组以及重复元素较多的数据,BlockQuicksort 均优于 std::sort,仅在极少数情况(如已排序输入)下例外。
  • 即使在随机排列数据上,由于更好的分支预测和缓存行为,BlockQuicksort 也略快于使用线性额外空间的 Super Scalar Sample Sort。
  • 该算法实现了较低的指令计数和缓存未命中率,平均每元素仅有 2.25 次分支预测错误,远低于 std::sort 的 10.23 次。
  • 使用重复元素检查(dc)和中位数- $\sqrt{n}$ 的枢纽选择策略可进一步提升性能,尤其在存在重复元素的数据上表现更优。

更好的研究,从现在开始

从阅读论文到最终审阅,大幅缩短您的研究时间。

无需绑定信用卡

本解读由 AI 生成,并经人工编辑审核。