From 2e2634e97daf2ff8c1ce763d79cc28240c923b58 Mon Sep 17 00:00:00 2001 From: zhupengyang <1165938320@qq.com> Date: Wed, 12 Feb 2020 11:04:57 +0800 Subject: [PATCH] [NPU] test transpose below 4-D (#2849) --- lite/kernels/npu/bridges/transpose_op.cc | 5 + lite/tests/kernels/transpose_compute_test.cc | 120 ++++++++++++------- 2 files changed, 85 insertions(+), 40 deletions(-) diff --git a/lite/kernels/npu/bridges/transpose_op.cc b/lite/kernels/npu/bridges/transpose_op.cc index bdac84df3c..97df11f923 100644 --- a/lite/kernels/npu/bridges/transpose_op.cc +++ b/lite/kernels/npu/bridges/transpose_op.cc @@ -37,7 +37,12 @@ int TransposeConverter(void* ctx, OpLite* op, KernelBase* kernel) { CHECK(x_type->layout() == DATALAYOUT(kNCHW)); auto x = scope->FindMutableTensor(x_name); auto x_dims = x->dims(); + auto out_name = op_info->Output("Out").front(); + auto out_type = kernel->GetOutputDeclType("Out"); + CHECK(out_type->precision() == PRECISION(kFloat)); + CHECK(out_type->layout() == DATALAYOUT(kNCHW)); + auto axis = op_info->GetAttr>("axis"); // X node diff --git a/lite/tests/kernels/transpose_compute_test.cc b/lite/tests/kernels/transpose_compute_test.cc index b4407bb569..0ec010e47f 100644 --- a/lite/tests/kernels/transpose_compute_test.cc +++ b/lite/tests/kernels/transpose_compute_test.cc @@ -21,19 +21,40 @@ namespace paddle { namespace lite { -int data_index(std::vector pos, DDimLite dims) { - int d1 = dims[1]; - int d2 = dims[2]; - int d3 = dims[3]; - return pos[0] * d1 * d2 * d3 + pos[1] * d2 * d3 + pos[2] * d3 + pos[3]; +std::vector CalStrides(const DDim& dims) { + int dsize = dims.size(); + std::vector strides(dsize, 1); + for (int i = dsize - 2; i >= 0; i--) { + strides[i] = strides[i + 1] * dims[i + 1]; + } + return strides; +} + +std::vector CalIndex(const std::vector& strides, int offset) { + int dsize = strides.size(); + std::vector index(dsize, 0); + for (int i = 0; i < dsize; i++) { + index[i] = offset / strides[i]; + offset %= strides[i]; + } + return index; } -std::vector pos_trans(std::vector in_pos, std::vector axis) { - std::vector out_pos(in_pos.size()); +std::vector TransIndex(const std::vector& in_index, + const std::vector& axis) { + std::vector out_index(in_index.size(), 0); for (int i = 0; i < axis.size(); i++) { - out_pos[i] = in_pos[axis[i]]; + out_index[i] = in_index[axis[i]]; + } + return out_index; +} + +int CalOffset(const std::vector& strides, const std::vector& index) { + int offset = 0; + for (int i = 0; i < index.size(); i++) { + offset += strides[i] * index[i]; } - return out_pos; + return offset; } class TransposeComputeTester : public arena::TestCase { @@ -64,29 +85,19 @@ class TransposeComputeTester : public arena::TestCase { out_shape[i] = dims_[axis_[i]]; } out->Resize(out_shape); + auto out_dims = out->dims(); + + std::vector x_strides = CalStrides(dims_); + std::vector out_strides = CalStrides(out_dims); + + auto x_data = x->data(); + auto out_data = out->mutable_data(); - auto y_dims = out->dims(); - - int input_n = dims_[0]; - int input_c = dims_[1]; - int input_h = dims_[2]; - int input_w = dims_[3]; - - auto input_data = x->data(); - auto output_data = out->mutable_data(); - - for (int n = 0; n < input_n; ++n) { - for (int c = 0; c < input_c; ++c) { - for (int h = 0; h < input_h; ++h) { - for (int w = 0; w < input_w; ++w) { - std::vector in_pos{n, c, h, w}; - std::vector out_pos = pos_trans(in_pos, axis_); - int in_index = data_index(in_pos, dims_); - int out_index = data_index(out_pos, y_dims); - output_data[out_index] = input_data[in_index]; - } - } - } + for (int i = 0; i < dims_.production(); i++) { + std::vector x_index = CalIndex(x_strides, i); + std::vector out_index = TransIndex(x_index, axis_); + int out_offset = CalOffset(out_strides, out_index); + out_data[out_offset] = x_data[i]; } if (op_type_ == "transpose2") { @@ -114,6 +125,41 @@ class TransposeComputeTester : public arena::TestCase { } }; +void TestTranspose2D(Place place, float abs_error) { + DDim x_dims{{4, 5}}; + std::vector> axes{{0, 1}, {1, 0}}; + for (auto axis : axes) { + std::unique_ptr tester( + new TransposeComputeTester(place, "def", x_dims, axis)); + arena::Arena arena(std::move(tester), place, abs_error); + arena.TestPrecision({"xshape"}); + } +} + +void TestTranspose3D(Place place, float abs_error) { + DDim x_dims{{3, 4, 5}}; + std::vector> axes{ + {0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {2, 1, 0}}; + for (auto axis : axes) { + std::unique_ptr tester( + new TransposeComputeTester(place, "def", x_dims, axis)); + arena::Arena arena(std::move(tester), place, abs_error); + arena.TestPrecision({"xshape"}); + } +} + +void TestTranspose4D(Place place, float abs_error) { + DDim x_dims{{2, 3, 4, 5}}; + std::vector> axes{ + {0, 1, 2, 3}, {0, 1, 3, 2}, {0, 2, 1, 3}, {3, 1, 2, 0}, {3, 1, 0, 2}}; + for (auto axis : axes) { + std::unique_ptr tester( + new TransposeComputeTester(place, "def", x_dims, axis)); + arena::Arena arena(std::move(tester), place, abs_error); + arena.TestPrecision({"xshape"}); + } +} + TEST(Transpose, precision) { LOG(INFO) << "test Transpose op"; float abs_error = 2e-5; @@ -127,15 +173,9 @@ TEST(Transpose, precision) { return; #endif - DDim x_dims{{2, 3, 4, 5}}; - std::vector> axes{ - {0, 1, 2, 3}, {0, 1, 3, 2}, {0, 2, 1, 3}, {3, 1, 2, 0}, {3, 1, 0, 2}}; - for (auto axis : axes) { - std::unique_ptr tester( - new TransposeComputeTester(place, "def", x_dims, axis)); - arena::Arena arena(std::move(tester), place, abs_error); - arena.TestPrecision({"xshape"}); - } + TestTranspose2D(place, abs_error); + TestTranspose3D(place, abs_error); + TestTranspose4D(place, abs_error); } } // namespace lite -- GitLab