c++ - 为什么当我使用 std::algorithms 而不是普通循环时这段代码变慢了?

标签 c++ algorithm optimization runtime

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

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

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 元素的 vector 进行每 10k 次调用所花费的时间时,我得到的循环版本约为 2.0 秒,算法版本约为 3.2 秒。这是为什么?

我已经比较了 CPU 时间和实时时间,但似乎两者都在单个 CPU 上运行(正如预期的那样)。我在使用算法时是否犯了一些愚蠢的错误?

编辑:我并不是说这两个版本是等价的。尽管如此,我本以为第二个版本会更快。正如评论和答案中所指出的,第二个版本对元素使用了额外的迭代和额外的 DVector。 (顺便说一句,这只是一个 typedef std::vector<double> )。但是,我对标准算法不够熟悉,无法改进第二个版本。所以,现在我的问题是:

我怎样才能改进带有算法的版本,使其比使用普通循环的版本更快?

最佳答案

我不认为这些程序是等效的。在第二个版本中(使用算法)一个新的 double vector 被填充并且还涉及额外的迭代。

你可以试试这个(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;
}

没有 lambda(未测试,可能需要一些小改动)

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;
}

关于c++ - 为什么当我使用 std::algorithms 而不是普通循环时这段代码变慢了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29943678/

相关文章:

c++ - 默认情况下不会执行c++

c++ - valgrind - hellgrind 与泄漏检查的不同结果

c++ - 您有菱形继承(钻石问题)有用的例子吗?

java - Java 中 ArrayList 的 add() 方法背后的算法是什么?

.net - 绕过 WPF 渲染瓶颈

optimization - 如何为向量中的每个元素计算另一个向量中较小的元素的分数?

html - 从我的所有网站页面中删除 HTML 部分块会影响 SEO 和我的网站排名吗?

C++17 模板推导指南不用于空参数集?

algorithm - 计算机科学理论 : Image Similarity

python - 破解python编码面试中urlify问题尝试写java代码