c++ - Weird behaviours of std::vector, can you explain them? -



c++ - Weird behaviours of std::vector, can you explain them? -

so i've been reading this question , playing code. has been couple of years since posted , curious on how new compilers handle it. however, i'm finding out on g++4.9.1 leaving me extremely perplexed.

i have code:

#include <cstdlib> #include <vector> #include <iostream> #include <string> #include <boost/date_time/posix_time/ptime.hpp> #include <boost/date_time/microsec_time_clock.hpp> constexpr int outerloopbound = 1000; class testtimer { public: testtimer(const std::string & name) : name(name), start(boost::date_time::microsec_clock<boost::posix_time::ptime>::local_time()) {} ~testtimer() { using namespace std; using namespace boost; posix_time::ptime now(date_time::microsec_clock<posix_time::ptime>::local_time()); posix_time::time_duration d = - start; cout << name << " completed in " << d.total_milliseconds() / 1000.0 << " seconds" << endl; } private: std::string name; boost::posix_time::ptime start; }; struct pixel { pixel() {} pixel(unsigned char r, unsigned char g, unsigned char b) : r(r), g(g), b(b) {} unsigned char r, g, b; }; double usevector() { testtimer t("usevector"); double sum = 0.0; for(int = 0; < outerloopbound; ++i) { int dimension = 999; std::vector<pixel> pixels; pixels.resize(dimension * dimension); for(int = 0; < dimension * dimension; ++i) { pixels[i].r = 255; pixels[i].g = 0; pixels[i].b = 0; } sum += pixels[0].b; } homecoming sum; } double usevector2() { testtimer t("usevector2"); double sum = 0.0; for(int = 0; < outerloopbound; ++i) { int dimension = 999; std::vector<pixel> pixels(dimension*dimension, pixel(255,0,0)); sum += pixels[0].b; } homecoming sum; } double usevector3() { testtimer t("usevector3"); double sum = 0.0; for(int = 0; < outerloopbound; ++i) { int dimension = 999; pixel p(255, 0, 0); std::vector<pixel> pixels(dimension*dimension, p); sum += pixels[0].b; } homecoming sum; } double usevectorpushback() { testtimer t("usevectorpushback"); double sum = 0.0; for(int = 0; < outerloopbound; ++i) { int dimension = 999; std::vector<pixel> pixels; pixels.reserve(dimension * dimension); for(int = 0; < dimension * dimension; ++i) pixels.push_back(pixel(255, 0, 0)); sum += pixels[0].b; } homecoming sum; } void usevectoremplaceback() { testtimer t("usevectorpushback"); for(int = 0; < outerloopbound; ++i) { int dimension = 999; std::vector<pixel> pixels; pixels.reserve(dimension * dimension); for(int = 0; < dimension * dimension; ++i) pixels.emplace_back(pixel(255, 0, 0)); } } double usearray() { testtimer t("usearray"); double sum = 0.0; for(int = 0; < outerloopbound; ++i) { int dimension = 999; pixel * pixels = (pixel *)malloc(sizeof(pixel) * dimension * dimension); for(int = 0 ; < dimension * dimension; ++i) { pixels[i].r = 255; pixels[i].g = 0; pixels[i].b = 0; } sum += pixels[0].b; free(pixels); } homecoming sum; } int main() { testtimer t1("the whole thing"); double result = 0.0; result += usearray(); result += usevector(); result += usevector2(); result += usevector3(); result += usevectorpushback(); std::cout << "result is: " << result << '\n'; homecoming 0; }

i've modified bit original code in hope avoid compiler nullifying everything. have:

usevector: creates empty vector, uses resize, loops , sets pixels. usevector2: creates vector straight of size needed, , instantiates pixels temporary. usevector3: creates vector straight of size needed, , instantiates pixels single lvalue. usevectorpushback: creates empty vector, uses reserve, adds pixels push_back. usevectoremplaceback: creates empty vector, uses reserve, adds pixels emplace_back. usearray: mallocs array, loops setting pixels, deallocates.

in add-on these functions accumulate values in sum variable returned prevent compiler eliminating loops. in main function test of these functions but usevectoremplaceback. of import later.

so compile next flags: g++ -o3 -march=native -std=c++11 main.cpp. i'm on fx-8350.

round one

as is, code produces me:

usearray completed in 0.248 seconds usevector completed in 0.245 seconds usevector2 completed in 0.872 seconds usevector3 completed in 0.981 seconds usevectorpushback completed in 4.779 seconds result is: 0 whole thing completed in 7.126 seconds

so first thing notice usevector, in original question slower, on par c array, though in theory should doing 2 passes on data.

on other hand, usevector2 , usevector3 4 times slow usevector. this seems unusual me, why happen?.

round two

ok, have usevectoremplaceback function, we're not testing it. why not comment it? comment it, , seek 1 time again code:

usearray completed in 0.246 seconds usevector completed in 0.245 seconds usevector2 completed in 0.984 seconds usevector3 completed in 0.8 seconds usevectorpushback completed in 4.771 seconds result is: 0 whole thing completed in 7.047 seconds

ok, apparently while before usevector2 bit faster usevector3, situation has reversed. result keeps happening after running code multiple times. so changed running time of 2 functions commenting unused function. wait what?

round three

continuing here, @ point think usevector3 reason faster one. want create faster, , comment next line in usevector3 cut down workload:

// sum += pixels[0].b;

now function faster, our incredible coding ability! let's test it:

usearray completed in 0.245 seconds usevector completed in 0.244 seconds usevector2 completed in 0.81 seconds usevector3 completed in 0.867 seconds usevectorpushback completed in 4.778 seconds result is: 0 whole thing completed in 6.946 seconds

ok removed operation usevector3, slowed down, while usevector2, untouched, became faster other.

conclusions

in add-on there bunch of other weird behaviours numerous mention. seems every random edit on code produces weird effects overall. i'm curious 3 things showed here:

why usevector faster both usevector2 , usevector3? why commenting unused function alters time of 2 other functions, not rest? why removing operation function slows down, accelerates another?

c++ performance c++11 vector stl

Comments

Popular posts from this blog

Delphi change the assembly code of a running process -

json - Hibernate and Jackson (java.lang.IllegalStateException: Cannot call sendError() after the response has been committed) -

C++ 11 "class" keyword -