// Copyright (c) 2025 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/common/enforce.h" #include "paddle/phi/backends/gpu/gpu_context.h" #include "paddle/phi/core/kernel_registry.h" #include "paddle/phi/core/tensor_utils.h" namespace phi { template struct alignas(16) VectorType { T data[N]; }; template __device__ __forceinline__ float LoadScale(const ScaleT* ptr, int64_t idx) { if constexpr (using_ue8m0_scale) { int packed_scale = reinterpret_cast(ptr)[idx / 4]; int scale_offset = idx % 4; uint8_t scale_u8 = (packed_scale >> (scale_offset * 8)) & 0xFF; int val_as_int = static_cast(scale_u8) << 23; return __int_as_float(val_as_int); } else { return ptr[idx]; } } template __global__ void FusedActDequant(const phi::float8_e4m3fn* __restrict__ Xin, const ScaleT* __restrict__ Xscale, phi::bfloat16* __restrict__ out, const int rows, const int cols) { const int this_row_idx = blockIdx.x; if (this_row_idx >= rows) return; const int Xscale_stride = (cols + 127) / 128; const int vector_size = 16; const int num_vectors = cols / vector_size; const int remaining_elements = cols % vector_size; const int tid = threadIdx.x; for (int vec_idx = tid; vec_idx < num_vectors; vec_idx += blockDim.x) { int x_offset = vec_idx * vector_size; int64_t X_idx = (int64_t)this_row_idx * (int64_t)cols + (int64_t)x_offset; const VectorType<__nv_fp8_e4m3, vector_size>* X_vec_ptr = reinterpret_cast*>(Xin + X_idx); VectorType<__nv_fp8_e4m3, vector_size> X_vec = X_vec_ptr[0]; int64_t scale_idx = (int64_t)this_row_idx * (int64_t)Xscale_stride + (x_offset / 128); float this_scale = LoadScale(Xscale, scale_idx); VectorType<__nv_bfloat16, vector_size> out_vec; #pragma unroll for (int i = 0; i < vector_size; ++i) { float X_value = static_cast(X_vec.data[i]); X_value *= this_scale; out_vec.data[i] = __float2bfloat16(X_value); } VectorType<__nv_bfloat16, vector_size>* out_vec_ptr = reinterpret_cast*>(out + X_idx); out_vec_ptr[0] = out_vec; } if (remaining_elements > 0) { int x_offset = num_vectors * vector_size; int64_t X_idx = (int64_t)this_row_idx * (int64_t)cols + (int64_t)x_offset; int64_t idx = X_idx + tid; if (tid < remaining_elements) { float X_value = static_cast(Xin[idx]); int64_t scale_idx = (int64_t)this_row_idx * (int64_t)Xscale_stride + (x_offset / 128); float this_scale = LoadScale(Xscale, scale_idx); X_value *= this_scale; out[idx] = __float2bfloat16(X_value); } } } template void FusedActDequantKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& x_scale, DenseTensor* out) { auto x_dims = x.dims(); PADDLE_ENFORCE_LE_INT_MAX(x_dims[0], "fused_act_dequant rows"); PADDLE_ENFORCE_LE_INT_MAX(x_dims[1], "fused_act_dequant cols"); PADDLE_ENFORCE_LE_UINT32_MAX(x_dims[0], "fused_act_dequant grid.x"); int rows = static_cast(x_dims[0]); int cols = static_cast(x_dims[1]); out->Resize({rows, cols}); dev_ctx.template Alloc(out); auto out_ptr = reinterpret_cast(out->template data()); dim3 grid(static_cast(x_dims[0])); dim3 block(256); if (x_scale.dtype() == phi::DataType::FLOAT32) { FusedActDequant <<>>(x.data(), x_scale.data(), out->data(), rows, cols); } else if (x_scale.dtype() == phi::DataType::INT32) { FusedActDequant <<>>(x.data(), x_scale.data(), out->data(), rows, cols); } #ifdef PADDLE_WITH_CUDA_CHECK auto cuda_error = cudaGetLastError(); PADDLE_ENFORCE_GPU_SUCCESS(cuda_error); #endif } } // namespace phi PD_REGISTER_KERNEL(fused_act_dequant, GPU, ALL_LAYOUT, phi::FusedActDequantKernel, float, double, int, int64_t, phi::float8_e4m3fn) { kernel->OutputAt(0).SetDataType(phi::DataType::BFLOAT16); }