External Sorting¶
约 1280 个字 12 张图片 预计阅读时间 4 分钟
Info
- 外部排序(External Sorting) 是一种用于处理无法完全加载到内存中的大规模数据集的排序算法。外部排序通过将数据分块处理,每次只加载一部分数据到内存中进行排序,然后将排序后的数据块合并,最终得到排序后的完整数据集。
Implementation¶
- 外部排序通常采用 归并排序(Merge Sort) 的思想,分为两个主要步骤:
-
分块排序(Run Generation):
-
将大数据集分成多个可以加载到内存的小块。
-
对每个小块在内存中进行排序,并将排序后的数据块写回磁盘。
-
-
多路归并(Multi-way Merge):
-
将多个已排序的数据块逐步合并,直到得到一个完整的排序数据集。
-
使用优先队列(最小堆)来高效地进行多路归并。
-
Example
-
先引入三个概念:1.block:我们把大的数据集划分成小block;2.run:我们把大的数据集划分成小块,小块在内存中排序好的结果叫做run;3.pass:我们在磁盘中进行的划分和归并算作一次pass
-
\(Pass = 1+\lceil\text{log}_2(N/M)\rceil\)(初始的划分算一次pass,后面归并会使得每次数据减半,因而是开log,然后取上整)
Optimize¶
- 影响这个算法性能的因素主要有4个:
-
Seek time —— \(O(number of passes)\)
-
Time to read or write one block
-
Time to internally sort
-
Time to merge
- 所以,我们的目标是:
-
减少pass次数
-
加速run之间合并的速度
-
run的generation能快速一点
减少pass次数¶
-
我们来看pass的公式:\(Pass = 1+\lceil\text{log}_2(N/M)\rceil\),其中N、M、1都动不了,我们能动的只有log的底数\(2\);然后这个底数,其实就是每次merge序列的数量
-
所以,我们采用k-way merge;然后用最小堆来加速多路归并
-
此时,\(Pass = 1 + \lceil\text{log}_k(N/M)\rceil\)
-
但代价就是需要更多的tapes,\(tapes = 2k\)
3-way merge with 最小堆
Polyphase Merge¶
-
上面那种均匀地划分,会使用到2k个tapes;空间成本大
-
于是想到了一种不均匀的划分方式,其中我们聪明地把每次要merge数拆成两个相邻的斐波那契数\(F_{N-1},F_{N-2}\)
-
这种划分方式来merge,会稍微多一点pass,但是只需要\(k+1\)个tapes
使用IO和CPU并行来提高读写buffer效率¶
-
把output buffer进行划分,使得能一边IO操作,一边进行存储比较得到的结果
-
把input buffer也进行划分,这样如果其中一个序列读完了,可以让下一个接着来,别闲着(让输入的IO也和CPU处理并行)
generate longer run¶
-
原来我们是认为每个run的大小是和内存大小相同
-
但假如我们使用最小堆维护内存里的数据,那么每次DeleteMin之后,内存就会空出一个位置,可以让我们读进来新的数据,于是就能generate longer run
Example--generate longer run
Minimize the merge time¶
-
例:给定4个runs,长度分别是:2,4,5,15;如何安排合并的顺序,可以使得merge时间最短;(merge的时间就是参与合并的两个序列的长度和,比如第一次选择2和4,时间就是2+4;第二次选择5和6,时间就是5+6)
-
那么很明显,我们每次都选择长度最短的两个序列来合并就好了,合并的序列长度再放回去;这就是Huffman algorithm,我们由此构建出一棵Huffman Tree