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

时间:2018-05-28 08:25:16

标签: 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;
}

我还检查过它实际上是在运行循环并调用函数 n 次。

有谁知道可能导致此问题的原因?

谢谢!

1 个答案:

答案 0 :(得分:8)

  

然而,如果我在最后打印总数,它就可以了。

这可能是optimizing compiler效果(合法,符合C11标准n1570)。

由于程序中没有可见的side-effect(没有printf),因此允许编译器(根据as-if rule)将其优化为无操作程序。< / p>

对于某些版本的GCCClang以及某些optimization flags,您可以观察到相同的情况。尝试使用gcc -O3 -S -fverbose-asm编译代码并查看生成的汇编代码(您将在Linux / x86-64上观察到带有GCC 8.1的空生成main

  

有谁知道可能导致此问题的原因?

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

顺便说一下,即使使用printf,理论上也允许编译器将程序优化为一个简单的常量printf。在实践中,目前的编译器(遗憾地)并不那么聪明。

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

 unsigned long n = (argc<2)?1000:(unsigned long)atol(argv[1]);

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

顺便说一下,在几年之后(在完成CS课程之后,包括一篇关于编译和/或阅读Dragon Book)之后,您可能会尝试实施一些GCC plugin使用显式printf(但仍将n初始化为编译时常量)优化您的函数到main只调用一些printf并执行循环计算{ {1}}在编译时(这样的优化是合法的)。您会发现进行这样的优化需要花费大量的工作(当然是几个月,也许是几年!),并且可能not适用于许多现有程序,但您可以乐于实现它。

如果您对浮点计算感兴趣,请务必阅读floating point guide(这很棘手)。