My program does not run properly when compiled with icc

I'm having a problem with icc and so far I've not found any solution. My program runs normally when compiled with gcc, but apparently does not perform any operation when compiled with icc. No runtime errors occur. The program just ends very fast (a few milliseconds), but was expected to take a few seconds (about 11 seconds for n = 1 billion). However it works okay if I print the total at the end.

It's a small code:

# 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;
}

I also checked that it actually runs the loop and calls the function n times.

Does anyone know what could be causing this problem?

Thanks!

Upvotes: 2

Views: 132

Answers (1)

However it works okay if I print the total at the end.

This is probably an optimizing compiler effect (legal, per the C11 standard n1570).

Since there is no visible side-effect in your program (without the printf), the compiler is allowed (per the as-if rule) to optimize it into a no-operation program.

With some versions of GCC or Clang, and some optimization flags you could observe the same. Try to compile your code with gcc -O3 -S -fverbose-asm and look into the generated assembler code (you'll observe an empty generated main with GCC 8.1 on Linux/x86-64)

Does anyone know what could be causing this problem?

Your code, and your misunderstanding of the tricky semantics of C. The implementation is behaving per the C standard (and your program is running properly).

BTW, even with the printf, in theory the compiler is allowed to optimize your program into a simple constant printf. In practice, current compilers are (sadly) not that clever.

If you want some robust benchmark, the n could depend on the program arguments (and you still need to keep the printf, because you want some visible side-effect) perhaps:

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

When measuring performance, don't forget to enable optimizations in your compiler!

BTW, in a few years (after having followed more CS courses, including one on compilation, and/or having read the Dragon Book), you might try to implement some GCC plugin which would be able to optimize your function with an explicit printf (but still n being initialized to a compile-time constant) into a main just calling some printf and doing the loop computing total at compile-time (such an optimization is legal). You'll discover that making such an optimization takes a lot of work (certainly months, perhaps years!), and might not apply to a lot of existing programs, but you could have fun implementing it.

If you are interested in floating point calculations, be sure to read the floating point guide (it is tricky).

Upvotes: 8

Related Questions