[SOLVED] c++ 11, Moving slower than copying?!?



  • Hi all, some days ago I've started testing some of the c++11 features, in order to have a better understanding of the language. One of this test was benchmarking the execution of a piece of code that use std::move instead of copy, both by filling a vector without memory reserved, so vector must call move to move its elements, and the other to copy object; What i've see is that moving vectors is extremely efficient instead of copying it, instead for my class is a bit slower.. Searching on Internet one possibility is that the code is optimized by the compiler using copying elision, that is seems more efficient.. So my question is how i can benchmark better the code? There is something wrong with my move constructor? Why in my test moving is slower??

    @//System
    #include <iostream>
    #include <vector>
    #include <memory>
    #include <string>
    #include <QTime>

    //user

    using namespace std;
    class Constructors
    {
    public:
    //Cnstructors
    Constructors() : m_TestMember{0}{} // Empty Constructor
    Constructors(int value)
    {
    m_TestMember = value +5;
    m_TestMember1 = m_TestMember + 5;
    m_TestMember2 = m_TestMember1 + 5;
    m_TestMember3 = m_TestMember2 + 5;
    m_TestMember4 = m_TestMember3 + 5;
    } //Constructor
    ~Constructors()
    {
    // std::cout<<"destructing object..."<<std::endl;
    } //Destructor
    Constructors(const Constructors &c)
    {
    m_TestMember = c.m_TestMember;
    m_TestMember1 = c.m_TestMember1;
    m_TestMember2 = c.m_TestMember2;
    m_TestMember3 = c.m_TestMember3;
    m_TestMember4 = c.m_TestMember4;
    // std::cout<<"Copying constructor..."<<std::endl;
    } //Copy Constructor

    Constructors & operator=(Constructors &c)
    {
    m_TestMember = c.m_TestMember;
    m_TestMember1 = c.m_TestMember1;
    m_TestMember2 = c.m_TestMember2;
    m_TestMember3 = c.m_TestMember3;
    m_TestMember4 = c.m_TestMember4;
    std::cout<<"Copying constructor..."<<std::endl;
    }

    Constructors(Constructors &&c)
    {
    this->m_TestMember = c.m_TestMember;
    this->m_TestMember1 = c.m_TestMember1;
    this->m_TestMember2 = c.m_TestMember2;
    this->m_TestMember3 = c.m_TestMember3;
    this->m_TestMember4 = c.m_TestMember4;

    c.m_TestMember = 0;
    c.m_TestMember1 = 0;
    c.m_TestMember2 = 0;
    c.m_TestMember3 = 0;
    c.m_TestMember4 = 0;
    //    std::cout<<"Moving constructor..."<<std::endl;
    

    } //Move Constructor

    Constructors & operator=(Constructors &&c)
    {
    m_TestMember = std::move(c.m_TestMember);
    m_TestMember1 = std::move(c.m_TestMember1);
    m_TestMember2 = std::move(c.m_TestMember2);
    m_TestMember3 = std::move(c.m_TestMember3);
    m_TestMember4 = std::move(c.m_TestMember4);

    c.m_TestMember = 0;
    c.m_TestMember1 = 0;
    c.m_TestMember2 = 0;
    c.m_TestMember3 = 0;
    c.m_TestMember4 = 0;
    //    std::cout<<"Moving assignment..."<<std::endl;
    return *this;
    

    }

    private:
    int m_TestMember;
    int m_TestMember1;
    int m_TestMember2;
    int m_TestMember3;
    int m_TestMember4;
    };
    class ConstructorsB
    {
    public:
    //Cnstructors
    ConstructorsB() : m_TestMember{0}{} // Empty Constructor
    ConstructorsB(int value)
    {
    m_TestMember = value +5;
    m_TestMember1 = m_TestMember + 5;
    m_TestMember2 = m_TestMember1 + 5;
    m_TestMember3 = m_TestMember3 + 5;
    m_TestMember4 = m_TestMember3 + 5;
    } //Constructor
    ~ConstructorsB() {
    // std::cout<<"destructing object..."<<std::endl;
    } //Destructor
    ConstructorsB(const ConstructorsB &c)
    {
    m_TestMember = c.m_TestMember;
    m_TestMember1 = c.m_TestMember1;
    m_TestMember2 = c.m_TestMember2;
    m_TestMember3 = c.m_TestMember3;
    m_TestMember4 = c.m_TestMember4;
    // std::cout<<"Copying constructor..."<<std::endl;
    } //Copy Constructor

    private:
    int m_TestMember;
    int m_TestMember1;
    int m_TestMember2;
    int m_TestMember3;
    int m_TestMember4;
    };

    //! moving bendhmark, return number of millsec elapsed
    //! Note: Moving it's much more faster when assign object or initialize them
    //! instead of move in vector !
    float scopedMovingBenchmark(bool reserving, const int &elements)
    {
    QTime timer;

    vector<Constructors> constructorVector;
    vector<Constructors> constructorVector2;

    //! reserving half the time of execution..
    //! it avoid continuos moving, destructing
    if(reserving)
    constructorVector.reserve(elements);

    Constructors testClass{10};

    timer.start();

    for(int i{0}; i != elements; i++)
    constructorVector.push_back(testClass);
    // int a{std::move(10)};

    // constructorVector2 = std::move(constructorVector);
    return timer.elapsed()/1000.0f;
    }

    //! copying bendhmark, return number of millsec elapsed
    float scopedCopyingBenchmark(bool reserving, const int &elements)
    {
    QTime timer;

    vector<ConstructorsB> constructorVector;
    vector<ConstructorsB> constructorVector2{};

    //! reserving half the time of execution..
    //! it avoid continuos moving, destructing and copying
    if(reserving)
    constructorVector.reserve(elements);

    ConstructorsB testClass{10};

    timer.start();

    for(int i{0}; i != elements; i++)
    constructorVector.push_back(testClass);
    // int a = int {10};

    // constructorVector2 = constructorVector;
    return timer.elapsed()/1000.0f;
    }

    int main()
    {
    const int elements{1000000};
    const bool reserve{false};

    float movingMedia{0.0f};
    float copyingMedia{0.0f};
    
    for(int i{0}; i!=5; i++)
      movingMedia += scopedMovingBenchmark(reserve ,elements);
    for(int i{0}; i!=5; i++)
      copyingMedia += scopedCopyingBenchmark(reserve ,elements);
    
    movingMedia /= 5.0f;
    copyingMedia /= 5.0f;
    
    std::cout<<"moving time: "<<movingMedia<<endl;
    std::cout<<"copying time: "<<copyingMedia<<endl;
    std::cout<<"delta: "<<movingMedia - copyingMedia<<endl;
    

    return 0;
    }

    @



  • interresting, experiment with bigger iteration value:

    @int main( int argc, char **argv )
    {
    const int elements{1000000};
    const bool reserve{false};

    float movingMedia{0.0f};
    float copyingMedia{0.0f};
    

    double factor = 5;
    if ( argc > 1 )
    factor = atof( argv[1] );

    for(int i{0}; i < factor; i++)
      movingMedia += scopedMovingBenchmark(reserve ,elements);
    for(int i{0}; i < factor; i++)
      copyingMedia += scopedCopyingBenchmark(reserve ,elements);
    
    movingMedia /= factor;
    copyingMedia /= factor;
    

    ...
    @



  • I think i found the problem: basically moving is made for heap allocated memory, so when copying it avoid continuous memory allocation. So modifying the variable m_TestMember to a pointer type and consequently all the related moving copying constructor, the code is more faster.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.