関数を使用できるため、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が合法であるにしてもそれを行わない理由はありますか?
TBHひどいアルゴリズムのように聞こえますが、オプティマイザが少なくともいくつかのバージョンを救済することは印象的です。線形アクセスO(N)アルゴリズムを非線形アクセスのO(N log N)バリアントに変更しました。 – MSalters
@MSaltersこれは正しくありません。アクセスはまだO(N)です。それはN + N/2 + N/4 + N/8です。この幾何級数はN * 2に収束します。さらに、アクセスはすべての繰り返し内で線形です。最後に重要なのは、プロファイルに関連するNのパフォーマンスが向上していることです。 –
Fairポイントは、奇数と偶数の2つの内部ループのように見えますが、2つのうちの1つだけが使用されるため、N + 2 *(N/2)+ 4 *(N/4)+ ... 'となる。 – MSalters