gpt4 book ai didi

c++ - Valgrind 导致长 double 的数字问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:50:14 25 4
gpt4 key购买 nike

我的代码中有以下函数用于检查数字是否具有允许值(在对数空间中):

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.");
}

在使用此函数的上下文中,我专门使用长 double 。当我在没有 valgrind 的情况下运行我的程序时,一切正常,但是当我使用 valgrind 运行它时,该函数实际上引发了异常。我怀疑 valgrind 做了一些改变 long double 的格式或类似的事情。我发现了这个:

Valgrind has the following limitations in its implementation of x86/AMD64 floating point relative to IEEE754.

Precision: There is no support for 80 bit arithmetic. Internally, Valgrind represents all such "long double" numbers in 64 bits, and so there may be some differences in results. Whether or not this is critical remains to be seen. Note, the x86/amd64 fldt/fstpt instructions (read/write 80-bit numbers) are correctly simulated, using conversions to/from 64 bits, so that in-memory images of 80-bit numbers look correct if anyone wants to see.

The impression observed from many FP regression tests is that the accuracy differences aren't significant. Generally speaking, if a program relies on 80-bit precision, there may be difficulties porting it to non x86/amd64 platforms which only support 64-bit FP precision. Even on x86/amd64, the program may get different results depending on whether it is compiled to use SSE2 instructions (64-bits only), or x87 instructions (80-bit). The net effect is to make FP programs behave as if they had been run on a machine with 64-bit IEEE floats, for example PowerPC. On amd64 FP arithmetic is done by default on SSE2, so amd64 looks more like PowerPC than x86 from an FP perspective, and there are far fewer noticeable accuracy differences than with x86.

Rounding: Valgrind does observe the 4 IEEE-mandated rounding modes (to nearest, to +infinity, to -infinity, to zero) for the following conversions: float to integer, integer to float where there is a possibility of loss of precision, and float-to-float rounding. For all other FP operations, only the IEEE default mode (round to nearest) is supported.

Numeric exceptions in FP code: IEEE754 defines five types of numeric exception that can happen: invalid operation (sqrt of negative number, etc), division by zero, overflow, underflow, inexact (loss of precision).

For each exception, two courses of action are defined by IEEE754: either (1) a user-defined exception handler may be called, or (2) a default action is defined, which "fixes things up" and allows the computation to proceed without throwing an exception.

Currently Valgrind only supports the default fixup actions. Again, feedback on the importance of exception support would be appreciated.

When Valgrind detects that the program is trying to exceed any of these limitations (setting exception handlers, rounding mode, or precision control), it can print a message giving a traceback of where this has happened, and continue execution. This behaviour used to be the default, but the messages are annoying and so showing them is now disabled by default. Use --show-emwarns=yes to see them.

The above limitations define precisely the IEEE754 'default' behaviour: default fixup on all exceptions, round-to-nearest operations, and 64-bit precision.

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)

顺便说一句。如果这与导致此行为的原因相关,我在 64 位系统上使用 g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

上面的引述是否可能是我观察到这一点的原因,如果不是,还有什么原因?

最佳答案

关于c++ - Valgrind 导致长 double 的数字问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44102050/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com