CoderXL's Blog

Back

Bitonic Sort 双调排序Blur image

Bitonic 似乎是一个双关,既表示 bi + tonic “双调”,即先增后减或先减后增,又可以理解为 bit + onic “关于二进制位的”,提示了里面使用了很多位运算优化。


概述#

由于这个算法是专门为数据并行处理而设计的,可以做到同一层排序内的比较和交换互不依赖,因此只有在并行计算框架下才能发挥出其完全性能。当串行处理时,其复杂度不是最优的,达到了 O(nlog2n)O(n\log^2 n),但由于每一层可以完全并行,所以在并行框架下可以达到 O(nplog2n)O({n\over p}\log^2 n).

这个算法类似归并,但将归并中的“合并”(代价 O(n)O(n))这一无法并行的操作(双指针步进互相依赖,无法预测)替换为了可以并行的“双调合并”(代价 O(nlogn)O(n\log n),可以并行到 O(nplogn)O({n\over p}\log n))。

具体地,它有两个递归的任务:

  1. 将一段双调序列变为一段单调序列
  2. 将两段相邻的单调性不同的单调序列拼成一段更长的双调序列

为了严谨讨论,我们约定:双调序列的长度为 2 的幂,其前半段递增(递减),后半段递减(递增),并称其为“凸的”(“凹的”)。

刚刚的任务中,1. 自身可以递归 logn\log n 次完成。具体地,当当前双调序列长度为 2n2n 时,每次依次比较 a[i]a[i]a[i+n]a[i+n],其中 i[1,n]i\in[1,n],通过必要的交换保证 a[i] op a[i+n]a[i]\ \mathrm{op}\ a[i+n],其中 op{,}\mathrm{op}\in \{\le, \ge\}. 经过操作之后,这个双调序列会变成两个相邻的、凸凹性相反的双调序列,其中凸的序列中的元素都小于等于凹的序列中的元素。这就形成了 [1,n][1,n][n+1,2n][n+1,2n] 这两个区间之间的单调性。 继续递归直到 n=1n=1,此时将会变成单调序列。

综上,任务 1. 可以 O(nlogn)O(n\log n) 地完成,且完成后任务 2. 可以瞬间完成。

总共需要完成 logn\log n 次任务,因此总复杂度 O(nlog2n)O(n\log^2 n).

上述算法中,高亮的部分可以完全并行。


实现#

实现中,为了发挥并行性能,使用了 PyTorch 框架配合 CUDA/mps.


附录 - 图示#

每个双调序列,递归地变成单调序列。

两个单调性相反的单调序列,拼成一个双调序列。

回溯到更大的问题上,将这个大的双调序列,继续递归地变成单调序列:

排序完成。

Bitonic Sort 双调排序
https://blog.leosrealms.top/blog/miscellaneous/2026-03-22-bitonic-sort
Author CoderXL
Published at 2026年3月22日
Comment seems to stuck. Try to refresh?✨