Which is faster?

Program A:

for (int i = functionA(value--); i < functionB(value+value); i++)
{
....
}

Program B:

int initIndex = functionA(value--);
int limitIndex = functionB(value+value);

for (int i = initIndex; i < limitIndex; i++)
{
...
}


Will program B be faster than program A since we are only calling the two functions just once? As opposed to program A which calls it after each iteration?
Try it!

I'm guessing that any optimiser cannot determine whether functionB is affected by what goes on in the loop, so is obliged to evaluate this function every time. Method A therefore takes longer. (But this is a pretty extreme example.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <cmath>
#include <ctime>
using namespace std;


int functionA( int i ){ return i; }


int functionB( int i )
{
   const int NMAX = 10000;
   // do something expensive
   for ( int n = 0; n <= NMAX; n++ ) double x = exp( -( n + 0.0 ) / NMAX );
   // make it loop a lot
   return NMAX;
}


int main()
{
   clock_t t;
   int value;


   // Method A
   t = clock();
   value = 1;
   for (int i = functionA(value--); i < functionB(value+value); i++)
   {
      double x = exp( -i / 1000.0 );
   }
   double timeA = (double)( clock() - t ) / CLOCKS_PER_SEC;


   // Method B
   t = clock();
   value = 1;
   int initIndex = functionA(value--);
   int limitIndex = functionB(value+value);
   for (int i = initIndex; i < limitIndex; i++)
   {
      double x = exp( -i / 1000.0 );
   }
   double timeB = (double)( clock() - t ) / CLOCKS_PER_SEC;


   cout << "Method A: " << timeA << " seconds\n";
   cout << "Method B: " << timeB << " seconds\n";
}
Last edited on
It depends on if value is being modified inside the loop, on the functions, and on the compiler and the compiler flags that are being used. GCC generates the exact same result for both methods when compiling the code posted by lastchance with the -O2 -ffast-math compiler flags.

For simple functions that are likely to be inlined (e.g. std::vector::size()) I would just do whatever is less error prone, or more readable, or easier to maintain. If on the other hand the function is costly and you want to make absolutely sure it is not called more than once you better use method B.
but, does version B pick up any additional optimizations if you throw a const on it?


1
2
3
4
5
6
7
Program B:

const int initIndex = functionA(value--);
const int limitIndex = functionB(value+value);

for (int i = initIndex; i < limitIndex; i++)


sometimes I have seen this trick clean up the assembly a little bit (and other times nothing happens). You can also throw a 'register' suggestion on it and sometimes it helps, but here, it should have already figured out to have the value in the register for the loop.

it also depends on whether value changes. If value changes, the 2 versions are NOT identical and you have a performance problem that will take a deep understanding of the problem to see what the best answer might be.

finally, the for loop initialize is only invoked once, so there is no gain from dealing with initIndex differently. Ignore it, you can do it either way and it will be identical. The question is whether it determines that it MUST do the function call each time on the comparison, or not. It may incorrectly decide this if the call is in the loop, and it never will if its in the variable, but I can't see a modern compiler making this mistake!

Last edited on
Topic archived. No new replies allowed.