Skip to content
This repository was archived by the owner on Nov 17, 2023. It is now read-only.

Commit 8173b85

Browse files
[v1.x][FEATURE] Add MKLDNN Deconvolution 1D and 3D support (#20137) (#20726)
Co-authored-by: Paweł Głomski <[email protected]>
1 parent 200b284 commit 8173b85

File tree

4 files changed

+35
-15
lines changed

4 files changed

+35
-15
lines changed

src/operator/nn/deconvolution-inl.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,11 @@ class DeconvolutionOp {
219219
using namespace mshadow::expr;
220220

221221
if (param_.kernel.ndim() > 2) {
222-
LOG(FATAL) << "If not using CUDNN, only 1D or 2D Deconvolution is supported";
222+
LOG(FATAL) << "Only 1D or 2D Deconvolution is natively supported. "
223+
<< ((MXNET_USE_MKLDNN || MXNET_USE_CUDNN)
224+
? "Fallback to native implementation (if occurred) is therefore "
225+
"impossible for 3D Deconvolution."
226+
: "");
223227
}
224228

225229
CHECK_EQ(req[deconv::kOut], kWriteTo);

src/operator/nn/deconvolution.cc

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,14 @@ static void DeconvolutionComputeExCPU(const nnvm::NodeAttrs& attrs,
4242
const std::vector<NDArray>& outputs) {
4343
const DeconvolutionParam& params = nnvm::get<DeconvolutionParam>(attrs.parsed);
4444
if (SupportMKLDNNDeconv(params, inputs[0])) {
45-
MKLDNN_OPCHECK_INIT(false, outputs.size(), inputs, outputs);
46-
MKLDNNRun(MKLDNNDeconvolutionForward, attrs, ctx, inputs, req, outputs);
47-
MKLDNN_OPCHECK_RUN(DeconvolutionCompute<cpu>, attrs, ctx, inputs, req, outputs);
45+
if (params.kernel.ndim() == 3) {
46+
// we cannot check the output, as 3D deconvolution is not natively supported yet
47+
MKLDNNRun(MKLDNNDeconvolutionForward, attrs, ctx, inputs, req, outputs);
48+
} else {
49+
MKLDNN_OPCHECK_INIT(false, outputs.size(), inputs, outputs);
50+
MKLDNNRun(MKLDNNDeconvolutionForward, attrs, ctx, inputs, req, outputs);
51+
MKLDNN_OPCHECK_RUN(DeconvolutionCompute<cpu>, attrs, ctx, inputs, req, outputs);
52+
}
4853
return;
4954
}
5055
FallBackCompute(DeconvolutionCompute<cpu>, attrs, ctx, inputs, req, outputs);
@@ -57,9 +62,14 @@ static void DeconvolutionGradComputeExCPU(const nnvm::NodeAttrs& attrs,
5762
const std::vector<NDArray>& outputs) {
5863
const DeconvolutionParam& params = nnvm::get<DeconvolutionParam>(attrs.parsed);
5964
if (SupportMKLDNNDeconv(params, inputs[0])) {
60-
MKLDNN_OPCHECK_INIT(true, outputs.size(), inputs, outputs);
61-
MKLDNNRun(MKLDNNDeconvolutionBackward, attrs, ctx, inputs, req, outputs);
62-
MKLDNN_OPCHECK_RUN(DeconvolutionGradCompute<cpu>, attrs, ctx, inputs, req, outputs);
65+
if (params.kernel.ndim() == 3) {
66+
// we cannot check the output, as 3D deconvolution is not natively supported yet
67+
MKLDNNRun(MKLDNNDeconvolutionBackward, attrs, ctx, inputs, req, outputs);
68+
} else {
69+
MKLDNN_OPCHECK_INIT(true, outputs.size(), inputs, outputs);
70+
MKLDNNRun(MKLDNNDeconvolutionBackward, attrs, ctx, inputs, req, outputs);
71+
MKLDNN_OPCHECK_RUN(DeconvolutionGradCompute<cpu>, attrs, ctx, inputs, req, outputs);
72+
}
6373
return;
6474
}
6575
FallBackCompute(DeconvolutionGradCompute<cpu>, attrs, ctx, inputs, req, outputs);
@@ -99,12 +109,12 @@ static bool DeconvolutionShape(const nnvm::NodeAttrs& attrs,
99109
mxnet::ShapeVector *in_shape,
100110
mxnet::ShapeVector *out_shape) {
101111
const DeconvolutionParam& param_ = nnvm::get<DeconvolutionParam>(attrs.parsed);
102-
#if MXNET_USE_CUDNN == 0
112+
#if MXNET_USE_CUDNN == 0 && MXNET_USE_MKLDNN == 0
103113
if (param_.kernel.ndim() > 2) {
104-
LOG(FATAL) << "If not using CUDNN, only 1D or 2D Deconvolution is supported";
114+
LOG(FATAL) << "If not using CUDNN or MKLDNN, only 1D or 2D Deconvolution is supported";
105115
return false;
106116
}
107-
#endif // CUDNN
117+
#endif
108118

109119
using namespace mshadow;
110120
if (!param_.no_bias) {

src/operator/nn/mkldnn/mkldnn_deconvolution.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ namespace mxnet {
2929
namespace op {
3030

3131
bool SupportMKLDNNDeconv(const DeconvolutionParam &params, const NDArray &input) {
32-
return params.kernel.ndim() == 2 && input.shape().ndim() == 4 &&
32+
return params.kernel.ndim() >= 1 && params.kernel.ndim() <= 3 &&
33+
input.shape().ndim() == (params.kernel.ndim() + 2) &&
3334
(input.dtype() == mshadow::kFloat32 || input.dtype() == mshadow::kBfloat16);
3435
}
3536

@@ -322,10 +323,10 @@ DeconvDescCreator::DeconvDescCreator(const DeconvolutionParam &param, const NDAr
322323
strides(param.stride.ndim()),
323324
padding(param.pad.ndim()),
324325
dilates(param.dilate.ndim()) {
325-
// assuming only deconv2D is supported for now
326326
CHECK_EQ(param.stride.ndim(), param.pad.ndim());
327327
CHECK_EQ(param.stride.ndim(), param.dilate.ndim());
328-
CHECK_EQ(param.stride.ndim(), 2);
328+
CHECK_GE(param.stride.ndim(), 1);
329+
CHECK_LE(param.stride.ndim(), 3);
329330
for (int i = 0; i < param.stride.ndim(); ++i) {
330331
strides[i] = param.stride[i];
331332
padding[i] = param.pad[i];

tests/python/mkl/test_mkldnn.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,8 +471,8 @@ def check_convolution_training(stype):
471471
@with_seed()
472472
def test_Deconvolution():
473473
def check_Deconvolution_training(stype):
474-
for shape in [(3, 3, 10, 10)]: # testing only 2D for now
475-
data_tmp = np.random.randint(256, size=shape)
474+
for shape in [(3, 3, 10), (3, 3, 10, 10), (3, 3, 10, 10, 10)]:
475+
data_tmp = np.random.normal(-0.1, 1, size=shape)
476476
data = mx.symbol.Variable('data', stype=stype)
477477

478478
if np.array(shape).shape[0] == 3:
@@ -481,6 +481,11 @@ def check_Deconvolution_training(stype):
481481
elif np.array(shape).shape[0] == 4:
482482
test = mx.symbol.Deconvolution(data=data, kernel=(3, 3), stride=(2, 2), num_filter=4)
483483
weight_tmp = np.random.normal(-0.1, 0.1, size=(3, 4, 3, 3))
484+
elif np.array(shape).shape[0] == 5 and stype == "default":
485+
# Unable to test fallback to native implementation for non-default storage types
486+
# as 3D deconvolution is not natively supported
487+
test = mx.symbol.Deconvolution(data=data, kernel=(3,3,3), stride=(2,2,2), num_filter=4)
488+
weight_tmp = np.random.normal(-0.1, 0.1, size=(3, 4, 3, 3, 3))
484489
else:
485490
return 0
486491
bias_tmp = np.random.normal(0.1, 0.1, size=(4,))

0 commit comments

Comments
 (0)