3

これらの不等式があるとしましょう:

if (a*a+b*b>0) {
    ...
}

if (a*b+c*d>0) {
    ...
}

明らかに、どちらも評価するために 2 つの乗算が必要です。
問題は、これらの式が正かどうかを確認するためだけに、2 つの完全精度の積を計算する必要があるのでしょうか?
2 つの製品を評価する必要なく if コマンドを記述できる数学的なトリックはありますか?
それはより速くなりますか?
それとも、コンパイラーが可能な限り高速化を図っているのでしょうか?
私は考えすぎですか?

編集:まあ、それはすぐにエスカレートしました。私は一般的な言葉で話していることを指摘したいだけです。とにかく、私のプロジェクトではそのようなマイクロ最適化は必要ありません。また、はい、些細すぎるため、最初のものを省略できたはずです。おそらく2番目の方が面白いです。

4

4 に答える 4

2

あなたの「考えすぎですか」という質問は、コードを実際にプロファイリングすることによって、これが実際のボトルネックであることに気付いていないことを示唆しています。そうです、時期尚早の最適化をしようとしているだけです。

ただし、これが実際にアプリケーションの主要なパフォーマンス クリティカルな部分である場合、現時点で考えられる唯一の改善点は次のとおりです。実数の 2 乗は決して負になることはないため、「a の 2 乗は 0 より大きい」は「a は 0 ではない」と同じです。したがって、アーキテクチャ上で比較が高速である場合 (これは相対的です。乗算よりも高速です)、次のようになります。

if (a*a+b*b>0) {
    ...
}

次のように書くことができます

if (a || b) {
    ...
}

(まれなケースが発生しない場合。変数が符号付き整数または実数を表す浮動小数点数である場合、これで問題ありません。ただし、符号なし整数のオーバーフローまたは複素数が含まれる場合は、実行する必要があります追加のチェックが必要であり、その時点で、真のプロファイリングなしで相対的なパフォーマンスを判断するのは困難です)。

2番目のケースのような「賢い」「最適化」は頭にありませんが、おそらく他の誰かが似たようなものを思い付くことができます-それが絶対に必要な場合に限ります. パフォーマンスが重要でない場合は、パフォーマンスよりもコードの読みやすさが優先されます。

于 2013-11-23T23:12:08.127 に答える
1

最初のものは常に >= 0 になります。 と が 0 の場合にのみa0bになるため、次と同等です。

if (a || b) {
   ...
}

2 つ目について: の符号が の符号aと等しく、 の符号が のb符号cと等しい場合d、上記と同じ状況になります。

if (sign(a)==sign(b) && sign(c)==sign(d))
{
  if ((a && b) || (c && d))
  {
    ... > 0
  }
  else
  {
    ... = 0
  }
}
else
{
  if (sign(a)*sign(b)==sign(c)*sign(d))
  {
     ... <= 0
  }
  else
  {
    /* must do the actual product to find out */
  }
}

IEEE-754 準拠の浮動小数点数の場合、符号は各数値の MSb にあります。

FP がエミュレートされる環境では、比較を少し最適化するためにできることが 1 つあります。次のように、製品の 2 つの結果を比較するだけであれば、追加を避けることができます。

if (a*b>c*d) {
   ...
}

2 つの浮動小数点数を比較するには、それらが符号付き整数であるかのように比較するだけなので、これは少し高速です。FP のない CPU には、FP ソフトウェアの実行に費やす時間よりも速く 2 つの整数を比較するためのリソースがあります。添加。

于 2013-11-23T23:17:05.083 に答える
1

型にオーバーフローの概念がないか、値が範囲内にあるため、これらの式のいずれもオーバーフローしないと想定しています。オーバーフローと潜在的なラップアラウンドが発生した場合 (例: ifabare unsigned int)、異なるルールが適用されます。

最初のステートメントは明らかに同等です

if (a != 0 || b != 0)

また

if (a || b)

これは、余分な分岐を 2 つの乗算と加算と交換します。

a*b2 番目のステートメントはもう少し興味深いものです。オペランドの符号を決定し、とc*dが反対の符号を持つ場合にのみ実際の計算を行うのが合理的であると思います。それ以外の場合はすべて、実際の値を知らなくても条件を判断できます。結果のロジックが計算よりも高速かどうかは、型によって異なると思います。

于 2013-11-23T23:15:45.000 に答える