-
Notifications
You must be signed in to change notification settings - Fork 26.3k
Added "same" padding for conv*d #22484
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
Conversation
6764c31 to
5d695a4
Compare
fmassa
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my view, I think we should have 1:1 parity between the functional and the module interface.
This means that we should probably push the "same" handling down to the functional interface, but I'll let the others chime in as well.
|
@fmassa I initially did it this way as it seems that Soumith implied that it should be separate from the functional interface: #3867 (comment) I continued doing it this way because it seemed like there already were differences between the functional and module interfaces. For example, the module interface supports an argument Putting it in the functional interface also requires delving substantially deeper into the darker sides of Pytorch, and it wasn't clear to me where the appropriate location was, nor whether it would break something to have one op actually become 2 ops. |
|
Uhhh are we sure we want this? I remember @Yangqing strongly arguing against adding this option as it's often quite surprising. |
|
@apaszke Do you remember any of the reasons he gave for strongly warning against this? @soumith mentioned that dynamically calculating padding is bad for a "variety of efficiency/serialization reasons", but these concerns don't seem relevant for research users. On the other hand, for research users this is an unnecessary pain point. I've had multiple people complain that this isn't in Pytorch. I'm not convinced that the performance/serialization issues are worth the cost here. |
|
yes, we want this. YQ's concerns were around exported models not being static, and the ONNX export pass needs to error out if the padding info cannot be statically determined (@Chillee you might have to add a test for the ONNX export). At this point, the user need and benefits outweigh not wanting it, and our JIT / production export now can comfortably handle dynamic models (it wasn't true when we last thought about this) |
|
@Chillee I wasn't aware that I'm less sure we want to diverge the functionalities of both the module and functional interfaces, because some things are only possible to be done with the functional interface (for example, when we want to have the weights of a model to be the output of a network). |
|
my main thinking around matching everything in the functional interface was around how much state we can carry to reuse previous calculations. We can carry state across I didn't explore the line of thought around how much state (such as pre-calculating padding values etc.) can be carried across iterations and how much benefits it brings. |
|
@fmassa One issue with putting it in the functional interface is that the semantics around auto-calculating "static padding" become fairly muddled. Currently, we can auto-calculate static padding and have it for free if certain rules are followed (stride=1, (filter-1)*dilation is divisible by 2). It's not clear how we would do this in the functional interface. I think the right place to add this in the functional interface would be in the |
|
Added tests and fixed JIT compatibility. Removed the |
I don't quite get this. The overhead of calculation of if the padding is static or not is negligible wrt the convolution time, so doing this in the functional codepath would not be a problem at all.
Here is an example def _conv2d(...):
# same as conv2d now
def conv2d(...):
is_static, padding = _compute_if_padding_is_static(...)
if is_static:
input = pad(input, padding, etc)
return _conv2d(input, ...)
return _conv2d(input, ...)
I actually think we should instead add support for different paddings on left / right / top / bottom. This would be a generalization of what we currently have. |
|
@fmassa I guess it wasn't clear to me what "static padding" actually meant. If that's still considered static padding, then I'm fine with doing it in the functional interface. Would you be able to provide a pointer to what I should be changing? Also, as a side note, the documentation for It says it supports |
I agree with @soumith 's comment in that ONNX Conv op will support similar semantics as |
|
@Chillee do you want someone else to take on finishing this ? It would be nice to get this in for 1.3 |
|
@eellison I've been busy (and will be busy) until the 23rd, but I should be able to finish it up in the week after that (which should be at least a week before 1.3?). |
|
I think the cut is the 24th actually... although potentially we could cherry-pick this in |
|
Ah alright I'll take a crack tonight at fixing it then. |
|
@ZolotukhinM @jamesr66a @raghuramank100 this PR breaks convolution tests. Do you think it's doable to land this PR before the release and have quant parity with it ? |
|
To clarify a bit more, the tests that break are the ones that look like (the last line specifically). The tests pass as long as I comment that out - it's not clear to me if that's the right thing to do. |
|
@Chillee quantization has a mirror'd I forgot that quantization needed to maintain parity when I commented above about getting it into the release, that's my bad. |
|
Not that it matters, but I have a python notebook detailing the design choices: As an architect, I still believe that the SAME padding is not something that we should introduce back into the common usage patterns. This being said, I was the person that included SAME paddings in ONNX for compatibility reasons, so I can understand why one might want it. |
|
I somehow missed the notification 16 days ago, sorry.
Could you please paste what graph do we actually have there? To print it, you could add before the I'm pretty sure this test can be adjusted to the changes you're doing - it basically just checks that after the transformation we have instrumentation calls to "observers" before the |
|
@Chillee , @ZolotukhinM @jamesr66a what can we do to land this |
|
Sorry I've been busy recently - will get back to this within a week or two. |
|
Somebody else pushed it across the finish line when I couldn't :) #45667 |
#3867
The implementation is taken from here (with some comments annotating the logic): https://github.com/mlperf/inference/blob/master/others/edge/object_detection/ssd_mobilenet/pytorch/utils.py#L40
In addition, I've stress tested it for all combinations of input image, kernel size, stride, and dilation from 1-6 (6^8 combinations). For all of them, the output dimensions follow the rules listed here for "same": https://www.tensorflow.org/api_docs/python/tf/nn/convolution
I still need to add tests and test JIT compatability.Then I can tackle the other ones.