// 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/flip_kernel.h" #include "paddle/common/array.h" #include "paddle/phi/backends/gpu/gpu_context.h" #include "paddle/phi/backends/gpu/gpu_launch_config.h" #include "paddle/phi/common/place.h" #include "paddle/phi/core/kernel_registry.h" namespace phi { template __global__ void FlipCudaKernel(const T* in_data, T* out_data, Array shape, Array stride, Array flip_dims, const int rank, const int64_t numel, const int flip_dims_size) { int64_t idx = static_cast(blockIdx.x) * static_cast(blockDim.x) + static_cast(threadIdx.x); if (idx >= numel) { return; } int64_t cur_indices = idx; int64_t rem = 0; int64_t dst_offset = 0; #pragma unroll for (int i = 0; i < DDim::kMaxRank; ++i) { if (i >= rank) { break; } int64_t temp = cur_indices; cur_indices = cur_indices / stride[i]; rem = temp - cur_indices * stride[i]; // flip the indices if it is in flip_dims for (int j = 0; j < flip_dims_size; ++j) { if (i == flip_dims[j]) { cur_indices = shape[i] - 1 - cur_indices; } } dst_offset += cur_indices * stride[i]; cur_indices = rem; } out_data[idx] = in_data[dst_offset]; } template void FlipKernel(const Context& dev_ctx, const DenseTensor& x, const std::vector& axis, DenseTensor* out) { auto* in_data = x.data(); auto* out_data = dev_ctx.template Alloc(out); if (out->numel() == 0) { return; } auto x_dims = x.dims(); const int rank = x_dims.size(); const int64_t numel = x.numel(); size_t flip_dims_size = axis.size(); auto x_stride = common::stride(x_dims); Array stride_array; Array shape_array; Array flip_dims_array; for (int i = 0; i < rank; ++i) { stride_array[i] = x_stride[i]; shape_array[i] = x_dims[i]; if (i < flip_dims_size) { flip_dims_array[i] = axis[i] < 0 ? axis[i] + rank : axis[i]; } else { flip_dims_array[i] = 0; } } auto config = backends::gpu::GetGpuLaunchConfig1D(dev_ctx, numel); FlipCudaKernel <<>>( in_data, out_data, shape_array, stride_array, flip_dims_array, rank, numel, flip_dims_size); } } // namespace phi PD_REGISTER_KERNEL(flip, GPU, ALL_LAYOUT, phi::FlipKernel, float, double, phi::float16, phi::bfloat16, int, int64_t, bool, phi::complex64, phi::complex128) {}