[cpp-threads] Belated comments on dependency-based ordering proposal
Lawrence Crowl
Lawrence at Crowl.org
Sat Sep 15 02:04:54 BST 2007
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.
> 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.
> 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.
--
Lawrence Crowl
More information about the cpp-threads
mailing list