簡體   English   中英

為什么pow函數比簡單操作慢?

[英]Why is the pow function slower than simple operations?

從我的一個朋友那里,我聽說pow函數比簡單地乘以基數(即乘以其指數的次數)要慢得多。 例如,據他說,

#include <stdio.h>
#include <math.h>

int main () {
    double e = 2.71828
    e2 = pow (e, 2.0)
    printf("%le", e2)
}

比慢

#include <stdio.h>

int main() {
    double e = 2.71828
    e2 = e * e
    printf("%le", e2)
}

作為新手,我認為它們的編譯速度和邏輯相同,因此我更喜歡前者的典型信奉度。 那么,為什么前一個代碼塊比后一個代碼塊慢?

pow(double,double)需要處理任何冪 ,而不僅僅是基於整數的冪,尤其是2 這樣,它比僅對兩個double值進行簡單的乘法要復雜得多。

因為pow函數必須實現一個必須在所有情況下都可以使用的更通用的算法(特別是,它必須能夠提升為double表示的任何有理指數),而e*e只是一個簡單的乘法,它將沸騰精簡到一兩個匯編指令。

不過,如果編譯器足夠聰明,它可能會自動以e*e自動替換pow(e, 2.0) (嗯,實際上,在您的情況下,它可能只會在編譯時執行整個計算)。


只是為了好玩,我進行了一些測試:編譯以下代碼

#include <math.h>

double pow2(double value)
{
    return pow(value, 2.);
}

double knownpow2()
{
    double e=2.71828;
    return pow(e, 2.);
}

double valuexvalue(double value)
{
    return value*value;
}

double knownvaluexvalue()
{
    double e=2.71828;
    return e*e;
}

使用g++ -O3 -c pow.c (g ++ 4.7.3)並使用objdump -d -M intel pow.o分解輸出,我得到:

0000000000000000 <_Z4pow2d>:
   0:   f2 0f 59 c0             mulsd  xmm0,xmm0
   4:   c3                      ret    
   5:   66 66 2e 0f 1f 84 00    data32 nop WORD PTR cs:[rax+rax*1+0x0]
   c:   00 00 00 00 

0000000000000010 <_Z9knownpow2v>:
  10:   f2 0f 10 05 00 00 00    movsd  xmm0,QWORD PTR [rip+0x0]        # 18 <_Z9knownpow2v+0x8>
  17:   00 
  18:   c3                      ret    
  19:   0f 1f 80 00 00 00 00    nop    DWORD PTR [rax+0x0]

0000000000000020 <_Z11valuexvalued>:
  20:   f2 0f 59 c0             mulsd  xmm0,xmm0
  24:   c3                      ret    
  25:   66 66 2e 0f 1f 84 00    data32 nop WORD PTR cs:[rax+rax*1+0x0]
  2c:   00 00 00 00 

0000000000000030 <_Z16knownvaluexvaluev>:
  30:   f2 0f 10 05 00 00 00    movsd  xmm0,QWORD PTR [rip+0x0]        # 38 <_Z16knownvaluexvaluev+0x8>
  37:   00 
  38:   c3                      ret    

因此,在編譯器已經知道所有涉及的值的地方,它只是在編譯時執行了計算。 對於pow2valuexvalue它發出單個mulsd xmm0,xmm0 (即,在兩種情況下,都歸結為在單個匯編指令中值與自身的乘積)。

這是一個(簡單,請注意注釋)pow實現 在泛型中,它涉及多個分支以及一個潛在的分支,並調用exp,log,modf ..

另一方面,在大多數更高的CPU上,乘法是一條指令(給定或取指令)。

暫無
暫無

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

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