[英]Why would < be slower than <=? [C]
自然地,我假设<和<=运算符以相同的速度运行( 根据Jonathon Reinhart的逻辑,在此处 )。 最近,我决定测试该假设,结果令我有些惊讶。
我知道,对于大多数现代硬件而言,这个问题纯粹是学术性的,因此必须编写循环大约10亿次的测试程序(以获取任何微小的差异,以达到更可接受的水平)。 这些程序尽可能基本(以消除所有可能的干扰源)。
lt.c:
int main() {
for (int i = 0; i < 1000000001; i++);
return 0;
}
le.c:
int main() {
for (int i = 0; i <= 1000000000; i++);
return 0;
}
使用带有-std = c11标志的GCC,可以编译它们并在Linux VirtualBox 3.19.0-18-通用#18-Ubuntu x86_64安装上运行。
lt.c的二进制文件的平均时间为:
real 0m2.404s
user 0m2.389s
sys 0m0.000s
le.c的平均时间为:
real 0m2.397s
user 0m2.384s
sys 0m0.000s
差别很小,但是无论我运行二进制文件多少次,我都无法消除它或反转它。
<
编译为jge
和<=
编译为jg
。 那是在处理if语句而不是for循环,但这是否仍是原因? jge
的执行时间可能比jg
时间长一点吗? (我认为这是具有讽刺意味的,因为这意味着从C转换为ASM会反转这是更复杂的指令,C中的lt转换为ASM中的gte,而lte转换为gt。 在对我的问题的评论中有一些请求,要求包括GCC为我生成的程序集。 在进入编译器弹出每个文件的程序集版本之后,我检查了一下。
结果:
事实证明,默认优化设置将两个for循环都转换为同一程序集。 实际上,两个文件在组装形式上都是相同的。 ( diff
确认了这一点。)
先前观察到的时差的可能原因:
看来我运行二进制文件的顺序是造成运行时间差异的原因。
time ./lt
和time ./le
之间来回time ./le
,因此第一次跑步会偏向平均时间。 代码摘录:
movl $0, -4(%rbp)
jmp .L2
.L3:
addl $1, -4($rbp)
.L2
cmpl $1000000000, -4(%rbp)
jle .L3
mol $0, %eax
pop %rbp
* *遮住脸* ...继续...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.