2013-03-24 53 views
28

我假設計算一個數的模數是一個相當昂貴的操作,至少與簡單的算術測試(比如看一個數是否超出數組的長度)相比是一個相當昂貴的操作。如果確實如此,替換例如下面的代碼是否更有效:儘可能避免使用mod運算符更好嗎?

res = array[(i + 1) % len]; 

以下內容? :

res = array[(i + 1 == len) ? 0 : i + 1]; 

第一個是對眼睛更容易,但我不知道如果第二可能是更有效的。如果是這樣,我可能希望優化編譯器在使用編譯語言時用第二個代碼片段替換第一個片段?

當然,這種「優化」(如果確實是優化)在所有情況下都不起作用(在這種情況下,只有在i+1永遠不會超過len時才起作用)。

+10

這可能是錯過了樹林的情況。 – 2013-03-24 07:58:13

+1

如果'len'是一個編譯時常量,最近的GCC編譯器(帶有'-02')通常會做很聰明的事情,通常會避免目標處理器的模數指令。 – 2013-03-24 07:59:34

+2

這真的是你應該忘記的那種優化。優化編譯器會比你做得更好。更重要的是你的代碼的可讀性。 – 2013-03-24 08:04:47

回答

20

我的一般建議如下。使用您認爲更易於理解的版本,然後分析整個系統。只優化探查器標記爲瓶頸的那些代碼部分。我敢打賭,我的最低收益是模運營商不會成爲其中的一員。

就具體示例而言,只有基準測試可以通過使用特定的編譯器來確定哪個更快。你可能會用branching來代替mod,而且它會更快。

+0

在最近的機器上整數算術幾乎是免費的;更重要的是緩存未命中......這是更昂貴的。 L1高速緩存未命中使處理器停止數百個週期,在此期間處理器可以執行數十個分區或模數;所以最終的模數成本就是噪音 – 2013-03-24 08:00:56

+3

@BasileStarynkevitch:好吧,這兩個代碼片段之間的緩存行爲將是相同的。重要的是版本#2是否使用分支,如果是的話,分支預測器要做的工作有多好。 – NPE 2013-03-24 08:02:15

+0

@Basile Starynkevitch我已經看到了模塊與訪問筆記本電腦上的大桌子之間的約300倍。 (爲了避免訪問數組而增加一個可分性的測試,仍然是有益的。) – starblue 2013-03-24 09:44:35

0

Modulo可以在大多數體系結構上使用單處理器指令完成(例如x86上的DIV)。然而,它可能是您需要的不成熟的優化。

+14

只是因爲有一個操作指令,並不意味着它發生在一個時鐘週期。 – 2013-03-24 08:46:00

+2

@ChrisDesjardins同意,但如果第二個運算符是2的冪,則'%'可以表示爲位掩碼。 – Alex 2013-03-24 08:49:50

+5

對不起,必須downvote。我曾與很多體系結構(但不是x86)合作,並且尚未與一個在一條指令中完成mod/div的工作。我已經看到了應用程序,其中mod是前10個CPU消費函數調用之一,因爲所有的循環緩衝 - 每個「樣本」副本後面跟着一個%buffersize。在我的情況下,如果可以的話,我嘗試避免mod - 通常通過聲明輸入緩衝區大小可以被2整除,以便編譯器可以優化mod。 – 2013-03-25 05:22:56

16

一些簡單的測量:

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char *argv[]) 
{ 
    int test = atoi(argv[1]); 
    int divisor = atoi(argv[2]); 
    int iterations = atoi(argv[3]); 

    int a = 0; 

    if (test == 0) { 
     for (int i = 0; i < iterations; i++) 
      a = (a + 1) % divisor; 
    } else if (test == 1) { 
     for (int i = 0; i < iterations; i++) 
      a = a + 1 == divisor ? 0 : a + 1; 
    } 

    printf("%d\n", a); 
} 

與任一的gcc或鐺編譯與-O3,並運行time ./a.out 0 42 1000000000(模版)或time ./a.out 1 42 1000000000(比較版本)

  • 6.25秒用於模數版本的用戶運行時間,
  • 1.03秒用於比較版本。

(使用gcc 5.2.1或3.6.2鏗鏘;英特爾酷睿i5-4690K @ 3.50GHz,64位Linux)

這意味着它可能是使用比較的版本是個好主意。

+2

對於更真實的數據(例如,如果數字是隨機的),那麼差異將不會那麼大 – user1209304 2016-10-24 12:23:38

+1

比較版本只會更快,因爲if語句的結果每次都是相同的,所以分支預測器每次都得到它時間。如果你隨機化輸入,比較版甚至可能會比mod更差 – Bigminimus 2017-06-26 10:39:03

+1

@Bigminimus Hmm但是if語句的結果對於兩個測試都是一樣的嗎? – 2017-08-09 12:54:24

相關問題