簡體   English   中英

在這種情況下,是否有更快的替代if-else?

[英]Is there a faster alternative to if-else in this case?

while(some_condition){  
    if(FIRST)  
    {   
        do_this;  
    }  
    else  
    {  
        do_that;  
    }
}

在我的程序中, if(FIRST)成功的可能性大約是10000中的1。在C / C ++中可以有任何替代方法,這樣我們就可以避免在while循環內的每次迭代中檢查條件,希望看到更好的性能這個案例。

好! 讓我詳細介紹一下。 我正在為信號采集和跟蹤方案編寫代碼,其中我的系統狀態將更頻繁地保持在跟蹤模式,即ACQUISITION模式。

while(signal_present)  
{    
    if(ACQUISITION_SUCCEEDED)  
    {     
        do_tracking();  // this functions can change the state from TRACKING to ACQUISITION  
    }    
    else  
    {    
        do_acquisition();  // this function can change the state from ACQUISITION to TRACKING  
    }     
}    

所以這里發生的是系統通常保持跟蹤模式,但是當跟蹤失敗時它可以進入采集模式但不常見。(假設輸入數據的數量是無限的。)

單個分支的性能成本不會是一個大問題。 你唯一能做的就是把最可能的代碼放在第一位,保存在一些指令緩存上。 也許。 這非常深入到微優化。

嘗試優化它沒有特別好的理由。 幾乎所有現代架構都包含分支預測器 這些推測分支(if或者其他)將基本上采用過去的方式。 在您的情況下,推測將始終成功,消除所有開銷。 有一些不可移植的方法暗示條件采取某種方式,但任何分支預測器都可以正常工作。

您可能想要做的一件事是改進指令緩存局部性是將do_that移出while循環(除非它是一個函數調用)。

在最近的x86處理器系統上,最終執行速度幾乎不依賴於源代碼實現。

您可以查看此頁面http://igoro.com/archive/fast-and-slow-if-statements-branch-prediction-in-modern-processors/,以查看處理器內部發生的優化量。

GCC有一個__builtin_expect “函數”,您可以使用它來向編譯器指示可能采用的分支。 你可以像這樣使用它:

if(__builtin_expect(FIRST, 1)) …

這有用嗎? 我不知道。 我從未使用它,從未見過它(據稱在Linux內核中除外)。 GCC文檔實際上不鼓勵使用它來支持使用分析信息來實現更可靠的度量。

如果你不知道什么時候“FIRST”是真的,那么沒有。

問題是FIRST是否耗時; 也許你可以在循環(或部分循環)之前評估FIRST,然后測試布爾值。

我會稍微改變一下moonshadow的代碼

while( some_condition )
{
   do_that;
   if( FIRST )
   {
     do_this; // overwrite what you did earlier.
   }
}

根據您的新信息,我會說如下:

while(some_condition)
{
  while(ACQUISITION_SUCCEEDED)
  {
    do_tracking();
  }
  if (some_condition)
    while(!ACQUISITION_SUCCEEDED)
    {
      do_acquisition();
    }
}

關鍵是ACQUISITION_SUCCEEDED狀態必須在some_condition包含some_condition信息(即如果some_condition為false,它將突破內部循環 - 因此有可能突破外部循環)

這是優化中的經典之作。 如果可以的話,你應該避免將條件放在循環中。 這段代碼:

while(...)
{
    if( a )
    {
       foo();
    }
    else
    {
       bar();
    }
}

通常更好地重寫為:

if( a )
{
    while(...)
    {
        foo();
    }
}
else
{
    while(...)
    {
        bar();
    }
}

雖然並不總是這樣,但是當你嘗試優化某些東西來測量前后的性能時,你應該總是這樣。

如果與do_aquisition的實現相比,此測試確實消耗了大量時間,那么您可以通過使用函數表來獲得提升:

typedef void (*trackfunc)(void);
trackfunc tracking_action[] = {do_acquisition, do_tracking};
while (signal_present)
{
   tracking_action[ACQUISITION_STATE]();
}

這些手動優化的效果非常依賴於平台,編譯器和優化設置。

通過花時間測量和調整do_aquisition和do_tracking算法,您很可能會獲得更大的性能提升。

您可以使用您的示例進行更多有用的優化。

do_thisdo_that的調用/分支可能會通過優化if-then-else語句來抵消您獲得的任何節省。

性能優化的一個規則是減少分支。 大多數處理器更喜歡執行順序代碼。 他們可以獲取一大塊順序代碼並將其拖入緩存中。 分支中斷了這種愉悅,並可能導致指令緩存的完全重新加載(這會浪費寶貴的執行時間)。

在此級別進行微量優化之前,請檢查您的設計,看看是否可以:

  1. 消除不必要的分支。
  2. 拆分代碼使其適合緩存。
  3. 組織數據以減少從內存或硬盤驅動器中取出。

我確信上述步驟將比優化發布的循環獲得更多性能。

暫無
暫無

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

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