// Copyright (c) 2022 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 "paddle/phi/kernels/slice_kernel.h" #include "paddle/phi/backends/xpu/enforce_xpu.h" #include "paddle/phi/core/kernel_registry.h" #include "paddle/phi/kernels/funcs/slice_utils.h" namespace phi { template void SliceRawKernel(const Context& ctx, const DenseTensor& input, const std::vector& axes, const IntArray& starts_t, const IntArray& ends_t, const std::vector& infer_flags, const std::vector& decrease_axis, DenseTensor* out) { using XPUType = typename XPUTypeTrait::Type; // Step 1: Get the accurate attribute value of starts and ends std::vector starts = starts_t.GetData(); std::vector ends = ends_t.GetData(); PADDLE_ENFORCE_EQ( starts.size(), axes.size(), phi::errors::InvalidArgument( "The size of starts must be equal to the size of axes.")); PADDLE_ENFORCE_EQ(ends.size(), axes.size(), phi::errors::InvalidArgument( "The size of ends must be equal to the size of axes.")); // Step 2: Compute output auto in_dims = input.dims(); auto out_dims = out->dims(); auto slice_dims = out_dims; // 2.1 Infer output dims for (size_t i = 0; i < axes.size(); ++i) { // when start == -1 && end == start+1 if (starts[i] == -1 && ends[i] == 0 && infer_flags[i] == -1) { auto ret = std::find(decrease_axis.begin(), decrease_axis.end(), axes[i]); if (ret != decrease_axis.end()) { ends[i] = in_dims[axes[i]]; } } } phi::funcs::CheckAndUpdateSliceAttrs(in_dims, axes, &starts, &ends); slice_dims = funcs::GetSliceDims( in_dims, axes, starts, ends, nullptr, nullptr); out_dims = funcs::GetDecreasedDims(slice_dims, decrease_axis); out->Resize(out_dims); // 2.2 Get output size_t shape_size = in_dims.size(); // the slice XPU kernel require that the length of `start`, `end` must be // equal // to the dims size of input tensor, therefore, if shape_size > // axes.size(), the `starts_extension` and `ends_extension` is necessary. std::vector starts_extension(shape_size, 0); std::vector ends_extension(shape_size, 0); if (shape_size > axes.size()) { for (size_t i = 0; i < shape_size; ++i) { ends_extension[i] = in_dims[i]; } for (size_t i = 0; i < axes.size(); ++i) { starts_extension[axes[i]] = starts[i]; ends_extension[axes[i]] = ends[i]; } } else { for (size_t i = 0; i < axes.size(); ++i) { starts_extension[i] = starts[i]; ends_extension[i] = ends[i]; } } // prepare shape on XPU std::vector shape(shape_size, 0); for (size_t i = 0; i < shape_size; ++i) { shape[i] = in_dims[i]; } ctx.template Alloc(out); int r = xpu::slice(ctx.x_context(), reinterpret_cast(input.data()), reinterpret_cast(out->data()), shape, starts_extension, ends_extension); PADDLE_ENFORCE_XDNN_SUCCESS(r, "slice"); } } // namespace phi PD_REGISTER_KERNEL(slice, XPU, ALL_LAYOUT, phi::SliceRawKernel, float, int, phi::dtype::float16, int64_t) {}