chapel-lang / chapel

a Productive Parallel Programming Language
https://chapel-lang.org
Other
1.79k stars 420 forks source link

chpl__initCopy or init= invocable concurrently? #13293

Open vasslitvinov opened 5 years ago

vasslitvinov commented 5 years ago

In the following code:

proc myProc(in arg) {...}
var myVar...;
coforall ... {
  myProc(myVar);
}

the compiler may insert formal temps at callsite, for example when myVar:string, turning it into:

proc myProc(ref arg) {...}
var myVar...;
coforall ... with (const ref myVar) {
  _formal_tmp_myVar = chpl_initCopy(myVar);
  myProc(_formal_tmp_myVar);
}

What if initCopy modifies its argument, or modifies something through a ref from its argument, such as a ref counter, without locking, getting us in trouble?

Does this happen when myVar is an owned or shared ?

The coforall example above could be thought of as the user's fault, ex. because they want to transfer the ownership of the same thing in multiple concurrent tasks. However...

What if the coforall is part of the leader iterator, and the in-intent formal is in the follower iterator? Since the leader may invoke several followers concurrently, the above scenario can arise. Also, the current implementation does not handle this case at all.

In either case, the user should not bear responsibility for this. This may be a subtle data race, resulting in silent incorrect answers. So the ideal solution is to avoid data race altogether.

vasslitvinov commented 5 years ago

@benharsh @mppf how much are you concerned about the above?

benharsh commented 5 years ago

Couldn't this also happen with parallel array initialization and initializers that modify a shared thing?

The only way I can think to handle this would be for the compiler to examine compiler-invoked methods like this and issue warnings for non-parallel-safe operations. That would probably be difficult.

Have you encountered this somewhere, or are you just pointing out a potential problem?

vasslitvinov commented 5 years ago

Have you encountered this somewhere, or are you just pointing out a potential problem?

I discovered that we hit this in the context of follower iterators (now described in the main text of this issue) while testing my fix-in-progress for #13169. This results in odd semantics for arrays and domains and memory management violation for strings - even without concurrency, merely when the leader yields 2 or more times.

If the record G in the example in #13169 is POD, then this problem is potential, because initCopy is par-safe. Otherwise the problem is real-life and still open.

mppf commented 5 years ago

What if initCopy modifies its argument, or modifies something through a ref from its argument, such as a ref counter, without locking, getting us in trouble?

Does this happen when myVar is an owned or shared ?

shared should atomically update the reference counters.

I would expect that whatever the pattern you might be trying to implement with owned would be invalid always.