在C ++中使用位运算符或if语句是否更快?

时间:2015-04-23 15:29:27

标签: c++ performance bitwise-operators

我在某处读到,在可能的情况下使用按位运算符而不是if语句会更快。我正在研究一个图像处理项目,我有各种方法可以对像素进行数学运算。例如,当我添加一个像素时,我会检查并确保总和不会超过最大值。我把它改成了......

    Pixel16 operator+(Pixel16 p) const noexcept
    {
        uint_fast32_t r = red + p.red;
        uint_fast32_t g = green + p.green;
        uint_fast32_t b = blue + p.blue;
        return Pixel16(r | -(r > 0xffff), g | -(g > 0xffff), b | -(b > 0xffff));
    }

你们认为这比编写像...这样的陈述更快吗?

if(r > 0xffff)
 r = 0xffff;

FYI红色,绿色和蓝色是uint16_t

类型的成员变量

3 个答案:

答案 0 :(得分:2)

鉴于此代码:

#include <algorithm>
#include <cstdint>

struct Pixel16 {
    uint16_t red;
    uint16_t blue;
    uint16_t green;

    Pixel16(uint16_t red, uint16_t green, uint16_t blue);

};

Pixel16 v1(Pixel16 const & p, Pixel16 const & s) {
    uint_fast32_t r = p.red   + s.red;
    uint_fast32_t g = p.green + s.green;
    uint_fast32_t b = p.blue  + s.blue;
    return Pixel16(r | -(r > 0xffff), g | -(g > 0xffff), b | -(b > 0xffff));
}

Pixel16 v2(Pixel16 const & p, Pixel16 const & s) {
    uint_fast32_t r = p.red   + s.red;
    uint_fast32_t g = p.green + s.green;
    uint_fast32_t b = p.blue  + s.blue;

    r = std::min(r, (uint_fast32_t) 0xFFFF);
    g = std::min(g, (uint_fast32_t) 0xFFFF);
    b = std::min(b, (uint_fast32_t) 0xFFFF);

    return Pixel16(r, g, b);
}

我的编译器给出了什么结果?

OS X上的Clang将为v1v2生成功能相同的代码。唯一的区别是,对min()的调用和v1中的等效工作的顺序以不同的顺序发生。

在这两种情况下,都没有分支。

要点:

编写最易理解的代码。使用函数和语言功能以可读的方式表达您的代码。您的按位代码是否比min()函数更具可读性?

答案 1 :(得分:1)

几乎在所有情况下&#34;更快&#34;将在很大程度上取决于目标系统和使用的编译器,以及运算符可能如何过载。但是,在这种情况下,我非常怀疑会有那么大的差别,因为你仍然使用比较运算符,这应该是比简单的if分支更昂贵的操作。

上面列出的代码困扰着我。否定比较操作的结果(布尔操作,除非您已经覆盖了操作符)并不是按位或者像您一样安全的操作。此外,它很难理解,这意味着以后某人很难维持。然而,if版本解释了发生了什么。

答案 2 :(得分:0)

知道,您必须衡量(配置代码)。

关于为什么按位运算可能更快的理论是,分支预测失败可能是一个重要的性能损失。通过使用按位运算而不是控制流程开关,您可以完全避免条件分支,因此您永远不会在那里发生分支预测错过。

根据具体情况,计算而不是分支也可能稍微缓存一下。

但除非你测量,否则你不会知道实际效果。简单分析代码的因素太多了。