【问题标题】:Speed of Comparison operators比较运算符的速度
【发布时间】:2011-06-18 20:40:02
【问题描述】:

在诸如...之类的语言中,

如果(x

如果 (x

【问题讨论】:

  • 与大多数其他优化/性能问题一样,它取决于太多因素(编译器、使用的确切代码等)。但是,如果您担心这一级别的优化,您可能会在代码的其他部分使用 1000 多次。
  • @Ken White,+1,因为您总体上是对的,记住这一点很重要。但是,我认为采用简单的指导方针(只要它们不损害可读性)是一种很好的做法,这往往会使代码平均更快。您在 C/C++ 中经常看到这一点,它倾向于通过引用而不是通过值传递对象。没有单一的传球真的对表现造成如此大的伤害,但它们加起来。 (这个案例显然没有那么重要。)

标签: performance operator-keyword


【解决方案1】:

假设没有编译器优化(大假设),第一个会更快,因为 jle 指令实现,而后者需要一个加法,然后是 jl 指令。

http://en.wikibooks.org/wiki/X86_Assembly/Control_Flow#Jump_if_Less

【讨论】:

  • 使用现代流水线处理器,您无法使用指令数来预测性能。
  • Voight:当然,我应该将它添加到我最初关于编译器的免责声明中。但是,我认为您可以预测,在我能想到的所有情况下,第一个都不会,而且它偶尔可能会更快(尽管仅在可能有 10 年历史的机器上或旧的,而且只有一点点)。
  • jljle 快吗? x <= y + 1x < y + 2之间有速度差异吗?
  • @AaronFranke — 那里不太可能存在速度差异。我无法想象在速度上会有差异的机器架构或编译器。
【解决方案2】:

就性能而言,我根本不会担心这一点。以 C 为例,在我使用面向 x86 的 GCC 4.5.1(使用 -O2)运行的一个简单测试中,(x <=y ) 操作编译为:

    // if (x <= y) {
    //     printf( "x <= y\n");
    // }
    //
    // `x` is [esp+28]
    // `y` is [esp+24]

    mov eax, DWORD PTR [esp+24]     // load `y` into eax 
    cmp DWORD PTR [esp+28], eax     // compare with `x`
    jle L5                          // if x < y, jump to the `true` block
L2:

    // ...

    ret

L5: // this prints "x <= y\n"
    mov DWORD PTR [esp], OFFSET FLAT:LC1
    call    _puts
    jmp L2      // jumps back to the code after the ` if statement

(x &lt; y + 1) 操作编译为:

    // if (x < y +1) {
    //     printf( "x < y+1\n");
    // }
    //
    // `x` is [esp+28]
    // `y` is [esp+24]

    mov eax, DWORD PTR [esp+28]     // load x into eax
    cmp DWORD PTR [esp+24], eax     // compare with y
    jl  L3                          //  jump past the true block if (y < x)
    mov DWORD PTR [esp], OFFSET FLAT:LC2
    call    _puts
L3:

所以你可能会在一个跳跃左右有一个跳跃的差异,但你真的应该只在它真的是一个热点的奇怪时间关心这种事情。当然,语言之间可能存在差异,具体发生的情况可能取决于正在比较的对象的类型。但就性能而言,我仍然完全不担心这一点(直到它成为一个明显的性能问题——如果它在我的一生中不止一次或两次这样做,我会感到惊讶)。

所以,我认为担心使用哪种测试的唯一两个原因是:

  • 正确性 - 当然,这胜过任何其他考虑
  • 风格/可读性

虽然您可能认为样式/可读性考虑因素不多,但我确实有点担心。在我今天的 C 和 C++ 代码中,我更倾向于使用 &lt; 运算符而不是 &lt;=,因为我认为使用 &lt; 比使用 &lt;= 测试更容易终止循环。所以,例如:

  • 按索引迭代数组,通常应使用index &lt; number_of_elements 测试
  • 使用指向元素的指针迭代数组应使用ptr &lt; (array + number_of_elements) 测试

实际上,即使在 C 中,我现在也倾向于使用 ptr != (array + number_of_elements),因为我已经习惯了 &lt; 关系赢得工作的 STL 迭代器。

事实上,如果我在 for 循环条件中看到 &lt;= 测试,我会仔细查看 - 通常潜伏着一个错误。我认为这是一种反模式。

不,我承认其中很多可能不适用于其他语言,但如果我使用另一种语言时,我不得不担心性能问题,因为我选择使用&lt; 超过 &lt;=

【讨论】:

    【解决方案3】:

    什么数据类型?

    如果yINT_MAX,那么无论x 是什么,第一个表达式都是true(假设x 是相同或更小的类型),而第二个表达式始终是false

    如果答案不需要是正确的,你可以更快地得到它。

    【讨论】:

      【解决方案4】:

      您是否认为这两个论点是不同的?如果 x 和 y 是浮点数 - 它们可能不会给出相同的结果。这就是两个比较运算符都存在的原因。

      【讨论】:

        【解决方案5】:

        更喜欢第一个。

        在某些具有动态类型的语言中,运行环境必须确定 y 的类型并执行适当的 + 运算符。

        【讨论】:

          【解决方案6】:

          像您一样含糊其辞会导致这是一个无法回答的问题。除非您有要测量的软件和硬件,否则无法评估性能 - 什么语言?什么语言实现?什么目标CPU架构?等等

          话虽如此,&lt;=&lt; 在性能方面通常是相同的,因为它们在逻辑上等同于 &gt;&gt;=,只是交换了底层 goto(分支指令)的目标,或者交换了底层“真/假”评估的逻辑。

          如果您使用 C 或 C++ 进行编程,编译器也许能够弄清楚您在做什么,并换成更快的替代方案。

          按顺序编写易于理解、可维护、正确且高性能的代码。对于性能,找到衡量整个程序性能的工具,并明智地花费时间。仅在您的程序足够快之前优化瓶颈。通过编写更好的代码或制作更酷的功能来节省时间:)

          【讨论】:

            猜你喜欢
            • 2011-05-03
            • 1970-01-01
            • 1970-01-01
            • 2021-01-13
            • 2019-08-13
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多