Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficiently print every x iterations in for loop

Tags:

performance

c

hpc

I am writing a program in which a certain for-loop gets iterated over many many times.

One single iteration doesn't take to long but since the program iterates the loop so often it takes quite some time to compute.

In an effort to get more information on the progress of the program without slowing it down to much I would like to print the progress every xth step.

Is there a different way to do this, than a conditional with a modulo like so:

for(int i = 0; i < some_large_number; i++){
    if(i % x == 0)
        printf("%f%%\r", percent);
    //some other code
    .
    .
    .
}

?

Thanks is advance

like image 506
lookatdatcake Avatar asked Jan 26 '23 02:01

lookatdatcake


1 Answers

This code:

for(int i = 0; i < some_large_number; i++){
    if(i % x == 0)
        printf("%f%%\r", percent);
    //some other code
    .
    .
    .
}

can be restructured as:

/*  Partition the execution into blocks of x iterations, possibly including a
    final fragmentary block.  The expression (some_large_number+(x-1))/x
    calculates some_large_number/x with any fraction rounded up.
*/
for (int block = 0, i = 0; block < (some_large_number+(x-1))/x; ++block)
{
    printf("%f%%\r", percent);

    //  Set limit to the lesser of the end of the current block or some_large_number.
    int limit = (block+1) * x;
    if (some_large_number < limit) limit = some_large_number;

    //  Iterate the original code.
    for (; i < limit; ++i)
    {
        //some other code
    }
}

With the following caveats and properties:

  • The inner loop has no more work than the original loop (it has no extra variable to count or test) and has the i % x == 0 test completely removed. This is optimal for the inner loop in the sense it reduces the nominal amount of work as much as possible, although real-world hardware sometimes has finicky behaviors that can result in more compute time for less actual work.
  • New identifiers block and limit are introduced but can be changed to avoid any conflicts with uses in the original code.
  • Other than the above, the inner loop operates identically to the original code: It sees the same values of i in the same order as the original code, so no changes are needed in that code.
  • some_large_number+(x-1) could overflow int.
like image 97
Eric Postpischil Avatar answered Jan 30 '23 03:01

Eric Postpischil