-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reference over temporaries #10
Comments
I've seen this w/ gcc 4.7. I had assumed it was a bug in gcc. Are you sure that gcc w/ optimizations on is really conforming to the The idea of using const refs in all of the parameters is so that
how can you confirm this? const values are stored in a separate area -Whit |
also, which exact gcc version are you on? and this is on Fedora as well? -Whit On Sun, Jul 8, 2012 at 2:21 PM, jhjourdan
|
Le 08/07/2012 20:38, Whit Armstrong a écrit :
Actually, this is more complicated than that : the compiler can actually movabsq $4591870180066957722, %r10 ; 4591870180066957722 is Where 4591870180066957722 is actually the qword bit-equivalent to the A few lines later, there is : movq %r9, -6440(%rbp) That is, the compiler is using the stack location -6440(%rbp) for So yes, I can confirm this behavior. And I would be /very/ surprised if Jacques-Henri Jourdan
|
It is gcc 4.7.0, the latest version on Fedora 17. Jacques-Henri Jourdan Le 08/07/2012 21:01, Whit Armstrong a écrit :
|
Thanks for digging into this. can you send or post your test code? -Whit On Sun, Jul 8, 2012 at 5:53 PM, jhjourdan
|
The more I look at this the worse it seems. There is a snip here, which basically describes how gcc did this to be "G++ now properly re-uses stack space allocated for temporary objects I'll take a closer look at your proposals. I agree that rvalues my be My main gripe is that there is no way to detect when a literal is -Whit On Mon, Jul 9, 2012 at 7:07 AM, Whit Armstrong [email protected] wrote:
|
Do you still want me to provide you an example ? My actual code is quite Le 09/07/2012 20:44, Whit Armstrong a écrit :
Well, actually, rvalue references can do this detection (in our case, we Anyway, thanks for thinking about this problem ! If you want, I can implement one of these solution. Jacques-Henri Jourdan
|
I think rvalues are the way to go. However, that could complicate the classes significantly. All the permutations of rvalues in the hyper-parameters would need to be handled... for instance, using Normal(x, mu, tau) One would need and two additional class members both initialized to null, both deleted in the destructor, and only assigned a value if the rvalue constructor is called. For instance (using shorthand, not actual code):
|
I implemented it using type traits (see my fork of the repo) and templates. It uses very few copy and paste. The basic idea is that for any type T, T& && reduces to T&, and the compiler knows that it can instantiate U by T& in a function template taking U&& as argument, so it can pass a lvalue reference to the function. That is a classical trick on rvalue references, for avoiding exponential explosion of overloadings. Fell free to ask questions for the details ! BR, |
you're way ahead of me! Ok, let me check out your fork. So, this is working for you in your production code? -Whit On Mon, Jul 16, 2012 at 9:03 PM, jhjourdan
|
It's hard to say whether it's working on my production code, given that Anyway, what I can say is that it does compile and it does not seem to By the way, I have a comment : I removed the MCMCSpecialized class, as JH Le 16/07/2012 18:36, Whit Armstrong a écrit :
|
I have a problem with the way the track and dxxxx functions take their
arguments. Let's take the following example (it uses the same idioms as
CppBugds examples):
MCModelboost::minstd_rand m(model);
m.track(lambda).dgamma(0.1, 0.1);
The dgamma function takes its arguments by reference and do not store a
copy of its arguments. Moreover, 0.1 is stored in a temporary before being
passed to dgamma. Thus, the compiler is allowed to deallocate the memory
used for this temporary just after the call, and use it for something
else. However, this value will be used afterward during the sampling. So,
we have a problem, because the value used during the sampling can be
different.
For some reason, it seems like this problem actually happens only for gcc
I have different ideas for solving this problem. None of them are
perfect. Please give me your thoughts about them:
1- Ask the user code not to pass temporaries to these functions. This makes
the user code heavier, but there is not change of the library code.
The client code would be:
double zeropointone = 0.1;
m.track(lambda).dgamma(zeropointone, zeropointone);
2- For each of these parameters, give two overloads of the functions. One
will take a pointer to the value, and the other will take the value (not a
reference to it !). The second one first stores the value in a safe place
before calling the first version.
The client code would be:
double zeropointone = 0.1;
m.track(&lambda).dgamma(0.1, 0.1);
Pros: flexibility for the user
Cons: no backward compatibility, somewhat less clean user code (and the
user has not to forget to put the &).
3- Idem as 2-, but with const references in place of pointers. That is, the
copy will take place only when the given expression is either an rvalue or
a const variable. The typical client code would not change:
m.track(lambda).dgamma(0.1, 0.1);
Pro: backward compatibility, basic user code more intuitive.
Cons: even if it seems to be a good criterion for most cases in practice,
there is no good reason for using constness for this purpose. In
particular, the non-copying versions of the dxxx functions will have
non-const parameter but const behaviour.
3bis- Idem as 3, but using rvalue references in place of const references
Pro: backward compatibility, basic user code more intuitive
Cons: using rvalue-references which are a new feature of C++11 that nobody
really understand in details...
Thanks !
Jacques-Henri Jourdan
The text was updated successfully, but these errors were encountered: