2017-01-23 2 views
1

関数を使用できるため、std :: accumulateよりも高速なベクトルの値を累積するためにベクトル化される。この関数の主な前提条件は、ベクトルが蓄積後も使用されなくなることです。次のようにコードがある:Cスタイルのポインタを使用してベクトル化されたものの、反復子を使用しないベクトル化されたループの場合

template <typename floatType> 
template <typename Iterator> 
double Numeric_class<floatType>::AmDestructiveAccumulate(Iterator A, size_t length) 
{ 
    if (length == 1) 
    { 
     return A[0]; 
    } 

    Iterator temp_; 
    while (length > 1) 
    { 
     if (length & 1) // odd 
     { 
      A[0] += A[length - 1]; // We add the last value which would otherwise be lost. 
      length >>= 1; 
      temp_ = A+length; 
      for (int i = 0; i < length; i++) 
      { 
       A[i] += temp_[i]; 
      } 
     } 
     else // even 
     { 
      length >>= 1; 
      temp_ = A+length; 
      for (int i = 0; i < length; i++) 
      { 
       A[i] += temp_[i]; 
      } 
     } 
    } 
    return A[0]; 
} 

機能は基本的に2つのhalfsでベクトルを分割二halfsの対の和をとります。この後、2つの等しく長い範囲で合計された前半を分割し、再び上向きに合計します。

この機能はstd::vector<double> dataで使用しました。私がdata.data()であるとそれを呼び出す場合。ベクトル化の話は予想どおりに行われ、実行速度も大幅に向上します。 data.begin()を使用すると、ベクトル化は行われません。 VC2015を完全最適化してコードをコンパイルしました。コードのイテレータバージョンをベクトル化することが違法であるか、VCが合法であるにしてもそれを行わない理由はありますか?

+0

TBHひどいアルゴリズムのように聞こえますが、オプティマイザが少なくともいくつかのバージョンを救済することは印象的です。線形アクセスO(N)アルゴリズムを非線形アクセスのO(N log N)バリアントに変更しました。 – MSalters

+0

@MSaltersこれは正しくありません。アクセスはまだO(N)です。それはN + N/2 + N/4 + N/8です。この幾何級数はN * 2に収束します。さらに、アクセスはすべての繰り返し内で線形です。最後に重要なのは、プロファイルに関連するNのパフォーマンスが向上していることです。 –

+0

Fairポイントは、奇数と偶数の2つの内部ループのように見えますが、2つのうちの1つだけが使用されるため、N + 2 *(N/2)+ 4 *(N/4)+ ... 'となる。 – MSalters

答えて

2

コアの問題はA[i] += temp_[i];です。 Atempはお互いにエイリアスですが、ランタイムの選択肢が[i]であることはこれが理論的なことに過ぎないことに注意してください。今、[i]は実際に何を意味していますか? Aがポインタの場合は、*(A+i)の省略形ですが、Aがイテレータの場合は関数呼び出しです。

効率的なベクトル化では、A[i]への書き込みがtemp[i]からの次の読み取りに影響しないことをコンパイラーが認識する必要がありますが、これは軽微な観察ではありません。ループに依存する依存関係はありませんが、オプティマイザはそれを証明できる必要があります。

+0

つまり、イテレーターの場合は違法ではありませんが、オプティマイザがそれを理解するためには複雑です。正直言って、ダブルの場合、利得はかなり小さいです。しかし、ベクトル単位で4つの値を同時に処理する浮動小数点数の場合、その効果は約2倍になります。 –

+1

@PaulR:個人的には、AVXを使用して昔ながらの線形加算として書いています。 'A []'へのすべての書き込みは傷つくでしょう。このような簡単な操作のために帯域幅が制限されることになります。 – MSalters

+0

有望なサウンド。私はそれをチェックします。 –

関連する問題