我正在使用gcc44和gdb调试在64位Linux CentOS 5.7上运行的ANSI C程序。我在程序中有以下循环:
for (ii = 1; ii < 10001; ii++) {
time_sec[ii] = ( 10326 ) * dt - UI0_offset; /* in seconds */
printf("\ntime_sec[%d] = %16.15e, dt = %16.15e, UI0_offset = %26.25e\n",
ii, time_sec[ii], dt, UI0_offset);
}
其中time_sec,dt和UI0_offset是双倍的。相关的gdb会话是:
(gdb) p time_sec[1]
$2 = 2.9874137906250006e-15
(gdb) p ( 10326 ) * dt - UI0_offset
$3 = 2.9874137906120759e-15
为什么$ 2和$ 3不同的数字? $ 2 = time_sec [1]由c程序计算,而$ 3是相同的等式,但是以gdb计算。
我将Matlab算法移植到C和Matlab(在不同的机器上运行)完全匹配gdb编号$ 3,我需要这个精度。任何人都知道这里会发生什么,以及如何解决?
更新:经过一些调试后,似乎差异在于UI0_offset的值。我探测gdb为这个变量揭示了一些额外的数字(注意:有人知道更好的方法来查看gdb中的更多数字吗?我尝试了一个sprintf语句,但无法让它工作):
(gdb) p UI0_offset -1e-10
$5 = 3.2570125862093849e-12
然后我将printf()代码插入上面原始帖子中显示的循环中,当它在gdb中运行时显示:
time_sec[1] = 2.987413790625001e-15, dt = 1.000000000000000e-14,
UI0_offset = 1.0325701258620937565691357e-10
因此,总结一下:
1.032570125862093849e-10 (from gdb command line, the correct value)
1.0325701258620937565691357e-10 (from program's printf statement, NOT correct value)
任何理论为什么UI0_offset的值在gdb命令行和在gdb中运行的程序之间是不同的(以及如何使程序与gdb命令行一致)?
答案 0 :(得分:4)
我不确定x64架构是否包含与x86相同的80位(长双)FP寄存器,但是当中间结果(即第一次乘法)保留时,x86世界中的结果通常会出现80位寄存器而不是刷新回缓存/ RAM。有效地计算的一部分是以更高的精度完成的,因此会产生不同的结果。
GCC有一个选项(-ffloat-store
,如果我的内存服务),这将导致中间结果被刷新回64位精度。尝试启用它,看看你是否匹配GDB / Matlab结果。