我正在阅读wikipedia的外部排序,需要了解为什么2阶段合并比1阶段合并更有效。
Wiki:但是,单程合并存在限制。作为 块的数量增加,我们将内存分成更多的缓冲区,所以 每个缓冲区都较小,所以我们必须做很多较小的读取 而不是更大的。
因此,使用单个合并对100 MB RAM中的50 GB进行排序 pass效率不高:磁盘需要填充输入 来自500个块中每个块的数据的缓冲区(我们读取100MB / 501~ 每次从每个块200KB)占用大部分的排序时间。运用 两个合并过程解决了这个问题。然后排序过程可能会 看起来像这样:
Run the initial chunk-sorting pass as before.
Run a first merge pass combining 25 chunks at a time, resulting in 20 larger sorted chunks.
Run a second merge pass to merge the 20 larger sorted chunks.
有没有人能给我一个简单的例子来理解这个概念。我特别感到困惑的是在2阶段合并中分配更多buffers
。
答案 0 :(得分:0)
问题是随机访问开销,平均旋转延迟大约为4毫秒,平均搜索时间大约为9毫秒,所以说平均访问时间为10毫秒,而平均传输速率大约为每秒150兆字节。因此,平均访问开销与读取或写入1.5兆字节的时间大致相同。
大I / O减少了访问时间的相对开销。如果一次读取或写入10兆字节的数据,则开销降低到15%。使用wiki示例100MB的工作缓冲区和25个块进行合并,加上一个用于写入的块,这是3.8兆字节的块,在这种情况下,随机访问开销约为39%。
在大多数PC上,可以为1GB工作缓冲区分配足够的内存,因此每块超过40兆字节的26个块,将随机访问开销减少到3.75%。每块大约50个块大约20兆字节,随机访问开销约为7.5%。
请注意,即使有50个块,它仍然是两次通过排序,第一次使用所有1gb缓冲区进行内存排序,然后写入已排序的1gb块。第二遍合并了导致排序文件的所有50个块。
50个块的另一个问题是,需要一个最小堆类型方法来维护已排序的信息,以便确定哪个块的哪个块是50中最小的块并移动到输出缓冲区。将元素移动到输出缓冲区后,将新元素移入堆中,然后重新堆化堆,这需要大约2 log2(50)次操作,或大约12次操作。这比做49的简单方法要好,以便在进行50路合并时确定50个元素组中的最小元素。堆由结构,当前元素组成,它是块(文件位置或文件),块中剩余的元素数,......。