On Fri, Aug 24, 2012 at 9:56 PM, Andy Gibbs <span dir="ltr"><<a href="mailto:andyg1001@hotmail.co.uk" target="_blank">andyg1001@hotmail.co.uk</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im">On Saturday, August 25, 2012 3:51 AM, Richard Smith wrote:<br>
> Hi Andy,<br>
><br>
> Editorializing somewhat, I think it's unfortunate that people expect<br>
> constexpr evaluation to be asymptotically more efficient than the runtime<br>
> evaluation of the same functions, and I'm a little concerned that this<br>
> caching will lead people to write code which has surprising poor<br>
> performance in the cases where a constexpr function gets invoked<br>
> dynamically. But... g++ already implements a similar optimization, so<br>
> we'll probably need this to handle code written for it.<br>
<br>
</div>Oh dear, I'm one of those unfortunate people then :o)<br>
<br>
But (as always) I have a use-case: 5 MB of compile-time evaluated lookup<br>
tables for modelling physical systems. Yes, these could be evaluated via<br>
a separate program to generate the lookup tables, but like you say, gcc<br>
supports this optimisation. And you're right: hugh performance penalty if<br>
these functions are ever called at run-time (but there would be anyway,<br>
hence wanting to do it at compile time)</blockquote><div><br></div><div>Well, my point was, the run-time performance penalty could be *much* worse than the compile-time penalty, since you don't get the caching behavior there. But I have sympathy for your use case: constexpr does not make it easy for you to cache and reuse intermediate results yourself.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">> Have you measured the impact of this cache on "well-written" constexpr<br>
> functions (those not requiring memoization for efficiency)? What's the<br>
> memory usage and performance impact on, say,<br>
> test/SemaCXX/constexpr-turing.cpp, with a more complex Turing machine?<br>
> Can you provide some figures for typical and worst-case slowdowns?<br>
<br>
</div>I did do some "informal" testing back when I first worked on this patch,<br>
but I'll have to do it again so that you have more formal numbers.<br>
<br>
>From memory, though, yes you have the memory impact (obviously can't<br>
avoid this), but the speed of compilation is generally not affected, and<br>
in fact, in some of my testing was actually improved (even on the "well<br>
written" case) since clang does two evaluations on each constexpr<br>
function: first to check whether it can be constexpr and then its actual<br>
use: with this patch some of these cases are only evaluated once since<br>
the first evaluation is cached.<br>
<br>
I have a suggestion though: how about a "cache_constexpr" function<br>
attribute: then the user can attach this attribute where the feature is<br>
required and not where it isn't -- then the "well-written" code need<br>
never change its compile-time characteristics. (If this were done,<br>
though, would it be possible somehow to halt evaluation of a constexpr<br>
function when it had taken more than, say, 10 minutes and produce a<br>
diagnostic suggesting use of the attribute -- or to consider again the<br>
algorithm used?! crazy suggestion, yes?)<br>
<div class="im"><br>
> There is a nasty corner case where the value of a global changes between<br>
> successive calls to a constexpr function (this happens if a variable is<br>
> read after it's zero-initialized but before it's dynamically initialized,<br>
> from a constexpr function called within its own initializer). Your patch<br>
> doesn't seem to handle that (though perhaps I just missed it).<br>
<br>
</div>No, you're right, I don't think I do handle it. I was under the obviously<br>
mistaken impression that constexpr functions were, by their very nature,<br>
guaranteed to return the same value whenever invoked (assuming the same<br>
arguments) -- I had understood that this had to be ensured in order to<br>
determine that it was "safe" to evaluate at compile-time rather than at<br>
run-time.<br>
<br>
Could you give me some example code for your "nasty corner case", and I'll<br>
fix my code. Thanks.<br></blockquote><div><br></div><div>extern const int n;</div><div>constexpr int get() { return n; }</div><div>constexpr int n = get() + 1;</div><div>constexpr int m = get();</div><div>static_assert(m == n, "");</div>
</div>