至少从标题搜索来看,似乎没有任何预先存在的问题。我正在寻找外部合并的最佳通行证数量。因此,如果我们有 1000 个数据块,那么一次将是 1000 路合并。两遍可能是 5 组 200 个块,然后是 1 组 5 个块的最终合并。等等。我做了一些数学运算,这肯定有缺陷,因为看起来两次传球永远不会胜过一次传球。不过,这很可能是对如何读取数据的误解。
首先,一个数值示例:
数据:100 GB
内存:1 GB
由于我们有 1GB 内存,我们可以一次加载 1GB 以使用快速排序或合并排序进行排序。现在我们有 100 个要排序的块。我们可以进行 100 路合并。这是通过制作RAM/(chunks+1)
大小桶 = 1024MB/101
=来完成的10.14MB
。10.14MB
100个块中的每一个都有 100 个桶,并且一个输出桶的大小也为10.14MB
. 当我们合并时,如果任何输入存储桶为空,我们会执行磁盘搜索以重新填充该存储桶。同样,当输出桶装满时,我们写入磁盘并将其清空。我声称“磁盘需要读取的次数”是(data/ram)*(chunks+1)
. 我从我们已经确定了输入桶大小的事实中得到了这一点,ram/(chunks+1)
我们必须为给定的 pass 读取整个数据,所以我们读取(data/bucket_size)
次。换句话说,每次输入桶清空时,我们都必须重新填充它。我们在这里做了 100 多个块,所以numChunks*(chunk_size/bucket_size)
=datasize/bucket_size
或100*(1024MB/10.14MB)
. BucketSize = ram/(chunks+1)
so 100*(1024/10.14)
= (data/ram) * (chunks+1)
= 1024*100MB/1024MB * 101
= 10100 次读取。
对于两遍系统,我们执行 A 组 B #chunks,然后最终合并 1 组 A #chunks。使用前面的逻辑,我们有 numReads = A*( (data/ram)*(B+1)) + 1*( (data/ram)*(A+1))
。我们也有A*B
= Data/Ram
。例如,10 个组,每组 10 个块,其中每个块是一个 GB。这里,A = 10 B = 10。10*10 = 100/1 = 100,即Data/Ram
。这是因为Data/Ram
是原始的块数。对于 2 次通过,我们想要Data/Ram
分成 A 组 B #chunks。
我将尝试在这里分解公式,让 D = 数据,A = #groups,B = #chunks/group,R = RAM
A*(D/R)*(B+1) + 1*(D/R)*(A+1)
- 这是 A 乘以 B #chunks 上的外部合并的读取次数加上 A #chunks 上的最终合并。
A = D/(R*B) => D^2/(B*R^2) * (B+1) + D/R * (D/(R*B)+1)
(D^2/R^2)*[1 + 2/B] + D/R
是 2 次通过外部合并的读取次数。对于 1 遍,我们有(data/ram)*(chunks+1)
where chunks = data/ram for 1 pass。因此,对于一次通行证,我们有D^2/R^2 + D/R
. 我们看到,只有当块大小 B 变为无穷大时,第 2 遍才达到这一点,即使如此,额外的最终合并也给了我们D^2/R^2 + D/R
. 所以一定有一些关于我错过的阅读,或者我的数学有缺陷。感谢任何花时间帮助我的人!