26
Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Embed Size (px)

Citation preview

Page 1: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group

Impact of C++11 Move Semantics on Performance

Francisco Almeida

Page 2: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 2

Move semantics and performance

• A little bit of background.– What are R-value references?– What is it good for?

• What about compiler optimizations?– Copy elision/return value optimization.

• Execution time comparisons (STL).– Using GCC 4.7.0

3rd of April, 2012

Page 3: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 3

L-Value References

• What do we mean by L-value reference?

3rd of April, 2012

std::string becpp = “BeCppUG”;

L-value (named object)std::string&

Page 4: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 4

R-Value References

3rd of April, 2012

std::string GetGroupName(){ return std::string(“BECppUG”);}

R-value (unnamed object)

• What do we mean by R-value reference?

std::string&&

Page 5: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 5

Construct by moving

• Default constructor• Parameterized constructor• Copy constructor• Move constructor

3rd of April, 2012

MyClass::MyClass(MyClass&& other){ data = other.data;}

Page 6: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 6

std::move

3rd of April, 2012

MyClass::MyClass(MyClass&& other){ data = other.data;}

MyClass::MyClass(MyClass&& other){ data = std::move(other.data);}

L-value

R-value

Page 7: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 7

std::move

3rd of April, 2012

MyClass& MyClass::operator=(MyClass&& other){ data = other.data; return *this;}

MyClass& MyClass::operator=(MyClass&& other){ data = std::move(other.data); return *this;}

L-value

R-value

Page 8: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 8

std::move definition

3rd of April, 2012

template<typename T>inline typename std::remove_reference<T>::type&&move(T&& t){ return static_cast<typename std::remove_reference<T>::type&&>(t);}

Page 9: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 9

By the way…

• Even if you don’t use it, the STL will!

3rd of April, 2012

template<typename T>inline void swap(T& a, T& b){ T tmp = a; a = b; b = tmp;}

template<typename T>inline void swap(T& a, T& b){ T tmp = std::move(a); a = std::move(b); b = std::move(tmp);}

Page 10: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 10

Default move constructor• The compiler will provide your class an implicit move constructor if:

– No user-defined copy constructor or assignment.– No user-defined destructor.– No user-defined move assignment.

• Your class will also get an implicit move assignment if:– No user-defined copy constructor or assignment.– No user-defined destructor.– No user-define move constructor.

• Strong guarantee required:• Copy constructor and destructor have no side effects.• Constructors do not throw (tell the compiler noexcept).

3rd of April, 2012

Page 11: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 11

Imperfect forwarding

• How to ensure that a reference type is always correctly forwarded?

3rd of April, 2012

template<typename T, typename U>shared_ptr<T> create_shared(U& arg){ return shared_ptr<T>(new T(arg));}

template<typename T, typename U>shared_ptr<T> create_shared(const U& arg){ return shared_ptr<T>(new T(arg));}

template<typename T, typename U>shared_ptr<T> create_shared(U arg){ return shared_ptr<T>(new T(arg));}

Page 12: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 12

C++11 Reference Collapsing Rules

When passing… … it becomes…

A& & A&

A& && A&

A&& & A&

A&& && A&&

3rd of April, 2012

template<typename T>inline T&& forward(typename std::remove_reference<T>::type& t) noexcept{ return static_cast<T&&>(t);}

Page 13: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 13

Perfect forwarding

• “One overload to forward them all”

3rd of April, 2012

template<typename T, typename U>shared_ptr<T> create_shared(U&& arg){ return shared_ptr<T>(new T(std::forward(arg)));}

Page 14: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 14

Doesn’t the compiler do all this, anyway?

3rd of April, 2012

Page 15: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 15

Return Value Optimization

3rd of April, 2012

std::string GetGroupName(){ return std::string(“BECppUG”);}

// ...

std::string name = GetGroupName();No copying!

Page 16: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 16

Return Value Optimization

• Compiler skips object copying (elides copy)– Stack frame optimization technique.– First introduced by Walter Bright, in the Zortech

C++ Compiler.• Compiler dependent, and not always

guaranteed.

3rd of April, 2012

Page 17: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 17

I don’t need “move semantics” to move!

3rd of April, 2012

Page 18: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 183rd of April, 2012

void MyClass::Swap(MyClass& other){ std::swap(data, other.data);}

MyClass obj1;obj1.Swap(temp);

Explicit swaps do get most of the job done…

Page 19: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 19

…and return value optimization does the rest…

3rd of April, 2012

MyClass& MyClass::operator=(MyClass other){ Swap(other); return *this;}

…but it is not portable, nor guaranteed to always work.

• Copy-and-Swap idiom:

Page 20: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 20

Optimal use of copy and move semantics

3rd of April, 2012

Page 21: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 21

But does it really make any difference?

3rd of April, 2012

Page 22: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 22

A simple example

• “Benchmark” for comparing move-enabled STL to move-disabled STL performance.

• Tested using GCC 4.7.0– Without -std=c++0x (C++98 rules, no move)– With -std=c++0x (C++11, use move in STL)

• Refer to:http://cpp-next.com/archive/2010/10/howards-stl-move-semantics-benchmark/

3rd of April, 2012

Page 23: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 23

Howard’s STL move semantics “benchmark”

• Fill a std::vector with N std::sets of N randomly generated values.– We will use N = 5001 here.

• Sort the std::vector.

• Rotate the std::vector by half its size.

3rd of April, 2012

Page 24: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 24

Execution times comparison(containers passed by value)

Construc-tion

Sort Rotate Destruction Total0.000

10.000

20.000

30.000

40.000

50.000

C++98C++11

3rd of April, 2012

Page 25: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 25

Execution times comparison(containers passed by reference)

Construc-tion

Sort Rotate Destruction Total0.000

10.000

20.000

30.000

40.000

50.000

C++98C++11

3rd of April, 2012

Page 26: Belgian C++ User Group Impact of C++11 Move Semantics on Performance Francisco Almeida

Belgian C++ User Group 26

Conclusions

• Move semantics are another optimization tool in the C++ arsenal.

• Profile your code and compare approaches.– Use noexcept wherever possible.– Do not overuse move semantics, you may actually lose

performance.

• STL is move-enabled “out of the box”– Optimizations for free

3rd of April, 2012