From 4d749bb1927f26026e71a20ba0deb40090205671 Mon Sep 17 00:00:00 2001 From: ming zhang Date: Thu, 5 Nov 2015 14:45:55 +0800 Subject: [PATCH 1/9] add swapaxis --- src/operator/swapaxis-inl.h | 199 ++++++++++++++++++++++++++++++++++++ src/operator/swapaxis.cc | 32 ++++++ src/operator/swapaxis.cu | 20 ++++ 3 files changed, 251 insertions(+) create mode 100644 src/operator/swapaxis-inl.h create mode 100644 src/operator/swapaxis.cc create mode 100644 src/operator/swapaxis.cu diff --git a/src/operator/swapaxis-inl.h b/src/operator/swapaxis-inl.h new file mode 100644 index 000000000000..865f69565441 --- /dev/null +++ b/src/operator/swapaxis-inl.h @@ -0,0 +1,199 @@ +/*! + * Copyright (c) 2015 by Contributors + * \file swapaxis-inl.h + * \brief + * \author Ming Zhang +*/ +#ifndef MXNET_OPERATOR_SWAPAXIS_INL_H_ +#define MXNET_OPERATOR_SWAPAXIS_INL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "./operator_common.h" + +namespace mxnet { +namespace op { + +struct SwapAxis{ +enum SwapAxisOpInputs {kData}; +enum SwapAxisOpOutputs {kOut}; +}; + + +struct SwapAxisParam : public dmlc::Parameter { + // use int for enumeration + uint32_t dim1, dim2; + DMLC_DECLARE_PARAMETER(SwapAxisParam) { + DMLC_DECLARE_FIELD(dim1) + .set_default(0) + .describe("the first axis to be input."); + DMLC_DECLARE_FIELD(dim2) + .set_default(0) + .describe("the second axis to be input."); + } +}; + +//a1 higher dimension to be swapped, assert a1 > a2 +//a2 lower dimension to be swapped +template +class SwapAxisOp : public Operator { + public: + explicit SwapAxisOp(SwapAxisParam p) { + this->param_ = p; + } + + virtual void Forward(const OpContext &ctx, + const std::vector &in_data, + const std::vector &req, + const std::vector &out_data, + const std::vector &aux_args) { + using namespace mshadow; + using namespace mshadow::expr; + Stream *s = ctx.get_stream(); + + uint32_t dim1 = param_.dim1; + uint32_t dim2 = param_.dim2; + + TBlob data_in = in_data[SwapAxis::kData]; + TBlob data_out = out_data[SwapAxis::kData]; +#if 0 //free dimension + int ndim_in = data_in.ndim(); + + int aDims_in = new int[ndim_in]; + int aDims5[5]; + int si; + for (si = 0; si < ndim_in; si++) + { + aDims_in[si] = data_in.size(si); + } + for (si = 0; si < 5; si++) + { + aDims5[si] = 1; + } + //dim_0 + for (si = 0; si < dim1; si++) + { + aDims5[0] *= aDims_in[si]; + } + //dim_1 + aDims5[1] = aDims_in[dim1]; + //dim_2 + for (si = dim1+1; si < dim2; si++) + { + aDims5[2] *= aDims_in[si]; + } + //dim_3 + aDims5[3] = aDims_in[dim2]; + //dim_4 + for (si = dim2+1; si < ndim_in; si++) + { + aDims5[4] *= aDims_in[si]; + } + + Shape<5> inter_shape = Shape5(aDims5[0], aDims5[1], aDims5[2], aDims5[3], aDims5[4]); +#else //fix 4 dimension + Shape<4> shape_in = data_in.shape_.get<4>(); + Shape<5> inter_shape = Shape5(shape_in.ProdShape(0, dim1), shape_in[dim1], + shape_in.ProdShape(dim1+1, dim2), shape_in[dim2], + shape_in.ProdShape(dim2+1, 4)); +#endif + Tensor inter_data_in = data_in.get_with_shape(inter_shape, s); +// Tensor inter_data = swapaxis<3, 1>(inter_data_in); +// swapaxis<3, 1>(inter_data_in); + Tensor out = data_out.get(s); + Shape<4> shape_out = data_out.shape_.get<4>(); + int dwTmp = 0; + Shape<4> shape_in_tmp = shape_in; + dwTmp = shape_in_tmp[dim1]; + shape_in_tmp[dim1] = shape_in_tmp[dim2]; + shape_in_tmp[dim2] = dwTmp; + + assert(shape_out == shape_in_tmp); + + out = reshape(swapaxis<3, 1>(inter_data_in), shape_out); + +#if 0 + delete []aDims_in; +#endif + } + + virtual void Backward(const OpContext &ctx, + const std::vector &out_grad, + const std::vector &in_data, + const std::vector &out_data, + const std::vector &req, + const std::vector &in_grad, + const std::vector &aux_args) { + + } + + SwapAxisParam param_; +}; + + +template +Operator* CreateOp(SwapAxisParam param); + + +#if DMLC_USE_CXX11 +class SwapAxisProp : public OperatorProperty { + public: + std::vector ListArguments() const override { + return {"data"}; + } + + void Init(const std::vector >& kwargs) override { + param_.Init(kwargs); + } + + std::map GetParams() const override { + return param_.__DICT__(); + } + + bool InferShape(std::vector *in_shape, + std::vector *out_shape, + std::vector *aux_shape) const override { + return true; + } + + OperatorProperty* Copy() const override { + auto ptr = new SwapAxisProp(); + ptr->param_ = param_; + return ptr; + } + + std::string TypeString() const override { + return "SwapAxis"; + } +/* + std::vector DeclareBackwardDependency( + const std::vector &out_grad, + const std::vector &in_data, + const std::vector &out_data) const override; + + std::vector ForwardResource( + const std::vector &in_shape) const override; + + std::vector BackwardResource( + const std::vector &in_shape) const override; +*/ + Operator* CreateOperator(Context ctx) const override; + + private: + SwapAxisParam param_; +}; // class SwapAxisProp +#endif // DMLC_USE_CXX11 + + +} +} + +#endif + + diff --git a/src/operator/swapaxis.cc b/src/operator/swapaxis.cc new file mode 100644 index 000000000000..1ab832edbdbe --- /dev/null +++ b/src/operator/swapaxis.cc @@ -0,0 +1,32 @@ +/*! + * Copyright (c) 2015 by Contributors + * \file swapaxis.cc + * \brief + * \author Ming Zhang +*/ + +#include "./swapaxis-inl.h" + +namespace mxnet { +namespace op { + +template<> +Operator* CreateOp(SwapAxisParam param) { + return new SwapAxisOp(param); +} + +Operator* SwapAxisProp::CreateOperator(Context ctx) const { + DO_BIND_DISPATCH(CreateOp, param_); +} + + +DMLC_REGISTER_PARAMETER(SwapAxisParam); + +MXNET_REGISTER_OP_PROPERTY(SwapAxis, SwapAxisProp) +.add_argument("data", "Symbol", "Input data to the SwapAxisOp.") +.add_arguments(SwapAxisParam::__FIELDS__()) +.describe("Apply swapaxis to input."); + + +} +} diff --git a/src/operator/swapaxis.cu b/src/operator/swapaxis.cu new file mode 100644 index 000000000000..c27d3d2f7a1b --- /dev/null +++ b/src/operator/swapaxis.cu @@ -0,0 +1,20 @@ +/*! + * Copyright (c) 2015 by Contributors + * \file swapaxis.cu + * \brief + * \author Ming Zhang +*/ + +#include "./swapaxis-inl.h" + +namespace mxnet { +namespace op { + +template<> +Operator *CreateOp(SwapAxisParam param) { + return new SwapAxisOp(param); +} + +} // namespace op +} // namespace mxnet + From ab19122c2af3d2921e324861f21f86bccbd6b8fe Mon Sep 17 00:00:00 2001 From: ming zhang Date: Fri, 6 Nov 2015 15:49:26 +0800 Subject: [PATCH 2/9] symbol.SwapAxis can run now, but not sure whether work ok. --- make/config.mk | 6 ++--- mshadow | 2 +- src/operator/swapaxis-inl.h | 48 ++++++++++++++++++++++++++++++++++--- src/operator/swapaxis.cc | 3 +++ 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/make/config.mk b/make/config.mk index db59c81ea4d0..f3784c5869f6 100644 --- a/make/config.mk +++ b/make/config.mk @@ -38,15 +38,15 @@ ADD_CFLAGS = #--------------------------------------------- # whether use CUDA during compile -USE_CUDA = 0 +USE_CUDA = 1 # add the path to CUDA libary to link and compile flag # if you have already add them to enviroment variable, leave it as NONE # USE_CUDA_PATH = /usr/local/cuda -USE_CUDA_PATH = NONE +USE_CUDA_PATH = /usr/local/cuda # whether use CUDNN R3 library -USE_CUDNN = 0 +USE_CUDNN = 1 # whether use opencv during compilation # you can disable it, however, you will not able to use diff --git a/mshadow b/mshadow index ded43f16aedd..dc33ddb9978c 160000 --- a/mshadow +++ b/mshadow @@ -1 +1 @@ -Subproject commit ded43f16aeddd607fde8c2754df67c92bbcaee76 +Subproject commit dc33ddb9978c46aea803526dc0c95105fe0d39d5 diff --git a/src/operator/swapaxis-inl.h b/src/operator/swapaxis-inl.h index 865f69565441..824f24902c17 100644 --- a/src/operator/swapaxis-inl.h +++ b/src/operator/swapaxis-inl.h @@ -17,6 +17,8 @@ #include #include "./operator_common.h" +#define SWAPAXIS_DBG 1 + namespace mxnet { namespace op { @@ -32,10 +34,10 @@ struct SwapAxisParam : public dmlc::Parameter { DMLC_DECLARE_PARAMETER(SwapAxisParam) { DMLC_DECLARE_FIELD(dim1) .set_default(0) - .describe("the first axis to be input."); + .describe("the first axis to be swapped."); DMLC_DECLARE_FIELD(dim2) .set_default(0) - .describe("the second axis to be input."); + .describe("the second axis to be swapped."); } }; @@ -45,6 +47,10 @@ template class SwapAxisOp : public Operator { public: explicit SwapAxisOp(SwapAxisParam p) { + CHECK_LT(p.dim1, p.dim2) << "dim1 must be lower than dim2."; +#if SWAPAXIS_DBG + printf("hello swapaxis SwapAxisOp:dim1:%d, dim2:%d!\n", p.dim1, p.dim2); +#endif this->param_ = p; } @@ -55,8 +61,11 @@ class SwapAxisOp : public Operator { const std::vector &aux_args) { using namespace mshadow; using namespace mshadow::expr; +#if SWAPAXIS_DBG + printf("hello swapaxis Forward!\n"); +#endif Stream *s = ctx.get_stream(); - + uint32_t dim1 = param_.dim1; uint32_t dim2 = param_.dim2; @@ -106,6 +115,7 @@ class SwapAxisOp : public Operator { Tensor inter_data_in = data_in.get_with_shape(inter_shape, s); // Tensor inter_data = swapaxis<3, 1>(inter_data_in); // swapaxis<3, 1>(inter_data_in); + Tensor out = data_out.get(s); Shape<4> shape_out = data_out.shape_.get<4>(); int dwTmp = 0; @@ -159,6 +169,38 @@ class SwapAxisProp : public OperatorProperty { bool InferShape(std::vector *in_shape, std::vector *out_shape, std::vector *aux_shape) const override { + int input_num = in_shape->size(); + if (input_num == 0) + { + std::cout << "Have no input data.\n"; + return false; + } + TShape &shape0 = (*in_shape)[SwapAxis::kData]; +#if SWAPAXIS_DBG + printf("in_shape_num:%d\n", input_num); + printf("in_shape_0, dim:%d, size:%d\n", (int)shape0.ndim(), (int)shape0.Size()); +#endif + if (shape0.ndim() != 4) + { + std::cout << "Input data should be 4D.\n"; + return false; + } + out_shape->clear(); + out_shape->push_back(shape0); + TShape &shape1 = (*out_shape)[SwapAxis::kOut]; +#if 1 + int tmp = 0; + tmp = shape1[param_.dim1]; + shape1[param_.dim1] = shape1[param_.dim2]; + shape1[param_.dim2] = tmp; +#endif +#if SWAPAXIS_DBG + for (int i = 0; i < 4; i++) + { + printf("%d[%d], ", shape1[i], shape0[i]); + } + printf("\n"); +#endif return true; } diff --git a/src/operator/swapaxis.cc b/src/operator/swapaxis.cc index 1ab832edbdbe..8f479088634f 100644 --- a/src/operator/swapaxis.cc +++ b/src/operator/swapaxis.cc @@ -16,6 +16,9 @@ Operator* CreateOp(SwapAxisParam param) { } Operator* SwapAxisProp::CreateOperator(Context ctx) const { +#if SWAPAXIS_DBG + printf("hello swapaxis CreateOperator!\n"); +#endif DO_BIND_DISPATCH(CreateOp, param_); } From 0ca99da558f425e5927b0ede2c38faf62d6a93aa Mon Sep 17 00:00:00 2001 From: ming zhang Date: Fri, 6 Nov 2015 17:39:00 +0800 Subject: [PATCH 3/9] finished forward and backward of symbol.SwapAxis.but still need more tests. --- src/operator/swapaxis-inl.h | 113 ++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 51 deletions(-) diff --git a/src/operator/swapaxis-inl.h b/src/operator/swapaxis-inl.h index 824f24902c17..4e592ec8dd06 100644 --- a/src/operator/swapaxis-inl.h +++ b/src/operator/swapaxis-inl.h @@ -27,6 +27,8 @@ enum SwapAxisOpInputs {kData}; enum SwapAxisOpOutputs {kOut}; }; +using namespace mshadow; +using namespace mshadow::expr; struct SwapAxisParam : public dmlc::Parameter { // use int for enumeration @@ -53,80 +55,84 @@ class SwapAxisOp : public Operator { #endif this->param_ = p; } - - virtual void Forward(const OpContext &ctx, - const std::vector &in_data, - const std::vector &req, - const std::vector &out_data, - const std::vector &aux_args) { - using namespace mshadow; - using namespace mshadow::expr; -#if SWAPAXIS_DBG - printf("hello swapaxis Forward!\n"); -#endif - Stream *s = ctx.get_stream(); - - uint32_t dim1 = param_.dim1; - uint32_t dim2 = param_.dim2; - - TBlob data_in = in_data[SwapAxis::kData]; - TBlob data_out = out_data[SwapAxis::kData]; -#if 0 //free dimension - int ndim_in = data_in.ndim(); - - int aDims_in = new int[ndim_in]; - int aDims5[5]; + + + void Reshape2Five(Shape<5> &inter_shape, TShape &shape, uint32_t dim1, uint32_t dim2) + { + int ndim_in = shape.ndim(); int si; - for (si = 0; si < ndim_in; si++) - { - aDims_in[si] = data_in.size(si); - } for (si = 0; si < 5; si++) { - aDims5[si] = 1; + inter_shape[si] = 1; } //dim_0 for (si = 0; si < dim1; si++) { - aDims5[0] *= aDims_in[si]; + inter_shape[0] *= shape[si]; } //dim_1 - aDims5[1] = aDims_in[dim1]; + inter_shape[1] = shape[dim1]; //dim_2 for (si = dim1+1; si < dim2; si++) { - aDims5[2] *= aDims_in[si]; + inter_shape[2] *= shape[si]; } //dim_3 - aDims5[3] = aDims_in[dim2]; + inter_shape[3] = shape[dim2]; //dim_4 for (si = dim2+1; si < ndim_in; si++) { - aDims5[4] *= aDims_in[si]; + inter_shape[4] *= shape[si]; } + } + + void __swapaxis(Stream *s, const std::vector &in_data, const std::vector &out_data) + { + uint32_t dim1 = param_.dim1; + uint32_t dim2 = param_.dim2; + + TBlob data_in = in_data[SwapAxis::kData]; + TBlob data_out = out_data[SwapAxis::kData]; + + TShape shape_in = data_in.shape_; + TShape shape_out = data_out.shape_; + + Shape<5> inter_shape; + + Reshape2Five(inter_shape, shape_in, dim1, dim2); - Shape<5> inter_shape = Shape5(aDims5[0], aDims5[1], aDims5[2], aDims5[3], aDims5[4]); -#else //fix 4 dimension - Shape<4> shape_in = data_in.shape_.get<4>(); - Shape<5> inter_shape = Shape5(shape_in.ProdShape(0, dim1), shape_in[dim1], - shape_in.ProdShape(dim1+1, dim2), shape_in[dim2], - shape_in.ProdShape(dim2+1, 4)); -#endif Tensor inter_data_in = data_in.get_with_shape(inter_shape, s); -// Tensor inter_data = swapaxis<3, 1>(inter_data_in); -// swapaxis<3, 1>(inter_data_in); - Tensor out = data_out.get(s); - Shape<4> shape_out = data_out.shape_.get<4>(); int dwTmp = 0; - Shape<4> shape_in_tmp = shape_in; - dwTmp = shape_in_tmp[dim1]; - shape_in_tmp[dim1] = shape_in_tmp[dim2]; - shape_in_tmp[dim2] = dwTmp; - assert(shape_out == shape_in_tmp); + Shape<5> inter_shape2 = inter_shape; + inter_shape2[1] = inter_shape[3]; + inter_shape2[3] = inter_shape[1]; + + Tensor inter_data_out = data_out.get_with_shape(inter_shape2, s); - out = reshape(swapaxis<3, 1>(inter_data_in), shape_out); + TShape shape_tmp = shape_in; + dwTmp = shape_tmp[dim1]; + shape_tmp[dim1] = shape_tmp[dim2]; + shape_tmp[dim2] = dwTmp; + + CHECK(shape_out == shape_tmp); + + inter_data_out = swapaxis<3, 1>(inter_data_in); + } + + virtual void Forward(const OpContext &ctx, + const std::vector &in_data, + const std::vector &req, + const std::vector &out_data, + const std::vector &aux_args) { + +#if SWAPAXIS_DBG + printf("hello swapaxis Forward!\n"); +#endif + Stream *s = ctx.get_stream(); + + __swapaxis(s, in_data, out_data); #if 0 delete []aDims_in; @@ -140,7 +146,12 @@ class SwapAxisOp : public Operator { const std::vector &req, const std::vector &in_grad, const std::vector &aux_args) { - +#if SWAPAXIS_DBG + printf("hello swapaxis Backward!\n"); +#endif + Stream *s = ctx.get_stream(); + __swapaxis(s, in_data, out_data); + __swapaxis(s, out_grad, in_data); } SwapAxisParam param_; From 1dd6adaf27b6f39ffb22172c0bd56315d98861b1 Mon Sep 17 00:00:00 2001 From: ming zhang Date: Fri, 6 Nov 2015 17:41:58 +0800 Subject: [PATCH 4/9] disable the debug out. --- src/operator/swapaxis-inl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/operator/swapaxis-inl.h b/src/operator/swapaxis-inl.h index 4e592ec8dd06..e326a36547b2 100644 --- a/src/operator/swapaxis-inl.h +++ b/src/operator/swapaxis-inl.h @@ -17,7 +17,7 @@ #include #include "./operator_common.h" -#define SWAPAXIS_DBG 1 +#define SWAPAXIS_DBG 0 namespace mxnet { namespace op { @@ -150,8 +150,8 @@ class SwapAxisOp : public Operator { printf("hello swapaxis Backward!\n"); #endif Stream *s = ctx.get_stream(); - __swapaxis(s, in_data, out_data); - __swapaxis(s, out_grad, in_data); + __swapaxis(s, in_data, out_data); + __swapaxis(s, out_grad, in_data); } SwapAxisParam param_; From 1a2dc811fb394567548a633e50fc1482397424c8 Mon Sep 17 00:00:00 2001 From: ming zhang Date: Fri, 6 Nov 2015 17:55:48 +0800 Subject: [PATCH 5/9] fixed a bug in Backward. --- src/operator/swapaxis-inl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/operator/swapaxis-inl.h b/src/operator/swapaxis-inl.h index e326a36547b2..efeaa20edfc0 100644 --- a/src/operator/swapaxis-inl.h +++ b/src/operator/swapaxis-inl.h @@ -150,8 +150,8 @@ class SwapAxisOp : public Operator { printf("hello swapaxis Backward!\n"); #endif Stream *s = ctx.get_stream(); - __swapaxis(s, in_data, out_data); - __swapaxis(s, out_grad, in_data); +// __swapaxis(s, in_data, out_data); + __swapaxis(s, out_grad, in_grad); } SwapAxisParam param_; From a0ec24dc99360eb65b9001d7d44ad9cc9a024022 Mon Sep 17 00:00:00 2001 From: ming zhang Date: Fri, 6 Nov 2015 18:00:58 +0800 Subject: [PATCH 6/9] add myself into CONTRIBUTORS.md. --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 9f72042fb3ce..6defe7f66bb6 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -55,3 +55,4 @@ List of Contributors * [Xiaodong](https://github.com/XD-DENG) * [Nan Xiao](https://github.com/road2stat) * [Junyuan Xie](https://github.com/piiswrong) +* [Ming Zhang](https://github.com/starimpact) From 23cfadc39fda8c405144b0f468b7445d47235586 Mon Sep 17 00:00:00 2001 From: ming zhang Date: Sat, 7 Nov 2015 16:10:54 +0800 Subject: [PATCH 7/9] add test_SwapAxis in file test_operator.py. remove the debug info in swapaxis files.some code style change. function is ready to go. --- make/config.mk | 2 +- src/operator/swapaxis-inl.h | 97 +++++++------------------- src/operator/swapaxis.cc | 3 - tests/python/unittest/test_operator.py | 21 ++++++ 4 files changed, 49 insertions(+), 74 deletions(-) diff --git a/make/config.mk b/make/config.mk index f3784c5869f6..34aadee637d1 100644 --- a/make/config.mk +++ b/make/config.mk @@ -38,7 +38,7 @@ ADD_CFLAGS = #--------------------------------------------- # whether use CUDA during compile -USE_CUDA = 1 +USE_CUDA = 0 # add the path to CUDA libary to link and compile flag # if you have already add them to enviroment variable, leave it as NONE diff --git a/src/operator/swapaxis-inl.h b/src/operator/swapaxis-inl.h index efeaa20edfc0..8c4957188e50 100644 --- a/src/operator/swapaxis-inl.h +++ b/src/operator/swapaxis-inl.h @@ -17,8 +17,6 @@ #include #include "./operator_common.h" -#define SWAPAXIS_DBG 0 - namespace mxnet { namespace op { @@ -43,51 +41,39 @@ struct SwapAxisParam : public dmlc::Parameter { } }; -//a1 higher dimension to be swapped, assert a1 > a2 -//a2 lower dimension to be swapped + template class SwapAxisOp : public Operator { public: explicit SwapAxisOp(SwapAxisParam p) { - CHECK_LT(p.dim1, p.dim2) << "dim1 must be lower than dim2."; -#if SWAPAXIS_DBG - printf("hello swapaxis SwapAxisOp:dim1:%d, dim2:%d!\n", p.dim1, p.dim2); -#endif + CHECK_NE(p.dim1, p.dim2) << "dim1 can not be equal dim2."; + if (p.dim1 > p.dim2) { + std::swap(p.dim1, p.dim2); + } this->param_ = p; } - - void Reshape2Five(Shape<5> &inter_shape, TShape &shape, uint32_t dim1, uint32_t dim2) - { + void Reshape2Five(Shape<5> &inter_shape, const TShape &shape, const uint32_t &dim1, const uint32_t &dim2) { int ndim_in = shape.ndim(); - int si; - for (si = 0; si < 5; si++) - { - inter_shape[si] = 1; - } + const index_t *shdata = shape.data(); //dim_0 - for (si = 0; si < dim1; si++) - { - inter_shape[0] *= shape[si]; - } + inter_shape[0] = std::accumulate(shdata, shdata + dim1, 1, std::multiplies()); + //dim_1 - inter_shape[1] = shape[dim1]; + inter_shape[1] = shdata[dim1]; + //dim_2 - for (si = dim1+1; si < dim2; si++) - { - inter_shape[2] *= shape[si]; - } + inter_shape[2] = std::accumulate(shdata + dim1 + 1, shdata + dim2, 1, std::multiplies()); + //dim_3 - inter_shape[3] = shape[dim2]; + inter_shape[3] = shdata[dim2]; + //dim_4 - for (si = dim2+1; si < ndim_in; si++) - { - inter_shape[4] *= shape[si]; - } + inter_shape[4] = std::accumulate(shdata + dim2 + 1, shdata + ndim_in, 1, std::multiplies()); + } - void __swapaxis(Stream *s, const std::vector &in_data, const std::vector &out_data) - { + void __swapaxis(Stream *s, const std::vector &in_data, const std::vector &out_data) { uint32_t dim1 = param_.dim1; uint32_t dim2 = param_.dim2; @@ -106,8 +92,7 @@ class SwapAxisOp : public Operator { int dwTmp = 0; Shape<5> inter_shape2 = inter_shape; - inter_shape2[1] = inter_shape[3]; - inter_shape2[3] = inter_shape[1]; + std::swap(inter_shape2[1], inter_shape2[3]); Tensor inter_data_out = data_out.get_with_shape(inter_shape2, s); @@ -126,17 +111,10 @@ class SwapAxisOp : public Operator { const std::vector &req, const std::vector &out_data, const std::vector &aux_args) { - -#if SWAPAXIS_DBG - printf("hello swapaxis Forward!\n"); -#endif Stream *s = ctx.get_stream(); __swapaxis(s, in_data, out_data); -#if 0 - delete []aDims_in; -#endif } virtual void Backward(const OpContext &ctx, @@ -146,11 +124,7 @@ class SwapAxisOp : public Operator { const std::vector &req, const std::vector &in_grad, const std::vector &aux_args) { -#if SWAPAXIS_DBG - printf("hello swapaxis Backward!\n"); -#endif Stream *s = ctx.get_stream(); -// __swapaxis(s, in_data, out_data); __swapaxis(s, out_grad, in_grad); } @@ -187,31 +161,12 @@ class SwapAxisProp : public OperatorProperty { return false; } TShape &shape0 = (*in_shape)[SwapAxis::kData]; -#if SWAPAXIS_DBG - printf("in_shape_num:%d\n", input_num); - printf("in_shape_0, dim:%d, size:%d\n", (int)shape0.ndim(), (int)shape0.Size()); -#endif - if (shape0.ndim() != 4) - { - std::cout << "Input data should be 4D.\n"; - return false; - } out_shape->clear(); out_shape->push_back(shape0); TShape &shape1 = (*out_shape)[SwapAxis::kOut]; -#if 1 - int tmp = 0; - tmp = shape1[param_.dim1]; - shape1[param_.dim1] = shape1[param_.dim2]; - shape1[param_.dim2] = tmp; -#endif -#if SWAPAXIS_DBG - for (int i = 0; i < 4; i++) - { - printf("%d[%d], ", shape1[i], shape0[i]); - } - printf("\n"); -#endif + + std::swap(shape1[param_.dim1], shape1[param_.dim2]); + return true; } @@ -224,12 +179,14 @@ class SwapAxisProp : public OperatorProperty { std::string TypeString() const override { return "SwapAxis"; } -/* + std::vector DeclareBackwardDependency( const std::vector &out_grad, const std::vector &in_data, - const std::vector &out_data) const override; - + const std::vector &out_data) const override { + return {out_grad[SwapAxis::kOut]}; + }; +/* std::vector ForwardResource( const std::vector &in_shape) const override; diff --git a/src/operator/swapaxis.cc b/src/operator/swapaxis.cc index 8f479088634f..1ab832edbdbe 100644 --- a/src/operator/swapaxis.cc +++ b/src/operator/swapaxis.cc @@ -16,9 +16,6 @@ Operator* CreateOp(SwapAxisParam param) { } Operator* SwapAxisProp::CreateOperator(Context ctx) const { -#if SWAPAXIS_DBG - printf("hello swapaxis CreateOperator!\n"); -#endif DO_BIND_DISPATCH(CreateOp, param_); } diff --git a/tests/python/unittest/test_operator.py b/tests/python/unittest/test_operator.py index fbc007b9fed7..c5cfd7f384c0 100644 --- a/tests/python/unittest/test_operator.py +++ b/tests/python/unittest/test_operator.py @@ -171,8 +171,29 @@ def test_regression(): lambda x: x, lambda x, y : x - y) +def test_SwapAxis(): + print 'test SwapAxis...' + data = mx.symbol.Variable('data') + shape = (2, 3, 4) + data_tmp = np.ones(shape) + data_tmp[0] = 1 + data_tmp[1] = 2 + arr_data = mx.nd.array(data_tmp) + swap0 = mx.symbol.SwapAxis(data=data, dim1=0, dim2=2) + swap = mx.symbol.SwapAxis(data=swap0, dim1=1, dim2=2) + exe_c = swap.bind(mx.cpu(), args=[arr_data]) + exe_c.forward() + out = exe_c.outputs[0].asnumpy() + print data_tmp.shape + print data_tmp + print out.shape + print out + print out.reshape((4, 6)) + + if __name__ == '__main__': test_elementwise_sum() test_concat() test_slice_channel() test_regression() + test_SwapAxis() From fcd62fd987d0860b3a409a5a944ad8e3c2fd571c Mon Sep 17 00:00:00 2001 From: ming zhang Date: Sun, 8 Nov 2015 15:39:11 +0800 Subject: [PATCH 8/9] make code be google style. remove std::accumulate which nvcc doesnot support.change test function name to test_swapaxes. --- make/config.mk | 6 +- src/operator/swapaxis-inl.h | 97 +++++++++++++------------- src/operator/swapaxis.cc | 6 +- tests/python/unittest/test_operator.py | 38 +++++----- 4 files changed, 71 insertions(+), 76 deletions(-) diff --git a/make/config.mk b/make/config.mk index 34aadee637d1..b35d8eac9f5e 100644 --- a/make/config.mk +++ b/make/config.mk @@ -43,10 +43,10 @@ USE_CUDA = 0 # add the path to CUDA libary to link and compile flag # if you have already add them to enviroment variable, leave it as NONE # USE_CUDA_PATH = /usr/local/cuda -USE_CUDA_PATH = /usr/local/cuda +USE_CUDA_PATH = NONE # whether use CUDNN R3 library -USE_CUDNN = 1 +USE_CUDNN = 0 # whether use opencv during compilation # you can disable it, however, you will not able to use @@ -59,7 +59,7 @@ USE_OPENMP = 1 # choose the version of blas you want to use # can be: mkl, blas, atlas, openblas USE_STATIC_MKL = NONE -USE_BLAS = blas +USE_BLAS = atlas # add path to intel libary, you may need it for MKL, if you did not add the path # to enviroment variable diff --git a/src/operator/swapaxis-inl.h b/src/operator/swapaxis-inl.h index 8c4957188e50..f9966f94e9ab 100644 --- a/src/operator/swapaxis-inl.h +++ b/src/operator/swapaxis-inl.h @@ -47,62 +47,61 @@ class SwapAxisOp : public Operator { public: explicit SwapAxisOp(SwapAxisParam p) { CHECK_NE(p.dim1, p.dim2) << "dim1 can not be equal dim2."; - if (p.dim1 > p.dim2) { - std::swap(p.dim1, p.dim2); - } - this->param_ = p; + this->param_ = p; } - - void Reshape2Five(Shape<5> &inter_shape, const TShape &shape, const uint32_t &dim1, const uint32_t &dim2) { - int ndim_in = shape.ndim(); - const index_t *shdata = shape.data(); - //dim_0 - inter_shape[0] = std::accumulate(shdata, shdata + dim1, 1, std::multiplies()); - - //dim_1 - inter_shape[1] = shdata[dim1]; - - //dim_2 - inter_shape[2] = std::accumulate(shdata + dim1 + 1, shdata + dim2, 1, std::multiplies()); - - //dim_3 - inter_shape[3] = shdata[dim2]; - - //dim_4 - inter_shape[4] = std::accumulate(shdata + dim2 + 1, shdata + ndim_in, 1, std::multiplies()); - + + void Reshape2Five(Shape<5> *inter_shape, const TShape &shape, uint32_t dim1, uint32_t dim2) { + index_t ndim_in = shape.ndim(); + int si; + + if (dim1 > dim2) { + std::swap(dim1, dim2); + } + + for (si = 0; si < 5; si++) { + (*inter_shape)[si] = 1; + } + // dim_0 + for (si = 0; si < dim1; si++) { + (*inter_shape)[0] *= shape[si]; + } + // dim_1 + (*inter_shape)[1] = shape[dim1]; + // dim_2 + for (si = dim1 + 1; si < dim2; si++) { + (*inter_shape)[2] *= shape[si]; + } + // dim_3 + (*inter_shape)[3] = shape[dim2]; + // dim_4 + for (si = dim2 + 1; si < ndim_in; si++) { + (*inter_shape)[4] *= shape[si]; + } } - - void __swapaxis(Stream *s, const std::vector &in_data, const std::vector &out_data) { + + void __swapaxis(Stream *s, + const std::vector &in_data, + const std::vector &out_data) { uint32_t dim1 = param_.dim1; uint32_t dim2 = param_.dim2; - + TBlob data_in = in_data[SwapAxis::kData]; TBlob data_out = out_data[SwapAxis::kData]; - + TShape shape_in = data_in.shape_; TShape shape_out = data_out.shape_; - + Shape<5> inter_shape; - - Reshape2Five(inter_shape, shape_in, dim1, dim2); - + + Reshape2Five(&inter_shape, shape_in, dim1, dim2); + Tensor inter_data_in = data_in.get_with_shape(inter_shape, s); - - int dwTmp = 0; - + Shape<5> inter_shape2 = inter_shape; std::swap(inter_shape2[1], inter_shape2[3]); - + Tensor inter_data_out = data_out.get_with_shape(inter_shape2, s); - - TShape shape_tmp = shape_in; - dwTmp = shape_tmp[dim1]; - shape_tmp[dim1] = shape_tmp[dim2]; - shape_tmp[dim2] = dwTmp; - - CHECK(shape_out == shape_tmp); - + inter_data_out = swapaxis<3, 1>(inter_data_in); } @@ -114,7 +113,6 @@ class SwapAxisOp : public Operator { Stream *s = ctx.get_stream(); __swapaxis(s, in_data, out_data); - } virtual void Backward(const OpContext &ctx, @@ -127,7 +125,7 @@ class SwapAxisOp : public Operator { Stream *s = ctx.get_stream(); __swapaxis(s, out_grad, in_grad); } - + SwapAxisParam param_; }; @@ -155,8 +153,7 @@ class SwapAxisProp : public OperatorProperty { std::vector *out_shape, std::vector *aux_shape) const override { int input_num = in_shape->size(); - if (input_num == 0) - { + if (input_num == 0) { std::cout << "Have no input data.\n"; return false; } @@ -201,9 +198,9 @@ class SwapAxisProp : public OperatorProperty { #endif // DMLC_USE_CXX11 -} -} +} // namespace op +} // namespace mxnet -#endif +#endif // MXNET_OPERATOR_SWAPAXIS_INL_H_ diff --git a/src/operator/swapaxis.cc b/src/operator/swapaxis.cc index 1ab832edbdbe..427e83e3619a 100644 --- a/src/operator/swapaxis.cc +++ b/src/operator/swapaxis.cc @@ -26,7 +26,5 @@ MXNET_REGISTER_OP_PROPERTY(SwapAxis, SwapAxisProp) .add_argument("data", "Symbol", "Input data to the SwapAxisOp.") .add_arguments(SwapAxisParam::__FIELDS__()) .describe("Apply swapaxis to input."); - - -} -} +} // namespace op +} // namespace mxnet diff --git a/tests/python/unittest/test_operator.py b/tests/python/unittest/test_operator.py index c5cfd7f384c0..5741c11b179f 100644 --- a/tests/python/unittest/test_operator.py +++ b/tests/python/unittest/test_operator.py @@ -171,24 +171,24 @@ def test_regression(): lambda x: x, lambda x, y : x - y) -def test_SwapAxis(): - print 'test SwapAxis...' - data = mx.symbol.Variable('data') - shape = (2, 3, 4) - data_tmp = np.ones(shape) - data_tmp[0] = 1 - data_tmp[1] = 2 - arr_data = mx.nd.array(data_tmp) - swap0 = mx.symbol.SwapAxis(data=data, dim1=0, dim2=2) - swap = mx.symbol.SwapAxis(data=swap0, dim1=1, dim2=2) - exe_c = swap.bind(mx.cpu(), args=[arr_data]) - exe_c.forward() - out = exe_c.outputs[0].asnumpy() - print data_tmp.shape - print data_tmp - print out.shape - print out - print out.reshape((4, 6)) +def test_swapaxes(): + print 'test swapaxes...' + data = mx.symbol.Variable('data') + shape = (2, 3, 4) + data_tmp = np.ones(shape) + data_tmp[0] = 1 + data_tmp[1] = 2 + arr_data = mx.nd.array(data_tmp) + swap0 = mx.symbol.SwapAxis(data=data, dim1=0, dim2=2) + swap = mx.symbol.SwapAxis(data=swap0, dim1=1, dim2=2) + exe_c = swap.bind(mx.cpu(), args=[arr_data]) + exe_c.forward() + out = exe_c.outputs[0].asnumpy() + print data_tmp.shape + print data_tmp + print out.shape + print out + print out.reshape((4, 6)) if __name__ == '__main__': @@ -196,4 +196,4 @@ def test_SwapAxis(): test_concat() test_slice_channel() test_regression() - test_SwapAxis() + test_swapaxes() From a21d3be9158119bb5eda972febcda00cdf45a94e Mon Sep 17 00:00:00 2001 From: ming zhang Date: Mon, 9 Nov 2015 10:40:26 +0800 Subject: [PATCH 9/9] perfect the codes. --- mshadow | 2 +- src/operator/swapaxis-inl.h | 19 ++++----------- tests/python/unittest/test_operator.py | 33 +++++++++++++------------- 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/mshadow b/mshadow index dc33ddb9978c..e457225d6d95 160000 --- a/mshadow +++ b/mshadow @@ -1 +1 @@ -Subproject commit dc33ddb9978c46aea803526dc0c95105fe0d39d5 +Subproject commit e457225d6d959a783abd4d01984b14e1ea569449 diff --git a/src/operator/swapaxis-inl.h b/src/operator/swapaxis-inl.h index f9966f94e9ab..004797282f1b 100644 --- a/src/operator/swapaxis-inl.h +++ b/src/operator/swapaxis-inl.h @@ -79,7 +79,7 @@ class SwapAxisOp : public Operator { } } - void __swapaxis(Stream *s, + void SwapAxis(Stream *s, const std::vector &in_data, const std::vector &out_data) { uint32_t dim1 = param_.dim1; @@ -112,7 +112,7 @@ class SwapAxisOp : public Operator { const std::vector &aux_args) { Stream *s = ctx.get_stream(); - __swapaxis(s, in_data, out_data); + SwapAxis(s, in_data, out_data); } virtual void Backward(const OpContext &ctx, @@ -123,7 +123,7 @@ class SwapAxisOp : public Operator { const std::vector &in_grad, const std::vector &aux_args) { Stream *s = ctx.get_stream(); - __swapaxis(s, out_grad, in_grad); + SwapAxis(s, out_grad, in_grad); } SwapAxisParam param_; @@ -152,11 +152,8 @@ class SwapAxisProp : public OperatorProperty { bool InferShape(std::vector *in_shape, std::vector *out_shape, std::vector *aux_shape) const override { - int input_num = in_shape->size(); - if (input_num == 0) { - std::cout << "Have no input data.\n"; - return false; - } + CHECK_EQ(in_shape->size(), 1); + TShape &shape0 = (*in_shape)[SwapAxis::kData]; out_shape->clear(); out_shape->push_back(shape0); @@ -183,13 +180,7 @@ class SwapAxisProp : public OperatorProperty { const std::vector &out_data) const override { return {out_grad[SwapAxis::kOut]}; }; -/* - std::vector ForwardResource( - const std::vector &in_shape) const override; - std::vector BackwardResource( - const std::vector &in_shape) const override; -*/ Operator* CreateOperator(Context ctx) const override; private: diff --git a/tests/python/unittest/test_operator.py b/tests/python/unittest/test_operator.py index 5741c11b179f..f2d09b98bf9c 100644 --- a/tests/python/unittest/test_operator.py +++ b/tests/python/unittest/test_operator.py @@ -172,23 +172,22 @@ def test_regression(): lambda x, y : x - y) def test_swapaxes(): - print 'test swapaxes...' - data = mx.symbol.Variable('data') - shape = (2, 3, 4) - data_tmp = np.ones(shape) - data_tmp[0] = 1 - data_tmp[1] = 2 - arr_data = mx.nd.array(data_tmp) - swap0 = mx.symbol.SwapAxis(data=data, dim1=0, dim2=2) - swap = mx.symbol.SwapAxis(data=swap0, dim1=1, dim2=2) - exe_c = swap.bind(mx.cpu(), args=[arr_data]) - exe_c.forward() - out = exe_c.outputs[0].asnumpy() - print data_tmp.shape - print data_tmp - print out.shape - print out - print out.reshape((4, 6)) + data = mx.symbol.Variable('data') + shape = (2, 3, 4) + data_tmp = np.ones(shape) + data_tmp[0] = 1 + data_tmp[1] = 2 + arr_data = mx.nd.array(data_tmp) + swap0 = mx.symbol.SwapAxis(data=data, dim1=0, dim2=2) + swap = mx.symbol.SwapAxis(data=swap0, dim1=1, dim2=2) + exe_c = swap.bind(mx.cpu(), args=[arr_data]) + exe_c.forward() + out = exe_c.outputs[0].asnumpy() + + swap0_ = np.swapaxes(data_tmp, 0, 2) + swap_ = np.swapaxes(swap0_, 1, 2) + + assert reldiff(out, swap_) < 1e-6 if __name__ == '__main__':