-2

次の 2 つの方法で速度に違いがあるかどうかを知りたい

#include<math.h>
#include<iostream>
using namespace std;

int main()
{
    float k=7;
    float b=4;
    cout<<(float)k/b<<" "<<endl;
    cout<<(float)(k*powf(b,-1))<<" "<<endl;

    return 0;
}
  1. 些細な分割k/b
  2. 乗算を使用してk*b^(-1)

2番目の方法では、実際の分割手順はないと思います。だから私は2番目が速いと思います。私は正しいですか?

4

6 に答える 6

4

あなたが間違っている可能性はかなり高いです。コンパイラがpowf組み込みとして生成できる (つまり、インライン コードを生成する) 場合でも、N -1は 1/N に相当するため、より回り道した方法で除算を行っているだけです。累乗が除算を行うためのより高速な方法である場合、コンパイラはおそらくその方法でそれを行うコードを既に生成しているでしょう。

一方、同じ分母を使用して多くの除算を行っている場合は、次のようなループを回すことで何かを得ることができます。

for (int i=0; i<some_size; i++)
    somearray[i] /= denom;

の中へ:

double scale = 1.0/denom;

for (int i=0; i<some_size; i++)
    somearray[i] *= scale;

もちろん、コンパイラはそれを行うのに十分賢いかもしれませんが、少なくともこのようなものでは、あなたがしていることは改善される可能性が十分にあります.唯一の問題は、コンパイラがすでにそれを行っているかどうかです.それはあなたのためです。

于 2012-04-16T19:18:28.280 に答える
2

両方のバージョンのプロファイルを作成し、どちらが速いかを確認する必要がありますが、いくつかの理由から、2 番目のバージョンである場合は、帽子をかぶる準備ができています。

  1. powf指数パラメータの典型的な値に対して非常に遅い一般的な関数です。ケースを特別に処理するように最適化されていても、この特別なケースをチェックする s など-1がまだあり、計算にオーバーヘッドが追加されます。if
  2. 実装によっては、powfインライン化されない場合があり、関数呼び出しのコストが発生します。
  3. k*(1.0/b)が よりも本当に高速である場合k/b、コンパイラは後者を前者に最適化します (特に、コンパイラ フラグを指定して高速であるが、IEEE 準拠の浮動小数点演算を完全に実行できるとは限りません)。

要するに、最新のコンパイラはマイクロ最適化の実行に非常に優れているということです。プロファイリングと逆アセンブルによって、コンパイラが非効率的なことを行っているという明確な証拠が示されない限り、このような「トリック」を試すことは夢にも思いません。

于 2012-04-16T19:20:28.297 に答える
1

x86-64 マシンで gcc -O2 を使用すると、k / b は 1 つの命令に変換されます。

divss   xmm0, xmm1

'powf' 方法の結果は次のようになります。

movss   xmm2, DWORD PTR .LC0[rip]
divss   xmm2, xmm1
mulss   xmm2, xmm0
movaps  xmm0, xmm2

ここで、.LC0 は 1065353216、つまり 1.0f です。

したがって、少なくとも最近一般的な x86-64 マシンでは、k / b の方が高速であるように思えます。

于 2012-04-16T19:33:03.703 に答える
1

速度は常に、コンパイラがどれだけ最適化されるかに依存します。したがって、信頼できる答えは、測定することによってのみ見つけることができます。

ただし、2 番目の方法は、最初の方法よりも多くの呼び出しを意味します。したがって、最初のほうが速いと思います。

于 2012-04-16T19:15:58.927 に答える
1

b^(-1) の計算は簡単ではなく、(常にではありませんが) オプティマイザによって 1/b に変換されることがあります。同様に、オプティマイザー*b^(-1)/b. これはおそらくハードウェアに依存します (また、コンパイル時に数値がわかっている場合は、数値に依存する可能性もあります)。

テストしたい場合は、それぞれを何度も実行するループに入れて (画面に何も出力しないでください)、実行ごとに時間を計ります。

また、正確な計算に関心がある場合、場合によっては、これら 2 つの方法で得られる結果がわずかに異なることにも注意してください。

于 2012-04-16T19:17:48.457 に答える
1

他の方もおっしゃっている通り、プロフィールです。コンピューター サイエンスでは、除算は減算の繰り返しによって実装される場合があります。これは、逆数による乗算よりも高速である可能性があります。

逆数を最初に計算してから乗算を実行する必要があるため、除算は逆数を掛けるよりも高速になると思います。したがって、除算が減算を実行している間、もう 1 つの方法は逆数を決定することです。逆数が計算された後、複数のシフトと加算 (乗算) を実行する必要があります。

除算アルゴリズムに関するウィキペディアの記事を参照してください

于 2012-04-16T19:25:20.403 に答える