// 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/cast_kernel.h" #include "paddle/phi/backends/xpu/enforce_xpu.h" #include "paddle/phi/core/kernel_registry.h" #include "paddle/phi/kernels/complex_kernel.h" #include "paddle/phi/kernels/funcs/math_function.h" namespace phi { #ifdef PADDLE_WITH_XPU_FFT template static DenseTensor Fill(const Context& dev_ctx, std::vector shape, T fill_value) { DenseTensor ret; ret.Resize(shape); dev_ctx.template Alloc(&ret); funcs::SetConstant()(dev_ctx, &ret, fill_value); return ret; } #endif template void CastXPUKernelImpl(const Context& dev_ctx, const DenseTensor& x, DenseTensor* out) { using XPUInT = typename XPUTypeTrait::Type; using XPUOutT = typename XPUTypeTrait::Type; const auto* in_data = x.data(); auto* out_data = dev_ctx.template Alloc(out); auto numel = x.numel(); if (numel == 0) { return; } if (std::is_same::value) { int ret = xpu::copy(dev_ctx.x_context(), reinterpret_cast(in_data), reinterpret_cast(out_data), x.numel() * phi::SizeOf(x.dtype())); PADDLE_ENFORCE_XDNN_SUCCESS(ret, "copy"); return; } if (std::is_same::value && !std::is_same::value || !std::is_same::value && std::is_same::value) { // bfloat -> non float, or non float -> bfloat, use float buffer xpu::ctx_guard RAII_GUARD(dev_ctx.x_context()); float* cast_buffer = RAII_GUARD.alloc_l3_or_gm(numel); // step 1: InT to float int r = xpu::cast(dev_ctx.x_context(), reinterpret_cast(in_data), cast_buffer, numel); PADDLE_ENFORCE_XDNN_SUCCESS(r, "cast"); // step 2: float to OutT r = xpu::cast(dev_ctx.x_context(), cast_buffer, reinterpret_cast(out_data), numel); PADDLE_ENFORCE_XDNN_SUCCESS(r, "cast"); return; } int r = xpu::cast(dev_ctx.x_context(), reinterpret_cast(in_data), reinterpret_cast(out_data), numel); PADDLE_ENFORCE_XDNN_SUCCESS(r, "cast"); } template void CastKernel(const Context& dev_ctx, const DenseTensor& x, DataType out_dtype, DenseTensor* out) { if (x.dtype() == out_dtype) { if (x.dims() == make_ddim({-1})) { *out = x; return; } if (!out->IsSharedWith(x)) { Copy(dev_ctx, x, dev_ctx.GetPlace(), false, out); } return; } switch (out_dtype) { case DataType::INT32: CastXPUKernelImpl(dev_ctx, x, out); break; case DataType::FLOAT32: CastXPUKernelImpl(dev_ctx, x, out); break; case DataType::FLOAT16: CastXPUKernelImpl(dev_ctx, x, out); break; case DataType::BFLOAT16: CastXPUKernelImpl(dev_ctx, x, out); break; case DataType::INT64: CastXPUKernelImpl(dev_ctx, x, out); break; case DataType::BOOL: CastXPUKernelImpl(dev_ctx, x, out); break; case DataType::INT8: CastXPUKernelImpl(dev_ctx, x, out); break; case DataType::UINT8: CastXPUKernelImpl(dev_ctx, x, out); break; case DataType::FLOAT64: CastXPUKernelImpl(dev_ctx, x, out); break; case DataType::INT16: CastXPUKernelImpl(dev_ctx, x, out); break; #ifdef PADDLE_WITH_XPU_FFT case DataType::COMPLEX64: { if (x.numel() == 0) { dev_ctx.template Alloc(out); return; } DenseTensor real; real.Resize(x.dims()); CastXPUKernelImpl(dev_ctx, x, &real); dev_ctx.template Alloc(out); DenseTensor imag = Fill( dev_ctx, vectorize(x.dims()), static_cast(0.0)); phi::ComplexKernel(dev_ctx, real, imag, out); break; } #endif default: PADDLE_THROW(common::errors::Unavailable( "Not supported cast %d -> %d", x.dtype(), out_dtype)); } } #ifdef PADDLE_WITH_XPU_FFT template <> void CastKernel(const XPUContext& dev_ctx, const DenseTensor& x, DataType out_dtype, DenseTensor* out) { using T = phi::complex64; if (x.dtype() == out_dtype) { if (x.dims() == make_ddim({-1})) { *out = x; return; } if (!out->IsSharedWith(x)) { Copy(dev_ctx, x, dev_ctx.GetPlace(), false, out); } return; } DenseTensor x_real = Real(dev_ctx, x); CastKernel(dev_ctx, x_real, out_dtype, out); } #endif } // namespace phi PD_REGISTER_KERNEL(cast, XPU, ALL_LAYOUT, phi::CastKernel, int16_t, int32_t, float, phi::float16, phi::bfloat16, #ifdef PADDLE_WITH_XPU_FFT phi::complex64, #endif int64_t, bool, int8_t, uint8_t, double) { kernel->OutputAt(0).SetDataType(phi::DataType::UNDEFINED); }