分拣网络如何击败通用排序算法?

Laz*_*zer 15 c sorting algorithm comparison sorting-network

关于最快排序的固定长度6 int数组,我不完全理解这个排序网络如何击败像插入排序这样的算法.

形成该问题,这里是完成排序所需的CPU周期数的比较:

Linux 32位,gcc 4.4.1,Intel Core 2 Quad Q8300,​​-O2

  • 插入排序(Daniel Stutzbach):1425
  • 排序网络(Daniel Stutzbach):1080

使用的代码如下:

插入排序(Daniel Stutzbach)

static inline void sort6_insertion_sort_v2(int *d){
    int i, j;
    for (i = 1; i < 6; i++) {
            int tmp = d[i];
            for (j = i; j >= 1 && tmp < d[j-1]; j--)
                    d[j] = d[j-1];
            d[j] = tmp;
    }
}
Run Code Online (Sandbox Code Playgroud)

排序网络(Daniel Stutzbach)

static inline void sort6_sorting_network_v1(int * d){
#define SWAP(x,y) if (d[y] < d[x]) { int tmp = d[x]; d[x] = d[y]; d[y] = tmp; }
    SWAP(1, 2);
    SWAP(0, 2);
    SWAP(0, 1);
    SWAP(4, 5);
    SWAP(3, 5);
    SWAP(3, 4);
    SWAP(0, 3);
    SWAP(1, 4);
    SWAP(2, 5);
    SWAP(2, 4);
    SWAP(1, 3);
    SWAP(2, 3);
#undef SWAP
}
Run Code Online (Sandbox Code Playgroud)

我知道排序网络非常适合并行排序,因为有些步骤与其他步骤无关.但在这里我们没有使用并行化.

我希望它更快,因为它具有预先知道元素的确切数量的优点.插入排序在何处以及为何进行不必要的比较?

EDIT1:

这是与这些代码进行比较的输入集:

int d[6][6] = {\
    {1, 2, 3, 4, 5, 6},\
    {6, 5, 4, 3, 2, 1},\
    {100, 2, 300, 4, 500, 6},\
    {100, 2, 3, 4, 500, 6},\
    {1, 200, 3, 4, 5, 600},\
    {1, 1, 2, 1, 2, 1}\
};\
Run Code Online (Sandbox Code Playgroud)

Dan*_*ach 19

但在这里我们没有使用并行化.

现代CPU可以确定指令何时是独立的并且将并行执行它们.因此,即使只有一个线程,也可以利用排序网络的并行性.

插入排序到底在哪里进行不必要的比较?

查看额外比较的最简单方法是手动做一个例子.

Insertion sort:
6 5 4 3 2 1
5 6 4 3 2 1
5 4 6 3 2 1
4 5 6 3 2 1
4 5 3 6 2 1
4 3 5 6 2 1
3 4 5 6 2 1
3 4 5 2 6 1
3 4 2 5 6 1
3 2 4 5 6 1
2 3 4 5 6 1
2 3 4 5 1 6
2 3 4 1 5 6
2 3 1 4 5 6
2 1 3 4 5 6
1 2 3 4 5 6

Sorting network:
6 5 4 3 2 1
6 4 5 3 2 1
5 4 6 3 2 1
4 5 6 3 2 1 # These three can execute in parallel with the first three
4 5 6 3 1 2 #
4 5 6 2 1 3 #
4 5 6 1 2 3
1 5 6 4 2 3
1 2 6 4 5 3
1 2 3 4 5 6
1 2 3 4 5 6
Run Code Online (Sandbox Code Playgroud)

  • @Daniel:很抱歉因为不清楚.换句话说,如果排序网络效率更高,我们为什么要使用插入排序? (2认同)
  • @Lazer:啊,这更有意义.:-)感谢您的澄清!排序网络的问题在于它们仅适用于固定的n.此外,它们仅在n很小时才实用,因为你必须手动写出所有的比较和交换,并且它们将有O(n log n).它们的速度很快,部分原因是代码被写出来并且没有循环,因此速度是限制的一部分. (2认同)
  • @Lazer:是的,这就是我的意思。:-) 如果一个算法使用变量 n,它需要在某个地方有某种循环。排序网络没有循环。您可以编写一个程序来生成交换然后执行它们,但是生成交换会消耗比使用排序网络节省的时间更多的时间。最接近的是使用递归算法,如 MergeSort 或 QuickSort,并使用排序网络作为基本情况。 (2认同)