// Copyright (c) 2024 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/affine_channel_kernel.h" #include "paddle/phi/backends/gpu/gpu_context.h" #include "paddle/phi/backends/gpu/gpu_primitives.h" #include "paddle/phi/core/kernel_registry.h" #include "paddle/phi/kernels/funcs/cub.h" namespace phi { template __global__ static inline void KeAffineChannelCUDA(const T* x, const T* scale, const T* bias, const int C, const int64_t HxW, const int64_t num, T* y) { int64_t gid = static_cast(blockIdx.x) * static_cast(blockDim.x) + static_cast(threadIdx.x); int stride = blockDim.x * gridDim.x; for (int64_t i = gid; i < num; i += stride) { const int c = layout == DataLayout::NCHW ? i / HxW % C : i % C; if (HasBias) { y[i] = scale[c] * x[i] + bias[c]; } else { y[i] = scale[c] * x[i]; } } } template void AffineChannelCUDAKernel(const Context& dev_ctx, const DenseTensor& x_in, const DenseTensor& scale_in, const DenseTensor& bias_in, const std::string& data_layout, DenseTensor* out) { auto* x = &x_in; auto* scale = &scale_in; auto* bias = &bias_in; auto* y = out; dev_ctx.template Alloc(y); const DataLayout layout = StringToDataLayout(data_layout); auto dims = x->dims(); const int64_t num = x->numel(); int64_t N = dims[0]; int64_t C = layout == DataLayout::NCHW ? dims[1] : dims[dims.size() - 1]; int64_t HxW = num / N / C; const T* x_d = x->data(); const T* scale_d = scale->data(); const T* bias_d = bias->data(); T* y_d = y->data(); #ifdef PADDLE_WITH_HIP int block = 256; #else int block = 1024; #endif // PADDLE_WITH_HIP int grid = (num + block - 1) / block; int max_threads = dev_ctx.GetMaxPhysicalThreadCount(); grid = std::min(std::max(max_threads / block, 1), grid); // NOTE(large-tensor): KeAffineChannelCUDA function signature uses int for C // parameter PADDLE_ENFORCE_LE_INT_MAX(C, "C"); if (layout == DataLayout::NCHW) { KeAffineChannelCUDA <<>>( x_d, scale_d, bias_d, static_cast(C), HxW, num, y_d); } else { KeAffineChannelCUDA <<>>( x_d, scale_d, bias_d, static_cast(C), HxW, num, y_d); } } } // namespace phi PD_REGISTER_KERNEL(affine_channel, GPU, ALL_LAYOUT, phi::AffineChannelCUDAKernel, float, double) {}