2013-11-25 6 views
5

は、ベクトル加算を考える:int値をdoubleに追加すると、パフォーマンス上の利点/ペナルティはありますか?

NPNumber NPNumber::plus(const double o) const { 
    vector<double> c; 
    for (double a : values) 
     c.push_back(a + o); 

    return NPNumber(width, c); 
    } 
NPNumber私は唯一の代わりに別のNPNumberの、単一の整数を追加ダブルス(フィールド値)のベクトルを含ん

、パフォーマンス上の利点またはペナルティこと変換と比較してあります整数と上記の関数を使用して?

すなわち、これは、任意のアーキテクチャ上の速い/遅い:

NPNumber NPNumber::plus(const int i) const { 
    vector<double> c; 
    for (double a : values) 
     c.push_back(a + i); 

    return NPNumber(width, c); 
    } 
+2

N.B. 'ベクトル c(values.size());' 'values.size()'デフォルトで初期化された要素(値 '0')を持つベクトルを作成し、' push_back'はそれらの後に*追加*要素を追加します。代わりに代わりに 'reserve'を使用したいでしょうか? – dyp

+0

あなたは正しいです。これは、別の方法のコピー&ペーストエラーのばかげたばかりです。割り当てがここで重要ではないので、私はそれを完全に削除しました。 – choeger

答えて

4

それは強く依存コンパイラのとあなたのコードでそれを測定する必要があります。私のマシン(32ビットMinGW/gcc 4.9)での素早く簡単な観測結果は、+自体がどちらの場合も同等であることを示していますが、積分演算はやや良いようです。

!  double d = 0.2; 
fldl 0x409070 
fstpl -0x10(%ebp) 

!  double y = 1.0; 
fld1 
fstpl -0x18(%ebp) 

!  double z = d + y; 
fldl -0x10(%ebp) 
faddl -0x18(%ebp) 
fstpl -0x20(%ebp) 

2つintを追加する:2つのdouble追加

!  double d = 0.2; 
fldl 0x409070 
fstpl -0x28(%ebp) 

!  int y = 1; 
movl $0x1,-0x2c(%ebp) 

!  double z = d + y; 
fildl -0x2c(%ebp) 
faddl -0x28(%ebp) 
fstpl -0x38(%ebp) 

両方が追加するfaddlを使用するが、コンパイラは、追加する前に整数をロードするためのより良い指示を使用します。したがって、倍精度に整数を追加する場合のペナルティはありません(2倍を加算するよりも良いかもしれません)。

アプリケーションでは、どちらが優れているかを調べるためのプロファイリングが最適です。

2

もう1つ考慮すべきことは、コンパイラの最適化です。

浮動小数点ユニットは、独自のレジスタを持つ傾向があります。これらは、場合によっては一般的なオペランド(たとえば、80ビットの一時的な実数)よりも精度が高い場合もありますが、コメントが多く変わる可能性があるのでこのコメントを参照してください。

すでにFPUにロードされている値を操作するほうが安いとコンパイラは知っているはずです。そのため、ループから一定値を引き上げて、FPUにロードされた値を保持することができます。その場合、大きなベクトルではその差はごくわずかです。

いずれにしても、特定のプラットフォームでintからdoubleへの変換が高価な場合は、妥当なコンパイラで重複して実行することはできません。そのように、おそらく私がやることはテンプレートメソッドにすることで、どんな型でも受け入れることができます。&精度の定数データは自然に由来します。これにより、コンパイラは特定の状況で特定のプラットフォームに対して「正しいことを行う」ことができます。

これは、コンパイラが最適化の戦略やプラットフォームによって多少異なることを示しています。&の性能特性が異なるため、最後のマイクロ秒ごとに圧縮しようとしている場合は、 ) 興味を持っている。

+1

FPUスタックはx87アーキテクチャの特徴であり、私は他のアーキテクチャには苦しんでいないと思います。 x86 SSEを含む他のFPUは、一般にレジスタを使用します。しかし結論は依然として関連しています。結果をFPUに効果的に保存できるならば、 'int'から' double'への変換が可能です。 – MSalters

+0

@MSalters:FPUレジスタファイルに関するヒントをありがとう。それを固定しました。 – Kevin

+0

ああ、FPレジスタは、通常、より高い精度も持っていません。それもx87の奇妙さです。実際には、一部のローエンドチップの精度は低いです(ハードウェアの浮動小数点、ソフトウェアの2倍が必要です)。 – MSalters

関連する問題