簡體   English   中英

分揀網絡如何擊敗通用排序算法?

[英]How does a sorting network beat generic sorting algorithms?

關於最快排序的固定長度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;
    }
}

排序網絡(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
}

我知道排序網絡非常適合並行排序,因為有些步驟與其他步驟無關。 但在這里我們沒有使用並行化。

我希望它更快,因為它具有事先知道元素的確切數量的優點。 插入排序在何處以及為何進行不必要的比較?

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}\
};\

但在這里我們沒有使用並行化。

現代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

更好的問題是為什么排序網絡僅比插入排序(通常非常慢的排序)高出約50%。 答案是,當n很小時,大O不是那么重要。 至於OP的問題,丹尼爾有最好的答案。

我認為循環展開是導致排序網絡算法更快結果的原因

我相信在並行算法和串行算法中完成的“工作量”總是幾乎相同。 只有這樣,因為工作分配,你會更快地得到輸出。 我認為如果輸入的大小足以證明使用並行算法是合理的話,你會更快地獲得輸出。

在插入的情況下,處理器之間的陣列分類是這樣的,它形成一個流水線,並且填充流水線需要一些時間,然后它將產生並行算法的好處。

理論上,如果編譯器可以完全展開插入排序中的循環,則代碼可能大致相同。 第一個循環可以很容易地展開,而第二個循環不能輕松展開。

也可能是這樣的情況,因為代碼不像網絡排序代碼那么簡單,編譯器可以進行較少的優化。 我認為插入排序中的依賴關系多於網絡排序,這可能會在編譯器嘗試優化代碼時產生很大的不同(如果我錯了,請糾正我)。

我想你們所有的問題都在Daniel Stutzbach的回答中回答了原帖:

您發布的算法類似於插入排序,但看起來您已經以更多比較為代價減少了掉期數量。 然而,比較遠比交換更昂貴,因為分支可能導致指令管道停滯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM