【问题标题】:My program does not run properly when compiled with icc使用 icc 编译时我的程序无法正常运行
【发布时间】:2018-05-28 08:25:15
【问题描述】:

我遇到了 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 次。

有谁知道是什么导致了这个问题?

谢谢!

【问题讨论】:

    标签: c icc


    【解决方案1】:

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

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

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

    对于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 并在编译时执行循环计算total(这样的优化是合法的)。您会发现进行这样的优化需要大量的工作(当然是几个月,也许是几年!),并且not 可能适用于很多现有的程序,但您可以享受实现它的乐趣。

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

    【讨论】:

    • 我实际上删除了 printf,因为我试图将这个顺序代码与它的其他几个并行版本(在没有 printf 的情况下工作)进行比较。所以我只打印运行时。我在原始版本中使用相同的语法使用 n 作为参数。但是我没有意识到这个icc优化问题。谢谢!
    • 不是icc 的问题。问题是您对 C 语义及其 as-if 规则的误解。正如我所展示的,GCC 具有相同的优化能力(但您需要提出要求)
    • 感谢您提供所有这些额外信息。我肯定会考虑将这个插件作为我未来研究的一部分。
    猜你喜欢
    • 1970-01-01
    • 2013-07-29
    • 2012-05-23
    • 2017-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多