為什麼處理已排序陣列比處理未排序陣列更快?

2021-06-28 01:37:11 字數 2035 閱讀 2477

很久以前在stackoverflow上看到下面這段**,今天忍不住把它摘錄過來。

#include #include #include int main()

}double elapsedtime = static_cast(clock() - start) / clocks_per_sec;

std::cout << elapsedtime << std::endl;

std::cout << "sum = " << sum << std::endl;

}

上面的程式在保留std::sort(data, data + arraysize);語句時,程式執行時間是 1.93 秒;但去掉排序語句後,程式執行時間是 11.54 秒。

問題:為什麼會出現這種情況?

解答:分支**。

考慮以下 if 語句塊。對於處理器來說,就是乙個分支指令,如下:

處理器每次遇到一條分支時,它都不知道該走哪一條道。這時候該怎麼辦?程式停下來,等待前面的指令執行完,得到確切的結果後,再接著走某一條分支。

現代處理器都支援指令並行處理和超流水線作業。因此,當處理器遇到程式分支時,都會去猜測應該走哪一條分支。

如果猜對了,程式接著流暢執行。如果猜錯了,則處理器需要做一些額外的工作,再次回到那條正確的分支。

因此,如果處理器每次都猜錯,那程式的執行時間就會邊長。

這就是上面的**為什麼執行時間會相差那麼大的原因。

對於分支語句:

if (data[c] >= 128)

sum += data[c];

在保留std::sort(data, data + arraysize);的情況下。陣列 data 中的內容是這樣的:

t = branch taken

n = branch not taken

data = 0, 1, 2, 3, 4, ... 126, 127, 128, 129, 130, ... 250, 251, 252, ...

branch = n n n n n ... n n t t t ... t t t ...

= nnnnnnnnnnnn ... nnnnnnnttttttttt ... tttttttttt (easy to predict)

在未排序的情況下,陣列 data 中的內容是這樣的:

data = 226, 185, 125, 158, 198, 144, 217, 79, 202, 118,  14, 150, 177, 182, 133, ...

branch = t, t, n, t, t, t, t, n, t, n, n, t, t, t, n ...

= ttnttttntnntttn ... (completely random - hard to predict)

也就是說,在已經排序的情況下,處理器便能更好的**分支了。因此,程式也執行的更快。

閱讀 linux 源**時,你會發現if(likely( )){}或是if(unlikely( ))這樣的語句。對於條件選擇語句,gcc 內建了一條指令用於優化,在乙個條件經常出現,或者該條件很少出現的時候,編譯器可以根據這條指令對條件分支選擇進行優化。而 linux 核心把這條指令封裝成了巨集likely()unlikely()

因此,在編寫程式時,如果乙個分支條件只有在很少數的情況下才出現時,我們使用unlikely( )likely( )能夠加快程式的執行,這也是一種優化程式的手段。

比如這樣:

if ( unlikely(statement) )
via 快課

已排序陣列二分查詢

劉汝佳 紫書提供方法 正確答案在 x,y 區間之內,即不會包括y。這種方法老是兩個細節搞不順,如下標註 int bsearch int a,int x,int y,int test return 1 沒有正確答案時返回 1 下面是一種邏輯清晰通順的實現寫法 只有兩個小細節不一樣,但理解起來很自然 以...

已排序陣列刪除重複元素

刪除排序陣列中的重複項 思路可以轉變為 前提陣列有序 可以理解為相鄰元素間要不相同,要不不同 要求刪除重複元素,實際上就是將不重複的元素移到陣列的左側。假如乙個有序陣列為 1,1,1,2,2,3,4,5 使用雙指標法 快慢指標 分別為p和q 在迴圈遍歷過程中,第一輪可以將陣列表示為 p在1的位置上q...

去除已排序陣列中的重複元素

給定乙個已排序的陣列,去除陣列中的重複元素,只保留乙個重複的元素,並且返回新的陣列長度。要求 不要給陣列分配額外的空間,你必須使用常量的記憶體大小進行原地操作。例如 給出陣列a 1,1,2 你的函式呼叫之後必須返回長度length 2,並且a現在變成 1,2 乙個已排序的陣列,例如 1,1,2 返回...