Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding repetition / loop unswitching

I have hotspot code which runs in a tight loop:

for (i = 0; i < big; i++)
{
    if (condition1) {
        do1();
    } else if (condition2) {
        do2();
    } else {
        do3();
    }
    // Shared code goes here
    // More shared code goes here
}

Since condition1 and condition2 are invariant, I unswitched the loop to

if (condition1) {
    for (i = 0; i < big; i++)
    {
        do1();
        // Shared code goes here
        // More shared code goes here
    }
} else if (condition 2) {
    for (i = 0; i < big; i++)
    {
        do2();
        // Shared code goes here
        // More shared code goes here
    }
} else {
    for (i = 0; i < big; i++)
    {
        do3();
        // Shared code goes here
        // More shared code goes here
    }
}

This runs much better, but I wonder if there's a clever way to do this without repeating myself?

like image 658
Charles Avatar asked Feb 02 '16 18:02

Charles


2 Answers

Another, possibly slightly more efficient option is to use a macro to construct the code for you:

#define DO_N(name, ...) for(int i = 0; i < big; i++){name(__VA_ARGS__);/*shared code*/}

if (condition1) {
    DO_N(do1, .../*arguments here*/)
} else if (condition 2) {
    DO_N(do2, ...)
} else {
    DO_N(do3, ...)
}

#undef DO_N

Its ugly, but I think it does what you want, and might allow inlining where a function pointer does not.

Additionally, you may find it more readable to put your shared code in a separate macro or function.

like image 51
Straw1239 Avatar answered Oct 19 '22 09:10

Straw1239


I think you can declare a function pointer and some function foo():

typedef void (*fp)(void);

void foo(int big, fp f) {
    for (int i = 0; i < big; ++i) {
        f();
        // Shared code goes here
        // More shared code goes her
    }
}

Then change your code for something like this:

if (condition1) {
    foo(big, do1);
} else if (condition2) {
    foo(big, do2);
} else {
    foo(big, do3);
}
like image 35
Edgar Rokjān Avatar answered Oct 19 '22 11:10

Edgar Rokjān