[我在全球范围内编辑了这个问题,以便更加“有用”和清晰]
我想知道在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?
答案 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)
与其他浮点运算所花费的时间相比,您是否对求幂所用的时间感兴趣?这将因实现而异,也可能因计算机而异(可能有不同的数学处理器),因此我们无法给出任何答案。
如果你想知道,正确的方法是编写测试函数并计算它们的时间。循环通过一百万个浮点赋值并对其进行计时,然后遍历一百万个指数和时间的浮点赋值,然后减去。注意这个优化器,就像你不使用赋值的结果一样,它允许删除整个循环。你会知道,非常快的运行时间不会随着循环的大小而变化。