C++ 什么更快:比较然后改变,还是立即改变?
让我做非常快速的循环,我必须确保在每个循环的末尾变量C++ 什么更快:比较然后改变,还是立即改变?,c++,c,C++,C,让我做非常快速的循环,我必须确保在每个循环的末尾变量a是SOMEVALUE。什么会更快 如果(a!=SOMEVALUE)a=SOMEVALUE 或者马上就去做 a=SOMEVALUE 它是特定于float/int/bool/语言的吗 更新:a是基本类型,而不是类。真正比较的可能性是50%。我知道算法是使循环快速的原因,所以我的问题也是关于编码风格 更新2:谢谢大家的快速回答 立即更改通常更快,因为它不涉及代码中的分支 正如下面的评论和其他人的回答,这确实取决于许多变量,但真正的问题是:你在乎之前
a
是SOMEVALUE
。什么会更快
如果(a!=SOMEVALUE)a=SOMEVALUE代码>
或者马上就去做
a=SOMEVALUE代码>
它是特定于float/int/bool/语言的吗
更新:a
是基本类型,而不是类。真正比较的可能性是50%。我知道算法是使循环快速的原因,所以我的问题也是关于编码风格
更新2:谢谢大家的快速回答 立即更改通常更快,因为它不涉及代码中的分支
正如下面的评论和其他人的回答,这确实取决于许多变量,但真正的问题是:你在乎之前的值是什么吗?如果你是,你应该检查,否则,你不应该。你应该分析它
我的猜测是,根据测试的正确频率(这是由于分支预测),差别不大
当然,只需将其设置为最小的绝对代码大小,就可以释放指令缓存以获得更有趣的代码
但是,同样,你应该对它进行分析。我会感到惊讶的是,答案不是a=somevalue
,但这个问题没有通用的答案。首先,这取决于复制的速度与相等比较的速度。如果相等比较非常快,那么您的第一个选项可能会更好。其次,一如既往,它取决于您的编译器/平台。回答此类问题的唯一方法是尝试这两种方法并计时。在几乎所有情况下,只设置值会更快
当您必须处理与其他CPU的缓存线共享时,或者如果“a”在某种特殊类型的内存中,它可能不会更快,但可以安全地假设分支预测失误可能是比缓存共享更常见的问题
此外,代码越小越好,这不仅是为了缓存,也是为了使代码易于理解
如果有疑问-配置文件。正如其他人所说,配置文件将是最容易判断的方法,因为它在很大程度上取决于您对它的输入类型。然而,如果你考虑这两种算法的计算复杂度,你投入的越多,它们之间可能的差异就越小。一般的答案是分析这类问题。但是,在这种情况下,可以进行简单的分析:
每个测试都是一个分支。每个分支都会受到轻微的性能惩罚。然而,我们已经做到了,这个惩罚在一定程度上是在时间上摊销的,这取决于循环的迭代次数和预测的正确性
在您的情况下,如果在循环过程中对a
有许多更改,则使用if
的代码很可能性能更差。另一方面,如果值很少更新,则两种情况之间的差异将非常小
不过,立即更改更好,而且应该使用,只要您不关心前面的值,正如您的代码片段所示
立即改变的其他原因:它导致更小的代码,从而更好的缓存位置,从而更好的代码性能。更新a
会使缓存线失效并导致性能下降的情况非常罕见。不过,如果我没记错的话,这只会在多处理器情况下使用字节,而且很少使用
请记住,有时两者并不相似。比较NaN
s是未定义的行为
此外,此注释只处理C++中C.的情况,可以使用赋值操作符/复制构造函数比相等的测试长的类。在这种情况下,您可能需要先进行测试
考虑到您的更新,只要您确信不处理未定义的行为(浮动),最好只使用赋值。编码风格明智,它也更好,更容易阅读。 < P>当你问这个C++程序时,我假设你正在编译代码到本机指令。
在任何情况下,直接赋值而不进行任何比较都应该快得多。要比较这些值,值a和SOMEVALUE都应传输到寄存器,并且必须执行一条机器指令cmp()
但在后面直接赋值的情况下,只需将一个值从一个内存位置移动到另一个内存位置
分配速度较慢的唯一方法是当内存写入的成本明显高于内存读取的成本时。我不认为会发生这种情况。分析代码。相应地更改。
对于基本类型,“无分支”选项应该更快。例如,MSV不会优化分支
也就是说,下面是一个比较版本更快的示例:
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;
}
struct X
{
布尔比较内;
X():comparisonone(false){}
布尔运算符!=(常量X和其他){comparisonDone=true;返回true;}
X运算符=(常量X和其他)
{
如果(!comparisonone)
{
对于(int i=0;i<1000000;i++)
可以一些编译器实际上可以“优化”掉if
,基本上将if
变成代码噪音(对于正在阅读它的程序员来说)
当我使用GCC for x86编译以下函数时(使用-O1
,这是一个非常合理的优化级别):
GCC只是“优化”了if
和赋值,并简单地使用参数进行添加:
foo:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
popl %ebp
addl $5, %eax
ret
.ident "GCC: (GNU) 4.4.3"
< > <或>没有<代码>如果生成完全相同的代码。C++中的,如果<代码> a < /C> >类型是一个测试成本低且代码< >运算符=()的类,首先测试更好。
foo:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
popl %ebp
addl $5, %eax
ret
.ident "GCC: (GNU) 4.4.3"