-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add several op mapping in PyTorch frontend #6472
Conversation
So we simply ignore "inplace-ness" of cc @t-vi I remember we had discussion of |
@masahi we found Have added a test cases
related graph:
|
yeah, that is also what happens with other inplace ops. TorchScript graph has distinct input/output tensors for each op, even though for inplace op output and one of input tensors point to the same memory. |
I see. Interesting, it is more like a TorchScript issue then |
Note that maskrcnn-benchmark isn't necessarily intended to be scripted, the worthwhile things have been incorporated into torchvision and improved there. The trouble with in-place operators is that their semantics are not functional (i.e. they modify their inputs) and thus cannot be mapped to TVM. For example that when operated on views (e.g. slices of a tensor, things that come from What you would need to do is to preprocess the graph to remove these side-effects - for example if you can exclude that the input to The last discussion we had on this was #6049 . |
Seems PyTorch already has a set of passes to remove mutation. For example, this pass looks like it removes inplace ops. https://github.com/pytorch/pytorch/blob/61623430d32c081124067fc4abf33bd4a023af90/torch/csrc/jit/passes/remove_inplace_ops.cpp#L35 Would be interesting to run |
8d535ba
to
fc672f9
Compare
the graph is still the same as before |
fc672f9
to
03bbd3c
Compare
Note fat warning at the top of the class, though. A typical use of copy is something like this:
|
Yeah, this pass only supports a very small subset of inplace ops, see It does seem though that their onnx export use inplace op removal (using a different pass than the one above) before they emit onnx. |
b474523
to
df27ece
Compare
just tested with a similar test case as the one you provided, the slicing assignment doesn't take effect in jit graph.
related graph:
|
@yongwww what does "the slicing assignment doesn't take effect in jit" mean? The JITed function does update Which thing in maskrcnn-benchmark produces the |
@t-vi I see, thanks for pointing the select out, yeah, for your case, the jit graph is okay and works fine with PyTorch. But seems tvm doesn't support this case without real in-place operation. For a reference, we can see the slicing stuff here https://github.com/facebookresearch/maskrcnn-benchmark/blob/4ac0a3b440320ff0d0159a280f2897d1f9f996f3/maskrcnn_benchmark/modeling/box_coder.py#L85-L93 |
@masahi @t-vi @zhiics @kevinthesun For test case @t-vi provided, the in-place copy is required, and the implementation in this pr doesn't work for that. I would suggest adding a warning and todo in this mapping since some other merged in-place op mapping should has the similar issues, don't have a quick solution for this in my mind at this point. Any suggestion? |
@yongwww to be clear, this translation works for box_coder from maskrcnn-benchmark you mentioned above? https://github.com/facebookresearch/maskrcnn-benchmark/blob/4ac0a3b440320ff0d0159a280f2897d1f9f996f3/maskrcnn_benchmark/modeling/box_coder.py#L85-L93 That looks similar to the test case @t-vi provided. By "work", of course I mean we get the same output as pytorch would.
I'm ok with this, if we can somehow detect inplace op patterns that we cannot support, we should immediately abort, rather than giving a warning and emitting a wrong relay graph. |
@masahi the copy_ mapping in this pr doesn't work for the code snippet in the box_coder I pointed, similar to that @t-vi provided, slicing assignment doesn't take effect. After modifying the model definition script, we get |
@masahi Just checked the op list under torch.Tensor, there are a bunch of inplace ops there, seems the op with suffix |
Yes, that is also my understanding. Removing and not supporting |
Yeah, any op ending in Without keeping track of memory locations some construct to represent So without a pure way, we have to balance the two
This appears also to be the rationale for the ad-hoc inplace removal for ONNX export, and I'm sure the PyTorch-ONNX people had a good think (and they have more alias analysis available to them) if there are better options. So I guess whatever they let go through by just assuming inplace can be made out-of-place might also be desirable to treat this way here. Maybe the list they use is a good guide. I would imagine that someone somewhere does things like
(so the nonzero bits would be normally distributed for normally distributed inputs to be clever about exploding/vanishing activations), but I don't think it's terribly popular, so I would not worry about it. For maskrcnn-benchmark in particular, I did a bit of tracing almost two years ago when I experimented with my PyTorch POC port to Android (but the tracing PR was never merged) and should be easy to remove their inplace use. But it would seem that it's more useful to focus on the TorchVision implementations, maskrcnn-benchmark is really dormant and my impression was that it itself wasn't fixed much but instead the lessons learned from there have flown into TorchVision and people have worked on JIT/ONNX/Quantization properties there. |
@masahi @t-vi seems the translation for every inplace op has similar issue as copy_, considering the translation works for some cases (those w/o real inplace), I would like to still keep copy_ and clamp_ in this pr, and add warning for all implace op. How do you think? getting more model supported is the first step for us, if overall inference result is not correct, then one of the first things is to look at the implace op mapping warning, does this make sense to you? or do I need to remove |
Is there a valid usage of |
For example, the copy_ translation works for the test cases I provided in test_forward.py. But the case from t_vi is more common for which the translation doesn't work. |
I mean, what kind of real world PyTorch code ends up generating |
I won't write model using |
Yes, I think we can keep |
makes sense to me. Thanks, will do that. |
I also want to take some time studying how PyTorch ONNX export handles inplace ops, and whether we can reuse some of their passes. |
df27ece
to
9a77478
Compare
* Add copy_ and clamp_ in PyTorch frontend * add true_divide in PyTorch frontend * more test cases for copy_ * fix format * remove copy_ * fix format * skip true_divide for torch < 1.5
* Add copy_ and clamp_ in PyTorch frontend * add true_divide in PyTorch frontend * more test cases for copy_ * fix format * remove copy_ * fix format * skip true_divide for torch < 1.5
@kevinthesun @zhiics @masahi pls help take a look