Bunder
Bunder

Reputation: 223

Informative "if" statement in "for" loop

Normally when I have a big for loop I put messages to inform me in which part of the process my program is, for example:

for(i = 0; i < large_n; i++) {
    if( i % (large_n)/1000 == 0) {
       printf("We are at %ld \n", i);
    }
    // Do some other stuff
}

I was wondering if this hurts too much the performance (a priori) and if it is the case if there is a smarter alternative.Thanks in advance.

Upvotes: 7

Views: 390

Answers (6)

PP.
PP.

Reputation: 10864

Your mod test probably doesn't hurt performance but if you want a very quick test and you're prepared for multiples of two then consider a mathematical and test:

if ( ( i & 0xFF ) == 0 ) {
    /* this gets printed every 256 iterations */
    ...
}

or

if ( ( i & 0xFFFF ) == 0 ) {
    /* this gets printed every 65536 iterations */
    ...
}

Upvotes: 3

Sparky
Sparky

Reputation: 14077

Notation:

Tp = total time spent executing the progress statements.
Tn = total time spent doing the other normal stuff.
>> = Much greater than

If performance is your main criteria, you want Tn >> Tp. This strongly suggests that the code should be profiled so that you can pick appropriate values. The routine 'printf()' is considered a slow routine (much slower than %) and is a blocking routine (that is, the thread that calls it may pend waiting for a resource used by it).

Personally, I like to abstract away the progress indicator. It can be a logging mechanism, a printf, a progress box, .... Heck, it may be updating a structure that is read by another thread/task/process.

id = progressRegister (<some predefined type of progress update mechanism>);
for(i = 0; i < large_n; i++) {
    progressUpdate (id, <string>, i, large_n);
    // Do some other stuff
}
progressUnregister(id);

Yes, there is some overhead in calling the routine 'progressUpdate()' on each iteration, but again, as long as Tn >> Tp, it usually is not that important.

Hope this helps.

Upvotes: 0

pcbabu
pcbabu

Reputation: 2329

The problem is IO operation printf takes a much time than processor calculates. you can reduce the time if you can add them all and print finally.

Upvotes: 0

A. Santavicca
A. Santavicca

Reputation: 29

By placing a print statement inside of the for loop, you are sacrificing some performance.

Because the program needs to do a system call to write output to the screen every time the message is printed, it takes CPU time away from the program itself.

You can see the difference in performance between these two loops:

int i;
printf("Start Loop A\n");
for(i = 0; i < 100000; i++) {
    printf("%d ", i);
}
printf("Done with Loop A\n");

printf("Start Loop B\n");
for(i = 0; i < 100000; i++) {
    // Do Nothing
}
printf("Done with Loop B\n");

I would include timing code, but I am in the middle of work and can update it later over lunch.

If the difference isn't noticeable, you can increase 100000 to a larger number (although too large a number would cause the first loop to take WAY too long to complete).

Whoops, forgot to finish my answer.

To cut down on the number of system calls your program needs to make, you could check a condition first, and only print if that condition is true.

For example, if you were counting up as in my example code, you could only print out every 100th number by using %:

int i;
for(i = 0; i < 100000; i++) {
    if(i%100 == 0)
        printf("%d", i);
}

That will reduce the number of syscalls from ~100000 to ~1000, which in turn would increase the performance of the loop.

Upvotes: 0

Ed King
Ed King

Reputation: 1863

Regardless of what is in your loop, I wouldn't be leaving statements like printf in unless it's essential to the application/user, nor would I use what are effectively redundant if statements, for the same reason.

Both of these are examples of trace level debugging. They're totally valid and in some cases very useful, but generally not ultimately so in the end application. In this respect, a usual thing to do is to only include them in the build when you actually want to use the information they provide. In this case, you might do something like this:

#define DEBUG

for(i = 0; i < large_n; i++) 
{
    #ifdef DEBUG
        if( i % (large_n)/1000 == 0) 
        {
            printf("We are at %ld \n", i);
        }
    #endif
}

Regarding the performance cost of including these debug outputs all the time, it will totally depend on the system you're running, the efficiency of whatever "printing" statement you're using to output the data, the check/s you're performing and, of course, how often you're trying to perform output.

Upvotes: 4

ChronoTrigger
ChronoTrigger

Reputation: 8617

Maybe you can split the large loop in order to check the condition sometimes only, but I don't know if this will really save time, that depends more on your "other stuff".

int T = ...; // times to check the condition, make sure large_n % T == 0
for(int t = 0; t < T; ++t)
{
  for(int i = large_n/T * t; i < large_n/T * (t+1); ++i)
  {
    // other stuff
  }
  printf("We are at %ld \n", large_n/T * (t+1));
}

Upvotes: 5

Related Questions