首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么当我使用std::算法而不是普通循环时,这段代码变慢了?

为什么当我使用std::算法而不是普通循环时,这段代码变慢了?
EN

Stack Overflow用户
提问于 2015-04-29 12:24:29
回答 1查看 344关注 0票数 6

我正在计算向量元素的平均偏差和标准差。我有两个版本,我完全不明白为什么使用标准算法的版本比使用普通循环的版本慢。

两个版本都使用此结构作为返回类型:

代码语言:javascript
复制
struct MeanAndSigma {
    double mean;
    double sigma;
};

有循环的版本是:

代码语言:javascript
复制
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;
}

还有有算法的:

代码语言:javascript
复制
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上运行(如预期的那样)。我在使用算法时做了什么愚蠢的错事吗?

编辑:我没有声称,这两个版本是等价的。不过,我原以为第二个版本会更快一些。正如注释和答案中指出的那样,第二个版本在元素上使用额外的迭代,并使用额外的DVector (顺便说一下,它只是一个typedef std::vector<double>)。但是,我对改进第二个版本的标准算法还不够熟悉。所以,现在我的问题是:

如何改进算法版本,使其比使用普通循环的版本更快?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-29 12:33:44

我不认为这些程序是等价的。在第二个版本(使用算法)中,正在填充一个新的加倍向量,并且还会涉及一个额外的迭代。

您可以尝试这个(c++11版本),它相当于第一个版本。我还没有试着运行它,它应该可以处理一些小的更改。

代码语言:javascript
复制
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;
}

如果没有lambda(未经测试,可能需要进行一些小的更改)

代码语言:javascript
复制
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;
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29943678

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档