From fd1266a13bfa9364da6d3dee84a6f2db6a523c3e Mon Sep 17 00:00:00 2001 From: luobao-intel Date: Tue, 10 Jul 2018 15:11:17 +0800 Subject: [PATCH] Fallback Amend This is the final rectify for fallback problem --- src/operator/nn/activation.cc | 48 ++++++------ src/operator/nn/convolution.cc | 25 +++++- src/operator/nn/deconvolution.cc | 26 ++++++- src/operator/nn/lrn.cc | 47 +++++++---- src/operator/nn/pooling.cc | 45 +++++++---- src/operator/nn/softmax.cc | 19 ++--- tests/python/mkl/test_mkldnn.py | 130 +++++++++++++++++++++++++++++++ 7 files changed, 270 insertions(+), 70 deletions(-) diff --git a/src/operator/nn/activation.cc b/src/operator/nn/activation.cc index d723bbe62d76..30159c28ffa0 100644 --- a/src/operator/nn/activation.cc +++ b/src/operator/nn/activation.cc @@ -31,6 +31,8 @@ #include "./mkldnn/mkldnn_base-inl.h" #include "./mkldnn/mkldnn_ops-inl.h" #endif // MXNET_USE_MKLDNN +#include "../operator_common.h" +#include "../../common/utils.h" namespace mxnet { namespace op { @@ -100,16 +102,16 @@ inline static bool ActivationStorageType(const nnvm::NodeAttrs& attrs, std::vector *out_attrs) { CHECK_EQ(in_attrs->size(), 1); CHECK_EQ(out_attrs->size(), 1); - bool ret = ElemwiseStorageType<1, 1, false, false, false>(attrs, dev_mask, - dispatch_mode, - in_attrs, out_attrs); #if MXNET_USE_MKLDNN == 1 const ActivationParam& param = nnvm::get(attrs.parsed); - if (dev_mask == mshadow::cpu::kDevMask && SupportMKLDNNAct(param)) { - *dispatch_mode = DispatchMode::kFComputeEx; - } + if (dev_mask == mshadow::cpu::kDevMask && SupportMKLDNNAct(param)) + return ElemwiseStorageType<1, 1, false, false, false>( + attrs, dev_mask, dispatch_mode, in_attrs, out_attrs); + else + return op::dispatch_fallback(out_attrs, dispatch_mode); #endif - return ret; +return ElemwiseStorageType<1, 1, false, false, false>( + attrs, dev_mask, dispatch_mode, in_attrs, out_attrs); } inline static bool BackwardActStorageType(const nnvm::NodeAttrs& attrs, @@ -120,18 +122,21 @@ inline static bool BackwardActStorageType(const nnvm::NodeAttrs& attrs, bool ret = false; #if (MXNET_USE_CUDNN == 1 || MXNET_USE_MKLDNN == 1) const ActivationParam& param = nnvm::get(attrs.parsed); - if (param.act_type != activation::kReLU) { - CHECK_EQ(in_attrs->size(), 3U); - ret = ElemwiseStorageType<3, 1, false, false, false>(attrs, dev_mask, - dispatch_mode, - in_attrs, out_attrs); - } else { - // for ReLU activation, the backward pass only needs ograd and output - CHECK_EQ(in_attrs->size(), 2U); - ret = ElemwiseStorageType<2, 1, false, false, false>(attrs, dev_mask, - dispatch_mode, - in_attrs, out_attrs); - } + if (dev_mask == mshadow::cpu::kDevMask && SupportMKLDNNAct(param)) + if (param.act_type != activation::kReLU) { + CHECK_EQ(in_attrs->size(), 3U); + ret = ElemwiseStorageType<3, 1, false, false, false>(attrs, dev_mask, + dispatch_mode, + in_attrs, out_attrs); + } else { + // for ReLU activation, the backward pass only needs ograd and output + CHECK_EQ(in_attrs->size(), 2U); + ret = ElemwiseStorageType<2, 1, false, false, false>(attrs, dev_mask, + dispatch_mode, + in_attrs, out_attrs); + } + else + ret = op::dispatch_fallback(out_attrs, dispatch_mode); #else CHECK_EQ(in_attrs->size(), 2U); ret = ElemwiseStorageType<2, 1, false, false, false>(attrs, dev_mask, @@ -139,11 +144,6 @@ inline static bool BackwardActStorageType(const nnvm::NodeAttrs& attrs, in_attrs, out_attrs); #endif CHECK_EQ(out_attrs->size(), 1U); -#if MXNET_USE_MKLDNN == 1 - if (dev_mask == mshadow::cpu::kDevMask && SupportMKLDNNAct(param)) { - *dispatch_mode = DispatchMode::kFComputeEx; - } -#endif return ret; } diff --git a/src/operator/nn/convolution.cc b/src/operator/nn/convolution.cc index ef70ccd6ec1e..38652e720330 100644 --- a/src/operator/nn/convolution.cc +++ b/src/operator/nn/convolution.cc @@ -25,6 +25,8 @@ */ #include "./convolution-inl.h" +#include "../operator_common.h" +#include "../../common/utils.h" #include "../elemwise_op_common.h" #include "./mkldnn/mkldnn_ops-inl.h" #include "./mkldnn/mkldnn_base-inl.h" @@ -305,8 +307,16 @@ inline static bool ConvStorageType(const nnvm::NodeAttrs& attrs, else #endif wanted_mode = DispatchMode::kFCompute; - return storage_type_assign(out_attrs, mxnet::kDefaultStorage, - dispatch_mode, wanted_mode); + + bool dispatched = false; + if (common::ContainsOnlyStorage(*in_attrs, kDefaultStorage)) { + dispatched = op::storage_type_assign(out_attrs, mxnet::kDefaultStorage, + dispatch_mode, wanted_mode); + } + if (!dispatched) { + dispatched = op::dispatch_fallback(out_attrs, dispatch_mode); + } + return dispatched; } inline static bool BackwardConvStorageType(const nnvm::NodeAttrs& attrs, @@ -327,8 +337,15 @@ inline static bool BackwardConvStorageType(const nnvm::NodeAttrs& attrs, else #endif wanted_mode = DispatchMode::kFCompute; - return storage_type_assign(out_attrs, mxnet::kDefaultStorage, - dispatch_mode, wanted_mode); + bool dispatched = false; + if (common::ContainsOnlyStorage(*in_attrs, kDefaultStorage)) { + dispatched = op::storage_type_assign(out_attrs, mxnet::kDefaultStorage, + dispatch_mode, wanted_mode); + } + if (!dispatched) { + dispatched = op::dispatch_fallback(out_attrs, dispatch_mode); + } + return dispatched; } void ConvolutionParamParser(nnvm::NodeAttrs* attrs) { diff --git a/src/operator/nn/deconvolution.cc b/src/operator/nn/deconvolution.cc index 9e0a70121bf9..c4698a888e8c 100644 --- a/src/operator/nn/deconvolution.cc +++ b/src/operator/nn/deconvolution.cc @@ -27,6 +27,8 @@ #include "./deconvolution-inl.h" #include "./mkldnn/mkldnn_ops-inl.h" #include "./mkldnn/mkldnn_base-inl.h" +#include "../operator_common.h" +#include "../../common/utils.h" namespace mxnet { namespace op { @@ -273,8 +275,16 @@ inline static bool DeconvStorageType(const nnvm::NodeAttrs& attrs, else #endif wanted_mode = DispatchMode::kFCompute; - return storage_type_assign(out_attrs, mxnet::kDefaultStorage, - dispatch_mode, wanted_mode); + + bool dispatched = false; + if (common::ContainsOnlyStorage(*in_attrs, kDefaultStorage)) { + dispatched = op::storage_type_assign(out_attrs, mxnet::kDefaultStorage, + dispatch_mode, wanted_mode); + } + if (!dispatched) { + dispatched = op::dispatch_fallback(out_attrs, dispatch_mode); + } + return dispatched; } inline static bool BackwardDeconvStorageType(const nnvm::NodeAttrs& attrs, @@ -294,8 +304,16 @@ inline static bool BackwardDeconvStorageType(const nnvm::NodeAttrs& attrs, else #endif wanted_mode = DispatchMode::kFCompute; - return storage_type_assign(out_attrs, mxnet::kDefaultStorage, - dispatch_mode, wanted_mode); + + bool dispatched = false; + if (common::ContainsOnlyStorage(*in_attrs, kDefaultStorage)) { + dispatched = op::storage_type_assign(out_attrs, mxnet::kDefaultStorage, + dispatch_mode, wanted_mode); + } + if (!dispatched) { + dispatched = op::dispatch_fallback(out_attrs, dispatch_mode); + } + return dispatched; } #if MXNET_USE_MKLDNN == 1 diff --git a/src/operator/nn/lrn.cc b/src/operator/nn/lrn.cc index 6b3d7c818378..3368afe75d26 100644 --- a/src/operator/nn/lrn.cc +++ b/src/operator/nn/lrn.cc @@ -26,6 +26,7 @@ #include "./lrn-inl.h" #include "../operator_common.h" +#include "../../common/utils.h" #if MXNET_USE_MKLDNN == 1 #include "./mkldnn/mkldnn_lrn-inl.h" #endif @@ -87,16 +88,23 @@ bool LRNForwardInferStorageType(const nnvm::NodeAttrs& attrs, std::vector *in_attrs, std::vector *out_attrs) { CHECK(!in_attrs->empty()); + DispatchMode wanted_mode; #if MXNET_USE_MKLDNN == 1 - if (dev_mask == mshadow::cpu::kDevMask) { - storage_type_assign(out_attrs, mxnet::kDefaultStorage, - dispatch_mode, DispatchMode::kFComputeEx); - return true; - } + if (dev_mask == mshadow::cpu::kDevMask) + wanted_mode = DispatchMode::kFComputeEx; + else #endif - storage_type_assign(out_attrs, mxnet::kDefaultStorage, - dispatch_mode, DispatchMode::kFCompute); - return true; + wanted_mode = DispatchMode::kFCompute; + + bool dispatched = false; + if (common::ContainsOnlyStorage(*in_attrs, kDefaultStorage)) { + dispatched = op::storage_type_assign(out_attrs, mxnet::kDefaultStorage, + dispatch_mode, wanted_mode); + } + if (!dispatched) { + dispatched = op::dispatch_fallback(out_attrs, dispatch_mode); + } + return dispatched; } bool LRNBackwardInferStorageType(const nnvm::NodeAttrs& attrs, @@ -105,16 +113,23 @@ bool LRNBackwardInferStorageType(const nnvm::NodeAttrs& attrs, std::vector *in_attrs, std::vector *out_attrs) { CHECK(!in_attrs->empty()); + DispatchMode wanted_mode; #if MXNET_USE_MKLDNN == 1 - if (dev_mask == mshadow::cpu::kDevMask) { - storage_type_assign(out_attrs, mxnet::kDefaultStorage, - dispatch_mode, DispatchMode::kFComputeEx); - return true; - } + if (dev_mask == mshadow::cpu::kDevMask) + wanted_mode = DispatchMode::kFComputeEx; + else #endif - storage_type_assign(out_attrs, mxnet::kDefaultStorage, - dispatch_mode, DispatchMode::kFCompute); - return true; + wanted_mode = DispatchMode::kFCompute; + + bool dispatched = false; + if (common::ContainsOnlyStorage(*in_attrs, kDefaultStorage)) { + dispatched = op::storage_type_assign(out_attrs, mxnet::kDefaultStorage, + dispatch_mode, wanted_mode); + } + if (!dispatched) { + dispatched = op::dispatch_fallback(out_attrs, dispatch_mode); + } + return dispatched; } #if MXNET_USE_MKLDNN == 1 diff --git a/src/operator/nn/pooling.cc b/src/operator/nn/pooling.cc index 3200a515d6f4..d766002a49f6 100644 --- a/src/operator/nn/pooling.cc +++ b/src/operator/nn/pooling.cc @@ -25,6 +25,8 @@ */ #include "../elemwise_op_common.h" #include "./pooling-inl.h" +#include "../operator_common.h" +#include "../../common/utils.h" #if MXNET_USE_NNPACK == 1 #include "../nnpack/nnpack_pooling-inl.h" #endif // MXNET_USE_NNPACK @@ -276,18 +278,26 @@ inline static bool PoolingStorageType(const nnvm::NodeAttrs &attrs, std::vector *in_attrs, std::vector *out_attrs) { CHECK_EQ(in_attrs->size(), 1); - + DispatchMode wanted_mode; #if MXNET_USE_MKLDNN == 1 const PoolingParam ¶m = nnvm::get(attrs.parsed); - if (dev_mask == mshadow::cpu::kDevMask && SupportMKLDNNPooling(param)) { - return storage_type_assign(out_attrs, mxnet::kDefaultStorage, - dispatch_mode, DispatchMode::kFComputeEx); - } + if (dev_mask == mshadow::cpu::kDevMask && SupportMKLDNNPooling(param)) + wanted_mode = DispatchMode::kFComputeEx; + else #else CHECK_EQ(out_attrs->size(), 1); #endif - return storage_type_assign(out_attrs, mxnet::kDefaultStorage, - dispatch_mode, DispatchMode::kFCompute); + wanted_mode = DispatchMode::kFCompute; + + bool dispatched = false; + if (common::ContainsOnlyStorage(*in_attrs, kDefaultStorage)) { + dispatched = op::storage_type_assign(out_attrs, mxnet::kDefaultStorage, + dispatch_mode, wanted_mode); + } + if (!dispatched) { + dispatched = op::dispatch_fallback(out_attrs, dispatch_mode); + } + return dispatched; } inline static bool BackwardPoolingStorageType(const nnvm::NodeAttrs &attrs, @@ -299,16 +309,25 @@ inline static bool BackwardPoolingStorageType(const nnvm::NodeAttrs &attrs, CHECK_EQ(in_attrs->size(), GetNumBackInputs(param)); CHECK_EQ(out_attrs->size(), 1); + DispatchMode wanted_mode; #if MXNET_USE_MKLDNN == 1 - if (dev_mask == mshadow::cpu::kDevMask && SupportMKLDNNPooling(param)) { - return storage_type_assign(out_attrs, mxnet::kDefaultStorage, - dispatch_mode, DispatchMode::kFComputeEx); - } + if (dev_mask == mshadow::cpu::kDevMask && SupportMKLDNNPooling(param)) + wanted_mode = DispatchMode::kFComputeEx; + else #else CHECK_EQ(in_attrs->size(), 3); #endif - return storage_type_assign(out_attrs, mxnet::kDefaultStorage, - dispatch_mode, DispatchMode::kFCompute); + wanted_mode = DispatchMode::kFCompute; + + bool dispatched = false; + if (common::ContainsOnlyStorage(*in_attrs, kDefaultStorage)) { + dispatched = op::storage_type_assign(out_attrs, mxnet::kDefaultStorage, + dispatch_mode, wanted_mode); + } + if (!dispatched) { + dispatched = op::dispatch_fallback(out_attrs, dispatch_mode); + } + return dispatched; } DMLC_REGISTER_PARAMETER(PoolingParam); diff --git a/src/operator/nn/softmax.cc b/src/operator/nn/softmax.cc index f04aac810f06..d8ae7ff0b732 100644 --- a/src/operator/nn/softmax.cc +++ b/src/operator/nn/softmax.cc @@ -27,7 +27,8 @@ #include "../tensor/elemwise_binary_op.h" #include "mkldnn/mkldnn_base-inl.h" #include "mkldnn/mkldnn_ops-inl.h" -#include "../../operator_common.h" +#include "../operator_common.h" +#include "../../common/utils.h" namespace mxnet { namespace op { @@ -50,6 +51,7 @@ static void SoftmaxComputeExCPU(const nnvm::NodeAttrs& attrs, FallBackCompute(SoftmaxCompute, attrs, ctx, inputs, req, outputs); } +#endif inline static bool SoftmaxStorageType(const nnvm::NodeAttrs& attrs, const int dev_mask, @@ -69,16 +71,15 @@ inline static bool SoftmaxStorageType(const nnvm::NodeAttrs& attrs, wanted_mode = DispatchMode::kFCompute; bool dispatched = false; - if (!dispatched && common::ContainsOnlyStorage(*in_attrs, kDefaultStorage)){ - dispatched = op::storage_type_assign(out_attrs, mxnet::kDefaultStorage, dispatch_mode, wanted_mode); - } - if (!dispatched){ - dispatched = op::dispatch_fallback(out_attrs, dispatch_mode); - } - + if (common::ContainsOnlyStorage(*in_attrs, kDefaultStorage)) { + dispatched = op::storage_type_assign(out_attrs, mxnet::kDefaultStorage, + dispatch_mode, wanted_mode); + } + if (!dispatched) { + dispatched = op::dispatch_fallback(out_attrs, dispatch_mode); + } return dispatched; } -#endif MXNET_OPERATOR_REGISTER_UNARY(softmax) .describe(R"code(Applies the softmax function. diff --git a/tests/python/mkl/test_mkldnn.py b/tests/python/mkl/test_mkldnn.py index dad1bd7d6151..d8b2de1e873b 100644 --- a/tests/python/mkl/test_mkldnn.py +++ b/tests/python/mkl/test_mkldnn.py @@ -240,5 +240,135 @@ def check_batchnorm_training(stype): for stype in stypes: check_batchnorm_training(stype) +@with_seed() +def test_softmax(): + def check_softmax_training(stype): + for shape in [(2, 3), (2, 3, 2, 2)]: + data_tmp = np.random.normal(-0.1, 0.1, size=shape) + + data = mx.symbol.Variable('data', stype=stype) + in_location = [mx.nd.array(data_tmp).tostype(stype)] + + test = mx.symbol.softmax(data, axis=-1) + check_numeric_gradient(test, in_location, numeric_eps=1e-2,rtol=0.16, atol=1e-4) + + stypes = ['row_sparse', 'default'] + for stype in stypes: + check_softmax_training(stype) + +@with_seed() +def test_SoftmaxOutput(): + def check_SoftmaxOutput_training(stype): + for shape in [(10, 3)]: + data_tmp = np.random.normal(-0.1, 0.1, size=shape) + label_tmp = np.random.randint(2,size=shape[0]) + + data = mx.symbol.Variable('data', stype=stype) + label = mx.symbol.Variable('label',stype=stype) + + in_location = [mx.nd.array(data_tmp).tostype(stype),mx.nd.array(label_tmp).tostype(stype)] + + test = mx.symbol.SoftmaxOutput(data,label) + check_numeric_gradient(test, in_location, numeric_eps=1e-2,rtol=0.16, atol=1e-4) + + stypes = ['row_sparse', 'default'] + for stype in stypes: + check_SoftmaxOutput_training(stype) + +@with_seed() +def test_pooling(): + def check_pooling_training(stype): + for shape in [(3, 3, 10),(3, 3, 20, 20)]: + data_tmp = np.random.normal(-0.1,0.1, size=shape) + data = mx.symbol.Variable('data', stype=stype) + in_location = [mx.nd.array(data_tmp).tostype(stype)] + + if np.array(shape).shape[0] == 3: + test = mx.symbol.Pooling(data=data, kernel=(3,), stride=(2), pool_type='avg') + elif np.array(shape).shape[0] == 4: + test = mx.symbol.Pooling(data=data, kernel=(3, 3), stride=(2, 2), pool_type='avg') + else: + return 0 + check_numeric_gradient(test, in_location, numeric_eps=1e-2,rtol=0.16, atol=1e-4) + + stypes = ['row_sparse', 'default'] + for stype in stypes: + check_pooling_training(stype) + +@with_seed() +def test_activation(): + def check_activation_training(stype): + for shape in [(2, 3, 3), (2, 3, 2, 2)]: + data_tmp = np.random.normal(-0.1, 1, size=shape) + + data = mx.symbol.Variable('data', stype=stype) + in_location = [mx.nd.array(data_tmp).tostype(stype)] + + test = mx.symbol.Activation(data, act_type="relu") + check_numeric_gradient(test, in_location, numeric_eps=1e-2,rtol=0.16, atol=1e-4) + + stypes = ['row_sparse', 'default'] + for stype in stypes: + check_activation_training(stype) + +def test_convolution(): + def check_convolution_training(stype): + for shape in [(3, 3, 10),(3, 3, 10, 10)]: + data_tmp = np.random.randint(256, size=shape) + data = mx.symbol.Variable('data', stype=stype) + + if np.array(shape).shape[0] == 3: + test = mx.symbol.Convolution(data=data, kernel=(3,), stride=(2), num_filter=4) + weight_tmp = np.random.normal(-0.1, 0.1, size=(4, 3, 3)) + elif np.array(shape).shape[0] == 4: + test = mx.symbol.Convolution(data=data, kernel=(3, 3), stride=(2, 2), num_filter=4) + weight_tmp = np.random.normal(-0.1, 0.1, size=(4,3,3,3)) + else: + return 0 + bias_tmp = np.random.normal(0.1, 0.1, size=(4,)) + in_location = [mx.nd.array(data_tmp).tostype(stype),mx.nd.array(weight_tmp).tostype(stype), mx.nd.array(bias_tmp).tostype(stype)] + check_numeric_gradient(test, in_location, numeric_eps=1e-2,rtol=0.16, atol=1e-4) + + stypes = ['row_sparse', 'default'] + for stype in stypes: + check_convolution_training(stype) + +def test_Deconvolution(): + def check_Deconvolution_training(stype): + for shape in [(3, 3, 10),(3, 3, 10, 10)]: + data_tmp = np.random.randint(256, size=shape) + data = mx.symbol.Variable('data', stype=stype) + + if np.array(shape).shape[0] == 3: + test = mx.symbol.Deconvolution(data=data, kernel=(3,), stride=(2), num_filter=4) + weight_tmp = np.random.normal(-0.1, 0.1, size=(3, 4, 3)) + elif np.array(shape).shape[0] == 4: + test = mx.symbol.Deconvolution(data=data, kernel=(3, 3), stride=(2, 2), num_filter=4) + weight_tmp = np.random.normal(-0.1, 0.1, size=(3,4,3,3)) + else: + return 0 + bias_tmp = np.random.normal(0.1, 0.1, size=(4,)) + in_location = [mx.nd.array(data_tmp).tostype(stype),mx.nd.array(weight_tmp).tostype(stype), mx.nd.array(bias_tmp).tostype(stype)] + check_numeric_gradient(test, in_location, numeric_eps=1e-2,rtol=0.16, atol=1e-4) + + stypes = ['row_sparse', 'default'] + for stype in stypes: + check_Deconvolution_training(stype) + +@with_seed() +def test_LRN(): + def check_LRN_training(stype): + for shape in [(3, 4, 5, 5)]: + data_tmp = np.random.normal(-0.1, 0.1, size=shape) + data = mx.symbol.Variable('data', stype=stype) + in_location = [mx.nd.array(data_tmp).tostype(stype)] + + test = mx.symbol.LRN(data,nsize=3) + check_numeric_gradient(test, in_location, numeric_eps=1e-2,rtol=0.16, atol=1e-4) + + stypes = ['row_sparse', 'default'] + for stype in stypes: + check_LRN_training(stype) + if __name__ == '__main__': test_mkldnn_install()