Why does this code get slower when I use std :: algorithm instead of regular loops?

I calculate the mean and standard deviation of the elements of a vector. I have two versions of this, and I am completely puzzled why a version using standard algorithms is slower than a version using simple loops.

Both versions use this structure as a return type:

struct MeanAndSigma { double mean; double sigma; }; 

And the loop version is this:

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

And the one who has the algorithms:

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

When I measure the time that they take for 10k calls with a vector with 10k elements, I get ~ 2.0 seconds for the version with loops and ~ 3.2 seconds for one with the algorithms. Why is this?

I already compared processor time and real time, but it seems that both of them work (as expected) on the same processor. Am I stupidly mistaken in using algorithms?

EDIT: I am not saying that the two versions are equivalent. However, I expected the second version to be faster. As stated in the comments and the answer, the second version uses an additional iteration over the elements and an additional DVector (which is btw only a typedef std::vector<double> ). However, I am not familiar with standard algorithms to improve the second version. So now my question is:

How to improve the version with algorithms faster than using simple loops?

+6
source share
1 answer

I do not think the programs are equivalent. In the second version (using algorithms) a new vector of doubling is filled, and an additional iteration is also involved.

You can try this (C ++ 11 version), this is equivalent to the first version. I did not try to run it, it should work with some minor changes.

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

Without lambdas (not verified, you may need to make minor changes)

 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
source

Source: https://habr.com/ru/post/986221/


All Articles