我刚刚偶然发现了这件事,我非常好奇现代CPU(当前的,也许是移动的或嵌入式的)在下面这种情况下是否实际上没有分支成本。
2. 相比之下:
假设
案例2
在两种方法的 -O3 版本之间几乎没有明显的区别,但是没有 -O3,第二种情况在我的机器上运行速度略快。我已经测试了没有 -O3 和循环 = 0xfffffffe 的情况下。
最佳时间:
alin@ubuntu:~/Desktop$ time ./1
real 0m20.231s
user 0m20.224s
sys 0m0.020s
alin@ubuntu:~/Desktop$ time ./2
real 0m19.932s
user 0m19.890s
sys 0m0.060s
1.假设我们有以下代码:
x += a; // let's assume they are both declared earlier as simple ints
if (flag)
do A // let's assume A is not the same as B
else
do B // and of course B is different than A
2. 相比之下:
if (flag)
{
x += a
do A
}
else
{
x += a
do B
}
假设
A
和 B
在流水线指令方面完全不同:
第二种方法会更快吗?
CPU 能够聪明地知道无论标志是什么,下一条指令都是相同的吗(因此它们不必因分支预测错误而丢弃流水线阶段)?
注意:
在第一种情况下,如果出现分支预测错误,CPU 没有选择,只能放弃执行 do A
或 do B
的前几个流水线阶段,因为它们是不同的。我认为第二个示例类似于延迟分支:“即使我不知道标志是什么,我也要检查它,但我可以继续进行下一条指令,因为它是相同的,无论标志是什么,我已经有了下一条指令,并且使用它对我来说没问题。”
编辑:
我做了一些研究,得到了一些不错的结果。你如何解释这种行为?抱歉我的最新编辑,但我遇到了一些缓存问题,就我所看到的,这些是更准确的结果和代码示例。
这是使用 -O3 编译的代码,编译器版本为 gcc version 4.8.2(Ubuntu 4.8.2-19ubuntu1)。
情况1。
#include <stdio.h>
extern int * cache;
extern bool * b;
extern int * x;
extern int * a;
extern unsigned long * loop;
extern void A();
extern void B();
int main()
{
for (unsigned long i = 0; i < *loop; ++i)
{
++*cache;
*x += *a;
if (*b)
{
A();
}
else
{
B();
}
}
delete b;
delete x;
delete a;
delete loop;
delete cache;
return 0;
}
int * cache = new int(0);
bool * b = new bool(true);
int * x = new int(0);
int * a = new int(0);
unsigned long * loop = new unsigned long(0x0ffffffe);
void A() { --*x; *b = false; }
void B() { ++*x; *b = true; }
案例2
#include <stdio.h>
extern int * cache;
extern bool * b;
extern int * x;
extern int * a;
extern unsigned long * loop;
extern void A();
extern void B();
int main()
{
for (unsigned long i = 0; i < *loop; ++i)
{
++*cache;
if (*b)
{
*x += *a;
A();
}
else
{
*x += *a;
B();
}
}
delete b;
delete x;
delete a;
delete loop;
delete cache;
return 0;
}
int * cache = new int(0);
bool * b = new bool(true);
int * x = new int(0);
int * a = new int(0);
unsigned long * loop = new unsigned long(0x0ffffffe);
void A() { --*x; *b = false; }
void B() { ++*x; *b = true; }
在两种方法的 -O3 版本之间几乎没有明显的区别,但是没有 -O3,第二种情况在我的机器上运行速度略快。我已经测试了没有 -O3 和循环 = 0xfffffffe 的情况下。
最佳时间:
alin@ubuntu:~/Desktop$ time ./1
real 0m20.231s
user 0m20.224s
sys 0m0.020s
alin@ubuntu:~/Desktop$ time ./2
real 0m19.932s
user 0m19.890s
sys 0m0.060s