簡體   English   中英

如何如此快速地評估 const expr

[英]How can a const expr be evaluated so fast

我一直在嘗試在編譯時計算的 const 表達式。 但是我玩了一個在編譯時執行時看起來非常快的示例。

#include<iostream> 

constexpr long int fib(int n) { 
    return (n <= 1)? n : fib(n-1) + fib(n-2); 
} 

int main () {  
    long int res = fib(45); 
    std::cout << res; 
    return 0; 
} 

當我運行此代碼時,大約需要 7 秒才能運行。 到現在為止還挺好。 但是當我將long int res = fib(45)更改為const long int res = fib(45)它甚至不需要一秒鍾。 據我了解,它是在編譯時評估的。 但是編譯大約需要0.3秒

編譯器怎么能這么快地評估它,但在運行時卻需要更多的時間? 我正在使用 gcc 5.4.0。

編譯器緩存較小的值,不需要像運行時版本那樣重新計算。
(優化器非常好,會生成大量代碼,包括我無法理解的特殊情況的詭計;天真的 2^45 遞歸需要幾個小時。)

如果您還存儲以前的值:

int cache[100] = {1, 1};

long int fib(int n) {
    int res = cache[n];
    return res ? res : (cache[n] = fib(n-1) + fib(n-2));
} 

運行時版本比編譯器快得多。

您可能會發現 5.4 的功能並沒有完全消除很有趣,為此您至少需要 6.1。

我不認為有任何緩存發生。 我確信優化器足夠聰明,可以證明fib(n - 2)fib(n-1)並完全避免第二次調用。 這是 GCC 5.4 輸出(從 Godbolt 獲得),沒有constexpr和 -O2:

fib(long):
        cmp     rdi, 1
        push    r12
        mov     r12, rdi
        push    rbp
        push    rbx
        jle     .L4
        mov     rbx, rdi
        xor     ebp, ebp
.L3:
        lea     rdi, [rbx-1]
        sub     rbx, 2
        call    fib(long)
        add     rbp, rax
        cmp     rbx, 1
        jg      .L3
        and     r12d, 1
.L2:
        lea     rax, [r12+rbp]
        pop     rbx
        pop     rbp
        pop     r12
        ret
.L4:
        xor     ebp, ebp
        jmp     .L2

我不得不承認我不理解 -O3 的輸出 - 生成的代碼非常復雜,有很多內存訪問和指針算法,很可能有一些緩存(記憶)使用這些設置完成。

暫無
暫無

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

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