什么是更快:比较然后改变,或立即改变?

时间:2012-07-19 14:41:32

标签: c++ c

让我做非常快的循环,我必须确保在每个循环结束时变量aSOMEVALUE。什么会更快?

if (a != SOMEVALUE) a = SOMEVALUE;

或立即执行

a = SOMEVALUE;

是浮动/ int / bool /语言特定的吗?

更新:a是基本类型,而不是类。 TRUE比较的可能性为50%。我知道算法是使循环快速的原因,所以我的问题也是编码风格。

Update2:感谢大家快速解答!

9 个答案:

答案 0 :(得分:2)

几乎在所有情况下,只设置值会更快。

当你必须处理与其他cpus的高速缓存行共享或者某个特殊类型的内存中有'a'时,它可能不会更快,但是可以安全地假设分支错误预测可能是比缓存更常见的问题共享。

此外 - 较小的代码更好,不仅适用于缓存,还适用于使代码易于理解。

如果有疑问 - 个人资料。

答案 1 :(得分:2)

一般的答案是描述这类问题。但是,在这种情况下,可以进行简单的分析:

每个测试都是一个分支。每个分支都会产生轻微的性能损失。但是,我们有branch prediction并且这个惩罚在某种程度上是按时分摊的,这取决于你的循环有多少次迭代以及预测的正确次数。

转换到您的情况,如果您在循环期间对a进行了很多更改,那么使用if的代码很可能会在性能上更差。另一方面,如果值很少更新,则两种情况之间会有无限小的差异。

尽管如此,只要您不关心之前的值,就会立即进行更改并且应该使用,就像您的代码段所示。

立即改变的其他原因:它导致更小的代码,从而更好地缓存局部性,从而提高代码性能。这种情况非常罕见,更新a会使缓存行无效并导致性能下降。尽管如此,如果我没记错的话,这只能在多处理器的情况下对你进行字节记录,很少见。

请记住,有两种情况不相似的情况。比较NaN s是未定义的行为。

此外,此注释仅处理C的情况。在C ++中,您可以使用赋值运算符/复制构造函数所需的时间比测试相等性更长的类。在这种情况下,您可能希望先测试。

考虑到您的更新,只要您确定不处理未定义的行为(浮点数),最好简单地使用赋值。编码风格明智,它也更好,更容易阅读。

答案 2 :(得分:1)

立即更改通常更快,因为它不涉及代码中的分支。

如下面评论并由其他人回答,它实际上取决于许多变量,但恕我直言,真正的问题是:你关心的是以前的价值吗?如果你是,你应该检查,否则,你不应该。

答案 3 :(得分:1)

您应该对其进行分析。

我的猜测是,差别很小,取决于测试的频率(这是由于分支预测)。

当然,只需设置它就具有最小的绝对代码大小,从而释放指令缓存以获得更有趣的代码。

但是,再次,你应该描述它。

答案 4 :(得分:1)

我很惊讶答案不是a = somevalue,但这个问题没有通用答案。 Firslty它取决于复制的速度与平等比较的速度。如果相等比较非常快,那么您的第一个选项可能会更好。其次,一如既往,它取决于您的编译器/平台。回答这些问题的唯一方法是尝试两种方法并计算时间。

答案 5 :(得分:1)

正如其他人所说的那样,分析它将是最简单的方式,因为它很大程度上取决于你投入的投入。但是,如果你考虑两种算法的计算复杂性,你输入的输入越多,它们之间可能存在的差异就越小。

答案 6 :(得分:1)

当你问这个C ++程序时,我假设您正在将代码编译为本机机器指令。

在任何情况下,无需任何比较直接分配值应该快得多。要比较这些值,应将值a和SOMEVALUE都传送到寄存器,并且必须执行一条机器指令cmp()。

但是在后面直接分配的情况下,您只需将一个值从一个内存位置移动到另一个内存位置。

只有在内存写入比内存读取成本高得多的情况下,分配才能更慢。我没有看到这种情况发生。

答案 7 :(得分:1)

配置代码。相应地改变。

对于基本类型,no branch选项应该更快。例如,MSVS不会优化分支。

话虽如此,这里是比较版本更快的例子:

struct X
{
    bool comparisonDone;
    X() : comparisonDone(false) {}
    bool operator != (const X& other) { comparisonDone = true; return true; }
    X& operator = (const X& other)
    {
       if ( !comparisonDone )
       {
           for ( int i = 0 ; i < 1000000 ; i++ )
               cout << i;
       }
       return *this;
    }
}

int main()
{
    X a;
    X SOMEVALUE;
    if (a != SOMEVALUE) a = SOMEVALUE;
    a = SOMEVALUE;
}

答案 8 :(得分:0)

if实际上可以被某些编译器“优化掉”,基本上将if转换为代码噪声(对于正在阅读它的程序员而言)。

当我使用GCC for x86编译以下函数时(使用-O1,这是一个非常合理的优化级别):

int foo (int a)
{
  int b;

  if (b != a)
    b = a;

  b += 5;

  return b;
}

GCC只需'优化'if 分配,只需使用参数进行添加:

foo:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
        popl    %ebp
        addl    $5, %eax
        ret
        .ident  "GCC: (GNU) 4.4.3"

是否拥有if生成完全相同的代码。