Files
2026-07-13 12:40:42 +08:00

164 lines
5.7 KiB
C++

// 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/addmm_grad_kernel.h"
#include "paddle/phi/backends/xpu/enforce_xpu.h"
#include "paddle/phi/backends/xpu/xpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/full_kernel.h"
#include "paddle/phi/kernels/xpu/xpu_api_wrapper.h"
namespace phi {
template <typename T, typename Context>
void AddmmGradKernel(const Context& dev_ctx,
const DenseTensor& input,
const DenseTensor& x,
const DenseTensor& y,
const DenseTensor& out_grad,
float alpha,
float beta,
DenseTensor* input_grad,
DenseTensor* x_grad,
DenseTensor* y_grad) {
using XPUType = typename XPUTypeTrait<T>::Type;
if (out_grad.numel() == 0) {
if (input_grad) {
Full<T, Context>(dev_ctx, input_grad->dims(), 0, input_grad);
}
if (x_grad) {
Full<T, Context>(dev_ctx, x_grad->dims(), 0, x_grad);
}
if (y_grad) {
Full<T, Context>(dev_ctx, y_grad->dims(), 0, y_grad);
}
return;
}
xpu::Context* xpu_ctx = dev_ctx.x_context();
xpu::ctx_guard RAII_GUARD(xpu_ctx);
int r;
if (input_grad) {
dev_ctx.template Alloc<T>(input_grad);
XPUType* input_grad_ptr = reinterpret_cast<XPUType*>(input_grad->data<T>());
r = xpu::constant(xpu_ctx, input_grad_ptr, input.numel(), (XPUType)(beta));
PADDLE_ENFORCE_XDNN_SUCCESS(r, "constant");
if (input_grad->dims().size() == 1 && out_grad.dims()[0] > 1) {
r = xpu::scale<XPUType>(xpu_ctx,
input_grad_ptr,
input_grad_ptr,
input_grad->numel(),
true,
static_cast<float>(out_grad.dims()[0]),
0.f);
PADDLE_ENFORCE_XDNN_SUCCESS(r, "scale");
}
}
if (x_grad) {
dev_ctx.template Alloc<T>(x_grad);
}
if (y_grad) {
dev_ctx.template Alloc<T>(y_grad);
}
if (x_grad && x_grad->numel() == 0) {
Full<T, Context>(dev_ctx, y_grad->dims(), 0, y_grad);
return;
}
if (y_grad && y_grad->numel() == 0) {
Full<T, Context>(dev_ctx, x_grad->dims(), 0, x_grad);
return;
}
const XPUType* out_grad_ptr =
reinterpret_cast<const XPUType*>(out_grad.data<T>());
const XPUType* x_ptr = reinterpret_cast<const XPUType*>(x.data<T>());
const XPUType* y_ptr = reinterpret_cast<const XPUType*>(y.data<T>());
XpuFcInfo info_forward;
GetFCInfo(x.dims(), y.dims(), false, false, &info_forward);
// begin calculate
const XPUType* a_1 = nullptr;
const XPUType* b_1 = nullptr;
const XPUType* a_2 = nullptr;
const XPUType* b_2 = nullptr;
XPUType* c_1 = reinterpret_cast<XPUType*>(x_grad->data<T>());
XPUType* c_2 = reinterpret_cast<XPUType*>(y_grad->data<T>());
if (x_grad && info_forward.is_x_need_broadcast) {
c_1 = RAII_GUARD.alloc_l3_or_gm<XPUType>(info_forward.bs * info_forward.m *
info_forward.k);
PADDLE_ENFORCE_XDNN_NOT_NULL(c_1);
}
if (y_grad && info_forward.is_y_need_broadcast) {
c_2 = RAII_GUARD.alloc_l3_or_gm<XPUType>(info_forward.bs * info_forward.k *
info_forward.n);
PADDLE_ENFORCE_XDNN_NOT_NULL(c_2);
}
XpuFcInfo info_x_grad;
XpuFcInfo info_y_grad;
std::tuple<XpuFcInfo,
XpuFcInfo,
const XPUType*,
const XPUType*,
const XPUType*,
const XPUType*>
fc_info = MatmulGradFcInfo(xpu_ctx,
&RAII_GUARD,
info_forward,
false,
false,
x_ptr,
y_ptr,
out_grad_ptr);
std::tie(info_x_grad, info_y_grad, a_1, b_1, a_2, b_2) = fc_info;
if (x_grad) {
MatMulXPUFunction<XPUType>(xpu_ctx, a_1, b_1, c_1, info_x_grad, alpha, 0.f);
if (info_forward.is_x_need_broadcast) {
r = xpu::reduce_sum<XPUType>(
xpu_ctx,
c_1,
reinterpret_cast<XPUType*>(x_grad->data<T>()),
{(int64_t)info_forward.bs,
(int64_t)info_forward.m,
(int64_t)info_forward.k},
{0LL});
PADDLE_ENFORCE_XDNN_SUCCESS(r, "reduce_sum");
}
}
if (y_grad) {
MatMulXPUFunction<XPUType>(xpu_ctx, a_2, b_2, c_2, info_y_grad, alpha, 0.f);
if (info_forward.is_y_need_broadcast) {
r = xpu::reduce_sum<XPUType>(
xpu_ctx,
c_2,
reinterpret_cast<XPUType*>(y_grad->data<T>()),
{(int64_t)info_forward.bs,
(int64_t)info_forward.k,
(int64_t)info_forward.n},
{0LL});
PADDLE_ENFORCE_XDNN_SUCCESS(r, "reduce_sum");
}
}
}
} // namespace phi
PD_REGISTER_KERNEL(addmm_grad,
XPU,
ALL_LAYOUT,
phi::AddmmGradKernel,
float,
phi::bfloat16,
phi::float16) {}