gpt4 book ai didi

c - 与-O3相比,gcc -Ofast的汇编代码中计算不精确的来源在哪里?

转载 作者:行者123 更新时间:2023-12-05 08:47:31 24 4
gpt4 key购买 nike

<分区>

以下 3 行使用 "gcc -Ofast -march=skylake" 给出了不精确的结果:

int32_t  i = -5;
const double sqr_N_min_1 = (double)i * i;
1. - ((double)i * i) / sqr_N_min_1

显然,sqr_N_min_1 得到 25.,在第 3 行 (-5 * -5)/25 应该变成 1. 这样第 3 行的总结果正好是 0.。事实上,对于编译器选项 “gcc -O3 -march=skylake” 也是如此。

但是对于 "-Ofast" 最后一行产生 -2.081668e-17 而不是 0. 和其他 i -5(例如 67)它会得到与 0 的其他非常小的正或负随机偏差。 。我的问题是:这种不精确的根源究竟在哪里?

为了研究这个问题,我用 C 编写了一个小测试程序:

#include <stdint.h>      /* int32_t */
#include <stdio.h>
#define MAX_SIZE 10

double W[MAX_SIZE];

int main( int argc, char *argv[] )
{
volatile int32_t n = 6; /* try 6 7 or argv[1][0]-'0' */
double *w = W;
int32_t i = 1 - n;
const int32_t end = n - 1;
const double sqr_N_min_1 = (double)i * i;

/* Here is the crucial part. The loop avoids the compiler replacing it with constants: */
do {
*w++ = 1. - ((double)i * i) / sqr_N_min_1;
} while ( (i+=2) <= end );

/* Then, show the results (only the 1st and last output line matters): */
w = W;
i = 1 - n;
do {
fprintf( stderr, "%e\n", *w++ );
} while ( (i+=2) <= end );

return( 0 );
}

Godbolt 向我展示了由 “x86-64 gcc9.3” 和选项 “-Ofast -march=skylake””生成的程序集-O3 -march=skylake”。请检查网站的五个栏目(1.源代码,2.使用“-Ofast”组装,3.使用“-O3”组装,4.输出第一次组装,5. 第二次组装的输出):

Godbolt site with five columns

如您所见,程序集的差异很明显,但我无法弄清楚不精确的确切来源。那么,问题是,哪些汇编指令对此负责?

后续问题是:是否有可能通过重新编写 C 程序来避免“-Ofast -march=skylake”的这种不精确性?

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