繁体   English   中英

为什么<慢于<=? [C]

[英]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

差别很小,但是无论我运行二进制文件多少次,我都无法消除它或反转它。

  • 我在lt.c的for循环中使比较值比le.c大一圈(因此它们都循环了相同的次数)。 这是一个错误吗?
  • 根据<是比<=快吗? <编译为jge<=编译为jg 那是在处理if语句而不是for循环,但这是否仍是原因? jge的执行时间可能比jg时间长一点吗? (我认为这是具有讽刺意味的,因为这意味着从C转换为ASM会反转这是更复杂的指令,C中的lt转换为ASM中的gte,而lte转换为gt。
  • 或者,这是否仅仅是硬件专用的,以致于不同的x86系列产品或单个芯片可能始终显示出相反的趋势,相同的趋势或没有差异?

在对我的问题的评论中有一些请求,要求包括GCC为我生成的程序集。 在进入编译器弹出每个文件的程序集版本之后,我检查了一下。

结果:
事实证明,默认优化设置将两个for循环都转换为同一程序集。 实际上,两个文件在组装形式上都是相同的。 diff确认了这一点。)

先前观察到的时差的可能原因:
看来我运行二进制文件的顺序是造成运行时间差异的原因。

  • 在给定的运行时间中,程序通常在每次连续执行时都更快地执行,大约执行3次后才达到稳定。
  • 我在time ./lttime ./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

* *遮住脸* ...继续...

让我们在组装中讲话。 (当然取决于架构)比较时,您将使用cmp或测试指令,然后-当您使用<时,等于指令将是jl,它检查SF和OF是否不相同(一些特殊的标志,称为符号和溢出) -当您使用<=时,相等指令是jle,它不仅检查SF!= OF,而且检查ZF == 1(零标志)等等, 这里更多但老实说,它甚至不是整个循环,所以...在正常情况下差异是无法测量的

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM