-5

これらのスニペットのどれがより速いか知りたいです。

私は通常、次の表現を使用します。

if(x <= y)
    break;

しかし、これを使用する利点はありますか?

if(!(x > y))
    break;

これが私の推論です。最初のステートメントは実際にはこれだと思います:

if(x == y)
    break;
if(x < y)
    break;

しかし、2番目のステートメントはこれだけだと思います:

if(!(x > y))
     break;

これにより、2 番目のステートメントの方が速いと思います。これは正しいですか?

4

6 に答える 6

8

を使用してコンパイルgcc -O3 -march=native -m64 -fomit-frame-pointer -S:

int f(int x, int y) {
    if (x <= y) return 1;
    return 0;
}

f:
    xorl    %eax, %eax
    cmpl    %edx, %ecx
    setle   %al
    ret

int f(int x, int y) {
    if (!(x > y)) return 1;
    return 0;
}

f:
    xorl    %eax, %eax
    cmpl    %edx, %ecx
    setle   %al
    ret

つまり、整数の場合、それらはまったく同じです。実際、コンパイラは 2 番目の例を最初の例に合わせて最適化しました。

于 2013-07-28T13:55:25.340 に答える
4

コンパイラが他とは異なるものを生成することはほとんどありません。最近のほぼすべてのプロセッサにはgreater or equalorless or equal比較/分岐操作があるため、より複雑な比較を行う理由はありません。

ステートメント

 if(x == y) 
      if (x < y) 
         break;

意味がありません。いずれかx == yが真であり、その場合x < yは真ではありません。Orx == yは false であり、2 番目の入力があったとしても入力しません。

明らかに、xyがクラスの場合、 は次のoperator<=ように記述できます。

operator<=(const A& x, const A& y)
{
    if (x == y) return true;
    return x < y; 
}

しかし、それは次のように書くこともできるので、かなりばかげています。

operator<=(const A& x, const A& y)
{
    return !(x > y); 
}
于 2013-07-28T13:49:26.023 に答える
1

x & y が組み込み型であると仮定すると、

これが私の推論です。最初のステートメントは実際にはこれだと思います:

if(x == y)
    if(x < y)
        break;

これは正しくないです。CPU は<=操作を行うことができます。過度に最適化しないでください ;)

于 2013-07-28T13:46:24.667 に答える
1

十分に高度なコンパイラは、これらの同等のステートメントをターゲット アーキテクチャで最速のものに自動的に最適化することが期待できるため、実際には同じように動作します。

しかし、x86 CPU 命令セットには jump-when-less と jump-when-less-or-equal の両方の命令があるため、これらのスニペットが文字どおりに解釈される場合、x86 アーキテクチャでは最初の操作は 1 つの操作になります。

于 2013-07-28T13:48:08.420 に答える
1

int (または short または long long など) に関しては、 を使用するだけx <= yで、コンパイラはそれを最適化する必要があります。たとえば、x86-64 の場合:

    cmpq %rax, %rcx
    jg false
#This is code to execute if (x <= y).
# Code
# .......
false:
    #This is code to execute once the
    # if statement is done or the condition
    # resulted in a falsy value.

if-else ステートメントがある場合、2 つのジャンプ命令があります。1 つ目は、条件が偽の値を生成する場合であり、2 つ目は、条件が真の値を生成する場合のコード ブロックの最後にあります (したがってスキップできます)。 else ブロックに使用されるコードを上書きします)。

jg (より大きい場合はジャンプ) 命令を使用していることに注意してください。x86 と x86-64 には両方とも jnle (以下でない場合はジャンプ) 命令もありますが、同じことを行います (結局のところ、x が y 以下でない場合、論理的に x は大きくなければなりません)。しかし、ASM で作業するという観点からは、条件を反転する方が理にかなっています。条件が反転されていなければ、前方にジャンプして if ステートメントのコードを実行し、後方にジャンプしてプログラムのメイン フローを再開します。1回のジャンプでできることを、なぜ2回のジャンプで行うのですか?

ところで、私は ASM の第一人者ではありません。ただし、少し操作すれば、このような質問を避けるのに役立ちます。これは、前述のように、コンパイラがコードの(x <= y)条件を最適化する必要があるためです。!(x > y)コンパイラを推測する必要はありません。コンパイラがコードを最適化するのに役立つ通常の最適化に焦点を当てます。たとえば、実行する必要のない条件を削除するなど、コンパイラが既に実行方法を知っている小さなことではありません。

于 2013-07-28T14:17:20.187 に答える
0

使うべき理由は2つ<=

  1. <=CPU はプリミティブの操作を実行できます。

  2. クラスにオーバーロードされた演算子がある場合、それよりも優れているか、少なくとも同等<=のことを行うように最適化されていると想定しても安全です。if(!(x > y))したがって、存在する場合はそれを使用してください。誰かが何らかの理由でそれを実装しようとしました。

于 2013-07-28T13:50:00.327 に答える