From 52381994f645e70148884b73a93fd11d46e45203 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 26 Oct 2018 18:01:48 +0000 Subject: [PATCH 1/3] adding unit test for MKLDNN FullyConnected operator --- tests/cpp/operator/mkldnn_operator_test.cc | 161 +++++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/tests/cpp/operator/mkldnn_operator_test.cc b/tests/cpp/operator/mkldnn_operator_test.cc index d53f17448d41..01e008b6f4a5 100644 --- a/tests/cpp/operator/mkldnn_operator_test.cc +++ b/tests/cpp/operator/mkldnn_operator_test.cc @@ -213,6 +213,38 @@ OpAttrs GetLRNBackwardsOp() { return attrs; } +OpAttrs GetFullyConnectedOp() { + OpAttrs attrs; + attrs.attrs.op = Op::Get("FullyConnected"); + attrs.attrs.dict.insert({"num_hidden" , "20"}); + attrs.num_inputs = 3; + attrs.num_outputs = 1; + attrs.attrs.op->attr_parser(&attrs.attrs); + attrs.dispatches.resize(2); + attrs.requests.insert(OpReqType::kWriteTo); + attrs.input_types = ArrayTypes::Normal | + ArrayTypes::MKLDNN | + ArrayTypes::NormalReshaped | + ArrayTypes::MKLDNNReshaped; + attrs.output_types = ArrayTypes::Normal | + ArrayTypes::MKLDNN | + ArrayTypes::NormalReshaped | + ArrayTypes::MKLDNNReshaped; + return attrs; +} + +OpAttrs GetFullyConnectedBackwardsOp() { + OpAttrs attrs; + attrs.attrs.op = Op::Get("_backward_FullyConnected"); + attrs.attrs.dict.insert({"num_hidden" , "20"}); + attrs.num_inputs = 3; + attrs.num_outputs = 3; + attrs.attrs.op->attr_parser(&attrs.attrs); + attrs.dispatches.resize(2); + attrs.requests.insert(OpReqType::kWriteTo); + return attrs; +} + void AssertEqual(const std::vector &in_arrs, const std::vector &out_arrs) { NDArray tmp1 = in_arrs[0]->Reorder2Default(); @@ -554,6 +586,129 @@ void TestOpEx(const OpAttrs &forward_attrs, const OpAttrs &backwards_attrs) { } } +uint32_t weight_dim2(const nnvm::TShape arr) { + uint32_t dim = 1; + for (int i = 1; i < arr.ndim(); i++) { + dim *= arr[i]; + } + return dim; +} + +void TestFullyConnectedOp(const OpAttrs &forward_attrs, const OpAttrs &backwards_attrs) { + std::vector inputs(forward_attrs.num_inputs); + std::vector outputs(forward_attrs.num_outputs); + std::vector ex_outputs(forward_attrs.num_outputs); + + std::vector backwards_input(backwards_attrs.num_inputs); + std::vector backwards_outputs(backwards_attrs.num_outputs); + std::vector backwards_ex_outputs(backwards_attrs.num_outputs); + + std::vector req(forward_attrs.num_outputs); + std::vector back_req(backwards_attrs.num_outputs); + + TestArrayShapes tas = GetTestArrayShapes(); + std::vector pds = tas.pds; + + std::vector in_arrs = GetTestInputArrays(forward_attrs.input_types, true); + std::vector> out_arrs(forward_attrs.num_outputs); + std::vector> ex_out_arrs(forward_attrs.num_outputs); + + std::string str_hid = const_cast(forward_attrs).attrs.dict["num_hidden"]; + int num_hid = std::stoi(str_hid); + + if (forward_attrs.requests.find(OpReqType::kWriteTo) != forward_attrs.requests.end()) { + for (int i1 = 0; i1 < in_arrs.size(); i1++) { + auto in_arr = in_arrs[i1]; + + if (in_arr.arr.shape().ndim() < 2) + continue; + + auto in_shape = in_arr.arr.shape(); + + nnvm::TShape wt_shape(2); + wt_shape[0] = num_hid; + wt_shape[1] = weight_dim2(in_shape); + NDArray weights(wt_shape, Context()); + InitDefaultArray(&weights, false); + + nnvm::TShape bias_shape(1); + bias_shape[0] = num_hid; + NDArray bias(bias_shape, Context()); + InitDefaultArray(&bias, false); + + inputs[0] = &in_arr.arr; + inputs[1] = &weights; + inputs[2] = &bias; + + nnvm::TShape out_shape(2); + out_shape[0] = in_shape[0]; + out_shape[1] = num_hid; + + for (int i = 0; i < forward_attrs.num_outputs; i++) { + out_arrs[i] = + GetTestOutputArrays(out_shape, pds, {1}, forward_attrs.output_types); + ex_out_arrs[i] = + GetTestOutputArrays(out_shape, pds, {1}, forward_attrs.output_types); + } + + for (size_t output_i = 0; output_i < out_arrs[0].size(); output_i++) { + if (out_arrs[0][output_i].arr.IsMKLDNNData()) + continue; + + for (int i = 0; i < forward_attrs.num_outputs; i++) { + req[i] = kWriteTo; + outputs[i] = &out_arrs[i][output_i].arr; + ex_outputs[i] = &ex_out_arrs[i][output_i].arr; + } + Imperative::Get()->set_is_training(true); + + PrintVerifyMsg(in_arr, out_arrs[0][output_i]); + Imperative::Get()->InvokeOp( + Context(), forward_attrs.attrs, inputs, outputs, req, + DispatchMode::kFCompute, mxnet::OpStatePtr()); + Imperative::Get()->InvokeOp( + Context(), forward_attrs.attrs, inputs, ex_outputs, req, + DispatchMode::kFComputeEx, mxnet::OpStatePtr()); + Engine::Get()->WaitForAll(); + AssertEqual(outputs, ex_outputs); + + // backwards test performed same time since output needed + backwards_input[0] = outputs[0]; // output grad + backwards_input[1] = inputs[0]; // input + backwards_input[2] = inputs[1]; // weights + + auto tmp_output = GetTestInputArrays(forward_attrs.input_types, true)[i1]; + NDArray back_weights(wt_shape, Context()); + NDArray back_bias(bias_shape, Context()); + backwards_outputs[0] = &tmp_output.arr; + backwards_outputs[1] = &back_weights; + backwards_outputs[2] = &back_bias; + + auto tmp_output2 = GetTestInputArrays(forward_attrs.input_types, true)[i1]; + NDArray back_ex_weights(wt_shape, Context()); + NDArray back_ex_bias(bias_shape, Context()); + backwards_ex_outputs[0] = &tmp_output2.arr; + backwards_ex_outputs[1] = &back_ex_weights; + backwards_ex_outputs[2] = &back_ex_bias; + + for (int i = 0; i < backwards_attrs.num_outputs; i++) + back_req[i] = kWriteTo; + + std::cout << "Backwards: "; + PrintVerifyMsg(out_arrs[0][output_i], tmp_output); + Imperative::Get()->InvokeOp( + Context(), backwards_attrs.attrs, backwards_input, backwards_outputs, + back_req, DispatchMode::kFCompute, mxnet::OpStatePtr()); + Imperative::Get()->InvokeOp( + Context(), backwards_attrs.attrs, backwards_input, backwards_ex_outputs, + back_req, DispatchMode::kFComputeEx, mxnet::OpStatePtr()); + Engine::Get()->WaitForAll(); + AssertEqual(backwards_outputs, backwards_ex_outputs); + } + } + } +} + void TestPoolingOp(const OpAttrs &forward_attrs, const OpAttrs &backwards_attrs) { std::vector inputs(forward_attrs.num_inputs); std::vector outputs(forward_attrs.num_outputs); @@ -714,6 +869,12 @@ TEST(IMPERATIVE, LRNOp) { TestOpEx(forward_attrs, backwards_attrs); } +TEST(IMPERATIVE, FullyConnectedOp) { + OpAttrs forward_attrs = GetFullyConnectedOp(); + OpAttrs backwards_attrs = GetFullyConnectedBackwardsOp(); + TestFullyConnectedOp(forward_attrs, backwards_attrs); +} + TEST(IMPERATIVE, PoolingOp) { for (int dim = 2; dim < 4; dim++) { for (int kernel = 1; kernel < 4; kernel++) { From 33691b22597c41f3a269db66c909186ddf75e978 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 31 Oct 2018 00:05:06 +0000 Subject: [PATCH 2/3] removing mkldnn filter --- tests/cpp/operator/mkldnn_operator_test.cc | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tests/cpp/operator/mkldnn_operator_test.cc b/tests/cpp/operator/mkldnn_operator_test.cc index 01e008b6f4a5..6d9d4e89598b 100644 --- a/tests/cpp/operator/mkldnn_operator_test.cc +++ b/tests/cpp/operator/mkldnn_operator_test.cc @@ -220,7 +220,6 @@ OpAttrs GetFullyConnectedOp() { attrs.num_inputs = 3; attrs.num_outputs = 1; attrs.attrs.op->attr_parser(&attrs.attrs); - attrs.dispatches.resize(2); attrs.requests.insert(OpReqType::kWriteTo); attrs.input_types = ArrayTypes::Normal | ArrayTypes::MKLDNN | @@ -240,7 +239,6 @@ OpAttrs GetFullyConnectedBackwardsOp() { attrs.num_inputs = 3; attrs.num_outputs = 3; attrs.attrs.op->attr_parser(&attrs.attrs); - attrs.dispatches.resize(2); attrs.requests.insert(OpReqType::kWriteTo); return attrs; } @@ -586,7 +584,8 @@ void TestOpEx(const OpAttrs &forward_attrs, const OpAttrs &backwards_attrs) { } } -uint32_t weight_dim2(const nnvm::TShape arr) { +// Computes second dimension of FC weight matrix based on input shape +uint32_t GetFCWeightDim2(const nnvm::TShape arr) { uint32_t dim = 1; for (int i = 1; i < arr.ndim(); i++) { dim *= arr[i]; @@ -627,7 +626,7 @@ void TestFullyConnectedOp(const OpAttrs &forward_attrs, const OpAttrs &backwards nnvm::TShape wt_shape(2); wt_shape[0] = num_hid; - wt_shape[1] = weight_dim2(in_shape); + wt_shape[1] = GetFCWeightDim2(in_shape); NDArray weights(wt_shape, Context()); InitDefaultArray(&weights, false); @@ -652,9 +651,6 @@ void TestFullyConnectedOp(const OpAttrs &forward_attrs, const OpAttrs &backwards } for (size_t output_i = 0; output_i < out_arrs[0].size(); output_i++) { - if (out_arrs[0][output_i].arr.IsMKLDNNData()) - continue; - for (int i = 0; i < forward_attrs.num_outputs; i++) { req[i] = kWriteTo; outputs[i] = &out_arrs[i][output_i].arr; From a0cf76e3748cf1d227062210c4d710051d489499 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 31 Oct 2018 00:15:56 +0000 Subject: [PATCH 3/3] removing mkldnn filter --- tests/cpp/operator/mkldnn_operator_test.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/cpp/operator/mkldnn_operator_test.cc b/tests/cpp/operator/mkldnn_operator_test.cc index 6d9d4e89598b..398ae97e2b97 100644 --- a/tests/cpp/operator/mkldnn_operator_test.cc +++ b/tests/cpp/operator/mkldnn_operator_test.cc @@ -618,11 +618,9 @@ void TestFullyConnectedOp(const OpAttrs &forward_attrs, const OpAttrs &backwards if (forward_attrs.requests.find(OpReqType::kWriteTo) != forward_attrs.requests.end()) { for (int i1 = 0; i1 < in_arrs.size(); i1++) { auto in_arr = in_arrs[i1]; - - if (in_arr.arr.shape().ndim() < 2) - continue; - auto in_shape = in_arr.arr.shape(); + if (in_shape.ndim() < 2) + continue; nnvm::TShape wt_shape(2); wt_shape[0] = num_hid;