views:

126

answers:

5

Hi guys,

Okay, so I've got some C code to perform a mathematical operation which could, pretty much, take any length of time (depending on the operands supplied to it, of course). I was wondering if there is a way to register some kind of method which will be called every n seconds which can analyse the state of the operation, i.e. what iteration it is currently at, possibly using a hardware timer interrupt or something?

The reason I ask this is because I know the common way to implement this is to be keeping track of the current iteration in a variable; say, an integer called progress and have an IF statement like this in the code:

if ((progress % 10000) == 0)
    printf("Currently at iteration %d\n", progress);

but I believe that a mod operation takes a relatively long time to execute, so the idea of having it inside a loop which will be ran many, many times scares me, from an optimisation point of view.

So I get the feeling that having an external way of signalling a progress print is nice and efficient. Are there any great ways to perform this, or is the simple 'mod check' the best (in terms of optimising)?

+1  A: 

While mod operations are usually slow, the compiler should be able to optimize and predict this really well and only mis-predict once ever 10'000 ifs, burning one mod operation and ~20 cycles (for the mis-prediction) on it, which is fine. So you are trying to optimize one mod operation every 10'000 iterations. Of course this assumes you are running it on a modern and typical CPU, and not some embedded system with unknown specs. This should even be faster than having a counter variable. Suggestion: Test it with and without the timing code, and figure out a complex solution if there is really a problem.

Premature optimisation is the root of all evil. -Knuth

Kdansky
+4  A: 

I'd go with the mod check, but maybe with subtractions instead :-)

icount = 0;
progress = 10000;
/* ... */
    if (--progress == 0) {
        progress = 10000;
        printf("Currently at iteration %d0000\n", ++icount);
    }
/* ... */
pmg
good call on the test for zero. that's a better optimization
SB
A: 

you could have a global variable for the iterations, which you could monitor from an external thread.

While () {
  Print(iteration);
  Sleep(1000);
}

You may need to watch out for data races though.

Alexander Rafferty
I like this idea, but I can't think what would be the fastest way to safely read the progress, because the thread running the loop would have to lock and unlock a mutex every iteration :/
panic
@panic: Not if you use `atomic_t` as the type. It's then guaranteed to be a value in the CPU's native word size (or the size which is atomic for the given CPU) and therefor doesn't need a lock since your just reading it.
DarkDust
@panic atomics, but they are MUCH MUCH MUCH more expensive than % (like 10 to 100x more), mod really isn't expensive at all unless you're using it in some really tight inner loop, in which case any progress monitor is going to have too much overhead for you...
Spudd86
@DarkDust you still need to do something to actually make the operations on it atomic
Spudd86
@Spudd86: Yes, you are right... e.g. `atomic_inc` and `atomic_dec`. Hehe, guess I was very lucky during all these years in which I've used it without these methods.
DarkDust
+1  A: 

mod is about the same speed as division, on most CPU's these days that means about 5-10 cycles... in other words hardly anything, slower than multiply/add/subtract, but not enough to really worry about.

However you are right to want to avoid sting in a loop spinning if you're doing work in another thread or something like that, if you're on a unixish system there's timer_create() or on linux the much easier to use timerfd_create()

But for single threaded, just putting that if in is enough.

Spudd86
+1  A: 

Use alarm setitimer to raise SIGALRM signals at regular intervals.

struct itimerval interval;

void handler( int x ) {
    write( STDOUT_FILENO, ".", 1 ); /* Defined in POSIX, not in C */
}

int main() {
    signal( SIGALRM, &handler );
    interval.it_value.tv_sec = 5; /* display after 5 seconds */
    interval.it_interval.tv_sec = 5; /* then display every 5 seconds */
    setitimer( ITIMER_REAL, &interval, NULL );

    /* do computations */

    interval.it_interval.tv_sec = 0; /* don't display progress any more */
    setitimer( ITIMER_REAL, &interval, NULL );
    printf( "\n" ); /* done with the dots! */
}

Note, only a smattering of functions are OK to call inside handler. They are listed partway down this page. If you want to communicate anything for a fancier printout, do it through a sig_atomic_t variable.

Potatoswatter
Just don't do much in the signal handler, write() is fine, fwrite would not be fine.
nos
@nos: yeah, I'm surprised that even `itoa` is forbidden. I guess the pthreads alternative really is better.
Potatoswatter