与FLOP相比,exp在cmath中的复杂性/实际成本是多少?

时间:2010-10-20 16:07:43

标签: c++ complexity-theory cmath exp

[我在全球范围内编辑了这个问题,以便更加“有用”和清晰]

我想知道在cmath中执行函数exp的复杂性。

复杂性,我指的是算法复杂性,如果可能的话。否则成本与浮点运算相比(例如,添加)

以下几行:

double x = 3;
double y = std::exp(x);

编译为:

...
19,23d16
       movq    %rax, -40(%rbp)
       movsd   -40(%rbp), %xmm0
       call    exp
       movsd   %xmm0, -40(%rbp)
       movq    -40(%rbp), %rax
...

exp必须在运行时动态加载,但我找不到很多关于实现算法复杂性的信息。似乎没有调用特殊的处理器指令(至少在我的x86_64平台上使用gcc)所以必须有一个我无法找到的实现。 在我看来,算法很可能使用输入的二进制表示具有非常弱的复杂性,但我无法找到关于这个主题的有价值的参考。

在这种情况下,可能谈到算法复杂性实际上是不可能的,我们所能做的就是测试(参见下面的答案),但我不知道如何客观地量化浮点运算和调用之间的区别到exp?

4 个答案:

答案 0 :(得分:4)

一般来说,原始类型的复杂性应该非常快。正如评论者所提到的那样,有时候会有说明,如果没有,那就是众所周知的快速算法,Knuth在这方面有很好的部分。

求幂的通常实现是square-and-multiply,它利用了观察,你可以将任何取幂分解为一定数量的方形加上最多一次乘法。 n**k的基本算法为here O lg k)。

答案 1 :(得分:4)

似乎复杂性实际上是不变的,因为MSVC9编译器做了一些涉及特定表,位掩码和偏置的魔术。因为在所有指令管道之后很少有分支应该帮助很多。以下是它实际做的事情。

unpcklpd    xmm0,xmm0 
movapd      xmm1,xmmword ptr [cv] 
movapd      xmm6,xmmword ptr [Shifter] 
movapd      xmm2,xmmword ptr [cv+10h] 
movapd      xmm3,xmmword ptr [cv+20h] 
pextrw      eax,xmm0,3 
and         eax,7FFFh 
mov         edx,408Fh 
sub         edx,eax 
sub         eax,3C90h 
or          edx,eax 
cmp         edx,80000000h 
jae         RETURN_ONE 
mulpd       xmm1,xmm0 
addpd       xmm1,xmm6 
movapd      xmm7,xmm1 
subpd       xmm1,xmm6 
mulpd       xmm2,xmm1 
movapd      xmm4,xmmword ptr [cv+30h] 
mulpd       xmm3,xmm1 
movapd      xmm5,xmmword ptr [cv+40h] 
subpd       xmm0,xmm2 
movd        eax,xmm7 
mov         ecx,eax 
and         ecx,3Fh 
shl         ecx,4 
sar         eax,6 
mov         edx,eax 
subpd       xmm0,xmm3 
movapd      xmm2,xmmword ptr Tbl_addr[ecx] 
mulpd       xmm4,xmm0 
movapd      xmm1,xmm0 
mulpd       xmm0,xmm0 
addpd       xmm5,xmm4 
mulsd       xmm0,xmm0 
addsd       xmm1,xmm2 
unpckhpd    xmm2,xmm2 
movdqa      xmm6,xmmword ptr [mmask] 
pand        xmm7,xmm6 
movdqa      xmm6,xmmword ptr [bias] 
paddq       xmm7,xmm6 
psllq       xmm7,2Eh 
mulpd       xmm0,xmm5 
addsd       xmm1,xmm0 
orpd        xmm2,xmm7 
unpckhpd    xmm0,xmm0 
addsd       xmm0,xmm1 
add         edx,37Eh 
cmp         edx,77Ch 
ja          ADJUST 
mulsd       xmm0,xmm2 
sub         esp,10h 
addsd       xmm0,xmm2 
movlpd      qword ptr [esp+4],xmm0 
fld         qword ptr [esp+4] 
add         esp,10h 
ret              

答案 2 :(得分:2)

Here可以找到使用exp指令的快速SSE实施。

答案 3 :(得分:1)

与其他浮点运算所花费的时间相比,您是否对求幂所用的时间感兴趣?这将因实现而异,也可能因计算机而异(可能有不同的数学处理器),因此我们无法给出任何答案。

如果你想知道,正确的方法是编写测试函数并计算它们的时间。循环通过一百万个浮点赋值并对其进行计时,然后遍历一百万个指数和时间的浮点赋值,然后减去。注意这个优化器,就像你不使用赋值的结果一样,它允许删除整个循环。你会知道,非常快的运行时间不会随着循环的大小而变化。