2015-02-10 38 views
1

我偶然发现了两个等价增量语法之间的奇怪的持续时间差异。C++ - 有和没有if语句的奇怪时间测量

if(seed != state) ++i; 

这个符号测量每个迭代1048576

i += (seed != state); 

2.25毫秒,每1048576次迭代这个2.80毫秒。

不应该第二个符号比第一个符号快一点? 这是要提到的是,种子==状态很少发生(在2^32-1次之一)。

感谢您的回答。

编辑: 我用gcc C编译器测试了同样的东西,其中第一个比第二个稍快,但第二个与C++编译器的速度相同。

+0

您是否使用优化版本进行了测量?那将是令人惊讶的。 – 2015-02-10 22:40:53

+0

这是没有足够的时间在操作系统下进行可靠的测量。运行几次,你可能会得到不同的结果。让它以十亿次迭代运行,差异可能会消失。如果没有,你如何编译这个?具体而言,是否进行优化?我希望优化编译器能够为此生成完全相同的代码,但可能并非没有优化。 – Wintermute 2015-02-10 22:40:59

+0

它以10亿次迭代运行,但结果除以1000以获得100万次运行的平均值。即使使用-O3,第一个也会慢一点。 – bakkaa 2015-02-10 22:59:13

回答

0

使用if语句,编译器可以将增量转换为条件执行语句(至少使用支持有条件执行的语句的处理器)。

第二个例子将总是执行1或0的加法。

这是微观优化,真正取决于处理器及其支持系统(缓存,分支预测等)。例如,第二个示例可能会更快,因为没有决策跳转。第一个例子可能在具有分支预测的处理器上更快。在可以将代码片段放入指令缓存的处理器中,两者之间的差异可以忽略不计(并且不需要获取其他指令)。

我很惊讶,代码执行是以毫秒为单位。对于这些示例,大多数现代处理器应该在纳秒内执行。

+0

我将nano转换为milli只是为了好玩。 – bakkaa 2015-02-11 00:10:07

+0

@bakkaa:真的,你应该因为提供错误的事实而失望“为了好玩”。例如,我想知道你可能使用了哪种CPU架构,并得出结论,它必须是一些古老的微控制器,时钟频率低于1MHz,因为它需要*毫秒*来计算。 – 2015-02-11 08:31:17

+0

@MarcusMüller:我没有提供错误的事实。你应该被低估不听。我说我把它从纳米转换为毫米,但时间是一样的。 1百万纳秒是1毫秒。你应该知道这一点。 – bakkaa 2015-02-11 15:29:25

3

if版本引发条件分支指令。另一个只是将一个bool转换为int并添加它。

编辑:

我会倾向使用由于技术上的转化(int)true不需要由标准以导致1的第一个,;只需要导致“不为零”。虽然在实践中,我从来没有见过boolint的转换,但没有使用1作为true

+1

”...并*无条件*添加它。“ – WhozCraig 2015-02-10 22:40:42

+0

是的,谢谢。 – iwolf 2015-02-10 22:41:07

+0

它不会仅在2^32-1个案例中添加1个。 – bakkaa 2015-02-10 22:50:18

2

你永远不知道你的编译器如何优化你的代码。分支预测实际上会使第一个更快。第二个取决于实际进行的比较,如果结果为i,则结果为1(这取决于您的CPU,但很可能会引入)“虚拟”1加载寄存器。

+0

由于你在托马斯马修斯的回答下的评论,你似乎误解了我的马库斯穆勒。请考虑再读一遍。 – bakkaa 2015-02-11 15:44:16

0

第一个可能有条件地不作为分支预测的结果执行添加。第二个将添加每个周期,因为没有选项可以跳过添加。比较的结果将始终添加到i。

我会假设你会发现第一个不执行添加每个循环,但只是偶尔当分支预测失败。

+0

添加不是仅在2^32-1个案例中的1个中执行 – bakkaa 2015-02-10 23:13:00