lo *_*cre 5 c++ valgrind numeric long-double
我的代码中具有以下功能,用于检查数字(在日志空间中)是否具有允许的值:
template<class T>
static void check_if_normal(T t)
{
T additive_neutral_element = make_additive_neutral_element<T>();
// probability is allowed to be 0 in logspace
// probability also is allowed to be -inf in logspace
if (!std::isnormal(t) && t != 0 && t != additive_neutral_element)
throw std::underflow_error(
"Probability of " + std::to_string(t) +
" is abnormal --- possible cause underflow.");
}
Run Code Online (Sandbox Code Playgroud)
在使用此函数的上下文中,我排他性地使用了长双精度。当我在不使用valgrind的情况下运行程序时,一切正常,但是当我在使用valgrind的程序运行时,该函数实际上会引发异常。我怀疑valgrind所做的事情会改变长双打的格式,或者类似的行为。我找到了这个:
Valgrind在相对于IEEE754的x86 / AMD64浮点实现中具有以下限制。
精度:不支持80位算术。在内部,Valgrind用64位表示所有此类“长双精度”数字,因此结果可能有所不同。这是否很关键还有待观察。请注意,x86 / amd64 fldt / fstpt指令(读/写80位数字)已使用到64位的转换进行了正确模拟,因此,如果有人要查看,则80位数字的内存图像看起来正确。
从许多FP回归测试中观察到的印象是,准确性差异并不明显。一般而言,如果程序依赖于80位精度,则可能很难将其移植到仅支持64位FP精度的非x86 / amd64平台。即使在x86 / amd64上,该程序也可能会获得不同的结果,具体取决于它是编译为使用SSE2指令(仅64位)还是x87指令(80位)。最终结果是使FP程序的行为就像在具有64位IEEE浮点数的计算机(例如PowerPC)上运行时一样。在amd64上,FPD算术运算默认情况下是在SSE2上完成的,因此从FP角度来看,amd64看起来更像PowerPC,而不是x86,并且与x86相比,明显的精度差异要少得多。
舍入:Valgrind确实对以下转换遵循4种IEEE规定的舍入模式(至最接近,至+无限,至-无限,至零):浮于整数,整数可能浮于精度的情况,以及浮动到浮动的舍入。对于所有其他FP操作,仅支持IEEE默认模式(四舍五入到最接近)。
FP代码中的数字异常:IEEE754定义了五种可能发生的数字异常:无效操作(负数的平方等),被零除,溢出,下溢,不精确(精度损失)。
对于每个异常,IEEE754定义了两个动作过程:(1)可以调用用户定义的异常处理程序,或者(2)定义一个默认动作,该动作可以“修正”并允许计算继续进行而无需引发异常。
当前,Valgrind仅支持默认的修正操作。同样,对于异常支持的重要性的反馈将不胜感激。
当Valgrind检测到程序试图超出这些限制中的任何一个(设置异常处理程序,舍入模式或精度控制)时,它可以打印一条消息,提供对该事件发生的位置的追溯,并继续执行。此行为曾经是默认行为,但是消息很烦人,因此默认情况下现在禁用显示消息。使用--show-emwarns = yes可以查看它们。
以上限制精确地定义了IEEE754的“默认”行为:所有异常的默认修正,最近舍入操作和64位精度。
http://www.valgrind.org/docs/manual/manual-core.html#manual-core.limits
但是我不确定这是否适用。Valgrind并未像引用中所说的那样打印出一条提供追溯的消息。它打印了这个:
terminate called after throwing an instance of 'std::underflow_error'
what(): Probability of -nan is abnormal --- possible cause underflow.
==4899==
==4899== Process terminating with default action of signal 6 (SIGABRT)
==4899== at 0x5710428: raise (raise.c:54)
==4899== by 0x5712029: abort (abort.c:89)
==4899== by 0x4EC984C: __gnu_cxx::__verbose_terminate_handler() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==4899== by 0x4EC76B5: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==4899== by 0x4EC7700: std::terminate() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==4899== by 0x4EC7918: __cxa_throw (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
Run Code Online (Sandbox Code Playgroud)
顺便说一句 g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609如果这与导致此行为的原因有关,则我在64位系统上使用。
以上引用是否可能是我遵守此规定的原因?
| 归档时间: |
|
| 查看次数: |
332 次 |
| 最近记录: |