-
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
[NNVM][CONVOLUTION] Group convolution generalization for NHWC #1232
Conversation
b0aed78
to
11738bf
Compare
@Huyuwei |
If we are good with this, I will add a test case for NHWC-depthwise. |
nnvm/src/top/nn/convolution.cc
Outdated
if (param.layout == "NHWC") { | ||
wshape[kernel_layout.indexof('I')] *= param.groups; | ||
} else { | ||
wshape[0] *= param.groups; |
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.
when param.layout == "NCHW", kernel_layout.indexof('I') = 0?
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.
yes, because the weights format for NCHW sent as CHNW from front end and expectation is also same at compute.
Ref.
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.
I think wshape[kernel_layout.indexof('O')] *= param.groups
can handle both cases
You can try some tests
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.
No it doesn't work this way as kernel layout for NCHW deviated from the format. (it's actually CNHW passed from frontend and same is expected in compute.).
nnvm/src/top/nn/convolution.cc
Outdated
if (param.layout == "NHWC") { | ||
wshape[kernel_layout.indexof('I')] *= param.groups; | ||
} else { | ||
wshape[0] *= param.groups; |
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.
I think wshape[kernel_layout.indexof('O')] *= param.groups
can handle both cases
You can try some tests
nnvm/src/top/nn/convolution.cc
Outdated
@@ -79,7 +79,15 @@ inline bool Conv2DInferShape(const nnvm::NodeAttrs& attrs, | |||
param.kernel_size[1]}); | |||
|
|||
wshape = ConvertLayout(wshape, kOIHW, kernel_layout); | |||
wshape[0] *= param.groups; | |||
|
|||
// Depthwise |
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.
it's group convolution, and depthwise is just a special case
In fact, only depthwise convolution with multiplier=1 is supported now since it can be expressed as group convolution, see https://github.com/dmlc/tvm/blob/master/nnvm/python/nnvm/top/nn.py#L100-L101
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.
This generalisation works only if we pass kernel_layout as CNHW (IOHW).
IOHW is agreement between frontend and nchw_deptiwise_compute which infer shape doesn't know.
In my case also multiplier is 1.
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.
Alternatively we could change frontend to pass kernel_layout as IOHW and generalise it to indexof('I') .
@srkreddy1238 Could you first add a test case that drives this change? It will help me better follow what's going on. You may need to modify these two files to test NHWC layout: |
We don't have a frontend with NHWC and depthwise now to give a clear test case. I could do this once we have tensorflow frontend. Ref: https://github.com/srkreddy1238/tvm/tree/mobilenet |
Test case added for NHWC, pls check. |
My suggestion is we use NHWC depthwise convolution can be expressed as depthconv_nhwc = sym.conv2d(data, layout="NHWC", kernel_layout="HWOI") while a normal grouped NHWC convolution can be expressed as groupconv_nhwc = sym.conv2d(data, layout="NHWC", kernel_layout="HWIO") The order of in_channel and out_channel in the kernel layout of topi.conv2d_nchw and topi.conv2d_nhwc is different, but the order of in_channel and multiplier in the kernel layout of topi.depthwise_conv2d_nchw and topi.depthwise_conv2d_nhwc is the same. It's better to deal with this asymmetry in frontend part, not c++ code. @srkreddy1238 what do you think? |
@srkreddy1238 May I ask one question? just for curiosity |
", but the order of in_channel and multiplier in the kernel layout of topi.depthwise_conv2d_nchw and topi.depthwise_conv2d_nhwc is the same" No, they are not same. Let me check mxnet compute implementation.. |
mxnet doesn't implement NHWC but we do. |
@srkreddy1238 aha, thanks for the pointer. In the kernel layout of both topi.depthwise_conv2d_nchw and topi.depthwise_conv2d_nhwc is, in_channel is before multiplier, is this right? |
Yes, channel is before multiplier. |
@srkreddy1238 For topi.conv2d_nchw, out_channel is before in_channel in kernel layout, while for topi.conv2d_nhwc, out_channel is after in_channel. And there is a mismatch between conv2d_nhwc and depthwise_conv2d_nhwc.
|
Thanks for the info. This makes clear to me. |
FusedBatchNorm, Relu6, DepthwiseConv2dNative, Shape
@Huyuwei |
nnvm/python/nnvm/top/nn.py
Outdated
return topi.generic.schedule_depthwise_conv2d_nchw(outs) | ||
elif groups == channels and layout == "NCHW": | ||
return topi.generic.schedule_depthwise_conv2d_nchw(outs) | ||
elif groups == channels and layout == "NHWC": |
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.
elif groups == channels and layout == "NHWC" and kernel_layout == "HWOI":
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.
Done.
nnvm/python/nnvm/top/nn.py
Outdated
@@ -98,9 +98,14 @@ def compute_conv2d(attrs, inputs, _): | |||
if groups == 1: | |||
out = topi.nn.conv2d(inputs[0], kernel, strides, padding, layout) | |||
elif groups == get_const_int(inputs[0].shape[1]) and groups == channels: |
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.
add more checks here
elif layout == "NCHW" and groups == get_const_int(inputs[0].shape[1]) and groups == channels:
out =
elif layout == "NHWC" and kernel_layout == "HWOI" and groups == get_const_int(inputs[0].shape[3]) and groups == channels:
out =
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.
Done
nnvm/python/nnvm/top/nn.py
Outdated
elif groups == get_const_int(inputs[0].shape[1]) and groups == channels: | ||
elif layout == "NCHW" and \ | ||
groups == get_const_int(inputs[0].shape[1]) and \ | ||
groups == channels: | ||
# NCHW |
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.
then this comment can be removed
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.
Handled
nnvm/python/nnvm/top/nn.py
Outdated
elif layout == "NHWC" and \ | ||
kernel_layout == "HWOI" and \ | ||
groups == get_const_int(inputs[0].shape[3]) and \ | ||
groups == channels: | ||
# NHWC |
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.
and this line
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.
handled.
@srkreddy1238 Can mobilenet be converted now? If so, add it to frontend tests. |
Ok. I will update frontend testcases with mobilenet this weekend. |
This is merged as @Huyuwei approved the change. Please add mobilnet test in a separate PR |
No description provided.