ベクトルの要素の平均と標準偏差を計算しています。私はこれの2つのバージョンを持っていますが、標準アルゴリズムを使用したバージョンがプレーンループを使用したバージョンよりも遅い理由に完全に戸惑っています。
どちらのバージョンも、この構造体を戻り値の型として使用します。
struct MeanAndSigma {
double mean;
double sigma;
};
そして、ループのあるバージョンはこれです:
MeanAndSigma getMeanAndSigma(const DVector& v){
MeanAndSigma ms;
ms.mean = 0;
for (int i=0;i<v.size();++i){ms.mean += v[i];}
ms.mean = ms.mean / v.size();
double sqsum = 0;
for (int i=0;i<v.size();++i){sqsum += (v[i]-ms.mean)*(v[i]-ms.mean);}
ms.sigma = std::sqrt(sqsum / (v.size()-1));
return ms;
}
そして、アルゴリズムを備えたもの:
MeanAndSigma getMeanAndSigma2(const DVector& v){
MeanAndSigma ms;
ms.mean = std::accumulate(v.begin(),v.end(),0.0) / v.size();
DVector diff(v.size());
std::transform(v.begin(),v.end(),diff.begin(),
std::bind2nd(std::minus<double>(), ms.mean));
double sqsum = std::inner_product(diff.begin(),diff.end(),diff.begin(),0.0);
ms.sigma = std::sqrt(sqsum / (v.size()-1));
return ms;
}
10k要素のベクトルを使用して10k呼び出しごとにかかる時間を測定すると、ループのあるバージョンでは約2.0秒、アルゴリズムのあるバージョンでは約3.2秒になります。どうしてこれなの?
私はすでにCPU時間とリアルタイムを比較しましたが、両方が(予想どおりに)単一のCPUで実行されているように見えます。アルゴリズムの使用で愚かな間違ったことをしていますか?
編集:私は2つのバージョンが同等であると主張していません。それにもかかわらず、私は2番目のバージョンがより高速になると予想していました。コメントと回答で指摘されているように、2番目のバージョンでは、要素に対する追加の反復と追加の反復が使用されますDVector
(これは単なるaですtypedef std::vector<double>
)。ただし、2番目のバージョンを改善するための標準アルゴリズムについては十分に理解していません。だから、今私の質問は:
アルゴリズムを使用してバージョンを改善し、プレーンループを使用するバージョンよりも高速にするにはどうすればよいですか?
プログラムは同等ではないと思います。2番目のバージョン(アルゴリズムを使用)では、doubleの新しいベクトルが入力されており、追加の反復も含まれています。
これ(c ++ 11バージョン)を試すことができます。これは最初のバージョンと同等です。私はそれを実行しようとしませんでした、それはいくつかのマイナーな変更で動作するはずです。
MeanAndSigma getMeanAndSigma2(const DVector& v){
MeanAndSigma ms;
ms.mean = std::accumulate(v.begin(),v.end(),0.0) / v.size();
double sqsum = std::accumulate(v.begin(),v.end(),
[ms](double sum, double ve){ return sum + (ve-ms.mean)*(ve-ms.mean);}
);
ms.sigma = std::sqrt(sqsum / (v.size()-1));
return ms;
}
ラムダなし(テストされていない、いくつかのマイナーな変更が必要な場合があります)
class DiffSquare
{
public:
DiffSquare(double m) : _m(m) {}
double operator()(double sum, double e)
{
return sum + (e - _m) * (e - _m);
}
private:
double _m;
};
MeanAndSigma getMeanAndSigma2(const DVector& v) {
MeanAndSigma ms;
ms.mean = std::accumulate(v.begin(),v.end(),0.0) / v.size();
DiffSquare diff_square(ms.mean);
double sqsum = std::accumulate(v.begin(),v.end(),
0.0,
diff_square
);
ms.sigma = std::sqrt(sqsum / (v.size()-1));
return ms;
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加