sta*_*tti 24 c++ linux floating-point assembly gcc
我有一个functor,它接受一个值,将其转换为double,获取日志并将值转换回原始类型.出于此问题的目的,原始和输出类型是float.这是原始的C++代码:
return static_cast< TOutput >( std::log( static_cast< double >( A ) ) )
Run Code Online (Sandbox Code Playgroud)
当我在调试模式下编译时,一切都按预期进行,GCC调用底层log
函数:
51:/myfile.h **** return static_cast< TOutput >( std::log( static_cast< double >( A ) ) );
219133 .loc 112 51 0
219134 0010 488B45F0 movq -16(%rbp), %rax # A, tmp64
219135 0014 F30F1000 movss (%rax), %xmm0 # *A_1(D), D.237346
219136 0018 0F14C0 unpcklps %xmm0, %xmm0 # D.237346, D.237346
219137 001b 0F5AC0 cvtps2pd %xmm0, %xmm0 # D.237346, D.237347
219138 001e E8000000 call log #
219138 00
219139 0023 660F14C0 unpcklpd %xmm0, %xmm0 # D.237347
219140 0027 660F5AC0 cvtpd2ps %xmm0, %xmm0 # D.237347, D.237346
219141 002b F30F1145 movss %xmm0, -20(%rbp) # D.237346, %sfp
219141 EC
219142 0030 8B45EC movl -20(%rbp), %eax # %sfp, <retval>
Run Code Online (Sandbox Code Playgroud)
但是,当我打开优化(-O2 -ggdb3 -DNDEBUG)时,它调用logf
(???)函数:
51:/myfile.h **** return static_cast< TOutput >( std::log( static_cast< double >( A ) ) );
145171 .loc 64 51 0
145172 01a0 F30F1004 movss (%rdx,%rax,4), %xmm0 # MEM[(const float &)_84], MEM[(const float &)_84]
145172 82
145173 01a5 E8000000 call logf #
Run Code Online (Sandbox Code Playgroud)
它给出了不同的输出.这是正常的吗?我做错了吗?在我看来,海湾合作委员会对我的代码采取了非常自由的解释,在没有-ffast-math
选项的情况下我不会期望.
Pas*_*uoq 33
这是一个边界优化,将float
双精度应用程序的转换转换为log
浮点数到单精度应用程序log
,但可以认为它是可以接受的.
假设logf
正确舍入并且双精度log
也正确舍入或至少忠实地舍入,两个计算将很少有所不同.它们可以不同(对于一些罕见的输入),因为双舍入(其中"double"表示"两次"并且不指代类型).与最终类型的有效数相比,中间类型的有效数字中存在额外数字的双舍入在统计上是不太重要的(并且这个统计参数从数学的角度来看稍微有些垃圾,但它"在实践中"用于没有被设计为反例).出于教学原因,人们(或维基百科)用一个或两个额外的精度数字解释它,但是当你有53 - 24 = 29个额外的二进制数字时,它可能会在2 29中很少发生一次.
我对优化感到惊讶,如果我自己编写代码来详尽搜索双舍入问题,我会感到不安log
,但考虑到C++标准并没有强制要求任何精度std::log
,有可能认为它"不是一个bug".
如果log
我们不是在讨论其中一个基本操作(例如*
),那么对于声称提供IEEE 754语义的编译器,当它引入可见的更改时,转换将是不正确的.对于基本操作,精度由IEEE 754间接指定,并且规范没有留下变化的余地.
碰巧的是,对于基本操作,floatOP(flx,fly)
替换时不会有明显的变化(float)doubleOP((double)flx, (double)fly)
(本文在第6章中对此进行了论证),但是当类型为double
和时,可能存在明显的差异long double
.这个确切的错误最近由Stephen Canon在Clang中修复.
归档时间: |
|
查看次数: |
1848 次 |
最近记录: |