I am checking a condition inside a loop, and if it holds, do something.
for (i = 0; i < n; i++)
{
// do lots of work here
.
.
.
if (constant_condition)
do_something(n);
}
The condition is independent of n
, so it feels redundant to check it every time. I could instead do this:
if (constant_condition)
for (i = 0; i < n; i++)
{
// do lots of work here
.
.
.
do_something(n);
}
else
for (i = 0; i < n; i++)
{
// do lots of work here
.
.
.
}
This new code is more efficient, but I had to copy paste the same code in my program. Is there an efficient way to do this without repeating the same block of code?
Edit: the condition is not known at compile time, but it will be given at runtime and will not change.
First of all, profile to see if it matters. If it does, you have several options:
Cache the constant outside of the loop if the compiler hasn't done so already. This is the simplest and in most cases, enough:
const bool constant_condition = ...;
for (...) {
...
if (constant_condition) do_something(...);
}
If you really need to avoid the branch, a typical approach is to define an auxiliary function or a local lambda (C++11) to factor out the common blocks of code. However, this still duplicates code and, depending on the case, may not look pretty at all:
auto main_work = [...](...) { ... };
if (constant_condition)
for (...) { main_work(...); }
else
for (...) { main_work(...); do_something(...); }
Define a template and parametrize as needed. The compiler will typically optimize properly, so you can simply copy-paste the code. If you really want to ensure the branch is removed, you can force it specializing the template, or taking advantage of if constexpr
(C++17) etc. However, beware of code bloat and compilation times.
template <bool constant_condition>
void f(...) { ... }
if (constant_condition)
f<true>(...);
else
f<false>(...);
Finally, don't forget to profile again. Sometimes, removing a branch may look good, yet be detrimental overall. This is specially true if the code changes a lot and what initially looked like a small duplication of instructions is now several memory pages full of duplicated code.
Another alternative is trying to see if the algorithm/code can be written as branchless instead; however, that isn't a general solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With