2013-08-05 63 views
3

我有代碼看起來像這樣:可以重複調用相同的函數來提供更好的性能嗎?

void foo(unsigned long k) 
{ 
    if (k & 1) 
    { 
     bar(k/2 + 1); 
     bar(k/2); 
     bar(k/2 + 1); 
    } 
    else 
    { 
     bar(k/2); 
     bar(k/2); 
     bar(k/2); 
    } 
} 

void bar(unsigned long k) 
{ 
    switch(k) 
    { 
    case default: special_default(); break; 
    case 1: specialbar1(); break; 
    case 2: specialbar2(); break; 
    <more cases> 
    case 16: specialbar16(); break; 
    } 
} 

的表現要好得多時foo被調用的k偶數值。每個specialbar#()方法使用多個堆棧變量,這些變量的數量隨着k的增加而急劇增加。要清楚specialbar#()使用約3 * k局部變量都是unsigned long long變量。

例如foo(32)執行比foo(31)快約15%。我使用Visual Studio 2012和性能分析向我保證,兩次調用specialbar16和一個呼叫specialbar15花費的時間比連續三次調用specialbar16相當多的工作。

是否有可能編譯器會連續三個電話的優勢,當k是什?也就是說,是否可以意識到,即使在k的連續三次調用中,堆棧基本上都是相同的,但對於奇數k,相同的優化是不可能的?

+1

你是不是真的測量同樣的事情,因爲你是調用不同的'specialbar_k()'在每種情況下的功能,他們可能做不同的事情。 – interjay

回答

2

當k是偶數時,編譯器是否有可能利用三次連續調用?那是否可以認識到,在連續三次調用k次後,堆棧本質上是相同的,但對於奇數k,相同的優化是不可能的?

這似乎不值得回答,但是,是的,這完全有可能。編譯器可能會認識到每次調用都需要相同的堆棧佈局,因爲它每次都是相同的方法,因此避免了每個方法調用的整個堆棧設置/拆卸。在這種情況下,可能還會內聯方法調用 - 代碼在調用方中就地生成。

最有可能類似的優化也爲其他情況下,進行爲好,雖然優化是棘手的,有時有微妙的原因,編譯器將無法執行它。

+0

也許最好用等價方法替換特殊欄#()方法,每個方法處理偶數k值和相應的k-1值。不過,我認爲這不太可讀,有點迂腐。當人們注意到最好連續調用相同的方法時,會不會有這樣的長度? – Peter

+0

我個人建議,試圖智勝優化編譯器是一個不好的舉措。性能真的很重要,你需要考慮這樣做嗎?你最終可能會放慢兩種情況。 – davmac

+0

@davmac,「勝過」編譯器可以進行優化IFF這是你最後一件事,而且你需要最後一次提速。但是,從便攜性的角度來看,你是對的,這是一個不好的舉措。 – Adrian

1

你foo的函數執行額外的邏輯,當k爲奇數(K/2 + 1)+ 1

爲了回答您的具體問題,可以重複調用提高性能。是的,當參數相同時,函數中的各個分檔可以相同,並且這允許「分支預測」以最佳方式工作。

+0

是否有可能提供關於分支預測的進一步信息的鏈接,任何方向將是最有幫助的。 – Peter

+0

@Peter - 搜索分支預測,http://igoro.com/archive/fast-and-slow-if-statements-branch-prediction-in-modern-processors/還有緩存駐留,因爲該功能已經在您的處理器緩存後續調用將會更快,因爲不會有任何加載或緩存未命中來獲取操作代碼。 –

相關問題