質問

boolean a = false, b = true;
if ( a && b ) { ... };

ほとんどの言語では、 b 評価されないから a それは嘘なので a && b 真実であるはずがない。私の質問は、アーキテクチャの観点から、短絡の方が遅くなるのではないかということです。パイプラインでは、b を評価する必要があるかどうかを決定するために、a の結果を取得するのを待機している間にストールしますか?代わりにネストされた if を実行した方がよいでしょうか?それも役に立ちますか?

また、短絡評価を一般的に何と呼ぶか​​知っている人はいますか?この質問は、私のプログラミング友人が短絡評価について聞いたことがなく、それは一般的ではなく、多くの言語で見られず、パイプラインでは非効率的であると述べたことを知った後に生じました。最後についてはよくわからないので、皆さんに質問します。

さて、私の友人がどこから来たのかを説明するために別の例を考えます。彼は、次のようなステートメントを並行して評価しているため、次のように考えています。

(a) if ( ( a != null ) && ( a.equals(b) ) ) { ... }

システムがクラッシュする可能性があるため、短絡のない (したがって上記のようなステートメントを許可しない) アーキテクチャの方が、次のようなステートメントの処理が高速になります。

(b) if ( ( a == 4 ) && ( b == 5 ) )

なぜなら、(a) を並行して実行できない場合、(b) も並行して実行できないからです。この場合、ショートサーキットを許可する言語は、ショートサーキットを許可しない言語よりも遅くなります。

それが本当かどうかは分かりません。

ありがとう

役に立ちましたか?

解決

短絡ブール式は、ネストされた if のセットとまったく同じであるため、効率的です。

b に副作用がない場合でも、a と並行して実行できます (パイプライン処理を含む「並列」の任意の値)。

b に、分岐予測が失敗したときに CPU アーキテクチャがキャンセルできない副作用がある場合は、はい、両側が常に評価されていれば発生しない遅延が必要になる可能性があります。したがって、短絡演算子がコード内でパフォーマンスのボトルネックを生み出していることに気付いた場合には検討する必要がありますが、それ以外の場合は心配する必要はありません。

ただし、制御フローには不必要な作業を省くために短絡が使用されます。これは、私が使用した言語の間で一般的です。たとえば、Perl のイディオムです。

open($filename) or die("couldn't open file");

シェルのイディオム:

do_something || echo "that failed"

または C/C++/Java/etc イディオム:

if ((obj != 0) && (obj->ready)) { do_something; } // not -> in Java of course.

これらすべての場合において、左側が評価すべきであると指示した場合にのみ右側が評価されるように、短絡する必要があります。このような場合、間違っている代替コードとパフォーマンスを比較しても意味がありません。

他のヒント

短絡評価は、if ステートメントと同じ方法でアセンブリ言語のブランチに変換されます (ブランチは基本的に goto です)。つまり、if ステートメントよりも遅くなるわけではありません。

通常、分岐によってパイプラインが停止することはありませんが、プロセッサは分岐が成立するかどうかを推測し、プロセッサが間違っている場合は、間違った推測を行ってから起こったことをすべてパイプラインからフラッシュする必要があります。

短絡評価はその最も一般的な名前でもあり、ほとんどの言語で何らかの形で見られます。

正直に言うと、心配する必要はありません。ブール値のテストは 本当に速い. 。短絡は、2 番目の式に副作用がある場合にのみ興味深い/便利になります。

if ( ConfirmAction() && DestroyAllData() )
   Reboot();

...または最初のテストによって異なります。

if ( myDodgyVar != null && myDodgyVar.IsActive() )
   DoSomethingWith(myDodgyVar);

ショートサーキットをサポートする言語:

Ada、Eiffel、ALGOL 68、C1、C++、C#、Java、R、Erlang、標準 ML、JavaScript、MATLAB、Lisp、Lua、Scheme、OCaml、Haskell、Pascal、Perl、Ruby、PHP、Python、Smalltalk、Visual Basic 。ネット

から引用 短絡評価

VB.Net の構文は、短絡するかどうかに応じて異なります。従来の理由により、デフォルトの動作では短絡しません。構文は次のとおりです

非短絡

IF A And B THEN
    ...
END IF

短絡

IF A AndAlso B THEN
    ...
END IF

OR ステートメントを短縮したい場合は、Or / OrElse を使用できます。これは次のような状況で非常に便利です

If MyObj IsNot Nothing AndAlso MyObj.Value < SomeValue Then
    ....
End If

個人的には、短絡によって速度が向上することは理解していますが、コードを見ただけでそれが明らかになるわけではありません。経験の浅い開発者がこの動作に混乱しているのがわかりました。最適化レベルのコンパイラ フラグに応じて、何かが起こるか起こらないかのようにさえ思えます。実際にどのような動作を実現したいのかについて VB が詳細に説明しているところが気に入っています。

まず、あなたの友人は間違っています。短絡評価 (別名最小評価) はほとんどの言語で利用でき、並列言語の入れ子になった if よりも優れています (この場合、返される最初の条件によって実行が継続されます)。

いずれにせよ、単純な非並列言語であっても、最初の条件が評価されるまで実行がブロックされるため、ネストされた if がどのように高速になるかはわかりません。

入れ子になったものが停止しない場合、どうすればよいでしょうか?実際、a と b が両方とも変数であり、副作用のある式ではない場合、優れたコンパイラによってそれらを並列にロードできます。if を増やすことには、行数を増やすこと以外にメリットはありません。実際、これはコンパイラを二番目に推測する最悪の種類です。

それは短絡評価と呼ばれます。

私が使用する便利な短絡は次のようなものです。

if (a != null && a.equals(somevalue)) {
    ... do something.
}

私の意見では、これは非常に読みやすく、機能も非常に優れています。一般に、私はあまりネストを避けるようにしています。ネストすると醜いコードになるからです。

すべて私の意見ですが。

ほとんどの言語はブール式の短絡評価を行います。私はそれが短絡評価と呼ばれているといつも聞いたことがあります。

質問の例は非常に単純な例であり、実際にはパフォーマンス上の利点はあまりありません。式の評価が複雑な場合、パフォーマンス上の利点が得られます。

これが適切な例として、次のようなゲーム プログラムを想像してください。

if (someObject.isActive() && someOtherObject.isActive() && CollisionDetection.collides(someObject, someOtherObject) {
  doSomething();
}

この場合、衝突検出はアクティブなチェックよりもはるかに高価です。システム内に非アクティブなオブジェクトが多数ある場合、パフォーマンスは大幅に向上します。

短絡または最小限の評価は、入れ子になった if の糖衣構文にすぎません。それが非効率的である、または失速を引き起こすと仮定することは、時期尚早な最適化のケースです。現時点では、ほとんどのコンパイラーは、これらのステートメントを正しく解釈して最適化するのに十分なインテリジェントを備えています。これらのステートメントを使用すると、ネストを大幅に減らすことができるため、コードの可読性が向上します。これが最大の目標です。

短絡が効率的かどうかに関しては、パイプライン化がパフォーマンスに大きな影響を与える可能性は低いです。影響を与える可能性がある状況では、テストに副作用がない限り、コンパイラーが複数の条件を並行してテストすることを妨げるものはありません。さらに、最新の CPU には、分岐コードのパイプライン パフォーマンスを向上させるために役立つメカニズムがいくつかあります。

ネストされた if は、&& を短絡するのと同じ効果があります。

「短絡評価」はその最も一般的な名前ですが、あなたの友人はそれが一般的ではないという誤解をしています。それはとても一般的です。

私はパイプライン処理については何も知りませんが、短絡評価は多くの言語に共通の機能です (私が知っている名前でもあります)。C では、&& およびその他の演算子は、 シーケンスポイント ; と同じように。演算子はそうするので、複数のステートメントを使用するよりも短絡評価の効率がどれほど劣るかは分かりません。

短絡という話しか聞いたことがない。パイプラインでは、次に入る操作は if ステートメントの結果に依存しませんか?その場合は、毎回 2 つの値をテストする必要がないように、より最適化されます。

単一のスレッドはシーケンシャルであるため、2 つの if がある場合、最初の if は当然 2 番目の if より前に評価されるため、その点で違いはわかりません。私はネストされた if よりも、条件付き AND 演算子 (&& を私の知る限りそう呼んでいます) をよく使用します。評価に時間がかかる可能性のあるものをチェックしたい場合は、最初に簡単なテストを実行し、条件付き and の後に難しいテストを実行します。

a = obj.somethingQuickToTest() && obj.somethingSlowToTest();

と何ら変わらないようです

a = false;
if(obj.somethingQuickToTest())
   a = obj.somethingSlowToTest();

文脈によっては「ガード」とも呼ばれます。

そして、私がこれまで仕事をしてきたほぼすべての言語でそれを目にしてきましたが、その数は 12 近くにも及びます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top