简体   繁体   English

避免在C ++中循环的每一步都检查相同的条件

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM