[cpp-threads] Belated comments on dependency-based ordering proposal

Hans Boehm Hans.Boehm at hp.com
Sat Sep 15 05:02:24 BST 2007


On Fri, 14 Sep 2007, Lawrence Crowl wrote:

> On 9/14/07, Boehm, Hans <hans.boehm at hp.com> wrote:
>> Consider example 2:
>>
>> atomic<int> x;
>> vector<int> v;
>>
>> void f() {
>>         int i = x.load(memory_order_dependency);
>>         int j = v[i];
>>         ...
>> }
>>
>> I don't think we can reasonably annotate the standard vector class.
>> Thus I don't know how to enforce the dependency ordering here, since
>> operator[] is elsewhere and not annotated.  If you don't enforce
>> ordering here, it seems to me the code becomes brittle in that if you
>> change a C array to a C++ library one, things are allowed to break.
>
> What do you mean by break?  As I understand the proposal, all that
> happens is that the dependency ordering gets strengthened to acquire
> ordering before the call.  Even in the case that strengthening happens,
> there is still a potential performance advantage in less visited paths.
>
>    int i = x.load( memory_order_dependency );
>    if ( i > 0 )
>        int j = v[i];
>
> becomes (internally to the compiler)
>
>    int i = x.load( memory_order_dependency );
>    if ( i > 0 ) {
>        x.fence( memory_order_acquire );
>        int j = v[i];
>    }
>
> when v[i] is an unannotated function call.  If x is usually zero, you
> avoid the acquire cost.
You're describing what I thought we were going to do.  But N2360
states:

"Next, we define "dependency tree" (or, perhaps more accurately, attempt 
to do so):

An evaluation H that performs a dependency operation on an object M heads 
a dependency tree, and is also a member of that dependency tree. Any 
subsequent evaluation that consumes the result of a prior evaluation that 
is a member of H's dependency tree is also a member of H's dependency 
tree, unless that prior evaluation is an unannotated formal parameter or 
is a return value from a function whose function prototype specifies an 
unannotated return value. [Note: dependency annotations are described in 
N2361.] [Note: a given evaluation can be a member of multiple dependency 
trees.]"

I read this is saying that dependencies don't flow into unannotated
function calls.  Perhaps Paul can explain the intent?

> >> I thought we had tentatively concluded in Toronto that all 
"data
>> dependent" loads occurring as a result of the execution of f() should be
>> in the dependency tree anyway, no matter whether they occurred as a
>> result of a nested function call or not.  If the value flows into a
>> separately compiled function, the compiler has to back off and treat
>> memory_order_dependency as memory_order_acquire.  This may add
>> unexpected overhead in some cases.  But examples like the above will be
>> guaranteed to work as expected.
>>
>> But I think this also isn't reflected here?
>>
>> My guess is that the N2360 approach (if I understood it correctly) might
>> be viable for C, where function calls are obvious in the source.  But
>> too many things in C++ are a function call behind the scenes.  I'm not
>> very comfortable with an approach that treats v[i] differently depending
>> on whether v is a C int[10] or a C++ std::array<int, 10>.
>
> If the std::array index is inlined, the compiler has full knowledge
> of the dependences, and one gets a performance win.  If the index
> is not inlined, the performance drops.  But that is true anyway.  I
> am willing to live with a bit of performance uncertainty in C++
> codes, in part because we already have it.  More importantly, I
> think, is that programmers are unlikely to go to dependence-based
> ordering without serious experimental evidence and lots of other
> tuning, which may very well include careful management of the
> inlining process.
Again, I thought that was the plan, but I don't read the current proposal
that way.

>
>> I think we'll encounter many more problems along these lines,
>> e.g also with loads in destructors.
>
> Can you elaborate?
>
>> I suspect we need more work defining what it means to "consume the result
>> of a prior evaluation".  But someone from the C++ standards committee
>> core group will have to help there.
>
> Hm.  The pragmatic meaning is clear, which is that the C++ lowered
> to C uses the value.  The standard definition is probably a bit fuzzier.
There are no doubt borderline cases, especially with library functions.
Does strlen propagate a dependency from one of the characters?
Does a long long comparison depend on all parts of the numbers even
if the high halves are different?

Hans

>
> -- 
> Lawrence Crowl
>
> -- 
> cpp-threads mailing list
> cpp-threads at decadentplace.org.uk
> http://www.decadentplace.org.uk/cgi-bin/mailman/listinfo/cpp-threads
>



More information about the cpp-threads mailing list