3

expensive_foo()99.9% のケースで偽である条件文があります。barそして、〜50%の場合に当てはまる条件文があります。

そして、両方のステートメントが真である場合、何らかのアクションを実行したいと思います。したがって、それが偽であることはほぼ確実にわかっており、真のexpensive_foo()場合にのみ確認したいと思いbarます。

以下のコードは、真のexpensive_foo()場合のみをチェックしますか? barそれともexpensive_foo()毎回チェックしますか?

if ( bar && expensive_foo() )
{
    ...
}

または、次のような構造を作成する必要があります。

if ( bar )
{
    if ( expensive_foo() )
    {
        ...
    }
}
4

5 に答える 5

5

論理 AND 演算子&&はショートサーキットです。つまり、最初のオペランドが として評価された場合にのみ、2 番目のオペランドが評価されることが保証されtrueます。if (bar && foo)との条件if (bar) if (foo)は同じです。

計算にコストがかかることを考えるとfoo、ほぼ間違いなくbar最初に確認する必要があります。barは分岐予測子によってうまく予測できませんが、 の計算に比べれば小さな影響ですfoo

したがって、構造はおそらく次のようになります。

if (bar)
{
    if (bool const foo = compute())   // expensive
    {
        // ...
    }
}

これらの構造はすべて、 を呼び出す場合と呼び出さない場合があることを意味することに注意してくださいcompute()。無条件に関数呼び出しが必要な場合は、それを最初のチェックにする必要があります。その場合、結果の成功した分岐予測を利用する必要があります。

于 2012-09-14T12:50:52.290 に答える
2

どちらのコードもtrue のfoo場合にのみチェックされます。bar最初のケースでは、これは言語の遅延ブール式評価によって保証されます (一部のコンパイラでは実際には明示的にオフにすることができますが、デフォルトではオンになっています)。

于 2012-09-14T12:51:50.190 に答える
1

他の答えは良いですが、私は前提に疑問を投げかけています。

99.9%の確率でfalseである述語をクエリしている場合、これは2000エントリのリストで線形検索を実行するのと似ています。ここで、探しているアイテムはほぼ同じ確率でどこにでもある可能性があります。

その場合、通常、O(N)の代わりにO(logN)(またはそれ以上)の検索を実行するように、リストを別の方法で編成しようとします。あなたがこれを行うことができるかどうかはわかりませんが、それが私が焦点を当てるところです。

非常に偏った確率で質問が行われている場合、それを解くことができれば、それは大きなスピードアップの機会になる可能性があります。(このアクティビティに多くの時間が費やされていると仮定します。そうでない場合、ポイントは重要ではありません。)

于 2012-09-14T14:38:46.613 に答える
1

両方の最適化されたアセンブリがまったく同じでなかったとしたら、私は驚くでしょう。bar が false の場合、expensive_foo() は呼び出されません。

于 2012-09-14T16:31:25.117 に答える
1

コンパイラは操作の順序を変更できるというコメントを見ましたが、私はその意見に傾倒しています。逐次プログラムの自動並列化を改善するための努力により、コンパイラーがいくぶん改善され、プログラマーがプログラムから複雑な並列化ルーチンを回避するのに役立ちます。コンパイラは、並べ替えが局所性に違反したり悪化したりしない限り、または広い意味でプログラムの実際の意図に違反しない限り、操作を並べ替えることができます。

しかし、コンパイラが次のような条件文を並べ替えようとするという事実には疑問があります。

  if ( bar && expensive_foo() )

より安価なブール関数を最初に置くと、時間を節約できることは確かです。

于 2012-09-14T23:37:05.477 に答える