合并排序 - 按缓存行大小优化?

时间:2015-10-16 17:44:40

标签: arrays sorting caching mergesort insertion-sort

我的一位朋友最近提到,你可以通过“缩短它”来减少合并排序的实际运行时间。他没有将数组分解为各个块,而是提到应该停止在各个数组大小等于缓存行大小的位置,因为整个数组将被加载到缓存中。此时,您应该使用替代排序(即插入排序)来合并每个阵列,然后完成合并排序。

虽然BigO建议不然,但他的建议似乎具有直观意义。有人可以确认或否认这一点,和/或提供有关其工作原理和原因的更多信息吗?

感谢帮助人员!

3 个答案:

答案 0 :(得分:0)

嗯,(有点抽象)答案是Big-O只对大数字有用:它抛弃了常数因子:O(n)= O(3n),抛出低阶项:O(n² + 3N)= O(N²)。所以是的,你无法用Big-O表示法来判断。

此外,Big-O表示法通常用于一个非常简单的模型,其中每个“操作”只花费1,而且它不知道缓存。

这就是为什么模型没有告诉你这可能有用。我想你可以看看Donald E. Knuth的“排序和搜索”,在那里他用虚构的汇编语言对运行时分析进行了较低的术语(但仍然不考虑缓存,IIRC)。

答案 1 :(得分:0)

插入排序组合创建小运行,然后切换到合并排序称为timsort。维基文章:

http://en.wikipedia.org/wiki/Timsort

答案 2 :(得分:0)

使用 O ΩΘ等)分析复杂性仅用于描述算法如何作为输入执行规模增长。如果查看实际函数,可以看到随着输入的增长,常数因子变得不那么重要了。总的来说,输入大小占主导地位。

在实践中,常数因素确实很重要(缓存未命中,指令延迟等等),这就是为什么RadixSort通常很少使用的原因。例如,从寄存器读取大约需要从缓存中最低级别读取的时间的1/5(大约是下一级别的1/5等等)。由于它们是数量级的,实际上缓存成本通常主导算法的实际性能。

插入排序确实可以非常有效地使用缓存,通常只要数据适合缓存。由于它是连续的,它也与预测器很好地相互作用。两者都是为什么对较小的投入更好的原因。另一个很好的例子是QuickSort,它在技术上是O(n^2),但在实践中仍然使用很多,因为它具有更好的缓存特性。 TimSort(Python和Java的默认值)也对较小的输入使用插入排序。