プレーンループの代わりにstd :: Algorithmsを使用すると、このコードが遅くなるのはなぜですか?

idclev 463035818

ベクトルの要素の平均と標準偏差を計算しています。私はこれの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番目のバージョンを改善するための標準アルゴリズムについては十分に理解していません。だから、今私の質問は:

アルゴリズムを使用してバージョンを改善し、プレーンループを使用するバージョンよりも高速にするにはどうすればよいですか?

gkamal

プログラムは同等ではないと思います。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]

編集
0

コメントを追加

0

関連記事

分類Dev

std :: getが通常のパラメーターの代わりにテンプレートパラメーターを使用するのはなぜですか?

分類Dev

std :: getが通常のパラメーターの代わりにテンプレートパラメーターを使用するのはなぜですか?

分類Dev

SkylakeにVZEROUPPERがないと、このSSEコードが6倍遅くなるのはなぜですか?

分類Dev

SkylakeにVZEROUPPERがないと、このSSEコードが6倍遅くなるのはなぜですか?

分類Dev

SkylakeにVZEROUPPERがないと、このSSEコードが6倍遅くなるのはなぜですか?

分類Dev

GCC最適化を有効にすると、strlenを使用するこのコードが6.5倍遅くなるのはなぜですか?

分類Dev

std :: copy_nがstd :: size_tの代わりにテンプレートパラメータを使用するのはなぜですか?

分類Dev

コマの代わりにセミコロンがforループで使用されるのはなぜですか?

分類Dev

group by + partition byの代わりにpartitionbyを使用すると、レコードが増えるのはなぜですか?

分類Dev

このコードが他のすべてのオプションよりもわずかに多くabcとdを生成するのはなぜですか?

分類Dev

forループの代わりにイテレータが使用されるのはなぜですか?

分類Dev

怠惰に使用するとKotlinコードが遅くなるのはなぜですか

分類Dev

怠惰に使用するとKotlinコードが遅くなるのはなぜですか

分類Dev

プレーンなT :: AccountIdの代わりに<T :: Lookup as StaticLookup> :: Sourceを使用するのはなぜですか?

分類Dev

このループが徐々に遅くなるのはなぜですか?

分類Dev

for ループ内でカーネルを繰り返すと、CUDA コードが大幅に遅くなるのはなぜですか?

分類Dev

LLVMの代わりにG ++でコンパイルすると、コードが大幅に遅くなります

分類Dev

curlでコールバックの進行状況を使用すると、ファイルのダウンロードが遅くなるのはなぜですか?

分類Dev

なぜこのHaskellコードは-Oで遅くなるのですか?

分類Dev

GCを無効にすると、このXML解析Rubyコードの実行が遅くなるのはなぜですか?

分類Dev

SocketAsyncEventArgsからのCompletedコールバックが、制限されたスレッドプールを使用する代わりに、新しく作成されたスレッドで頻繁に実行されるのはなぜですか?

分類Dev

Javaで複数のスレッドを使用するとコードが遅くなるのはなぜですか?

分類Dev

最適化を有効にすると、このコードが6.5倍遅くなるのはなぜですか?

分類Dev

配列サイズが偶数の場合、このコードが遅くなるのはなぜですか?

分類Dev

Hadoopクラスターにノードを追加すると、スループットと平均ioレートが遅くなるのはなぜですか?

分類Dev

Cでプレーン変数の代わりに参照とポインターを指定する必要があるのはなぜですか

分類Dev

(myVariable + = 1)を(myVariable ++)に代わるものとしてJavaScriptの(forループ)に置くと、このコードで無限ループが生成されるのはなぜですか?

分類Dev

関数でテーブルの代わりにレコードを取得するのはなぜですか?

分類Dev

このjavascriptループがオプションの代わりに数字を出力するのはなぜですか?

Related 関連記事

  1. 1

    std :: getが通常のパラメーターの代わりにテンプレートパラメーターを使用するのはなぜですか?

  2. 2

    std :: getが通常のパラメーターの代わりにテンプレートパラメーターを使用するのはなぜですか?

  3. 3

    SkylakeにVZEROUPPERがないと、このSSEコードが6倍遅くなるのはなぜですか?

  4. 4

    SkylakeにVZEROUPPERがないと、このSSEコードが6倍遅くなるのはなぜですか?

  5. 5

    SkylakeにVZEROUPPERがないと、このSSEコードが6倍遅くなるのはなぜですか?

  6. 6

    GCC最適化を有効にすると、strlenを使用するこのコードが6.5倍遅くなるのはなぜですか?

  7. 7

    std :: copy_nがstd :: size_tの代わりにテンプレートパラメータを使用するのはなぜですか?

  8. 8

    コマの代わりにセミコロンがforループで使用されるのはなぜですか?

  9. 9

    group by + partition byの代わりにpartitionbyを使用すると、レコードが増えるのはなぜですか?

  10. 10

    このコードが他のすべてのオプションよりもわずかに多くabcとdを生成するのはなぜですか?

  11. 11

    forループの代わりにイテレータが使用されるのはなぜですか?

  12. 12

    怠惰に使用するとKotlinコードが遅くなるのはなぜですか

  13. 13

    怠惰に使用するとKotlinコードが遅くなるのはなぜですか

  14. 14

    プレーンなT :: AccountIdの代わりに<T :: Lookup as StaticLookup> :: Sourceを使用するのはなぜですか?

  15. 15

    このループが徐々に遅くなるのはなぜですか?

  16. 16

    for ループ内でカーネルを繰り返すと、CUDA コードが大幅に遅くなるのはなぜですか?

  17. 17

    LLVMの代わりにG ++でコンパイルすると、コードが大幅に遅くなります

  18. 18

    curlでコールバックの進行状況を使用すると、ファイルのダウンロードが遅くなるのはなぜですか?

  19. 19

    なぜこのHaskellコードは-Oで遅くなるのですか?

  20. 20

    GCを無効にすると、このXML解析Rubyコードの実行が遅くなるのはなぜですか?

  21. 21

    SocketAsyncEventArgsからのCompletedコールバックが、制限されたスレッドプールを使用する代わりに、新しく作成されたスレッドで頻繁に実行されるのはなぜですか?

  22. 22

    Javaで複数のスレッドを使用するとコードが遅くなるのはなぜですか?

  23. 23

    最適化を有効にすると、このコードが6.5倍遅くなるのはなぜですか?

  24. 24

    配列サイズが偶数の場合、このコードが遅くなるのはなぜですか?

  25. 25

    Hadoopクラスターにノードを追加すると、スループットと平均ioレートが遅くなるのはなぜですか?

  26. 26

    Cでプレーン変数の代わりに参照とポインターを指定する必要があるのはなぜですか

  27. 27

    (myVariable + = 1)を(myVariable ++)に代わるものとしてJavaScriptの(forループ)に置くと、このコードで無限ループが生成されるのはなぜですか?

  28. 28

    関数でテーブルの代わりにレコードを取得するのはなぜですか?

  29. 29

    このjavascriptループがオプションの代わりに数字を出力するのはなぜですか?

ホットタグ

アーカイブ