KEMBAR78
[jit] fix side-effects and aliasing for custom ops by suo · Pull Request #18711 · pytorch/pytorch · GitHub
Skip to content

Conversation

@suo
Copy link
Member

@suo suo commented Apr 2, 2019

Stack from ghstack:

Previously we didn't track aliasing, mutation, or side effects for
custom ops. This PR adds in guards with the most conservative
assumptions possible: the op will

  1. have side effects,
  2. write to everything
  3. produce a wildcard.

In order to tell whether a given operator is a custom op, this PR introduces
the concept of a "reserved" namespace (basically all our builtin namespaces).
Custom ops live in non-reserved namespaces, so a check on the namespace
is sufficient to tell whether a schema/node is "custom" or not.

This is just to get things correct for now. Follow-ups to this:

  • Users should be able to specify aliasing/mutability without having to learn
    the whole alias annotation schema.
  • Relax assumptions a bit. In particular outputs can only alias input tensors,
    they don't have to be wildcards.

Fixes #18490

Differential Revision: D14730978

Previously we didn't track aliasing, mutation, or side effects for
custom ops. This PR adds in guards with the most conservative
assumptions possible: the op will 1) have side effects, 2) write to
everything, and 3) produce a wildcard. We can reign in those
restrictions later, but want to get something correct for now.

It's a little weird because we have no way of knowing whether a given
node represents a custom op--I added it to the schema but I'm open to
suggestions for a better place.

Follow-ups to this:
- Users should be able to specify aliasing annotations/side effects to
get better perf somehow.
- Relax assumptions a bit.
@facebook-github-bot facebook-github-bot added the oncall: jit Add this issue/PR to JIT oncall triage queue label Apr 2, 2019
@suo suo requested review from eellison and zdevito April 2, 2019 00:40
Copy link
Contributor

@eellison eellison left a comment

Choose a reason for hiding this comment

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

Have a few comments but is just about ready I think

@suo
Copy link
Member Author

suo commented Apr 2, 2019

Okay, comments are addressed. This is only a short term fix to get things to be correct—I think in the long run, we should just use the options that #18589 introduces.

Copy link
Contributor

@eellison eellison 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!

const auto& aliasInfo = arg.alias_info();
return aliasInfo && aliasInfo.value().isWrite();
});
return is_inferred_from_custom_op_ ||
Copy link
Contributor

Choose a reason for hiding this comment

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

So to be clear we are saying that it is mutable even if it doesn't have any inputs, add comment maybe ?

@apaszke
Copy link
Contributor

apaszke commented Apr 2, 2019

Can we just assume that aten::/prim::/... namespaces are not custom, everything else is?

@suo
Copy link
Member Author

suo commented Apr 2, 2019

Can we just assume that aten::/prim::/... namespaces are not custom, everything else is?

That's an interesting idea…I don't think namespaces are restricted right now for custom ops, but it's easy to add. And we already have this distinction when emitting builtins.

@apaszke
Copy link
Contributor

apaszke commented Apr 2, 2019

Yeah, we could expose a special subclass of RegisterOperator to the users (still aliased to RegisterOperator), which disallows registering ops under those namespaces.

@eellison
Copy link
Contributor

eellison commented Apr 2, 2019

Can we just assume that aten::/prim::/... namespaces are not custom, everything else is?

This would require changing some of our tests which use the test namespace (probably among others) and in general I think would be hard to maintain

@suo
Copy link
Member Author

suo commented Apr 2, 2019

@eellison I think the idea is to designate "reserved" namespaces that users can't define custom ops in. I think this is good idea anyway (right now I think you could create an aten op that would participate in builtin schema resolution). Conveniently, we can also use the fact that a op has a non-reserved namespace to denote whether it's custom or not

Copy link
Contributor

@eellison eellison left a comment

Choose a reason for hiding this comment

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

Different implementation, have to re-review

@eellison eellison dismissed their stale review April 2, 2019 20:04

just trying to undo accept

}
{
RegisterOperators reg(
{createOperator("foo::no_input", []() -> double { return 4.0; })});
Copy link
Member Author

Choose a reason for hiding this comment

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

this test causes windows build to fail

@eellison
Copy link
Contributor

eellison commented Apr 2, 2019

I think the most recent commit will make it harder to move forward to a future api where users declare ops as functional, because we will have ops that are in user space which we do want to assume mutate the inputs.

Operators in c10/caffe2/TVM will also no longer be able to create an operator with specified aliasing, because the namespace will override any information that has been given.

@suo
Copy link
Member Author

suo commented Apr 2, 2019

Right now there is no way (short of writing alias annotations manually) for the user to specify the purity of their custom op, so we need to insert guards to make sure things are correct. I expect that when we give users the ability to specify purity, the guards will have to change.

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.

Code seems bug free, but see inline comments. I strongly suggest we switch this to whitelist aten and prim rather than special-case all primitive ops.

return aliasInfo && aliasInfo.value().isWrite();
});
}
bool is_custom_op() const {
Copy link
Contributor

Choose a reason for hiding this comment

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

For this PR, I think it would be safer to white-list prim and aten into the stronger alias behavior. I do not like the idea of making a publically-exposed distinction between custom ops and our ops, even for just a few commits.

// Does this symbol live in one of the above built-in namespaces?
// If not, that means that this symbol came from the user, through the
// defintiion of a custom operator.
bool is_builtin_ns() const;
Copy link
Contributor

Choose a reason for hiding this comment

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

Please do not commit this. I do not want to have people be able to easily special case stuff for built in ops. This will create huge long-term tech debt even if commit for a little while.

std::tuple_size<ArgumentTuple>::value;

auto schema = torch::jit::detail::inferAndCheckSchema<Traits>(schemaOrName);
Symbol name = Symbol::fromQualString(schema.name());
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't like this. I want to move our operator registration over to this API and this guard will prevent it. This will need to be removed in the future commit.

case prim::TimePoint:
return true;
}
// Custom ops may have arbitrary side effects
Copy link
Contributor

Choose a reason for hiding this comment

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

if (kind.is_aten() || kind.is_print())
 return false

@suo suo requested a review from zdevito April 4, 2019 22:17
[jit] fix side-effects and aliasing for custom ops

Previously we didn't track aliasing, mutation, or side effects for
custom ops. This PR adds in guards with the most conservative
assumptions possible: the op will 1) have side effects, 2) write to
everything, and 3) produce a wildcard. We can reign in those
restrictions later, but want to get something correct for now.

It's a little weird because we have no way of knowing whether a given
node represents a custom op--I added it to the schema but I'm open to
suggestions for a better place.

Follow-ups to this:
- Users should be able to specify aliasing annotations/side effects to
get better perf somehow.
- Relax assumptions a bit.

gh-metadata: pytorch pytorch 18711 gh/suo/15/head
[jit] fix side-effects and aliasing for custom ops

Previously we didn't track aliasing, mutation, or side effects for
custom ops. This PR adds in guards with the most conservative
assumptions possible: the op will 1) have side effects, 2) write to
everything, and 3) produce a wildcard. We can reign in those
restrictions later, but want to get something correct for now.

It's a little weird because we have no way of knowing whether a given
node represents a custom op--I added it to the schema but I'm open to
suggestions for a better place.

Follow-ups to this:
- Users should be able to specify aliasing annotations/side effects to
get better perf somehow.
- Relax assumptions a bit.

gh-metadata: pytorch pytorch 18711 gh/suo/15/head
zdevito pushed a commit to zdevito/ATen that referenced this pull request Apr 5, 2019
Summary:
Pull Request resolved: pytorch/pytorch#18711
ghimport-source-id: c9caedc0660b2b7ba3730cd0e1a2e0e9c3cf422b

Stack from [ghstack](https://github.com/ezyang/ghstack):
* **#18711 [jit] fix side-effects and aliasing for custom ops**

Previously we didn't track aliasing, mutation, or side effects for
custom ops. This PR adds in guards with the most conservative
assumptions possible: the op will
1) have side effects,
2) write to everything
3) produce a wildcard.

In order to tell whether a given operator is a custom op, this PR introduces
the concept of a "reserved" namespace (basically all our builtin namespaces).
Custom ops live in non-reserved namespaces, so a check on the namespace
is sufficient to tell whether a schema/node is "custom" or not.

This is just to get things correct for now. Follow-ups to this:
- Users should be able to specify aliasing/mutability without having to learn
the whole alias annotation schema.
- Relax assumptions a bit. In particular outputs can only alias input tensors,
they don't have to be wildcards.

Fixes #18490

Differential Revision: D14730978

fbshipit-source-id: 540b47a24ccf24145051609bdcc99c97e46e0fe0
@facebook-github-bot
Copy link
Contributor

This pull request has been merged in fefa6d3.

facebook-github-bot pushed a commit that referenced this pull request Apr 5, 2019
Summary:
Pull Request resolved: #18712
ghimport-source-id: e435150

Stack from [ghstack](https://github.com/ezyang/ghstack):
* **#18712 [jit][easy] remove unused func**
* #18711 [jit] fix side-effects and aliasing for custom ops

as title

Differential Revision: D14730979

fbshipit-source-id: 381d16ea2a45779bf6d5fc6d90a4f8585461e902
@suo suo deleted the gh/suo/15/head branch April 6, 2019 07:50
zhangguanheng66 pushed a commit to zhangguanheng66/pytorch that referenced this pull request May 6, 2019
Summary:
Pull Request resolved: pytorch#18711
ghimport-source-id: c9caedc

Stack from [ghstack](https://github.com/ezyang/ghstack):
* **pytorch#18711 [jit] fix side-effects and aliasing for custom ops**

Previously we didn't track aliasing, mutation, or side effects for
custom ops. This PR adds in guards with the most conservative
assumptions possible: the op will
1) have side effects,
2) write to everything
3) produce a wildcard.

In order to tell whether a given operator is a custom op, this PR introduces
the concept of a "reserved" namespace (basically all our builtin namespaces).
Custom ops live in non-reserved namespaces, so a check on the namespace
is sufficient to tell whether a schema/node is "custom" or not.

This is just to get things correct for now. Follow-ups to this:
- Users should be able to specify aliasing/mutability without having to learn
the whole alias annotation schema.
- Relax assumptions a bit. In particular outputs can only alias input tensors,
they don't have to be wildcards.

Fixes pytorch#18490

Differential Revision: D14730978

fbshipit-source-id: 540b47a24ccf24145051609bdcc99c97e46e0fe0
zhangguanheng66 pushed a commit to zhangguanheng66/pytorch that referenced this pull request May 6, 2019
Summary:
Pull Request resolved: pytorch#18712
ghimport-source-id: e435150

Stack from [ghstack](https://github.com/ezyang/ghstack):
* **pytorch#18712 [jit][easy] remove unused func**
* pytorch#18711 [jit] fix side-effects and aliasing for custom ops

as title

Differential Revision: D14730979

fbshipit-source-id: 381d16ea2a45779bf6d5fc6d90a4f8585461e902
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.

5 participants