Uh oh!
There was an error while loading. Please reload this page.
[NNVM][CONVOLUTION] Group convolution generalization for NHWC - #1232
Conversation
b0aed78 to
11738bfComparesrkreddy1238
commented
Jun 6, 2018
@Huyuwei |
srkreddy1238
commented
Jun 6, 2018
If we are good with this, I will add a test case for NHWC-depthwise. |
| if (param.layout == "NHWC") { | ||
| wshape[kernel_layout.indexof('I')] *= param.groups; | ||
| } else { | ||
| wshape[0] *= param.groups; |
There was a problem hiding this comment.
when param.layout == "NCHW", kernel_layout.indexof('I') = 0?
There was a problem hiding this comment.
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.
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.
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.).
| if (param.layout == "NHWC") { | ||
| wshape[kernel_layout.indexof('I')] *= param.groups; | ||
| } else { | ||
| wshape[0] *= param.groups; |
There was a problem hiding this comment.
I think wshape[kernel_layout.indexof('O')] *= param.groups can handle both cases
You can try some tests
| wshape = ConvertLayout(wshape, kOIHW, kernel_layout); | ||
| wshape[0] *= param.groups; | ||
| // Depthwise |
There was a problem hiding this comment.
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.
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.
Alternatively we could change frontend to pass kernel_layout as IOHW and generalise it to indexof('I') .
Huyuwei
commented
Jun 12, 2018
@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 |
srkreddy1238
commented
Jun 14, 2018
Test case added for NHWC, pls check. |
Huyuwei
commented
Jun 15, 2018
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? |
Huyuwei
commented
Jun 15, 2018
@srkreddy1238 May I ask one question? just for curiosity |
srkreddy1238
commented
Jun 15, 2018
", 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.. |
srkreddy1238
commented
Jun 16, 2018
mxnet doesn't implement NHWC but we do. |
Huyuwei
commented
Jun 16, 2018
@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? |
srkreddy1238
commented
Jun 16, 2018
Yes, channel is before multiplier. |
Huyuwei
commented
Jun 17, 2018
@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.
|
srkreddy1238
commented
Jun 18, 2018
Thanks for the info. This makes clear to me. |
srkreddy1238
commented
Jun 18, 2018
@Huyuwei |
| 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.
elif groups == channels and layout == "NHWC" and kernel_layout == "HWOI":
| @@ -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.
add more checks here
eliflayout=="NCHW"andgroups==get_const_int(inputs[0].shape[1]) andgroups==channels:
out=eliflayout=="NHWC"andkernel_layout=="HWOI"andgroups==get_const_int(inputs[0].shape[3]) andgroups==channels:
out=| elif layout == "NCHW" and \ | ||
| groups == get_const_int(inputs[0].shape[1]) and \ | ||
| groups == channels: | ||
| # NCHW |
There was a problem hiding this comment.
then this comment can be removed
| kernel_layout == "HWOI" and \ | ||
| groups == get_const_int(inputs[0].shape[3]) and \ | ||
| groups == channels: | ||
| # NHWC |
Huyuwei
commented
Jun 19, 2018
@srkreddy1238 Can mobilenet be converted now? If so, add it to frontend tests. |
srkreddy1238
commented
Jun 19, 2018
Ok. I will update frontend testcases with mobilenet this weekend. |
tqchen
commented
Jun 24, 2018
This is merged as @Huyuwei approved the change. Please add mobilnet test in a separate PR |
No description provided.