This is probably pretty similar to other questions; I looked around a bit but I don't know what I'm talking about well enough to be sure.
I'm writing a function that "should" be in-place, but which is implemented by a BLAS call. The BLAS call is not in-place so I need to make a temporary. Thus:
void InPlace(ArrayClass& U, const TransformMatrix* M){
ArrayClass U_temp;
CallBLASdgemm(U, M, U_temp); //Now U_temp contains the correct output.
U = std::move(U_temp);
}
Is this a valid use of std::move, or am I somehow breaking "copy elision" (or is it bad for some other reason)?
Edit: the signature of CallBLASDgemm was requested; it is
CallBLASdgemm(const ArrayClass& U, const TransformMatrix* M,
ArrayClass& V);
No copies are performed with or without copy elision in this case so that's already out of the question. Because U_temp is an lvalue the compiler has to call the copy constructor if you'd do :
U = U_temp;
However, you know that U_temp won't be used anymore and thus moving away its values is completely safe and can possibly be faster (that is, if ArrayClass implements a move assignment constructor). Using std::move here is fine and even encouraged.
Yes, this is a valid use case. If you have a named temporary (lvalue) the only way to move it into U is to use std::move to cast it to a rvalue.
I think what you are worried about is when people do return std::move(object);. That is a pessimization as that copy of object into the return value can be elided in most cases.
This is valid. However, what I'd do is this:
ArrayClass myCallBLASdgemm(const ArrayClass& U, const TransformMatrix* M) {
ArrayClass tmp;
CallBLASdgemm(U, M, tmp);
return tmp; // elided move
}
void InPlace(ArrayClass& U, const TransformMatrix* M){
U = myCallBLASdgemm(U, M);
}
which runs the same code, but does it without a temporary being visible in the outer scope.
In fact, myCallBLASdgemm is so clean you can probably eliminate InPlace and just call myClassBLASdgemm where you need it.
Related
Usually I use this to avoid copying cost:
void bar(const string& s);
void foo(const vector<int>& v);
Are STL containers in C++11 all support move semantics?
If so, does following code have the same performance as const &?
void bar(string s);
void foo(vector<int> v);
Move semantics don't just magically make your code faster.
With them, calling a function like void bar(string s) is faster than it would be if you had to copy your arguments, but only in the case where the argument can be moved. Consider this case:
std::string prompt(std::string prompt_text);
void askOnce(std::string question) { prompt(question); }
void askManyTimes(std::string question) {
for(int i=0; i<10; ++i) {
askOnce(question);
}
}
In the case of askOnce, the argument can be copied into the function or moved. When it's calling prompt, the argument can be moved.
In askManyTimes however, you need to keep the argument around so you can't move, so you actually end up having to create 10 copies of your question for no good reason.
Generally, if you don't need to modify your string or copy it somewhere else, you should still use const std::string&; You can leave the reference off if you need to do a copy later on anyway.
Are STL containers in C++11 all support move semantics?
Yes.
If so, does following code have the same performance as const &?
No, if the argument is an lvalue. If the argument is an rvalue, the performance is at least as good.
In the case of an lvalue, the argument has to be copied. There's no way around that. The function signature specifies that it doesn't modify its arguments, but a move operation might modify the object that is being moved from.
In the case of an rvalue, the argument can be moved from, if supported.
So if the parameter will be copied inside the function anyway, it is better to pass it by value, so that rvalues can be moved from, while lvalues will still be copied.
It depends what you pass in. If you pass a temporary object it will get moved in but if you pass a named variable it will get copied.
bar(func_returns_string()); // move
std::string s;
bar(s); // copy
You can force it to move a named variable using std::move:
bar(std::move(s)); // move (now s is empty)
In general I would like to know when and why a modern day compiler, say gcc 4.7 and up using c++11, can not apply an NVRO optimization.
EDIT: I oversimplified this code mistakenly not returning any local variables. A better example was supplied by #cooky451 below see ideone.com/APySue
I saw some snippets of code to answers on other questions that were as such
A f(A&& v)
{
return v;
}
and they were changed to be
A f(A&& v)
{
return std::move(v);
}
because they said that the rvalue passed in which is assigned to an lvalue v was still an rvalue and could be moved. However, others wrote that this will remove the ability for NVRO. Wny is this? If the compiler knows that a temporary is being returned can't it construct it directly in place without moving anything? I guess I don't understand why case one would have NVRO but not case 2. I might have the facts wrong hence the question. Also, I read that case 2 was an anti pattern for this reason and that you shouldn't return std::move like this. Any additional insight would be helpful. I was told that behind the scenes the compiler will create something like this below: A& __hidden__ is the assignment to the function, myValue in this case.
A myValue = f(A());
// behind the scenes pseudo code for direct in place construction
void f(A&& v, A& __hidden__ )
{
__hidden__ = v;
return;
}
Both won't use RVO, because it's impossible. The problem is: && is still just a reference. The variable you're returning is not inside your function-local scope! So, without std::move, you'll copy, and with it you'll move. I would advice btw not to expect something per rvalue-reference, as long as you're not writing a move constructor/assignment operator or some perfect-forwarding template-code. Just take it by value. It has a small overhead in some cases, but it's really not going to be significant. And it makes code a lot more readable. And simpler, as the caller can either copy or move the arguments, and you don't have to provide additional const& overloads.
A function needs to return two values to the caller. What is the best way to implement?
Option 1:
pair<U,V> myfunc()
{
...
return make_pair(getU(),getV());
}
pair<U,V> mypair = myfunc();
Option 1.1:
// Same defn
U u; V v;
tie(u,v) = myfunc();
Option 2:
void myfunc(U& u , V& v)
{
u = getU(); v= getV();
}
U u; V v;
myfunc(u,v);
I know with Option2, there are no copies/moves but it looks ugly. Will there be any copies/moves occur in Option1, 1.1? Lets assume U and V are huge objects supporting both copy/move operations.
Q: Is it theoretically possible for any RVO/NRVO optimizations as per the standard? If yes, has gcc or any other compiler implemented yet?
Will RVO happen when returning std::pair?
Yes it can.
Is it guaranteed to happen?
No it is not.
C++11 standard: Section 12.8/31:
When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the copy/move constructor and/or destructor for the object have side effects.
Copy elision is not a guaranteed feature. It is an optimization compilers are allowed to perform whenever they can. There is nothing special w.r.t std::pair. If a compiler is good enough to detect an optimization opportunity it will do so. So your question is compiler specific but yes same rule applies to std::pair as to any other class.
While RVO is not guaranteed, in C++11 the function as you have defined it I believe MUST move-return at the very least, so I would suggest leaving the clearer definition rather than warping it to accept output-variables (Unless you have a specific policy for using them).
Also, even if this example did use RVO, your explicit use of make_pair means you will always have at least one extra pair construction and thus a move operation. Change it to return a brace-initialized expression:
return { getU(), getV() };
RVO or Copy elision is dependant on compiler so if you want to have RVO and avoid call to Copy constructor best option is to use pointers.
In our product we use use pointers and boost containers pointer to avoid Copy constructor. and this indeed gives performance boost of around 10%.
Coming to your question,
In option 1 U and V's copy constructor will not be called as you are not returning U or V but returning std::pair object so it's copy constructor will be called and most compilers will definately use RVO here to avoid that.
Thanks
Niraj Rathi
If you need to do additional work on u and v after having created the pair, I find the following pattern pretty flexible in C++17:
pair<U,V> myfunc()
{
auto out = make_pair(getU(),getV());
auto& [u, v] = out;
// Work with u and v
return out;
}
This should be a pretty easy case for the compiler to use named return value optimization
I am writing a couple string sort algorithm with c++ and I wonder if I can make this swap operation faster.
void swap(string *items,int a, int b ){
string temp;
temp = items[a];
items[a] = items[b];
items[b] = temp;
}
I'll be appreciate if you can help...
String class has its own swap function.
items[a].swap(items[b]);
It's the fastest way to do this because it accesses the string internals and avoids all copying.
See here.
You can use std::swap():
void swap(string *items, int a, int b) {
std::swap(items[a], items[b]);
}
But there's no guarantee that this will be measurably faster, and this probably isn't the slow part of your code anyway. Have you measured the performance of the swap operation compared to the rest of your code?
Use std::swap; it will do the best job it can. If your compiler supports C++11's rvalue references, this means that it will take advantage of move semantics to avoid the copy that occurs in your swap function.
However, if your compiler doesn't support rvalue references, it will most likely perform the same way as your swap function does.
Most standard library implementations will implement std::swap as something similar to:
template<typename T>
void swap(T& a, T& b) {
T temp(std::move(a));
a = std::move(b);
b = std::move(temp);
}
The std::move function will return an rvalue reference (T&&) to the variable passed in. When you attempt to assign this rvalue reference, it will invoke the type's move operator, if one is available. If a move operator isn't available, it will invoke the copy operator as usual.
In the case of std::string, the above swap function will do no string copies with C++11; only the internal data, such as the string length and C string pointer, will be copied. Without C++11, it will perform three copies of the actual string contents.
You could change your algorithm to work on elements of type string* instead of string. Then all the assignments in your swap function would operate on pointers, and be faster because no string copying would be involved.
I'd like to use the following idiom, that I think is non-standard. I have functions which return vectors taking advantage of Return Value Optimization:
vector<T> some_func()
{
...
return vector<T>( /* something */ );
}
Then, I would like to use
vector<T>& some_reference;
std::swap(some_reference, some_func());
but some_func doesn't return a LValue. The above code makes sense, and I found this idiom very useful. However, it is non-standard. VC8 only emits a warning at the highest warning level, but I suspect other compilers may reject it.
My question is: Is there some way to achieve the very same thing I want to do (ie. construct a vector, assign to another, and destroy the old one) which is compliant (and does not use the assignment operator, see below) ?
For classes I write, I usually implement assignment as
class T
{
T(T const&);
void swap(T&);
T& operator=(T x) { this->swap(x); return *this; }
};
which takes advantage of copy elision, and solves my problem. For standard types however, I really would like to use swap since I don't want an useless copy of the temporary.
And since I must use VC8 and produce standard C++, I don't want to hear about C++0x and its rvalue references.
EDIT: Finally, I came up with
typedef <typename T>
void assign(T &x, T y)
{
std::swap(x, y);
}
when I use lvalues, since the compiler is free to optimize the call to the copy constructor if y is temporary, and go with std::swap when I have lvalues. All the classes I use are "required" to implement a non-stupid version of std::swap.
Since std::vector is a class type and member functions can be called on rvalues:
some_func().swap(some_reference);
If you don't want useless copies of temporaries, don't return by value.
Use (shared) pointers, pass function arguments by reference to be filled in, insert iterators, ....
Is there a specific reason why you want to return by value?
The only way I know - within the constraints of the standard - to achieve what you want are to apply the expression templates metaprogramming technique: http://en.wikipedia.org/wiki/Expression_templates Which might or not be easy in your case.