Skip to content

算法Algorithm

外存排序

施工中 · 内容逐步修订

External-memory sorting

在 I/O 模型中以块传输而非 CPU 比较次数衡量海量排序。

形式陈述 ​

I/O 上界 ​

在外存模型中,输入是外存中连续存放的 N≥1 个定长记录,内存容量为 M 项,每块为 B≥1 项。取 M/B 至少为一个足以容纳多个输入块、输出块和控制状态的固定常数,使用常数成本的键比较。扫描量为 Θ(⌈N/B⌉),比较排序的最优量级为

Sort(N)=Θ(1+NB[1+logM/B⁡max{1,N/B}]).

这里把不足一块和内存可容纳的输入也包括在内;空输入单独直接返回。大规模 N>M 时,主项为 (N/B)logM/B⁡(N/B),与比较 I/O 排序下界匹配。

外归并先生成内存大小的有序段,再一次合并 f=Θ(M/B) 路。选择 f 时给每路输入块、一个输出块和 O(f) 个堆/游标字预留空间,确保总量不超过内存;不能把 M/B 原样当成在所有参数下都能使用的确切路数。

直觉

外归并排序的关键不是减少比较,而是让每一趟都顺序搬完整块,并用内存同时供给尽可能多的输入 run。内存能容纳约 M/B 个输入缓冲,因此一趟可把 run 数缩小同样倍数;这直接形成对数的底数,也解释了二路归并为何浪费外存带宽。

初始 runs 与多路归并
例子与边界

边界 ​

公式抽象了随机 I/O、CPU 比较与设备并行,不能直接预测 SSD 常数。Distribution sort 需要键分布/分桶条件。B,M 以元素还是字节计须一致,tall-cache 假设只在使用它的算法中注明。

CPU 的 O(Nlog⁡N) 不能机械换成同阶 I/O;顺序块传输才是外存算法核心。

下界按块能区分的排列数计数;若键宇宙允许 radix 或 distribution 技巧,纯比较 I/O 下界需要重新审视。稳定性也须在归并相等键时显式保留原先次序。

Run 生成与多路归并 ​

每次读入 M 项在内存排序并写出一个 run,共 ⌈N/M⌉ 个。归并时为每个输入 run 保留一块缓冲、为输出保留一块,故 fan-in 为 Θ(M/B) 而非 M;最小堆选择各缓冲头,块耗尽再读下一块。

例如 N=5×108,M=106,B=103,生成 500 个各有 106 项的 run。选择 500 路归并,输入缓冲占 5×105 项,输出块和各路堆/游标仍有充足空间,因此一轮就能归并完成。二路归并需要 ⌈log2⁡500⌉=9 轮,两者都另付最初的 run 生成成本。

排序公式的推导 ​

设初始 run 数为 r0=⌈N/M⌉。选择 f≥2 路后,归并轮数为 ⌈logf⁡r0⌉,加上初始生成的一轮扫描,总成本为

O(⌈NB⌉[1+⌈logf⁡⌈NM⌉⌉]).

当 N≤M 时,r0=1,没有外部归并轮。对 N>M,利用 f=Θ(M/B) 和

logM/B⁡(N/B)=1+logM/B⁡(N/M)

便得到前述排序量级。常数内存比例及各轮最后不足一块的部分不会改变此界。

推论与应用

在不知道具体块大小 B 与缓存容量 M、但采用理想缓存假设时,Funnel Sort以递归漏斗归并实现 cache-oblivious 比较排序,并达到排序 I/O 界所要求的渐近扫描效率。它不是任意存储层上的无条件替代:证明依赖块传输、最优替换和 tall-cache 一类模型条件,工程实现还需处理写放大与并发 I/O。

实现与模型边界 ​

同键稳定归并要优先较早 run 中记录。Replacement selection 可生成平均更长 runs,却依输入分布;distribution sort 利用键结构,不受纯比较下界同样约束。SSD 并行、预取和 CPU 比较改变常数,但不会让随机单项访问自动等于块扫描。

四帧九页的逐趟账本与下游融合 ​

为把渐近式落实为精确页数,另取9页定长记录、4个数据帧,控制游标另计。初始run生成每次原位排序至多4页,再从已有帧写出,形成长度4、4、1页的三个run。读9写9,成本18。归并用三帧分别缓冲三个run,一帧输出;最小头项每次从其run移除,输出序列始终是已消耗项的有序排列。再读9写9,合计36次I/O,保留每一份重复记录。

再取13页、仍为4帧与三路归并:初始4、4、4、1页四个run,下一趟合成12页和1页两个run,再下一趟合成13页。若采用每趟完整读写、连未参与多路合并的单run也复制的明确调度,三趟共2×13×3=78次I/O。允许把单run原样保留可省其复制,但那是另一个需要逐文件记账的调度,不能把优化后的数字套进完整趟公式。

若消费者可以立即按该键做分组聚合,最终归并不必把9页有序文件写盘再读回:将归并输出直接交给消费者,外排阶段成本变为初始18加最后读9,即27,另计聚合输出。相对于“完整排序36再扫描9”,省去18次临时I/O。消费者只维护当前键及固定大小聚合状态,并能在原输出帧中形成摘要;若它还需更多同时驻留的数据帧,就必须重新分配,不能一边使用三路归并四帧,一边另借一帧。

排序归并连接也可尝试最后归并趟融合,但两侧各有多个run时,需要同时保留两侧输入缓冲、重复键组与输出。两次排序各自有四帧并不意味着融合连接仍只用四帧。DB-4选择先把两输入各物化成一个run,再按两游标、一重复组、一输出的四帧调度,避免隐藏额外缓冲。

参考资料
  • Aggarwal, Vitter, “The Input/Output Complexity of Sorting,” CACM, 1988.
  • Jeffrey Vitter, Algorithms and Data Structures for External Memory, 2008.
  • CMU 15-445/645 Fall 2025,Sorting & Aggregation Algorithms,§§2–3:多路归并与聚合;四帧九页账本为本文自定。
关系图谱14 个相邻概念 · 3 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组
类型化关系