【问题标题】:Adaptive sorting algorithms versus sorting networks for sorting a list of 32 random elements自适应排序算法与排序网络对 32 个随机元素的列表进行排序
【发布时间】:2018-10-07 00:44:39
【问题描述】:

如果我们使用顺序机器(无法进行并行比较),其中比较是按顺序进行的,并且我们希望在对 32 个随机元素进行排序时尽量减少处理器时钟周期数,我们应该使用排序网络还是自适应排序算法?

对于 n=32 个元素,目前还没有最佳网络。实际上,如果我们想尽量减少 CPU 时钟周期数,是否最好将 32 个元素分成 n=8 的四个子列表,并在每个子列表上应用最优排序网络,然后将列表合并在一起?

我们显然在这里使用“平均性能”,因为如果我们得到一个已经排序的列表,自适应算法会很幸运。

计算得到以下数字:

对大小为 n 的列表进行排序:

  • n=2 的最小比较次数为 1。

  • n=4 的最小比较次数为 5。

  • n=8 的最小比较次数为 19。

合并两个大小为 n 的列表:

  • 合并两个 n=2 的列表是 2*n - 1 = 3 次比较

  • 合并两个 n=4 的列表是 2*n - 1 = 7 次比较

  • 合并两个 n=8 的列表是 2*n - 1 = 15 次比较。

  • 合并两个 n=16 的列表是 2*n - 1 = 31 次比较。

如果我们将 n=32 划分为 16 个 n=2 子列表,则比较的总次数:

  • 排序:1*16 = 16
  • 合并:3*8 + 7*4 + 15*2 + 31*1 = 113
  • 总数:129

如果我们将 n=32 分成 8 个 n=4 子列表,则比较的总次数:

  • 排序:5*8 = 40
  • 合并:7*4 + 15*2 + 31*1 = 89
  • 总数:129

如果我们将 n=32 分成四个 n=8 子列表,则比较的总数:

  • 排序:19*4 = 76
  • 合并:15*2 + 31*1 = 61
  • 总数:137

现在人们可能会认为将 n=32 个元素划分为 n=2 或 n=4 个子列表会更好,因为比较的总数更少。但是 mergin 需要存储部分数组“异地”,这可能会抵消较少比较的好处?

我的直觉告诉我,平均而言,非自适应排序网络在总比较方面类似于算法,但排序网络因开销较小而获胜,对吗?


我试图在平均不到 1200 个时钟周期内对 n=32 个元素进行排序。我正在 on a simple sequential machine 使用简单的 256 字 * 16 位内存和只有四个寄存器,因此网络/算法必须简单、快速且不需要大量空间。 ALU 仅具有加法、减法、一位移位、一位旋转、AND 和 OR 功能。内存和 ALU 操作各需要一个时钟周期。

【问题讨论】:

  • 大多数排序算法都是 n*log(n),即 32*5 = 160。除了像基数排序这样的专业,但这取决于你要排序的值类型(如果你想对值 0-15 进行排序,您可以使用具有 16 个元素的计数数组,总共可以在大约 90 条指令中对其进行排序(16 到零计数数组,32 到计数元素,32 到输出排序数组))。这些元素真的是随机的,还是它们的“随机性”中存在一些弱点,让你有机会对它们有所期待? (在几乎排序的数组上,一些排序算法会比其他算法执行得更好)这会做什么?
  • (对我来说听起来有点像某种硬件精灵或类似的东西,所以在没有完全准确排序的情况下可能有一些丑陋的捷径来实现它)
  • 正如 cmets 中所指出的,32 个项目的最佳排序网络需要大约 160 次比较。这意味着您必须平均每次比较 7.5 个周期。我不知道你的机器的指令时间是多少,但这似乎很有野心。从内存中加载两个操作数、减法、比较和分支,所有这些都在不到 7.5 个周期内完成?然后将交换时间(另外两次内存访问)乘以所需的平均交换次数。考虑到这些限制,您确定您的问题甚至可以解决吗?
  • 我认为您没有足够的内存或足够快的 ALU 移位器来有效地进行 RadixSort。不过,您可以将高 1 或 2 位旋转到底部并屏蔽其他位。当您只有 4 个寄存器时,仅分析比较次数是一种完全有缺陷的方法;如果需要跟踪更多的东西,一些算法将需要更多的溢出/重新加载。 请更新您的机器如何访问内存:您是否总是需要在使用前加载到寄存器中,或者您是否有从 ALU 寄存器中减去内存操作数的指令?喜欢sub reg,[mem]
  • 这里要区分两种排序模型:在通用计算机上排序(通常指定为RAM)与使用专用的sorting network。我想你的机器(虽然 heavly 未指定)是(much 更接近)通用 RAM。令人困惑的是(?),排序 n 值所需的比较次数的最小上限对于仅从 5 开始的网络更高。 “RAM 风格”将有利于进行代价高昂的比较、带有条件移动的网络。

标签: arrays algorithm sorting optimization sorting-network


【解决方案1】:

堆排序是 nlogn。索引计算很简单——要比较的项目始终具有 n, 2n+{1,2 } 的索引,使其在您的架构中具有计算效率。

堆排序的主力基本上是套路:

while(true){
    r=(i+1)*2; l=r-1;
    if (*l > * i) { 
       if (*r > *l) swap(i,r);
       else swap(i,l);
    }
    else { 
       if (*r >* i) swap(i,r);
       else break;
    }
 }

交换操作还必须将地址i 更新为lr。 与教科书的解决方案不同,我们不检查孩子的地址是否有效,但我们交换空间以加快在数组末尾分配 32 个零的缓冲区。一旦i 不大于任何一个孩子,对堆底部的遍历就结束了。

【讨论】:

    猜你喜欢
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-17
    • 2014-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多