2014-02-13 58 views
10

我正在寫一些音頻代碼,基本上一切都是一個小循環。據我瞭解,分支預測失敗是一個足夠大的性能問題,我很難保持代碼分支免費。但是,只有到目前爲止,可以帶我,這讓我想知道不同種類的分支。分支預測與分支目標預測之間的性能差異?

在C++中,條件轉移到固定目標:

int cond_fixed(bool p) { 
    if (p) return 10; 
    return 20; 
} 

和(如果我沒有理解this question正確),無條件轉移到變化的目標:

struct base { 
    virtual int foo() = 0; 
}; 

struct a : public base { 
    int foo() { return 10; } 
}; 

struct b : public base { 
    int foo() { return 20; } 
}; 

int uncond_var(base* p) { 
    return p->foo(); 
} 

是否有性能差異?在我看來,如果兩種方法中的一種明顯比另一種快,編譯器會簡單地將代碼轉換爲匹配。

對於分支預測非常重要的情況,有關性能的詳細信息有助於瞭解?

編輯x : 10 ? 20的實際操作僅僅是一個佔位符。分支之後的實際操作至少非常複雜,以至於兩者效率不高。此外,如果我有足夠的信息來明智地使用__builtin_expect,在這種情況下分支預測就不成問題。

+0

哪個CPU?哪個編譯器?你是否檢查了會議以瞭解採取哪兩種策略? –

+1

注意:編譯器不能轉換後者'uncond_var',因爲它不知道'base'的可能派生類的完整集合。一般而言,* closed *問題(有限數量的可能輸入)比* open *問題更容易解決。 –

+0

@MatthieuM。編譯器GCC,處理桌面到智能手機的任何東西,儘管現代桌面CPU是我目前關心的問題。另外,我覺得編譯器不知道所有可能的基類派生類,這似乎很奇怪。它有所有的源代碼,所以這個信息存在。不,我對集會感到不夠熟悉,無法感受到這種細節。這就是爲什麼我轉向這個網站,希望從知道這些細節的人那裏得到更高層次的理解。 – porgarmingduod

回答

1

你沒有提到你的編譯器。我曾經使用過GCC作爲一個性能關鍵的應用程序(實際上是在我的大學舉辦的比賽),我記得GCC擁有宏觀的__builtin_expect。我經歷了代碼中的所有條件,並以5-10%的速度加速,結果令我驚奇,因爲我注意到了幾乎所有我知道的內容(內存佈局等),而且我沒有對於算法本身沒有任何改變。

該算法是一種非常基本的深度搜索方式。我在Core 2 Duo上運行它,但不確定哪些。

+1

注意:'__builtin_expect'具有什麼功能?給出這個提示,編譯器優化了兩件事:1 /它可以調整預測,2 /它可以佈置代碼,以便可能的塊緊跟在當前塊之後(以最小化緩存未命中)。顯而易見的一個警告是,那些表現得如同暗示的工作負擔將會受到影響;所以如果你使用這個內置的,你最好確定已經識別出可能的異常值。 –

+1

甚至比使用'__builtin_expect'更好的方法是使用'-fprofile-generate'和'-fprofile-use'來讓Profiler找出哪個分支應該被優化[gcc options](http://gcc.gnu.org /onlinedocs/gcc/Optimize-Options.html)。這應該將人爲錯誤排除在外,不會引入非便攜代碼。需要注意的是,分析不足會產生非最佳代碼。 – user2079303

4

端注:如果你有一個像

if (p) a = 20; else a = 10; 

代碼則沒有任何分支。編譯器正在使用條件移動(請參閱:Why is a conditional move not vulnerable for Branch Prediction Failure?

+0

我希望從問題中可以清楚地知道,這不是所有可用於避免分支的小細節。這個問題不是關於'p? 10:20' - 這僅僅是一個例子。我會做一個編輯來明確這一點。 – porgarmingduod

+0

這就是爲什麼我通過郵寄來說是一個「附註」。對不起,如果有幾個人將其視爲答案。 – hivert

+2

@hivert也許這是因爲你發佈是作爲一個答案。 –