diff --git a/.gitignore b/.gitignore index 53ea5038737b7295cb1465274d95db484fe7d5f7..9db2912c07bc2d6abb01c322a25519ac0ff158fa 100644 --- a/.gitignore +++ b/.gitignore @@ -72,6 +72,9 @@ build cmake-build-debug cmake-build-release +# vscode +.vscode + # ios tools/libomp.a diff --git a/lite/api/_paddle_use_kernels.h b/lite/api/_paddle_use_kernels.h index 50456e02cd2062239b970dcf86ada02efaafd74b..75756736f40a707fee06b0139f628b13225d04aa 100644 --- a/lite/api/_paddle_use_kernels.h +++ b/lite/api/_paddle_use_kernels.h @@ -139,6 +139,7 @@ USE_LITE_KERNEL(assign, kARM, kFloat, kNCHW, def); // USE_LITE_KERNEL(mul, kX86, kFloat, kNCHW, def); // USE_LITE_KERNEL(fc, kX86, kFloat, kNCHW, def); USE_LITE_KERNEL(scale, kX86, kFloat, kNCHW, def); +USE_LITE_KERNEL(slice, kX86, kFloat, kNCHW, def); // USE_LITE_KERNEL(fill_constant, kX86, kFloat, kNCHW, def); // USE_LITE_KERNEL(square, kX86, kFloat, kNCHW, def); // USE_LITE_KERNEL(elementwise_sub, kX86, kFloat, kNCHW, def); diff --git a/lite/kernels/x86/CMakeLists.txt b/lite/kernels/x86/CMakeLists.txt index e34f6823c9b4ef5b74cb88af30fb7fd0fd06eb66..7941cde03e78e01fa97b2565b4c6b4d642badd00 100644 --- a/lite/kernels/x86/CMakeLists.txt +++ b/lite/kernels/x86/CMakeLists.txt @@ -11,6 +11,9 @@ endif() # lite_cc_library(mul_compute_x86 SRCS mul_compute.cc DEPS ${lite_kernel_deps}) # lite_cc_library(relu_compute_x86 SRCS relu_compute.cc DEPS ${lite_kernel_deps}) add_kernel(scale_compute_x86 X86 basic SRCS scale_compute.cc DEPS ${lite_kernel_deps}) +add_kernel(slice_compute_x86 X86 basic SRCS slice_compute.cc DEPS ${lite_kernel_deps}) +add_kernel(squeeze_compute_x86 X86 basic SRCS squeeze_compute.cc DEPS ${lite_kernel_deps}) +add_kernel(reshape_compute_x86 X86 basic SRCS reshape_compute.cc DEPS ${lite_kernel_deps} reshape_op) # lite_cc_library(elementwise_compute_x86 SRCS elementwise_compute.cc DEPS ${lite_kernel_deps} elementwise_sub_op elementwise_add_op) # lite_cc_library(softmax_compute_x86 SRCS softmax_compute.cc DEPS ${lite_kernel_deps} softmax) # lite_cc_library(dropout_compute_x86 SRCS dropout_compute.cc DEPS ${lite_kernel_deps} ) @@ -36,6 +39,9 @@ add_kernel(sequence_pool_compute_x86 X86 basic SRCS sequence_pool_compute.cc DEP add_kernel(softmax_compute_x86 X86 basic SRCS softmax_compute.cc DEPS ${lite_kernel_deps} softmax) lite_cc_test(test_mul_compute_x86 SRCS mul_compute_test.cc DEPS mul_compute_x86) +lite_cc_test(test_slice_compute_x86 SRCS slice_compute_test.cc DEPS slice_compute_x86) +lite_cc_test(test_squeeze_compute_x86 SRCS squeeze_compute_test.cc DEPS squeeze_compute_x86) +lite_cc_test(test_reshape_compute_x86 SRCS reshape_compute_test.cc DEPS reshape_compute_x86) lite_cc_test(test_concat_compute_x86 SRCS concat_compute_test.cc DEPS concat_compute_x86) lite_cc_test(test_sequence_pool_compute_x86 SRCS sequence_pool_compute_test.cc DEPS sequence_pool_compute_x86) lite_cc_test(test_shape_compute_x86 SRCS shape_compute_test.cc DEPS shape_compute_x86) diff --git a/lite/kernels/x86/reshape_compute.cc b/lite/kernels/x86/reshape_compute.cc new file mode 100644 index 0000000000000000000000000000000000000000..abbb0f6af54106d06369c7a90cbdc2a554a42a3c --- /dev/null +++ b/lite/kernels/x86/reshape_compute.cc @@ -0,0 +1,36 @@ +// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "lite/kernels/x86/reshape_compute.h" + +REGISTER_LITE_KERNEL(reshape, + kX86, + kFloat, + kNCHW, + paddle::lite::kernels::x86::ReshapeCompute, + def) + .BindInput("X", {LiteType::GetTensorTy(TARGET(kX86))}) + .BindOutput("Out", {LiteType::GetTensorTy(TARGET(kX86))}) + .Finalize(); + +REGISTER_LITE_KERNEL(reshape2, + kX86, + kFloat, + kNCHW, + paddle::lite::kernels::x86::Reshape2Compute, + def) + .BindInput("X", {LiteType::GetTensorTy(TARGET(kX86))}) + .BindOutput("Out", {LiteType::GetTensorTy(TARGET(kX86))}) + .BindOutput("XShape", {LiteType::GetTensorTy(TARGET(kX86))}) + .Finalize(); diff --git a/lite/kernels/x86/reshape_compute.h b/lite/kernels/x86/reshape_compute.h new file mode 100644 index 0000000000000000000000000000000000000000..c17daf85aeab1713077fc8b0219bb431e443c1a9 --- /dev/null +++ b/lite/kernels/x86/reshape_compute.h @@ -0,0 +1,79 @@ +// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include +#include "lite/core/kernel.h" +#include "lite/core/op_lite.h" +#include "lite/core/op_registry.h" +#include "lite/core/type_system.h" +#include "lite/operators/reshape_op.h" + +namespace paddle { +namespace lite { +namespace kernels { +namespace x86 { + +template +void Compute(const lite::Tensor* in, + const lite::Tensor* actual_shape, + lite::Tensor* out) { + auto out_dims = out->dims(); + auto in_dims = in->dims(); + if (actual_shape) { + auto shape_dims = actual_shape->dims(); + const int* shape_data = actual_shape->data(); + std::vector shape = + std::vector(shape_data, shape_data + shape_dims.production()); + out_dims = lite::operators::ValidateShape(shape, in_dims); + out->Resize(out_dims); + } + out->CopyDataFrom(*in); + out->Resize(out_dims); +} + +template +class ReshapeCompute : public KernelLite { + public: + using param_t = operators::ReshapeParam; + + void Run() override { + auto& param = *param_.get_mutable(); + Compute(param.x, param.actual_shape, param.output); + } + + virtual ~ReshapeCompute() = default; +}; + +template +void reshape2_compute() {} + +template +class Reshape2Compute : public KernelLite { + public: + using param_t = operators::ReshapeParam; + + void Run() override { + auto& param = *param_.get_mutable(); + Compute(param.x, param.actual_shape, param.output); + } + + virtual ~Reshape2Compute() = default; +}; + +} // namespace x86 +} // namespace kernels +} // namespace lite +} // namespace paddle diff --git a/lite/kernels/x86/reshape_compute_test.cc b/lite/kernels/x86/reshape_compute_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..a9a8d38d06ce01a96223ed8abfc784a4067a6004 --- /dev/null +++ b/lite/kernels/x86/reshape_compute_test.cc @@ -0,0 +1,156 @@ +// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "lite/kernels/x86/reshape_compute.h" +#include +#include +#include +#include +#include +#include "lite/core/op_registry.h" +namespace paddle { +namespace lite { +namespace kernels { +namespace x86 { + +// reshape +TEST(reshape_x86, retrive_op) { + auto reshape = + KernelRegistry::Global().Create( + "reshape"); + ASSERT_FALSE(reshape.empty()); + ASSERT_TRUE(reshape.front()); +} + +TEST(reshape_x86, init) { + lite::kernels::x86::ReshapeCompute reshape; + ASSERT_EQ(reshape.precision(), PRECISION(kFloat)); + ASSERT_EQ(reshape.target(), TARGET(kX86)); +} + +TEST(reshape_x86, run_test) { + lite::Tensor x, actual_shape; + lite::Tensor out; + std::vector x_shape({1, 2, 4, 1}); + x.Resize(lite::DDim(x_shape)); + actual_shape.Resize(lite::DDim(std::vector({3}))); + std::vector out_shape({1, 8, 1, 1}); + out.Resize(lite::DDim(out_shape)); + + auto x_data = x.mutable_data(); + auto actual_data = actual_shape.mutable_data(); + auto out_data = out.mutable_data(); + + for (int64_t i = 0; i < x.dims().production(); ++i) { + x_data[i] = static_cast(i); + } + actual_data[0] = 1; + actual_data[1] = 4; + actual_data[2] = 2; + + std::vector shape({1, 8, 1, 1}); + + // ReshapeCompute reshape; + ReshapeCompute reshape; + operators::ReshapeParam param; + + param.x = &x; + param.output = &out; + param.shape = shape; + param.actual_shape = &actual_shape; + std::unique_ptr ctx(new KernelContext); + ctx->As(); + for (int i = 0; i < 2; ++i) { + if (1 == i) param.actual_shape = nullptr; + reshape.SetContext(std::move(ctx)); + reshape.SetParam(param); + reshape.Run(); + + for (int j = 0; j < out.dims().production(); ++j) { + EXPECT_NEAR(out_data[j], x_data[j], 1e-5); + } + } +} + +// reshape2 +TEST(reshape2_x86, retrive_op) { + auto reshape2 = + KernelRegistry::Global().Create( + "reshape2"); + ASSERT_FALSE(reshape2.empty()); + ASSERT_TRUE(reshape2.front()); +} + +TEST(reshape2_x86, init) { + lite::kernels::x86::Reshape2Compute reshape2; + ASSERT_EQ(reshape2.precision(), PRECISION(kFloat)); + ASSERT_EQ(reshape2.target(), TARGET(kX86)); +} + +TEST(reshape2_x86, run_test) { + lite::Tensor x, actual_shape; + lite::Tensor out, xshape; + std::vector x_shape({1, 2, 4}); + x.Resize(lite::DDim(x_shape)); + actual_shape.Resize(lite::DDim(std::vector({3}))); + std::vector out_shape({1, 4, 2}); + out.Resize(lite::DDim(out_shape)); + std::vector xshape_shape({1, 2, 4}); + xshape.Resize(lite::DDim(xshape_shape)); + + auto x_data = x.mutable_data(); + auto actual_data = actual_shape.mutable_data(); + auto out_data = out.mutable_data(); + auto xshape_data = xshape.mutable_data(); + + for (int64_t i = 0; i < x.dims().production(); ++i) { + x_data[i] = static_cast(i); + xshape_data[i] = static_cast(i); + } + actual_data[0] = 1; + actual_data[1] = 4; + actual_data[2] = 2; + + std::vector shape({0, -1, 2}); + + // Reshape2Compute reshape2; + Reshape2Compute reshape2; + operators::ReshapeParam param; + + param.x = &x; + param.output = &out; + param.xshape = &xshape; + param.shape = shape; + param.actual_shape = &actual_shape; + std::unique_ptr ctx(new KernelContext); + ctx->As(); + for (int i = 0; i < 2; ++i) { + if (1 == i) param.actual_shape = nullptr; + reshape2.SetContext(std::move(ctx)); + reshape2.SetParam(param); + reshape2.Run(); + + for (int j = 0; j < out.dims().production(); ++j) { + EXPECT_NEAR(out_data[j], x_data[j], 1e-5); + } + } +} + +} // namespace x86 +} // namespace kernels +} // namespace lite +} // namespace paddle + +USE_LITE_KERNEL(reshape, kX86, kFloat, kNCHW, def); +USE_LITE_KERNEL(reshape2, kX86, kFloat, kNCHW, def); diff --git a/lite/kernels/x86/slice_compute.cc b/lite/kernels/x86/slice_compute.cc new file mode 100644 index 0000000000000000000000000000000000000000..00602ce62b80814e2b78460122bd3ed3cc8b81a8 --- /dev/null +++ b/lite/kernels/x86/slice_compute.cc @@ -0,0 +1,25 @@ +// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "lite/kernels/x86/slice_compute.h" + +REGISTER_LITE_KERNEL(slice, + kX86, + kFloat, + kNCHW, + paddle::lite::kernels::x86::SliceCompute, + def) + .BindInput("Input", {LiteType::GetTensorTy(TARGET(kX86))}) + .BindOutput("Out", {LiteType::GetTensorTy(TARGET(kX86))}) + .Finalize(); diff --git a/lite/kernels/x86/slice_compute.h b/lite/kernels/x86/slice_compute.h new file mode 100644 index 0000000000000000000000000000000000000000..a3540cafdf4f219cae659b1a818d793302aab12c --- /dev/null +++ b/lite/kernels/x86/slice_compute.h @@ -0,0 +1,145 @@ +// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include +#include +#include "lite/core/kernel.h" +#include "lite/core/op_lite.h" +#include "lite/core/op_registry.h" +#include "lite/core/type_system.h" +#include "lite/fluid/eigen.h" +#include "lite/operators/relu_op.h" + +namespace paddle { +namespace lite { +namespace kernels { +namespace x86 { + +template +void slice_compute(const lite::Tensor* in, + lite::Tensor* out, + std::vector axes, + std::vector starts, + std::vector ends, + std::vector decrease_axis) { + auto out_dims = out->dims(); + auto in_dims = in->dims(); + + // resize out_dims + if (decrease_axis.size() > 0) { + if (decrease_axis.size() == (size_t)in_dims.size()) { + std::vector vec_origin_out_shape(decrease_axis.size(), 1); + // lite::DDim dims(vec_origin_out_shape); + out->Resize(vec_origin_out_shape); + } else { + std::vector vec_origin_out_shape( + out_dims.size() + decrease_axis.size(), -1); + for (size_t i = 0; i < decrease_axis.size(); ++i) { + vec_origin_out_shape[decrease_axis[i]] = 1; + } + int index = 0; + for (size_t i = 0; i < vec_origin_out_shape.size(); ++i) { + if (-1 == vec_origin_out_shape[i]) { + vec_origin_out_shape[i] = out_dims[index]; + ++index; + } + } + // lite::DDim dims(vec_origin_out_shape); + out->Resize(vec_origin_out_shape); + } + } + + out->mutable_data(lite::TargetType::kX86); + + auto new_out_dims = out->dims(); + auto offsets = Eigen::array(); + auto extents = Eigen::array(); + for (size_t i = 0; i < D; ++i) { + offsets[i] = 0; + extents[i] = new_out_dims[i]; + } + int start; + for (size_t i = 0; i < axes.size(); ++i) { + start = starts[i]; + if (start < 0) { + start = (start + in_dims[axes[i]]); + } + start = std::max(start, 0); + offsets[axes[i]] = start; + } + auto in_t = + lite::fluid::EigenTensor:: + From(*in, in->dims()); + auto out_t = + lite::fluid::EigenTensor:: + From(*out, new_out_dims); + out_t = in_t.slice(offsets, extents); + + out->Resize(out_dims); +} + +template +void slice_compute_(const lite::Tensor* Input, + lite::Tensor* Out, + std::vector axes, + std::vector starts, + std::vector ends, + std::vector decrease_axis) { + int rank = Input->dims().size(); + switch (rank) { + case 1: + slice_compute<1>(Input, Out, axes, starts, ends, decrease_axis); + break; + case 2: + slice_compute<2>(Input, Out, axes, starts, ends, decrease_axis); + break; + case 3: + slice_compute<3>(Input, Out, axes, starts, ends, decrease_axis); + break; + case 4: + slice_compute<4>(Input, Out, axes, starts, ends, decrease_axis); + break; + case 5: + slice_compute<5>(Input, Out, axes, starts, ends, decrease_axis); + break; + case 6: + slice_compute<6>(Input, Out, axes, starts, ends, decrease_axis); + break; + } +} + +template +class SliceCompute : public KernelLite { + public: + using param_t = operators::SliceParam; + + void Run() override { + auto& param = *param_.get_mutable(); + slice_compute_(param.X, + param.Out, + param.axes, + param.starts, + param.ends, + param.decrease_axis); + } + + virtual ~SliceCompute() = default; +}; + +} // namespace x86 +} // namespace kernels +} // namespace lite +} // namespace paddle diff --git a/lite/kernels/x86/slice_compute_test.cc b/lite/kernels/x86/slice_compute_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..db3cb35ccbe248d800a5975bcd62d9f1216f3997 --- /dev/null +++ b/lite/kernels/x86/slice_compute_test.cc @@ -0,0 +1,265 @@ +// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "lite/kernels/x86/slice_compute.h" +#include +#include +#include +#include +#include +#include "lite/core/op_registry.h" +namespace paddle { +namespace lite { +namespace kernels { +namespace x86 { + +TEST(slice_x86, retrive_op) { + auto slice = + KernelRegistry::Global().Create("slice"); + ASSERT_FALSE(slice.empty()); + ASSERT_TRUE(slice.front()); +} + +TEST(slice_x86, init) { + lite::kernels::x86::SliceCompute slice; + ASSERT_EQ(slice.precision(), PRECISION(kFloat)); + ASSERT_EQ(slice.target(), TARGET(kX86)); +} + +void test_case1(lite::Tensor x, lite::Tensor out) { + std::vector x_shape({3}); + x.Resize(lite::DDim(x_shape)); + std::vector out_shape({3}); + out.Resize(lite::DDim(out_shape)); + + auto x_data = x.mutable_data(); + auto out_data = out.mutable_data(); + + for (int64_t i = 0; i < x.dims().production(); ++i) { + x_data[i] = static_cast(i); + } + + std::vector starts({-3}); + std::vector ends({3}); + std::vector axes({0}); + + // SliceCompute slice; + SliceCompute slice; + operators::SliceParam param; + + param.X = &x; + param.Out = &out; + + std::unique_ptr ctx(new KernelContext); + ctx->As(); + slice.SetContext(std::move(ctx)); + slice.SetParam(param); + slice.Run(); + + for (int i = 0; i < out.dims().production(); i++) { + LOG(INFO) << out_data[i]; + } +} + +void test_case2(lite::Tensor x, lite::Tensor out) { + std::vector x_shape({3, 4}); + x.Resize(lite::DDim(x_shape)); + std::vector out_shape({3, 4}); + out.Resize(lite::DDim(out_shape)); + + auto x_data = x.mutable_data(); + auto out_data = out.mutable_data(); + + for (int64_t i = 0; i < x.dims().production(); ++i) { + x_data[i] = static_cast(i); + } + + std::vector starts({-3, 0}); + std::vector ends({3, 100}); + std::vector axes({0, 1}); + + // SliceCompute slice; + SliceCompute slice; + operators::SliceParam param; + + param.X = &x; + param.Out = &out; + + std::unique_ptr ctx(new KernelContext); + ctx->As(); + slice.SetContext(std::move(ctx)); + slice.SetParam(param); + slice.Run(); + + for (int i = 0; i < out.dims().production(); i++) { + LOG(INFO) << out_data[i]; + } +} + +void test_case3(lite::Tensor x, lite::Tensor out) { + std::vector x_shape({3, 4, 5}); + x.Resize(lite::DDim(x_shape)); + std::vector out_shape({3, 4, 2}); + out.Resize(lite::DDim(out_shape)); + + auto x_data = x.mutable_data(); + auto out_data = out.mutable_data(); + + for (int64_t i = 0; i < x.dims().production(); ++i) { + x_data[i] = static_cast(i); + } + + std::vector starts({-3, 0, 2}); + std::vector ends({3, 100, -1}); + std::vector axes({0, 1, 2}); + + // SliceCompute slice; + SliceCompute slice; + operators::SliceParam param; + + param.X = &x; + param.Out = &out; + + std::unique_ptr ctx(new KernelContext); + ctx->As(); + slice.SetContext(std::move(ctx)); + slice.SetParam(param); + slice.Run(); + + for (int i = 0; i < out.dims().production(); i++) { + LOG(INFO) << out_data[i]; + } +} +void test_case4(lite::Tensor x, lite::Tensor out) { + std::vector x_shape({3, 4, 5, 6}); + x.Resize(lite::DDim(x_shape)); + std::vector out_shape({3, 4, 2, 6}); + out.Resize(lite::DDim(out_shape)); + + auto x_data = x.mutable_data(); + auto out_data = out.mutable_data(); + + for (int64_t i = 0; i < x.dims().production(); ++i) { + x_data[i] = static_cast(i); + } + + std::vector starts({-3, 0, 2}); + std::vector ends({3, 100, -1}); + std::vector axes({0, 1, 2}); + + // SliceCompute slice; + SliceCompute slice; + operators::SliceParam param; + + param.X = &x; + param.Out = &out; + + std::unique_ptr ctx(new KernelContext); + ctx->As(); + slice.SetContext(std::move(ctx)); + slice.SetParam(param); + slice.Run(); + + for (int i = 0; i < out.dims().production(); i++) { + LOG(INFO) << out_data[i]; + } +} + +void test_case5(lite::Tensor x, lite::Tensor out) { + std::vector x_shape({3, 4, 5, 6, 3}); + x.Resize(lite::DDim(x_shape)); + std::vector out_shape({3, 4, 2, 6, 3}); + out.Resize(lite::DDim(out_shape)); + + auto x_data = x.mutable_data(); + auto out_data = out.mutable_data(); + + for (int64_t i = 0; i < x.dims().production(); ++i) { + x_data[i] = static_cast(i); + } + + std::vector starts({-3, 0, 2}); + std::vector ends({3, 100, -1}); + std::vector axes({0, 1, 2}); + + // SliceCompute slice; + SliceCompute slice; + operators::SliceParam param; + + param.X = &x; + param.Out = &out; + + std::unique_ptr ctx(new KernelContext); + ctx->As(); + slice.SetContext(std::move(ctx)); + slice.SetParam(param); + slice.Run(); + + for (int i = 0; i < out.dims().production(); i++) { + LOG(INFO) << out_data[i]; + } +} +void test_case6(lite::Tensor x, lite::Tensor out) { + std::vector x_shape({3, 4, 5, 6, 5, 2}); + x.Resize(lite::DDim(x_shape)); + std::vector out_shape({3, 4, 2, 6, 5, 2}); + out.Resize(lite::DDim(out_shape)); + + auto x_data = x.mutable_data(); + auto out_data = out.mutable_data(); + + for (int64_t i = 0; i < x.dims().production(); ++i) { + x_data[i] = static_cast(i); + } + + std::vector starts({-3, 0, 2}); + std::vector ends({3, 100, -1}); + std::vector axes({0, 1, 2}); + + // SliceCompute slice; + SliceCompute slice; + operators::SliceParam param; + + param.X = &x; + param.Out = &out; + + std::unique_ptr ctx(new KernelContext); + ctx->As(); + slice.SetContext(std::move(ctx)); + slice.SetParam(param); + slice.Run(); + + for (int i = 0; i < out.dims().production(); i++) { + LOG(INFO) << out_data[i]; + } +} + +TEST(slice_x86, run_test) { + lite::Tensor x; + lite::Tensor out; + + test_case1(x, out); + test_case2(x, out); + test_case3(x, out); + test_case4(x, out); + test_case5(x, out); + test_case6(x, out); +} + +} // namespace x86 +} // namespace kernels +} // namespace lite +} // namespace paddle + +USE_LITE_KERNEL(slice, kX86, kFloat, kNCHW, def); diff --git a/lite/kernels/x86/squeeze_compute.cc b/lite/kernels/x86/squeeze_compute.cc new file mode 100644 index 0000000000000000000000000000000000000000..17ecd0c49bd0ee96b525f688b9d1f7bce100232a --- /dev/null +++ b/lite/kernels/x86/squeeze_compute.cc @@ -0,0 +1,36 @@ +// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "lite/kernels/x86/squeeze_compute.h" + +REGISTER_LITE_KERNEL(squeeze, + kX86, + kFloat, + kNCHW, + paddle::lite::kernels::x86::SqueezeCompute, + def) + .BindInput("X", {LiteType::GetTensorTy(TARGET(kX86))}) + .BindOutput("Out", {LiteType::GetTensorTy(TARGET(kX86))}) + .Finalize(); + +REGISTER_LITE_KERNEL(squeeze2, + kX86, + kFloat, + kNCHW, + paddle::lite::kernels::x86::Squeeze2Compute, + def) + .BindInput("X", {LiteType::GetTensorTy(TARGET(kX86))}) + .BindOutput("Out", {LiteType::GetTensorTy(TARGET(kX86))}) + .BindOutput("XShape", {LiteType::GetTensorTy(TARGET(kX86))}) + .Finalize(); diff --git a/lite/kernels/x86/squeeze_compute.h b/lite/kernels/x86/squeeze_compute.h new file mode 100644 index 0000000000000000000000000000000000000000..67086f8c732d412064c6bb0bece7e8208f8a0799 --- /dev/null +++ b/lite/kernels/x86/squeeze_compute.h @@ -0,0 +1,70 @@ +// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include "lite/core/kernel.h" +#include "lite/core/op_lite.h" +#include "lite/core/op_registry.h" +#include "lite/core/type_system.h" +#include "lite/operators/squeeze_op.h" + +namespace paddle { +namespace lite { +namespace kernels { +namespace x86 { + +template +class SqueezeCompute : public KernelLite { + public: + using param_t = operators::SqueezeParam; + + void Run() override { + auto& param = *param_.get_mutable(); + auto x = param.X; + auto output = param.Out; + auto x_dims = x->dims(); + auto* x_data = x->data(); + auto* out_data = output->mutable_data(); + memcpy(out_data, x_data, x_dims.production() * sizeof(T)); + } + + virtual ~SqueezeCompute() = default; +}; + +template +class Squeeze2Compute : public KernelLite { + public: + using param_t = operators::SqueezeParam; + + void Run() override { + auto& param = *param_.get_mutable(); + auto x = param.X; + auto output = param.Out; + auto xshape = param.XShape; + auto x_dims = x->dims(); + auto* x_data = x->data(); + auto* out_data = output->mutable_data(); + auto* xshape_data = xshape->mutable_data(); + memcpy(out_data, x_data, x_dims.production() * sizeof(T)); + memcpy(xshape_data, x_data, x_dims.production() * sizeof(T)); + } + + virtual ~Squeeze2Compute() = default; +}; + +} // namespace x86 +} // namespace kernels +} // namespace lite +} // namespace paddle diff --git a/lite/kernels/x86/squeeze_compute_test.cc b/lite/kernels/x86/squeeze_compute_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..0799a522b339951521dc2a80b00e447e19657a62 --- /dev/null +++ b/lite/kernels/x86/squeeze_compute_test.cc @@ -0,0 +1,142 @@ +// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "lite/kernels/x86/squeeze_compute.h" +#include +#include +#include +#include +#include "lite/core/op_registry.h" +namespace paddle { +namespace lite { +namespace kernels { +namespace x86 { + +// squeeze +TEST(squeeze_x86, retrive_op) { + auto squeeze = + KernelRegistry::Global().Create( + "squeeze"); + ASSERT_FALSE(squeeze.empty()); + ASSERT_TRUE(squeeze.front()); +} + +TEST(squeeze_x86, init) { + lite::kernels::x86::SqueezeCompute squeeze; + ASSERT_EQ(squeeze.precision(), PRECISION(kFloat)); + ASSERT_EQ(squeeze.target(), TARGET(kX86)); +} + +TEST(squeeze_x86, run_test) { + lite::Tensor x; + lite::Tensor out; + std::vector x_shape({1, 3, 1, 5}); + x.Resize(lite::DDim(x_shape)); + std::vector out_shape({3, 5}); + out.Resize(lite::DDim(out_shape)); + + auto x_data = x.mutable_data(); + auto out_data = out.mutable_data(); + + for (int64_t i = 0; i < x.dims().production(); ++i) { + x_data[i] = static_cast(i); + } + + // SqueezeCompute squeeze; + SqueezeCompute squeeze; + operators::SqueezeParam param; + + param.X = &x; + param.Out = &out; + std::vector> ref_res({{3, 5}, {3, 5}}); + std::vector> axes({{0, -2}, {}}); + std::unique_ptr ctx(new KernelContext); + ctx->As(); + for (int i = 0; i < 2; ++i) { + param.axes = axes[i]; + squeeze.SetContext(std::move(ctx)); + squeeze.SetParam(param); + squeeze.Run(); + + for (int j = 0; j < out.dims().production(); ++j) { + EXPECT_NEAR(out_data[j], x_data[j], 1e-5); + } + } +} + +// squeeze2 +TEST(squeeze2_x86, retrive_op) { + auto squeeze2 = + KernelRegistry::Global().Create( + "squeeze2"); + ASSERT_FALSE(squeeze2.empty()); + ASSERT_TRUE(squeeze2.front()); +} + +TEST(squeeze2_x86, init) { + lite::kernels::x86::Squeeze2Compute squeeze2; + ASSERT_EQ(squeeze2.precision(), PRECISION(kFloat)); + ASSERT_EQ(squeeze2.target(), TARGET(kX86)); +} + +TEST(squeeze2_x86, run_test) { + lite::Tensor x; + lite::Tensor xshape; + lite::Tensor out; + std::vector x_shape({1, 3, 1, 5}); + x.Resize(lite::DDim(x_shape)); + std::vector out_shape({3, 5}); + out.Resize(lite::DDim(out_shape)); + std::vector xshape_shape({1, 3, 1, 5}); + xshape.Resize(lite::DDim(xshape_shape)); + + auto x_data = x.mutable_data(); + auto out_data = out.mutable_data(); + auto xshape_data = xshape.mutable_data(); + + for (int64_t i = 0; i < x.dims().production(); ++i) { + x_data[i] = static_cast(i); + xshape_data[i] = static_cast(i); + } + + // Squeeze2Compute squeeze2; + Squeeze2Compute squeeze2; + operators::SqueezeParam param; + + param.X = &x; + param.Out = &out; + param.XShape = &xshape; + std::vector> ref_res({{3, 5}, {3, 5}}); + std::vector> axes({{0, -2}, {}}); + std::unique_ptr ctx(new KernelContext); + ctx->As(); + for (int i = 0; i < 2; ++i) { + param.axes = axes[i]; + squeeze2.SetContext(std::move(ctx)); + squeeze2.SetParam(param); + squeeze2.Run(); + + for (int j = 0; j < out.dims().production(); ++j) { + EXPECT_NEAR(out_data[j], x_data[j], 1e-5); + } + } +} + +} // namespace x86 +} // namespace kernels +} // namespace lite +} // namespace paddle + +USE_LITE_KERNEL(squeeze, kX86, kFloat, kNCHW, def); +USE_LITE_KERNEL(squeeze2, kX86, kFloat, kNCHW, def); diff --git a/lite/operators/reshape_op.cc b/lite/operators/reshape_op.cc index 102e8e40816278403ffd26243e222c90cd1d7fae..b7f28fb6cb526957a4bfceb1474b2239f2f223d9 100644 --- a/lite/operators/reshape_op.cc +++ b/lite/operators/reshape_op.cc @@ -60,6 +60,7 @@ bool ReshapeOp::AttachImpl(const cpp::OpDesc &opdesc, lite::Scope *scope) { } const std::vector shape_vector = param_.shape; lite::Tensor *shape_tensor = new lite::Tensor; + shape_tensor->Resize({static_cast(shape_vector.size())}); int *data_shape = shape_tensor->mutable_data(); for (int i = 0; i < shape_vector.size(); i++) { @@ -83,6 +84,7 @@ bool ReshapeOp::AttachImpl(const cpp::OpDesc &opdesc, lite::Scope *scope) { << "The shape information must be set by Attr(shape)."; const std::vector shape_vector = param_.shape; lite::Tensor *shape_tensor = new lite::Tensor; + shape_tensor->Resize({static_cast(shape_vector.size())}); int *data_shape = shape_tensor->mutable_data(); for (int i = 0; i < shape_vector.size(); i++) { @@ -120,18 +122,19 @@ bool Reshape2Op::AttachImpl(const cpp::OpDesc &opdesc, lite::Scope *scope) { } DDim ValidateShape(const std::vector &shape, const DDim &input_dims) { - const DDim::value_type input_size = input_dims.production(); + const lite::DDim::value_type input_size = input_dims.production(); auto input_shape = input_dims.Vectorize(); - bool all_positive = std::all_of(input_shape.cbegin(), - input_shape.cend(), - [](DDim::value_type i) { return i > 0; }); + bool all_positive = std::all_of( + input_shape.cbegin(), input_shape.cend(), [](lite::DDim::value_type i) { + return i > 0; + }); // only one dimension can be set to -1, whose size will be automatically // infered. const int unk_dim_val = -1; const int copy_dim_val = 0; - std::vector output_shape(shape.size(), 0); - DDim::value_type capacity = 1; + std::vector output_shape(shape.size(), 0); + lite::DDim::value_type capacity = 1; int unk_dim_idx = -1; for (size_t i = 0; i < shape.size(); ++i) { if (shape[i] == unk_dim_val) { @@ -147,10 +150,10 @@ DDim ValidateShape(const std::vector &shape, const DDim &input_dims) { "be negtive except one unknown dimension."; } - capacity *= - (shape[i] ? static_cast(shape[i]) : input_shape[i]); - output_shape[i] = - (shape[i] ? static_cast(shape[i]) : input_shape[i]); + capacity *= (shape[i] ? static_cast(shape[i]) + : input_shape[i]); + output_shape[i] = (shape[i] ? static_cast(shape[i]) + : input_shape[i]); } if (unk_dim_idx != -1) { @@ -168,7 +171,7 @@ DDim ValidateShape(const std::vector &shape, const DDim &input_dims) { } else { CHECK_EQ(capacity, input_size) << "Invalid shape is given."; } - return DDim(output_shape); + return lite::DDim(output_shape); } } // namespace operators