web-dev-qa-db-ja.com

不等式演算子は等式演算子よりも高速ですか?

私はこれがミクロの最適化であることを知っているので、純粋な好奇心に尋ねます。

論理的には、マイクロプロセッサは、 "FALSE"の結果を決定するために、等価演算子の両方のオペランドのすべてのビットを比較する必要はありません。

これはプログラムの実行速度に影響を与えるため、これはプログラミングに関連しています。

53
Mackenzie

通常、マイクロプロセッサは電気ゲートを使用して比較を行い、そのような段階的なものではありません。一度にすべてのビットをチェックします。

47
Mehrdad Afshari

これはプラットフォームによって異なりますが、一般的には同じように動作します。

たとえば、X86では、アセンブリの動作を確認することでこれを確認できます。 X86アセンブリ制御フローの操作 を確認してください。同等か不等かを問わず、2つの操作として実行されます。

まず、CMP(比較)操作を行います。次に、比較が等しいか、等しくないかなどを確認します。これは、比較の結果を確認するだけです。どちらの場合も、2つの操作を実行しています。

ただし、多くの高レベルのプログラミング言語では、状況が異なります。多くの言語では、等価性の観点から不等式を定義しています。不等式をチェックするには、等価性チェックを実行してから、2番目のチェックでfalseかどうかを確認します。これにより、これらの言語での等価性が(微視的に)速くなります。多くの言語では、両方を具体的に記述することもできますが、多くの人々は、同等性に関して不等式を記述する傾向があり、これにより、同等性が一般に、わずかに速くなります。

29
Reed Copsey

Intel 64およびIA-32アーキテクチャ最適化リファレンスマニュアル をお読みください。

使用する命令の「パイプライン遅延」と「パイプライン遅延」を確認してください。 intを使用して行うすべての処理には、約1クロックサイクル(1秒間に40億)かかります。メモリからのデータの読み取りには、使用しているデータの量に応じて、100〜1000かかります。はるかに重要です。

12
Tom Leys

比較は通常、結果を無視する減算として実装されます。 CPUの加算器はすべてのビットで同時に動作するため、これは一定時間の動作です。

等価性は、出力が0かどうかを決定するだけです。x86では、比較の結果として設定されるフラグがあり、jzまたはjnzを介して分岐が行われます(ゼロの場合はジャンプ、ゼロでない場合はジャンプ)。つまり、実際の速度の違いはありません。

他のプラットフォーム(ARMおよびIA64など)も同様に動作します。

11
Michael

他の回答が示唆するように、命令自体は同じ速度で実行されます。

違いが発生する可能性があるのは、分岐予測またはキャッシュ効果です。これはプロセッサごとに異なり、コンパイラごとに異なるため、一般化することは不可能です。これが違いを生むレベルにいる場合、知る唯一の方法は、それを試して測定することです。

3
Mark Ransom

それが何らかの影響を与える可能性があるいくつかのマイナーなケースがあります。

ARMプロセッサ(32ビット/非サム命令セットアーキテクチャ(ISA)の場合)では、すべての命令が条件付きです。場合によっては、単一の分岐を持つ内部ループ(複数の条件にもかかわらず、いくつかのケースでは、論理比較(TEQ)により、いくつかのフラグが妨害されます(負(N)およびゼロ(Z)に影響しますが、キャリー(C)またはオーバーフロー( V))、毛深いコードが分岐命令を回避できるようにします(unaken)。

逆に、IIRC(実際にプログラムしたことはありませんが、10年以上前にCコンパイラの出力を見てきました)68000には、レジスタD4専用のリテラルEOR/XOR命令があります。したがって、算術比較の方がおそらく良いでしょう(ただし、無関係なフラグは無視できますが、命令セットが少し不規則であることがポイントです)。

以前のポスターで述べたように、アクションのほとんどは、メモリ、ディスク、ネットワーク、およびWebサービスのレイテンシが高いほど高くなります。

これをより一般的な質問に上げたい場合は、TRUEとFALSEの回答の合理的な分布を検討する必要があり、レジスタよりも長い任意の語長を検討する必要があります。

検索アルゴリズム(およびソートは検索の拡張と見なすことができます)では、「==」よりも「<」または「<=」のような演算子を使用する方が一般的です。これは、「==」演算子からの結果の分布が「false」に向かって偏っている傾向があるため、実行ごとのエントロピーが低い(つまり、情報の収量が低い)ためです。これは、同じ情報を取得するために、より多くの回数実行する必要があることを意味します。

どちらの場合も、それらはO(ワード長)のビット比較数を取りますが、ワード長が<=レジスタ長である場合、比較は並列に行われ、キャリー伝搬の遅延が発生する可能性があります。 (実際、私が考えているように、典型的な不平等の場合、どちらの比較も最初の不等ビットで停止する可能性があり、等価の確率が十分に小さい場合、それはかなり早期に発生する可能性があります。)

2
Mike Dunlavey

比較操作は、マイクロプロセッサのクロック信号の立ち上がり(または立ち下がり)エッジで発生します。その後、次の動作は次のクロックサイクルで発生します。したがって、実行速度の観点から、同等性と不等性は、今日市場に出ているほとんどすべてのプロセッサで同じ時間を要します。

ほぼと言うのは、クロックベースではなく、操作時間ベースであるはずのいくつかのプロセッサについて読んだことを思い出すからです。 n比較はn追加よりも時間がかかりません。しかし、私はそれが単なる研究プロジェクトであり、商用製品ではないことを約99%確信しています:)

2
Mark Rushakoff

このような比較にかかる時間は、通常1クロックサイクルです。

32ビットプロセッサは、32ビットすべてを一度に実行します。 64ビットは64ビットを一度に実行します。

パイプラインに遅延またはストールがある場合は、オペランドが利用できず、フェッチする必要があるためです。 つまりオーバーヘッドが最大になる場所。しかし、それはプロセッサのアーキテクチャに適したチャンクで行われていたので、32ビットまたは64ビットのユニットとして取り込まれていました。

1
lavinio

誰もが想定している1つの側面は、彼がレジスターレベルの命令について話していることです。誰もが正しい、それは基本的にCPUレベルでは物議を醸している。そしてさらに上位のほとんどの高レベルの操作では、不等式は否定された等式の呼び出しとして書き込まれます。

ただし、さらに上位では、質問者の最適化を使用すると、両方の方法で機能します。つまり、平等は不平等と同じくらい効率的に書くことができます。

さらに、アセンブリの操作に関係する人々にとって、CMPとSUBの唯一の違いは、どのフラグが設定されているかです。 CMPは、等しいか、より小さいか、より大きいかを表すフラグを返す必要があるため、通常はマシンの同じ部分で実行されます。

1
Adam Luter