Chapel: User-facing mechanisms for localizing remote class instances

Created on 18 Jul 2018  路  6Comments  路  Source: chapel-lang/chapel

Related #10275.

I want to make cheap copies/references to instance variables from parallel contexts.

It makes sense why there are remote gets on each reference because instance variables can be modified from a different locale. What I've seen, however, is a lot of boilerplate code for creating localized copies of instance variables from 'this' and other classes at the beginning of coforalls, foralls, etc.

// Today
... {
  on loc {
    ...
    const local_a = this.a;
    const local_b = this.b;
    const local_x = obj.x;
    ..
  }
}

A user would want a better approach, perhaps something like (syntax is up for debate):

... {
  on loc {
    ...
    var my_this = copy(this);
    var my_obj = copy(obj);
    ..
  }
}

Another idea is to supply an intent in the with-clause that can create a similar effect.

Language Feature Request user issue

Most helpful comment

I changed the title here to distinguish between localization (which I think of as "get a local copy of this thing") and privatization (which we generally use to mean "give every locale a copy of this thing"), since here the emphasis seems to be on a single locale / on-clause.

I understand the desire to potentially have language and/or compiler support for creating local copies of objects, but just wanted to point out that nothing prevents a user from writing a slight variation on what Bryant asked for today, if they add a copy() method to any classes on which they'd like to enable localization:

... {
  on loc {
    ...
    var my_this = this.copy();
    var my_obj = obj.copy();
    ..
  }
}

Note that in our code, we sometimes only localize certain fields, as in:

// Today
... {
  on loc {
    ...
    const local_a = this.a;
    const local_b = this.b;
    const local_x = obj.x;
    ..
  }
}

because we only want a few fields, not all of them (i.e., serializing and copying the whole object would be overkill).

This also touches on open questions related to cross-locale serialization of records, discussed in part in issue #7115. As noted in a comment I made on Louis's issue #9717, I tend to think that there's a relationship between serialization of records (if not classes), this localization of classes request, and the desire to make privatization more user-facing (issues #6393 and #10275).

All 6 comments

Relevant issue: #9936

Combining the ability to declare with clauses on on statements, what if declaring the intent of a class as in performed that copy you mentioned?

... {
  on loc with (in this, in obj) {
    ...
    // No additional code needed
    ..
  }
}

Perhaps specifying intent as inout would update the original copy with those changes as well.

I changed the title here to distinguish between localization (which I think of as "get a local copy of this thing") and privatization (which we generally use to mean "give every locale a copy of this thing"), since here the emphasis seems to be on a single locale / on-clause.

I understand the desire to potentially have language and/or compiler support for creating local copies of objects, but just wanted to point out that nothing prevents a user from writing a slight variation on what Bryant asked for today, if they add a copy() method to any classes on which they'd like to enable localization:

... {
  on loc {
    ...
    var my_this = this.copy();
    var my_obj = obj.copy();
    ..
  }
}

Note that in our code, we sometimes only localize certain fields, as in:

// Today
... {
  on loc {
    ...
    const local_a = this.a;
    const local_b = this.b;
    const local_x = obj.x;
    ..
  }
}

because we only want a few fields, not all of them (i.e., serializing and copying the whole object would be overkill).

This also touches on open questions related to cross-locale serialization of records, discussed in part in issue #7115. As noted in a comment I made on Louis's issue #9717, I tend to think that there's a relationship between serialization of records (if not classes), this localization of classes request, and the desire to make privatization more user-facing (issues #6393 and #10275).

Thinking out loud a bit more on this one and tagging @benharsh with whom I was discussing similar ideas today (and @mppf since he's worked on / thought about serialization in the past):

Assuming that PR #10643 is merged as expected, I believe that without compiler or language changes, we could create a generic localizeMe(t) record that could be used to cause a class (or other variable) to be automatically localized across any and all on-clauses in the following way:

  • the record is declared to "always RVF", guaranteeing that it'll be copied across on-clauses
  • the record could implement the serialization interface (#7115) where its implementation would essentially forward those serialization/deserialization calls the class/variable it wraps. Any type that implemented the expected serialization interface would qualify.
  • the record would forward any/all other methods to the wrapped variable (I suppose it could just rely on the forwarding to do the serialization as well?)

A use of the record might look something like this:

... {
  var obj = new localizeMe(new C());  // create a new self-localizing variable of arbitrary type (`C` here)
  on loc {   // the localizeMe will automatically be rvf'd and serialized/deserialized across here
    ...
    ...obj...;  // so this would refer to the localized copy of `obj`
    ...
  }
}

Would implementing such a record be as simple as:

```chapel
pragma "always RVF"
record localizeMe {
forwarding var x;
}

??

That's a not bad idea and definitely a step in the right direction. I can see it coming in handy if the user has a long sequence of updates or uses it in multiple on statements... but I'd say that its usefulness is limited and it can feel like just an additional step if the user just wants to localize a class instance in a one-off situation.

Three quick thoughts:

1) As argued above, I think the user _already_ has the ability in Chapel to localize a class instance in a one-off situation as you're requesting by (a) implementing a .localizeMe() method on the class that creates a new object and copies the old one over to it and then (b) calling that method. It could even look exactly as Bryant sketched by defining the wrapper routine:

proc copy(x) {
  return x.localizeMe();
}

I think this issue could arguably be closed given a proof-of-concept implementation of this (I realize it's not what _you_ want鈥攚hich is to say, intents on on-clauses鈥攂ut that's a different issue's request, not this one's).

2) The downside of the approach in point 1 is that it's likely that a user implementation of localizeMe() would likely do fine-grain field-by-field copies; whereas the approach I'm proposing in my previous comment would use the serialization interface which results in buffering of the fields (and any fields that they might point to as well) before communicating them. It might be the case that a savvy user would/could use the serialization interface in their implementation of localizeMe(), but I'm not certain.

3) You wrote:

its usefulness is limited and it can feel like just an additional step if the user just wants to localize a class instance in a one-off situation.

For cases I'm thinking of, I think its the opposite. If there's a type/value that I want to localize, I think I probably want to do it every time I cross locales, not just occasionally, and to pay the overhead of saying it once (at the object's declaration point) not every time I cross a new on-clause (which both Bryant's proposal and your proposal would require). If I don't want it to cross an on-clause, I could presumably always take the guts out of the record (localizeMe.x) and work with that instead.

And a bonus thought:

*) The downside of the proposal to support this case via a with (in myClass) intent on an on-clause is that an in intent on a class variable says to copy the pointer/reference to the class object into the scope in question, not the object (its fields) itself. So I don't think this approach would yield the desired behavior without creating a new intent (e.g., with (serialize in myClass)). But we already get criticized for having way too many intents, so this feels like more of a last resort to me.

I see, I see. I forgot that the serialization interface reduces a majority of the communication you would normally see from copying remotely. localizeMe definitely would be more efficient in the long-term, and definitely a viable solution to the problem, although part of me wants to go with changing with (in myClass) to perform this localization for the user, but I know better than to argue a language change at this point.

Was this page helpful?
0 / 5 - 0 ratings