【问题标题】:Use "greater than or equals" or just "greater than"使用“大于或等于”或仅使用“大于”
【发布时间】:2008-10-23 19:41:25
【问题描述】:

我记得从 C 天起我们就被鼓励使用

i > -1

而不是

i >= 0

因为性能。

这仍然适用于 C# .NET 世界吗?在当今的编译器中使用其中一种对性能有何影响?即编译器是否足够聪明,可以为您优化这些?

(顺便尝试在 Stack Overflow 上的问题字段中输入问题“使用 >= 或 >”,看看会发生什么。)

【问题讨论】:

    标签: c# .net c


    【解决方案1】:

    不,没有与比较运算符相关的性能问题。无论如何,任何好的编译器都会优化这种微不足道的东西。

    我不确定您从哪里得到使用“i > -1”而不是“i >= 0”的建议。在 x86 架构上,您使用哪个没有区别:任何一种情况都需要两条指令……一条用于比较,一条用于跳转:

     ;; if (i > -1) {
     cmp eax, -1
     jle else
    then:
     ...
    else:
    
     ;; if (i >= 0) {
     cmp eax, 0
     jl else
    then:
     ...
    else:
    

    在我知道的大多数 RISC 架构上,“i >= 0”实际上可能更快,因为通常有一个专用的零寄存器,而“i > -1”可能需要加载一个常量。例如,MIPS 只有一个

     // if (i >= 0) {   (assuming i is in register %t0)
    
     stl $t1, $0, $t0     // in C: t1 = (0 < t0)
     beq $t1, $0, else    // jump if t1 == 0, that is if t0 >= 0
     nop
    then:
     ...
    else:
    
    // if (i > -1) {    (assuming i is in register %t0)
    
     addi $t2, $0, -1      // in C: t2 = -1
     stl $t1, $t2, $t0      // in C: t1 = (t2 < t0) = (-1 < t0)
     bne $t1, $0, else     // jump if t1 != 0, that is if t0 > -1
     nop
    then:
     ...
    else:
    

    因此,在幼稚的一般情况下,在 MIPS 上执行“i >= 0”实际上会快一条指令。当然,RISC 代码的优化程度如此之高,以至于编译器可能会将这些指令序列中的任何一个更改得几乎无法识别:-)

    所以...简短的回答是不不不,没有区别。

    【讨论】:

    • (no no no, no difference) = !(!(!(!difference))) = !(!difference)) = difference ;)
    • @M.kazemAkhgary,这很难反驳。现在我有点想添加第五个“不”:-P
    【解决方案2】:

    除了任何体面的编译器都会做正确的事情这一事实之外,除了在现代架构中&gt;&gt;= 比较之间没有速度差异这一事实之外,更大的图景表明这是一个“微- 优化”在绝大多数情况下不会影响运行时性能。

    在比较的情况下,无论您以哪种方式编写它,它通常都不会影响可读性,但在某些情况下,选择一个边界而不是另一个边界会更清晰:例如,

    if (length >= str.size())
    

    if (length > str.size() - 1)
    

    我不了解你,但我会随时选择选项 1。 :-) 在不会明显影响性能的情况下,例如这种情况,更易读的选项应该会胜出。

    【讨论】:

    • 正确。 “过早的优化是万恶之源。” (唐纳德·克努斯)
    • 请注意,如果 str.size() 返回一个无符号数,则上面的两个语句是不等价的。特别是,如果 str.size() 为零,后一个语句将永远不会评估 true。我有时会使用这样的代码,尽管我通常会在 unsigned 中添加一个明确的类型转换:如果大小是'short',“if (length > (unsigned short)(str.size-1))”将有助于明确代码会期望包装行为。
    【解决方案3】:

    这里有一个非常相似的问题(没有暗示批评 - 正如你所说,搜索符号很棘手):"Should one use &lt; or &lt;= in a for loop"

    (是的,我碰巧能够很容易地找到它,因为我的答案得到了很多赞成...)

    基本上,做最易读的事情。有人正确猜测改变最易读的形式将解决性能问题(无需分析器的帮助)的那一天就是我停止谈论性能的那一天:)

    【讨论】:

      【解决方案4】:

      不,您不再需要这样做了。是的,编译器变得更加智能,这两个表达式没有性能差异。

      【讨论】:

      • 我仍然无法相信曾经有一个环境可以 有所作为。谁能告诉我一个现存的架构,其中一个需要的周期比另一个少???
      • 听起来像是编程都市传奇
      【解决方案5】:

      我记得从 C 天开始,我们就被鼓励使用 .... 因为性能。

      确定对此吗?早在 70 年代初,我就使用过计算机(是的,在我父亲的膝盖上……),我从未见过 CPU 不能处理 >= 和 > 一样快。 (IBM360 演讲中的 BH “Branch High”与 BNL “Branch Not Low”)。

      【讨论】:

      • 我同意,詹姆斯。我能想到的一个是 MIPS,它只有小于。所以编译器通常会将“a
      • 我认为这是一个常见的神话。我从同事那里听说过,甚至在过去几年里也曾在互联网上看过几次。即使没有编译器优化差异,节省一条 cpu 指令也是一种巨大的浪费。
      • 正如你所说 - 这可能是我被误导了 - 谢谢。
      【解决方案6】:

      对于一些将 >= 分解为 2 个比较的可疑脚本语言来说,这可能是正确的,但是无论谁鼓励你将它用于 C ......嗯......你可能应该努力忘记他们曾经告诉过的一切你。

      【讨论】:

        【解决方案7】:

        这让我想起了使用 ++i 而不是 i++(前置增量与后置增量)的建议,因为它据说快了一条指令。 (我忘记了我最初是从哪里读到这个的,但它可能是 C/C++ 用户日志或 Dobb 博士的日志,但我似乎无法找到网络参考。)

        我严重怀疑 > 或 >= 更快或更慢;而是为了清晰起见编写代码。

        作为旁注,我开发了对预增量 (++i) 运算符的偏好,即使原因现在可能已过时。

        【讨论】:

        • 在 C++ 中,有理由更喜欢一个增量而不是另一个 - 我相信这是推荐的预增量。
        【解决方案8】:

        对于大于零,它必须进行两次检查。它检查负位是否关闭,并检查零位是否关闭。

        对于大于或等于零,只需要检查负位是否关闭,因为我们不关心零位是打开还是关闭。

        【讨论】:

          猜你喜欢
          • 2011-12-21
          • 2011-01-25
          • 2013-09-02
          • 2012-01-10
          • 2013-11-11
          • 1970-01-01
          • 2013-12-17
          • 2012-10-22
          相关资源
          最近更新 更多