-1

分岐を 2 つの乗算に置き換えるか、または (キャッシュ ミスのペナルティにより) 置き換えない方が速いのだろうか?
これが私のケースです:

float dot = rib1.x*-dir.y + rib1.y*dir.x;

if(dot<0){
    dir.x = -dir.x;
    dir.y = -dir.y;
}

そして、私はそれを次のものに置き換えようとしています:

float dot = rib1.x*-dir.y + rib1.y*dir.x;

int sgn = (dot  < 0.0) - (0.0 < dot ); //returns -1 or 1 (no branching here, tested)
dir.x *= sgn;
dir.y *= sgn;
4

2 に答える 2

2

分岐はキャッシュミスを意味するものではありません。命令のプリフェッチ/パイプラインのみが妨げられるため、コンパイル時に SSE の最適化をブロックする可能性があります。

一方、x86 命令のみが使用されている場合、投機的実行により、プロセッサは最も使用されるブランチの実行を適切に開始できます。

反対に、50% の確率で if を入力すると、最悪の状態になります。この場合、SSE パイプラインを探し、SSE で実行を最適化して、おそらくいくつかのヒントを得ようとします。この投稿、コードの2番目のブロックに沿って。

ただし、コードのベンチマークを行い、作成されたアセンブラーをチェックして、この最適化のための最適なソリューションを見つけ、適切な洞察を得てください。そして最終的には私たちを最新の状態に保ちます:)

于 2014-03-22T23:45:32.503 に答える
1

乗算のコストは、32 ビットまたは 64 ビットの float を使用するかどうか、および SSE を有効にするかどうかなど、いくつかの要因によって異なります。このソースによると、2 つの float 乗算のコストは 10 サイクルです: http://www.agner.org/optimize/instruction_tables.pdf

ブランチのコストもいくつかの要因によって異なります。経験則として、コード内の分岐について心配する必要はありません。CPU 上の分岐予測子の正確な動作によってパフォーマンスが決まりますが、この場合、分岐はせいぜい予測不能であると想定する必要があるため、多くの分岐予測ミスが発生する可能性があります。このソースによると、分岐予測ミスのコストは 10 ~ 30 サイクルです: http://valgrind.org/docs/manual/cg-manual.html

ここで誰もができる最善のアドバイスは、プロファイリングとテストを行うことです。最新のCore i7では、2つの乗算は分岐よりも高速になるはずif the range of input varies sufficiently as to cause sufficient branch mispredictions as to outweigh the cost of the additional multiplicationです.

ミス率が 50% であると仮定すると、分岐の平均コストは 15 サイクル (30 * 0.5) であり、フロート mul のコストは 10 サイクルです。


編集:リンクを追加し、推定指導費用を更新しました。

于 2014-03-22T23:45:57.513 に答える