Skip to content

[JIT] Change expect, cast on Type to return shared pointers, make isSubtypeOf accept TypePtr#9786

Closed
wanchaol wants to merge 2 commits intopytorch:masterfrom
wanchaol:cleantype
Closed

[JIT] Change expect, cast on Type to return shared pointers, make isSubtypeOf accept TypePtr#9786
wanchaol wants to merge 2 commits intopytorch:masterfrom
wanchaol:cleantype

Conversation

@wanchaol
Copy link
Collaborator

@wanchaol wanchaol commented Jul 24, 2018

Follow up task of #9584.

Commit 1:

  • change expect/cast to return shared pointers instead of raw pointer
  • isSubtypeOf accept TypePtr instead. Use x->isSubtypeOf(NumberType::get()) rather than x->isSubtypeOf(*NumberType::get())

Commit 2:

  • to address enable_shared_from_this pitfalls, we make the constructor private and expose the factory method to make sure user can only create it using our factory method.

@wanchaol wanchaol added the oncall: jit Add this issue/PR to JIT oncall triage queue label Jul 24, 2018
Copy link
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wanchaol has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

Copy link
Contributor

@zdevito zdevito left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me.

@wanchaol
Copy link
Collaborator Author

@pytorchbot retest this please

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

Copy link
Contributor

@apaszke apaszke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but I'm not sure if using shared pointers everywhere is a good idea, compared to just using references. There are three issues I see:

  1. Equality can have surprising behavior, because comparing pointers doesn't use the operator== of the underlying types, but only compares their memory location. This is ok in case of singleton types, but definitely not what we want for TensorType. It's very easy to forget about it, and the compiler won't catch this error for us. If we still want to pursue the shared_ptr path, we might want to at least have a custom subclass of it, that overrides the equality semantics.
  2. Every XType::get() is an unnecessary refcount bump/decref, and we do those in plenty of places just to perform type checking.
  3. They are nullable, which is usually not what you want.

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

@zdevito
Copy link
Contributor

zdevito commented Jul 26, 2018

We were already using type pointers before, this is just making their use consistent. There were a bunch of places where you ended up with a derived type but needed the shared pointer again.

In the future, I think it would be better to make types behave like value types (e.g. like at::Tensor or IValue), meaning that equality etc. all just works and we can pass them around as Type objects. But this would be a more invasive change that we can't make while all our other PRs are in flight.

@wanchaol
Copy link
Collaborator Author

@apaszke As of today in JIT, I am seeing everywhere we are using std::make_shared<Type> for Tensor, List and Tuple type, and not using reference. Exposing both raw pointer and shared pointer is not ideal since it will cause undefined behaviors if we don't do it carefully, I think that's the main motivation we want to move to a single shared_pointer semantic. So for the issues:

  1. The only place we are using reference is when we have isSubtypeOf, and before the pr, we need to put * for most of the case like x->isSubtypeOf(*NumberType::get()) , most arguments we used is a typePtr, so it's easy for us to just accept the typePtr instead. I think there's not too much equality concern since even for isSubtypeOf we are using the object to test the equality (which use the operator==) rather than pointer.
  2. I don't think we are singletons for different types, in fact we are creating a new type object and let a new shared pointer point to it whenever we need a type. So the lifetime of the object and the shared pointer is bounded by the usage of XType::get() .
  3. Yes they are nullable but people are using make_shared or type::get() everywhere for different types and they are nullable too.

@wanchaol
Copy link
Collaborator Author

@smessmer Can you review this again? You can just review the second commit where it addressed the enable_shared_from_this pitfall.

Copy link
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wanchaol has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

private:
ListType(TypePtr elem)
: Type(TypeKind::ListType), elem(elem) {}
static const TypeKind Kind = TypeKind::ListType;

This comment was marked as off-topic.

This comment was marked as off-topic.

}
bool isSubtypeOf(const Type& rhs) const override {
return *this == rhs || rhs.kind() == TypeKind::NumberType;
bool isSubtypeOf(const TypePtr rhs) const override {

This comment was marked as off-topic.

@wanchaol wanchaol deleted the cleantype branch July 27, 2018 02:46
jramseyer pushed a commit to jramseyer/pytorch that referenced this pull request Jul 30, 2018
…Of accept TypePtr (pytorch#9786)

Summary:
Follow up task of pytorch#9584.

Commit 1:

- change expect/cast to return shared pointers instead of raw pointer
- isSubtypeOf accept TypePtr instead. Use `x->isSubtypeOf(NumberType::get())` rather than `x->isSubtypeOf(*NumberType::get())`

Commit 2:

- to address enable_shared_from_this pitfalls, we make the constructor private and expose the factory method to make sure user can only create it using our factory method.
Pull Request resolved: pytorch#9786

Reviewed By: zdevito

Differential Revision: D8980441

Pulled By: wanchaol

fbshipit-source-id: e5c923fc57a701014310e77cf29985b43bb25364
goodlux pushed a commit to goodlux/pytorch that referenced this pull request Aug 15, 2018
…Of accept TypePtr (pytorch#9786)

Summary:
Follow up task of pytorch#9584.

Commit 1:

- change expect/cast to return shared pointers instead of raw pointer
- isSubtypeOf accept TypePtr instead. Use `x->isSubtypeOf(NumberType::get())` rather than `x->isSubtypeOf(*NumberType::get())`

Commit 2:

- to address enable_shared_from_this pitfalls, we make the constructor private and expose the factory method to make sure user can only create it using our factory method.
Pull Request resolved: pytorch#9786

Reviewed By: zdevito

Differential Revision: D8980441

Pulled By: wanchaol

fbshipit-source-id: e5c923fc57a701014310e77cf29985b43bb25364
@ezyang ezyang added the merged label Jun 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

oncall: jit Add this issue/PR to JIT oncall triage queue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants