Hi Nikhil --
There are a few things going on here:
The main one is "task intents" which were introduced in version 1.8 of
Chapel and refined since then. That semantic change caused outer-scope
variables to be "passed" into tasks by some default intent based on their
type (much as different types are passed to functions differently). As
you correctly surmise, this was done to avoid simple races while not
introducing overly-expensive copies for potentially large data types.
So integers like 'x' have a 'const in' task intent by default which means
that the task gets a local copy of the variable, and it's considered
'const' to help the user who might try to assign to it realize that it's
not their original variable 'x'. These default intents can be overridden
so that if you wanted to refer back to the original 'x', you could say
'with (ref x)' after your coforall.
For records like R, we've had debates about whether the default intent
should be 'const ref' or 'const in', and I believe that the current plan
of record is that it should be 'const ref', but I think it may be that the
implementation doesn't match this and uses 'const in'. Others on the team
may be able to give a more accurate description of the current status quo
here.
Note that all of the above is independent of locales coming into play or
not. For those that aren't familiar with task intents, they're described
in the language spec; or more helpfully, the language evolution document
describes their introduction into the language:
http://chapel.cray.com/docs/latest/language/evolution.html#version-1-8-october-2013
http://chapel.cray.com/docs/latest/language/evolution.html#task-intents-syntax
A second factor is that the Chapel compiler uses a "remote value
forwarding" optimization to create local copies of variables on remote
locales when it encounters on-clause when it determins it is legal to do
so. Cases where it is legal include things like:
* consts: always safe to remote-value forward
* variables: safe to remote-value forward if the on-clause doesn't
write the variable, and if the memory consistency model permits it
(e.g., memory fences, or language constructs that imply them, like
syncs and atomics, could disable remote value forwarding).
There's been a longstanding open question about whether, if a .locale
query is applied to a variable that could be remote-value forwarded, it
should disable remote-value forwarding for that variable, reflect the
locale of the local copy of the variable, or reflect the original location
of the variable. And off the top of my head, I can't recall which of
these is true in the implementation today. One could eliminate this
question mark from the equation by throwing --no-remote-value-forwarding
when compiling their program (though note that, in production codes,
you'll typically want remote-value forwarding to fire for performance
reasons).
Incidentally, I'd be curious to hear if you (or anyone reading this far)
had an opinion about the relationship between remote-value forwarding and
.locale queries.
A third, and most worrisome, factor is that a team member showed me an
example this week where a .locale query seemed to be returning an
incorrect value independent of remote-value forwarding which suggested
that there are cases where we're making copies for on-clauses that we
shouldn't be. I couldn't say offhand whether that was coming into play in
your program or not (but others may be able to). I believe that person is
working on a fix for this as a priority because it relates to other issues
that we've wrestled with recently in terms of memory management...
So, of these, the task intents and remote value forwarding are intentional
and good things, but some of the question marks in the implementation may
make the behavior today more surprising than ideal.
Hope this is helpful even though some vaguenesses remain in my
explanation,
-Brad
On Fri, 10 Jun 2016, Nikhil Padmanabhan wrote:
> Hi ---
>
> I'm misunderstanding something about locales -- consider the following
> program :
>
> record R {
> var x : int;
> }
>
> proc main() {
> var r : R;
> var x : int;
> writeln("-----");
> for loc in Locales do on loc {
> writeln('X :',x.locale);
> writeln('R :',r.locale);
> }
> writeln("-----");
> coforall loc in Locales do on loc {
> writeln('X :',x.locale);
> writeln('R :',r.locale);
> }
> }
>
> $ ./a.out -nl 2
> -----
> X :LOCALE0
> R :LOCALE0
> X :LOCALE0
> R :LOCALE0
> -----
> X :LOCALE0
> R :LOCALE0
> X :LOCALE1
> R :LOCALE1
>
> So --- the for and coforall have very different behaviors regarding
> locales, which surprised me. I'm guessing this is because coforall makes a
> copy (to avoid races on X and R) while for doesn't....
>
> Is this behavior intentional?
>
> Thanks!
> -- Nikhil
>
>
>
>
> ---------------------------------
> Nikhil Padmanabhan
> [email protected]
>
------------------------------------------------------------------------------
What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic
patterns at an interface-level. Reveals which users, apps, and protocols are
consuming the most bandwidth. Provides multi-vendor support for NetFlow,
J-Flow, sFlow and other flows. Make informed decisions using capacity
planning reports. https://ad.doubleclick.net/ddm/clk/305295220;132659582;e
_______________________________________________
Chapel-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-users