哪个更有效 -
foo->bar |= x;
for(i=0; i<n; i++)
{
if (foo->bar & SOMETHING)
doOnething(i);
else if (foo->bar & SOMETHINGELSE)
doSecondthing(i);
else
doAnotherThing(i);
}
OR
foo->bar |= x;
if (foo->bar & SOMETHING) {
for(i=0; i<n; i++) {
doOneThing(i);
}
}
else if (foo->bar & SOMETHINGELSE) {
for(i=0; i<n; i++) {
doSecondThing(i);
}
}
else {
for(i=0; i<n; i++) {
doAnotherThing(i);
}
}
我知道声明循环会产生开销成本,但实际上在两种情况下都只执行一次。尽管在运行期间工作是相同的,但在编译期间还有更多工作要做?我们是否还考虑了指针被取消引用的位置?
感谢。
答案 0 :(得分:3)
我会选择第二个(对于更少的if-else命中和未命中)并将循环放在函数内部以减少函数开销。
foo->bar |= x;
if (foo->bar & SOMETHING) {
doOneThing(n); // loops inside so no excessive function overhead
}
else if (foo->bar & SOMETHINGELSE) {
doSecondThing(n);
}
else {
doAnotherThing(n);
}
答案 1 :(得分:2)
假设编译器优化,有两种可能的结果:
foo->bar
。那么你的代码样本实际上是一样的。foo->bar
字段读取 - 我们是否幸运地仍然可以在缓存中使用它。至于编译时性能,它完全取决于具体做什么*事情。在内联之后,第一个例子可以在循环迭代中引入一些棘手的数据依赖,或者增加额外的寄存器压力,并强制编译器比第二个做更多的工作。
答案 2 :(得分:1)
什么是SOMETHING,什么是SOMETHINGELSE?是否受到&#34; i&#34;不知何故?
如果是,第一个代码可以为每次迭代运行不同的函数(doOneThing,doSecondThing或doAnotherThing),而第二个代码将对每次迭代执行相同的函数。所以,两个代码都不相等。
假设SOMETHING和SOMETHINGELSE不受&#34; i&#34;的值的影响,在第一个代码中,if-else在每次迭代中被检查,而第二个代码只被检查一次,这会使你的性能在第一种情况下运行时间更糟糕。如果n具有高值,它可以产生真正的差异。
答案 3 :(得分:0)
这两种情况之间存在一个潜在的差异。如果编译器无法确定foo
,foo->bar
和x
在被调用函数内部是不可见的(通过指针),则可能必须每次重新加载并检查值。在第一种情况下循环。
第二种情况的一个缺点是,当您对代码进行更改时,您可能会意外地得到稍微不同的循环控件。
有时,使用函数指针组合这两种方法是有益的:
void (*fp)(int);
foo->bar |= x;
if (foo->bar & SOMETHING)
fp = doOnething;
else (foo->bar & SOMETHINGELSE)
fp = doSecondthing;
else
fp = doAnotherThing;
for(i=0; i<n; i++) {
fp(i);
}