使用icc编译时,我的程序无法正常运行

Adr*_*cia 2 c icc

我遇到了icc的问题,到目前为止我还没有找到任何解决方案.我的程序在使用gcc编译时正常运行,但显然在使用icc编译时不执行任何操作.不会发生运行时错误.程序只是非常快(几毫秒)结束,但预计需要几秒钟(n = 10亿约11秒).但是,如果我在最后打印总数,它可以正常工作.

这是一个小代码:

# include <stdlib.h>
# include <stdio.h>

double f(double x){
    double pi = 3.141592653589793;
    double value;
    value = 50.0 / (pi * (2500.0 * x * x + 1.0));
    return value;
}
int main (int argc, char *argv[]){
    double a = 0.0, b = 10.0, total = 0.0, x;
    unsigned long int i, n = 1000000000;

    for(i = 0; i < n; i++){
        x = ((n - i - 1) * a + (i) * b) / (n - 1);
        total = total + f(x);
    }
    total = (b - a) * total / (double) n;

    //printf("%f\n", total);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我还检查它实际上运行循环并调用该函数n次.

有谁知道可能导致这个问题的原因是什么?

谢谢!

Bas*_*tch 8

但是,如果我在最后打印总数,它可以正常工作.

这可能是一种优化的编译器效果(合法的,符合C11标准n1570).

由于程序中没有可见的副作用(没有printf),因此允许编译器(按照as-if规则)将其优化为无操作程序.

对于某些版本的GCCClang,以及一些优化标志,您可以观察到相同的情况.尝试编译代码gcc -O3 -S -fverbose-asm并查看生成的汇编程序代码(您将main在Linux/x86-64上观察到使用GCC 8.1 生成的空)

有谁知道可能导致这个问题的原因是什么?

您的代码,以及您对C 的棘手语义的误解.实现符合C标准(并且您的程序正常运行).

BTW,即使printf理论上,编译器也可以将程序优化为一个简单的常量printf.在实践中,目前的编译器(遗憾地)并不那么聪明.

如果你想要一些强大的基准,n可能取决于程序参数(你仍然需要保持printf,因为你想要一些可见的副作用)或许:

 unsigned long n = (argc<2)?1000:(unsigned long)atol(argv[1]);
Run Code Online (Sandbox Code Playgroud)

测量性能时,不要忘记在编译器中启用优化!

顺便说一下,在几年之后(在完成CS课程之后,包括一个关于编译和/或阅读过Dragon Book)之后,你可能会尝试实现一些能够用显式优化你的功能的GCC插件printf(但是仍然n被初始化为编译时常量),main只是调用一些printftotal编译时进行循环计算(这样的优化是合法的).你会发现,做这样的优化需要大量的工作的(当然个月,甚至数年!),并且可能适用于很多现有的方案,但你可以有乐趣实现它.

如果您对浮点计算感兴趣,请务必阅读浮点指南(这很棘手).

  • 它不是*icc`的问题.问题是你对C语义及其as-if规则的误解.正如我所示,GCC具有相同的优化能力(但您需要提出要求) (2认同)