外部排序思想

现在我要进行排序,不过需要排序的数据很大,有1000G那么大,但是我的机器内存只有2G大小,所以每次只能把2G的数据从文件中传入内存,然后用一个“内部排序“算法在内存排好序后,再将这有序数据,载入一个2G大小的文件。然后再载入第二个2G数据。。。循环500遍之后,我现在得到500个文件,每个文件2G,文件内部是有序的,然后我再比较这500个文件的第一个数,最小的肯定就是这1000G数据的最小的。那么之后的过程你肯能想到了,就是不断将这500个2G 数据进行一个归并,最终就能得到这1000G的有序数据文件了。

举个例子,比如我要排序10个数,但是我的内存一次只能装下5个数,所以最初的10个数我只能放到文件里面(文件时外存,只要硬盘或磁盘够大,想多大就多大)。内部排序肯定是得需要将数据载入内存中才可以进行的。

这10个数是[ 2 ,3,1,7,9 ,6, 8,4 ,5 ,0 ]。

第一次载入前五个数2,3,1,7,9. 排好序后是:1,2,3,7,9 然后导入一个只存五个数的文件中。

第二次载入后五个数6,8,4,5,0 排好序后是:0,4,5,6,8,然后倒入一个只存五个数的文件中。

之后在归并两个有序数列

第一个有序子数列的头位1,第二个为0,因为0然后在进行第二次比较,1和4进行比较。。。

重复进行最终得到一个有序数列的文件,里面存着,0,1,2,3,,,7,8,9

问题是:在这个过程中,你能想到哪些优化?

(擦,,,背景描述了半天,问题就一句话。。。当时我也很无语。。。)

解答:

想了大概一分钟,除了增设一个缓冲buffer,加速从文件到内存的转储之外,我脑子里面一片空空。。。而且我想到的那个缓冲buffer所得到的回复是“假设这个优化系统已经帮你优化了” 。。。无语。。。

他看我眉头紧锁,然后给我做了一个提示:假设我现在把文件中的2G数据载入内存这个过程定义为”L”,把内存中的排序过程定义为”S” ,把排序好的 2G数据再转储到另一个文件这个过程定义为”T”…

他还没说完,瞬间反应过来了!“用流水线并行实现“,然后我把流水线那个图画了出来,就是在计算机组成原理那本书中经常出现的“流水线图”。图画好后,他点点头,我也长嘘一口气。。。

然后他问我,用流水线技术之后为什么会加速整个过程。

当然这个问题就很容易了,过去得把一组2G数据的三个过程全部处理完之后,才能进行下一个2G数据的处理,现在就可以三个过程并行着进行了。当时我也忘了,加速比怎么计算了,所以就没提这个东西。。。

他接着问,做了这个并行处理之后,会出现什么问题?

。。。MD,又是一个恶心问题,其实我清楚,问题不难,但是“找问题”好讨厌啊。。。

想了一下,我说,在“S”这个过程,也就是内部排序的这个环节最好不要用“快速排序”,因为快速排序是不稳定的排序,所以在流水线那个图中会出现不均匀的时间块,影响整体性能。

他想了一下,点点头。问,还有吗?给你个提示吧,你想想加了这个优化之后,某个资源会不会出问题?

我想了想,“资源”,计算机的资源没几样啊,CPU,内存。。。再一次,瞬间恍然大明白,是内存出的问题,因为,如果并行进行的话,打个比方,比如现在同时处理的过程是,第一个2G数据的“T”阶段(因为第一个2G数据,比较早的进入流水线,所以之前的两个阶段已经处理完毕),第二个2G数据的“S”阶段,第三个2G数据的“L”阶段,那么这三个阶段是都需要把数据放到内存中的,所以一共得需要6G内存,但是目前计算机的实际内存只有2G啊!!!

解决方法很简单,将内存平均分为三份,分别用于处理三个阶段的数据。

这样带来的影响是,现在一次就不能处理2G数据了,只能处理2/3G的数据,流水线会加长。

他看这块处理的差不多了,就继续提示,你看看在最后的归并上有什么优化?

最后的归并就是不断在一组有序数列中找最小值,还用刚才那个例子,最后不是得到500个2G有序数列吗,但是扫描每个文件头,找最小值,最差情形要比较500次,平均复杂度是O(n),n为最后得到的有序数组的个数,此例子为500。

他既然问有没有什么优化?那么必然是存在logn的算法了。一提logn和最小值,那没的说,必须是“堆”啊!!!

然后我给他说了一下具体实现细节

就是维护一个大小为n的“最小堆”,每次返回堆顶元素,就为当前所有文件头数值的那个最小值。然后根据刚才弹出的那个最小值是属于哪个文件的,然后再将那个文件此时的头文件所指向的数,插入到最小堆中,文件指针自动后移。插入过程为logn复杂度,但是每次返回最小值的复杂度为O(1),运行时空间复杂度为O(n)。 OK,搞定。

总结:

优化包括:
1.缓存。加快数据读入到内存中。
2.流水线。将排序过程分为,读取数据→排序数据→写数据。3条线程并行处理。所以你在将数据分解到每一个文件中的时候,确保每个文件的大小最好是所给内存的1/3。
3.堆排序。根据堆排序的插入logn以及返回最小值o(1)。
单个文件排序用快排,最后的外部排序用堆排序。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值