02 The Polyphase Merge.md
我们已经知道了如何构建初始顺串,现在考虑各种合并模式,合并就是把顺串分布到各个磁带上,合并直至只剩一个顺串为止。
假定有三个磁带 ,考虑 5.4 里面描述的平衡合并,,形式如下: * B1. 交替的在 上分布顺串 * B2. 把 上的顺串合并到 ,如果 仅包含一个顺串时停止 * B3. 把 的顺串交替的拷贝回 ,跳到 B2
如果初始时有 个顺串,第一次合并将在 上产生 个顺串,第二次产生 ,以此类推。如果说 ,一次分配扫描,五次合并扫描,四次拷贝扫描。一般地,,扫描次数是 。
拷贝扫描完全是不必要的,因为并没有减少顺串。如果采用两阶段方式,可以减少一半的拷贝。 * A1. 交替的在 上分布顺串 * A2. 把 上的顺串合并到 ,如果 仅包含一个顺串时停止 * A3. 把 上一半的顺串拷贝到 上 * A4. 把 上的顺串合并到 ,如果 仅包含一个顺串时停止 * A5. 把 上一半的顺串拷贝到 ,跳回 A2
对数据扫描次数减少到了 ,因为 A3 和 A5 只拷贝了一半的数据,节省了大约 25% 的时间。
上有 个顺串, 上有 个顺串,其中 是连续的斐波那契数,那么可以完全消除不必要的拷贝。比如下面是 的情况:
Phase | Contents of T1 | Contents of T2 | Contents of T3 | Remarks |
---|---|---|---|---|
1 | 1,1,1,1,1,1,1,1,1,1,1,1,1 | 1,1,1,1,1,1,1,1 | Initial distribution | |
2 | 1,1,1,1,1 | - | 2,2,2,2,2,2,2,2 | Merge 8 runs to T3 |
3 | - | 3,3,3,3,3 | 2,2,2 | Merge 5 runs to T2 |
4 | 5,5,5 | 3,3 | - | Merge 3 runs to T1 |
5 | 5 | - | 8,8 | Merge 2 runs to T3 |
6 | - | 13 | 8 | Merge 1 run to T2 |
7 | 21 | - | - | Merge 1 run to T1 |
每个初始顺串长度为 1,2 表示长度为 2 的顺串,以此类推。上表中到处都是斐波那契数。
只有第一阶段和第七阶段对数据进行了完全扫描,第二阶段处理了 16/21,第三阶段仅仅处理了 15/21。如果假设初始顺串都差不多长,那么总共处理的数据量是 ,同样的数据两阶段需要 8 次扫描。一般地,满足这种斐波那契分布的模式,需要 次扫描,和 4个磁带的平衡合并一样快,但是只用了 3 个磁带。
同样的思想可以推广到 个磁带。对于 ,使用 路合并。后面会看到对于 4 个磁带的情况下,数据扫描次数是 。推广形式涉及到了广义的斐波那契数列。先考虑 的情况。
Phase | T1 | T2 | T3 | T4 | T5 | T6 | Initial runs processed |
---|---|---|---|---|---|---|---|
1 | - | 31 + 30 + 28 + 24 + 16 = 129 | |||||
2 | - | 16 × 5 = 80 | |||||
3 | - | 8 × 9 = 72 | |||||
4 | - | 4 × 17 = 68 | |||||
5 | - | 2 × 33 = 66 | |||||
6 | - | 1 × 65 = 65 | |||||
7 | - | - | - | - | - | 1 × 129 = 129 |
这里 表示 31 个长度为 1 的顺串, 表示 8 个长度为 9 的顺串,等等。R. L. Gilstad 提出这种模式,称为多阶段合并(polyphase merge
)。三个磁带的情况更早的时候由 B. K. Betz 提出的。
为了像上面的例子这样分配合并,我们需要完美的斐波那契分布。 时,自底向上看分布分别是 。现在我们面临以下四个问题: 1. 这些完全斐波那契数基于什么规则分布的? 2. 如果 不能对应完全斐波那契分布怎么办? 3. 我们应该如何设计初始分布使得它们在磁带上是期望的分布情况? 4. 个磁带, 个初始顺串,扫描多少次?
我们按序讨论这几个问题,先给出一个“简单的答案”,再进行更详细的分析。
完全斐波那契分布可以通过周期地转动磁带内容、向后运行而得到。下面是 的具体例子。
Level | T1 | T2 | T3 | T4 | T5 | Total | Final output will be on |
---|---|---|---|---|---|---|---|
0 | 1 | 0 | 0 | 0 | 0 | 1 | T1 |
1 | 1 | 1 | 1 | 1 | 1 | 5 | T6 |
2 | 2 | 2 | 2 | 2 | 1 | 9 | T5 |
3 | 4 | 4 | 4 | 3 | 2 | 17 | T4 |
4 | 8 | 8 | 7 | 6 | 4 | 33 | T3 |
5 | 16 | 15 | 14 | 12 | 8 | 65 | T2 |
6 | 31 | 30 | 28 | 24 | 16 | 129 | T1 |
7 | 61 | 59 | 55 | 47 | 31 | 253 | T6 |
8 | 120 | 116 | 108 | 92 | 61 | 497 | T5 |
初始化之后,T6 总是空的。 从 到 级,下面条件总是成立的: 同时,我们可以从 到 分析出它们之间的关系: 其中 , 时,。 阶斐波那契数 定义如下: 也就是说开始的时候有 个 0 和一个 1,然后每个数是前面 个数之和。 时就是通常的斐波那契数列。对于更大 的序列,Narayana Pandita 开始研究,V. Schlegel 在前人的基础上给出了生成函数: 公式 最后一个等式告诉我们六个磁带多阶段合并,T1 顺串数是五阶斐波那契数 。
一般地,如果令 , 个磁带的多阶段合并分布对应于第 阶斐波那契数。对于 ,完全斐波那契分布情况下,第 个磁带在 级初始顺串是 所有磁带总的顺串数是 这样就解决了完全斐波那契分布的问题。对于任意 ,不能完全分布的话,要怎么做呢?
可以向平衡合并的例子一样,加入虚拟顺串,使得 是完全的。我们不会先讨论最优解,而是先讨论分布的方法和指定虚拟顺串的方法,该方法不见得是最优的,但是很简洁,而且比其他同样简洁的方法要好些。
算法 D (Polyphase merge sorting with "horizontal" distribution
) 该算法一次分布一个顺串,直到初始顺串都被分配了为止。然后时合并这些顺串。假定 个磁带,使用 路合并。磁带 用于保存输入,因为它不会被分配初始顺串。下面是要维护的一些状态:
* ,我们追寻的完全斐波那契分布
* ,逻辑磁带 开头的虚拟顺串的个数
* ,逻辑磁带 对应的物理磁带号
下面是算法步骤: * D1. [Initialize.] 对于 ,初始化 ,。最后初始化 。 * D2. [Input to tape .] 写一个顺串到磁带号 的磁带,。如果所有顺串分配完毕,跳转到 D5。 * D3. [Advance .] 如果 , 然后跳转回 D2;否则如果 ,调转到 D4,否则设置 调回 D2。 * D4. [Up a level.] 设置 ,按 的顺序依次执行 。注意, 一直都是 0。这时,。设置 并跳转回 D2。 * D5. [Merge.] 如果 ,排序完成并且输出放在 TAPE[1] 上。否则把 合并到 直到 为空且。合并的时候做如下操作:如果对于所有的 ,都有 ,也就是所有的都是虚拟顺串,那么对于所有的 都执行 ,并且 ,否则的话从 的磁带 取出一个顺串进行合并,然后对于其他包含虚拟顺串的 执行 。这里,利用了一个假设信息,就是虚拟顺串在每个磁带的前面。 * D6. [Down a level.] 执行 ,并且将磁带 绕回。然后调转一下磁带集 ,然后调回 D5。
整个流程如下图所示:
步骤 D3 非常简洁的给出了分布的方法,就是假设有等量的虚拟顺串在每个磁带的开始。下图是六个磁带的具体例子,阴影部分是分配好的顺串,现在是从 4 级(33 个顺串)到 5 级(65 个顺串),开始分配顺串 34。假设只有 53 个初始顺串,那么大于等于 54 的顺串都是虚拟顺串了。这里虚拟顺串在磁带尾部,但是最好想象它们在头部,然后算法也是按照在头部描述的。
已经回答了三个问题,还剩一个就是扫描次数。六个磁带的详细情况列在了上面的表中,当 时,处理的初始顺串总数是 ,这里不包括初始分布时的扫描。习题 4 推导出生成函数 一般地,当 时,初始顺串的处理次数是 中 的系数加上初始分配的 。习题 5 到习题 7 会给出多阶段合并的渐进结果,下面的表是前几项:
Tapes | Phases | Passes | Pass/phase | Growth ratio |
---|---|---|---|---|
3 | 72% | 1.6180340 | ||
4 | 62% | 1.8392868 | ||
5 | 57% | 1.9275620 | ||
6 | 54% | 1.9659482 | ||
7 | 52% | 1.9835828 | ||
8 | 51% | 1.9919642 | ||
10 | 50% | 1.9980295 | ||
20 | 50% | 1.9999981 |
上表中的增长率是 ,表示每一级增长时,顺串个数增长的近似因子。扫描表示每个记录被处理的平均次数,即 乘以分布和合并阶段处理的初始顺串的总数。对于完全分布, 时,存在 ,在每种情况下扫描和阶段数最高是 。
下图展示了算法 D 处理不完全的情况下每个记录平均数扫描的次数,这是 的函数。对于 的时候,会有不高效的峰值,但是对于更多的磁带而言这种情况就不显著了。同时,8 或者 10 个磁带相比 6 个磁带,差距已经不大了。
习题
习题 1 可以参考算法 D 运行一下,也可以参考 的那个例子(一个表格)来分析前几级每个磁带怎么放置顺串。
1 | |||||
2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | ||
10 13 |
11 14 |
12 15 |
16 |
17 |
|
18 20 24 29 |
19 21 25 30 |
22 26 31 |
23 27 32 |
28 33 |
习题 4 从公式 可以得到
TODO 补充 A Walk Through Combinatorics
关于生成函数的链接
两遍同乘 的,然后对 求和得到
由于 ,所以作用同时加上 1,可以得到
右边第一项 ,所以等于从 0 开始求和,可以写作
其余各项由于负数项都等于零,类似地,可以得到
从公式 可以得到关于 的公式 根据生成函数的加法和移位的原理