[英]Avoid checking the same condition every step in a loop in C++
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. 该条件与n
无关,因此每次检查都感到多余。 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. 如果确实需要避开分支,通常的方法是定义一个辅助函数或局部lambda(C ++ 11)以分解出通用代码块。 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. 如果您确实要确保删除该分支,则可以强制使其专门用于模板,或者利用if constexpr
(C ++ 17)等优势。但是,请注意代码膨胀和编译时间。
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. 但是,这不是一个通用的解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.