Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unrolling for loops in a special case function

So I'm trying to optimize some code. I have a function with a variable sized loop. However for efficiency sake I want to make cases with 1, 2 and 3 sized loops special cases that are completely unrolled. My approach so far is to declare the loop size as a const parameter then define wrapper functions that call the main function handing it a literal for the const value. I've included a code snip it illustrating the kind of thing i have in mind.

inline void someFunction (const int a)
{
    for (int i=0; i<a; i++)
    {
        // do something with i.
    }
}

void specialCase()
{
    someFunction (3);
}

void generalCase(int a)
{
    someFunction (a);
}

So my question is is it reasonable for me to expect my compiler (GCC) to unroll the for loop inside of specialCase. I'm mean obviously I can copy - paste the contents of someFunction into specialCase and replace a with 3 but I'd rather only deal with one definition of someFunction in my code for clarity sake.

like image 960
p clark Avatar asked Sep 18 '17 10:09

p clark


1 Answers

However for efficiency sake I want to make cases with 1, 2 and 3 sized loops special cases that are completely unrolled.

Have you measured that this is actually faster? I doubt it will be (or that the compiler won't unroll the loop automatically).


My approach so far is to declare the loop size as a const parameter then define wrapper functions that call the main function handing it a literal for the const value.

const doesn't mean anything here. It won't affect the compiler's ability to unroll the loop. It just means that a cannot be mutated inside the function body, but it's still a runtime argument.


If you want to ensure unrolling, then force it. It's quite easy with C++17.

template <typename F, std::size_t... Is>
void repeat_unrolled_impl(F&& f, std::index_sequence<Is...>)
{
    (f(std::integral_constant<std::size_t, Is>{}), ...);
}

template <std::size_t Iterations, typename F>
void repeat_unrolled(F&& f)
{
    repeat_unrolled_impl(std::forward<F>(f), 
                         std::make_index_sequence<Iterations>{});
}

live example on godbolt

like image 123
Vittorio Romeo Avatar answered Oct 10 '22 02:10

Vittorio Romeo