2017-08-16 42 views
2

我試圖比較switch語句和查找表的性能,如下所示。C++:Switch語句與查找表的性能

這是使用switch語句的代碼

#include <stdio.h> 

int main() 
{ 
    int n = 3; 

    for (long i = 0; i < 10000000; ++i) { 
     switch (n) { 
     case 0: 
      printf("Alpha"); 
      break; 
     case 1: 
      printf("Beta"); 
      break; 
     case 2: 
      printf("Gamma"); 
      break; 
     case 3: 
      printf("Delta"); 
      break; 
     default: 
      break; 
     } 
    } 

    return 0; 
} 

,這裏是使用查找表的代碼:

#include <stdio.h> 

static char const * const Greek[4] = { 
    "Alpha", 
    "Beta", 
    "Gamma", 
    "Delta" 
}; 

int main() 
{ 
    int n = 3; 

    for (long i = 0; i < 10000000; ++i) { 
     if (n >= 0 && n < 4) { 
      printf(Greek[n]); 
     } 
    } 

    return 0; 
} 

我運行在Ubuntu 14.04兩個編程,gcc版本4.8.4,使用PERF版本4.4.13來分析性能。而結果是:

  • 開關聲明:6.764077822秒
  • 的查找表:6.665140483秒

我不知道爲什麼switch語句比查找表的運行速度較慢。正如我所知道的,使用跳轉表的切換語句,我認爲它應該比我的程序中的查找表運行得更快(它有額外的if語句)。

+7

您的計時包括對'printf'的調用,這可能會導致結果不準確。 – Jonas

+4

你應該看看生成的彙編代碼。 –

+5

,如果你打開了優化,'switch'和'if'將被一個優化的編譯器優化掉。 – geza

回答

8

如果您正在編譯優化,您的代碼沒有開關,也沒有查找表。我只是一個for循環,使用相同的固定字符串多次調用printf()。任何最低限度合理的編譯器實際上都會檢測到n = 3永遠不會被更改並優化它。也許你可以在循環中添加一個n = rand() % 4;

另一方面,如果您沒有通過優化進行編譯,那麼採用時間就沒有意義。

回想你的問題,我期望查詢表比switch語句更快,因爲switch語句將完全顛覆分支預測,而if將是沒有問題的,總是如此。

+0

我使用默認選項gcc版本4.8.4。我會嘗試沒有優化編譯器。 – tuanpm

+6

@tuanpm不!正如我所說,時間未優化的代碼是沒有意義的!它會告訴你什麼都沒有。 –

0

您的基準測試完全不足以衡量switch/lookup-table性能:幾乎所有的時間都是在printf()調用中花費的。如果switch/lookup-table差異有任何影響,則由於整個運行時間較長,所以它會因測量噪聲而變得相形見絀。


僅供參考:我希望在熱的緊密循環中查表只需要大約十個時鐘週期。在2 GHz CPU上,對於所有10000000次迭代(粗略估計,很容易出錯兩倍,但不影響整體評估),這僅爲0.05秒。這是您的總運行時間的1%的訂單!