Upload
mallory-emm
View
215
Download
0
Tags:
Embed Size (px)
Citation preview
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
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&
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&&
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;}
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
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
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);}
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);}
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
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));}
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);}
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)));}
Belgian C++ User Group 14
Doesn’t the compiler do all this, anyway?
3rd of April, 2012
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!
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
Belgian C++ User Group 17
I don’t need “move semantics” to move!
3rd of April, 2012
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…
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:
Belgian C++ User Group 20
Optimal use of copy and move semantics
3rd of April, 2012
Belgian C++ User Group 21
But does it really make any difference?
3rd of April, 2012
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
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
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
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
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