-3

After asking this question i was so confused, that decided to build similar test for a C compiler program. This is my code :

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

#define SUMMATIONS 20000000

int main() {

    static int speedups[2101] = { 0 };

    srand((unsigned)time(NULL));

    while (1) {

        unsigned int t1, t2, t3, t4;
        signed int tmp, i, n1, n2;

        // Slow version
        t1 = clock();
        for (n1 = rand() % 50, i = 0; i < SUMMATIONS; i++) {
            n1 += 3 * i * i;
        }
        t2 = clock();

        // Optimized version
        t3 = clock();
        for (n2 = rand() % 50, i = 0; i < SUMMATIONS; i++) {
            n2 += i * i;
        }
        n2 *= 3;
        t4 = clock();

        // gather speedup statistics
        if ((int)(t2 - t1) != 0) {
            tmp = (int)(100.0f * ((float)(t2 - t1) - (float)(t4 - t3)) / (float)(t2 - t1));
            tmp = tmp < -100 ? -100 : tmp > 100 ? 100 : tmp;
            tmp = (tmp >= 0 ? 1000 : 2000) + abs(tmp);
            speedups[tmp]++;
        }

        // output statistics
        for (i = 0; i < 2101; i++) {
            if (speedups[i] != 0) {
                char s = i / 1000 == 1 ? '+' : i / 1000 == 2 ? '-' : '?';
                printf("%c%i : %i\n", s, i % 1000, speedups[i]);
            }
        }
        printf("error %i ******************\n", abs(n2-n1));

    }

    return 0;
}

Compiled under GCC with options -O3 -march=native

EDIT

Test code changed so that error value could be known only at run-time (and not in compile-time), so that GCC optimizer could not delete for loop's code.

Results

When run - recalculates counters of CPU hits into specific speedup value and outputs counters table. If we draw CPU hits Vs Speedup values,- we'll get such graph:

enter image description here

So GCC made program produces ~ 20% speedup on average.

Question

Should we expect speedup in CPU ? (As predicted by GCC compiled program)

Agnius Vasiliauskas
  • 10,935
  • 5
  • 50
  • 70
  • 1
    It's unclear what all this code does, and how it relates to the output you quoted. Could you add some explanation? – Oliver Charlesworth Dec 04 '18 at 21:36
  • 1
    Fun fact: `gcc -O3` happily produces the following sequence (minimally edited for lack of formatting in this comment) as part of the translation: `call clock; movq %rax, %r14; call clock; movq %rax, %rbx; call clock; movq %rax, %r13; call clock` I invite you to ponder how much meaning the timings will have. – EOF Dec 04 '18 at 21:44
  • Measures execution speed of slow and optimized code blocks. Calculates relative speedup of "fast" block and increases counter of that speedup value in array to see how much processor hits into that speedup value. Prints data in format "speedup in percents : hit amount" – Agnius Vasiliauskas Dec 04 '18 at 21:44
  • If you analyze the resulting assembly code with [godbolt.org](https://godbolt.org) you find that clang with the given command parameters is able to optimize away the complete loops (i.e. make them empty). Modify your code to disable the optimizer to throw away the computation results. – Axel Kemper Dec 04 '18 at 21:45
  • @AxelKemper, I don't think that it is good idea to benchmark code with optimizer disabled. Benchmarking should be done with -O2 or -O3 i think. Somebody suggested to me that also, i probably agree – Agnius Vasiliauskas Dec 04 '18 at 21:53
  • 1
    @AgniusVasiliauskas No, my suggestion is to do something with the variables aggregated in the loops. In your code, these variables are not used aftwerwards. Therefore, the optimizer is happily throwing them away. So, by "disable" I rather mean "prevent" than switch off. – Axel Kemper Dec 04 '18 at 21:57
  • @AxelKemper Thats will try that – Agnius Vasiliauskas Dec 04 '18 at 22:04
  • Magic. Just magic. (all those who deny that ther *is* magic in C but only in C++ should look at that code and finally come to reason. There *is* magic in C!) – Swordfish Dec 04 '18 at 22:15
  • (sorry for editing but i can't read such stuff when it isn't properly indented. now i can read it but it doesn't help the cause ^^) – Swordfish Dec 04 '18 at 22:20
  • @AxelKemper I fixed the code for n1,n2 variable not to be skipped by optimizer. Still strange results. I don't know to what I should believe - GCC or CLANG. GCC results are more consistent, but that don't means that it produced optimal/correct ASM for **this** case. I don't know ASM, so that's why this question. Maybe somebody will explain CPU behavior with good degree of knowledge – Agnius Vasiliauskas Dec 04 '18 at 23:05

1 Answers1

2

Should we expect speedup in CPU ?

No. By choosing to use a high level language you've chosen to discard your right to expect anything related to performance.

You may assume (but not expect) that the first version has an additional multiplication (the extra 3*) inside the loop and therefore there might be additional costs associated with that multiplication.

You may also assume (but not expect) that the compiler might optimise both versions down to a constant, and might generate the equivalent of printf("error %i ******************\n", CONSTANT_CALCULATED_AT_COMPILE_TIME); without any code to calculate n1 or n2 at run-time.

Note that these random assumptions are mutually exclusive.

Agnius Vasiliauskas
  • 10,935
  • 5
  • 50
  • 70
Brendan
  • 35,656
  • 2
  • 39
  • 66
  • 1
    Your first paragraph is questionable; people do actually use C (and even C++) with an expectation of performance. – M.M Dec 05 '18 at 02:34
  • 1
    @M.M: Sure, people expect things that they have no right to expect all the time. Then they create assumptions, and take measurements to see how wrong the assumptions were for one specific version of one specific compiler with one specific set command line options/optimisations when generating code for one specific CPU. – Brendan Dec 05 '18 at 02:44
  • 1
    This person doing a crappy benchmark doesn't mean that well-written C programs can't have an expectation of performance – M.M Dec 05 '18 at 02:52
  • @M.M: I think you're confusing "can" with "should". E.g. "people can have expectations even though they have no right to expect anything, and even though they shouldn't expect anything because they have no right to expect anything". – Brendan Dec 05 '18 at 02:55
  • @M.M I would be _more_ than happy if you could write your non-crappy benchmark as your answer. You are more than welcome – Agnius Vasiliauskas Dec 05 '18 at 08:47