3

この記事に出くわしました:分岐せずに 2 つの整数の最小値または最大値を計算する

それは「[o]n 一部のまれなマシンでは分岐にコストがかかる...」から始まります。

私は以前、分岐はプロセッサに実行パイプラインのクリアと再起動を強制することが多いため、常にコストがかかると考えていました (たとえば、並べ替えられた配列を処理する方が、並べ替えられていない配列よりも速いのはなぜですか? を参照してください)。

これにより、いくつかの質問が残ります。

  • 記事を書いた人はその部分を間違えましたか? それとも、分岐が問題になる前にこの記事が書かれたのでしょうか (日付はわかりません)。
  • (x < y) ? x : y最新のプロセッサには、パフォーマンスを低下させることなく、 のような最小限の分岐を完了する方法がありますか?
  • それとも、最新のコンパイラはすべて、このハックを自動的に実装するだけですか? 具体的には、Java は何をするのでしょうか? 特にそのMath.min(...)機能はその三項ステートメントであるため...
4

1 に答える 1

6

記事を書いた人はその部分を間違えましたか? それとも、分岐が問題になる前にこの記事が書かれたのでしょうか (日付はわかりません)。

最も古いコメントは 5 年前のものなので、ホット ニュースではありません。ただし、予測不可能な分岐は常にコストがかかり、5 年前もそうでした。その間、最新の CPU はサイクルごとにより多くの処理を実行できるため、分岐の予測ミスにより多くの作業が必要になるため、事態はさらに悪化しました。

しかし、ある意味では、作家は正しいです。CPU の大部分は、PC やサーバーではなく、状況が異なる組み込み機器に搭載されています。

最新のプロセッサには、 (x < y) のような最小限の分岐を完了する方法がありますか? x : y パフォーマンス低下なし?

はいといいえ。AFAIKMath.maxは常に条件付き移動として変換されます。つまり、分岐はありません。maxJVM が収集した統計に応じて、使用する場合と使用しない場合があります。

銀の弾丸はありません。予測可能な結果により、分岐はより高速になります。CPU がどのパターンを認識しているかを正確に知ることは困難です。JVM は、ブランチが取得される頻度を単純に調べて、約 18% の魔法のしきい値を使用します。詳細については、自分の質問と回答を参照してください。

それとも、最新のコンパイラはすべて、このハックを自動的に実装するだけですか? 具体的には、Java は何をするのでしょうか? 特に、その Math.min(...) 関数は単なる三項ステートメントであるため...

実際にはコンパイラ組み込みです。JITc は、まさにこのメソッドが呼び出されたことを確認すると、それを特別に処理します。メソッドをコピーしても、特別な処理は行われません。

この場合、組み込みはあまり役に立ちません。のようなメソッドの場合、コードはかなり長くて遅く、最新の CPU は 1 サイクルで実行できるためLong#numberOfLeadingZeros、組み込み関数が不可欠です。

于 2014-10-01T03:16:47.677 に答える