Files
paddlepaddle--paddle/paddle/phi/kernels/sparse/impl/unary_kernel_impl.h
T
2026-07-13 12:40:42 +08:00

297 lines
14 KiB
C++

// 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.
#pragma once
#include "paddle/phi/core/meta_tensor.h"
#include "paddle/phi/core/sparse_coo_tensor.h"
#include "paddle/phi/core/sparse_csr_tensor.h"
#include "paddle/phi/core/tensor_utils.h"
#include "paddle/phi/core/visit_type.h"
#include "paddle/phi/kernels/abs_kernel.h"
#include "paddle/phi/kernels/activation_kernel.h"
#include "paddle/phi/kernels/cast_kernel.h"
#include "paddle/phi/kernels/isfinite_kernel.h"
#include "paddle/phi/kernels/scale_kernel.h"
#include "paddle/phi/kernels/sparse/empty_kernel.h"
namespace phi {
namespace sparse {
#define DEFINE_SPARSE_UNARY_KERNEL(prefix) \
template <typename T, typename Context> \
void prefix##CooKernel(const Context& dev_ctx, \
const SparseCooTensor& x, \
SparseCooTensor* out) { \
EmptyLikeCooKernel<T, Context>(dev_ctx, x, out); \
if (out->mutable_non_zero_elements()->numel() != 0) { \
phi::prefix##Kernel<T, Context>( \
dev_ctx, x.non_zero_elements(), out->mutable_non_zero_elements()); \
} \
out->SetIndicesDict(x.GetIndicesDict()); \
out->SetKmaps(x.GetKmaps()); \
} \
\
template <typename T, typename Context> \
void prefix##CsrKernel(const Context& dev_ctx, \
const SparseCsrTensor& x, \
SparseCsrTensor* out) { \
EmptyLikeCsrKernel<T, Context>(dev_ctx, x, out); \
if (out->mutable_non_zero_elements()->numel() == 0) { \
return; \
} \
phi::prefix##Kernel<T, Context>( \
dev_ctx, x.non_zero_elements(), out->mutable_non_zero_elements()); \
}
#define DEFINE_SPARSE_UNARY_KERNEL_WITH_ONE_ATTR(prefix, attr) \
template <typename T, typename Context> \
void prefix##CooKernel(const Context& dev_ctx, \
const SparseCooTensor& x, \
float attr, \
SparseCooTensor* out) { \
EmptyLikeCooKernel<T, Context>(dev_ctx, x, out); \
if (out->mutable_non_zero_elements()->numel() == 0) { \
return; \
} \
phi::prefix##Kernel<T, Context>(dev_ctx, \
x.non_zero_elements(), \
attr, \
out->mutable_non_zero_elements()); \
} \
\
template <typename T, typename Context> \
void prefix##CsrKernel(const Context& dev_ctx, \
const SparseCsrTensor& x, \
float attr, \
SparseCsrTensor* out) { \
EmptyLikeCsrKernel<T, Context>(dev_ctx, x, out); \
if (out->mutable_non_zero_elements()->numel() == 0) { \
return; \
} \
phi::prefix##Kernel<T, Context>(dev_ctx, \
x.non_zero_elements(), \
attr, \
out->mutable_non_zero_elements()); \
}
#define DEFINE_SPARSE_UNARY_KERNEL_WITH_COMPLEX(prefix) \
template <typename T, typename Context> \
void prefix##CooKernel(const Context& dev_ctx, \
const SparseCooTensor& x, \
SparseCooTensor* out) { \
*(out->mutable_indices()) = x.indices(); \
DenseTensor* out_values = out->mutable_values(); \
const DenseTensor& x_values = x.values(); \
out_values->Resize(x_values.dims()); \
dev_ctx.template Alloc<T>(out_values); \
if (out->mutable_non_zero_elements()->numel() != 0) { \
phi::prefix##Kernel<T, Context>( \
dev_ctx, x.non_zero_elements(), out->mutable_non_zero_elements()); \
} \
out->SetIndicesDict(x.GetIndicesDict()); \
} \
\
template <typename T, typename Context> \
void prefix##CsrKernel(const Context& dev_ctx, \
const SparseCsrTensor& x, \
SparseCsrTensor* out) { \
if (out && out->numel() == 0) { \
dev_ctx.template Alloc<T>(out); \
return; \
} \
*(out->mutable_crows()) = x.crows(); \
*(out->mutable_cols()) = x.cols(); \
DenseTensor* out_values = out->mutable_values(); \
const DenseTensor& x_values = x.values(); \
out_values->Resize(x_values.dims()); \
dev_ctx.template Alloc<T>(out_values); \
if (out->mutable_non_zero_elements()->numel() == 0) { \
return; \
} \
phi::prefix##Kernel<T, Context>( \
dev_ctx, x.non_zero_elements(), out->mutable_non_zero_elements()); \
}
DEFINE_SPARSE_UNARY_KERNEL(Sqrt)
DEFINE_SPARSE_UNARY_KERNEL(Relu)
DEFINE_SPARSE_UNARY_KERNEL(Relu6)
DEFINE_SPARSE_UNARY_KERNEL_WITH_ONE_ATTR(Pow, factor)
DEFINE_SPARSE_UNARY_KERNEL_WITH_ONE_ATTR(LeakyRelu, alpha)
DEFINE_SPARSE_UNARY_KERNEL_WITH_COMPLEX(Abs)
DEFINE_SPARSE_UNARY_KERNEL_WITH_COMPLEX(Sin)
DEFINE_SPARSE_UNARY_KERNEL_WITH_COMPLEX(Tan)
DEFINE_SPARSE_UNARY_KERNEL_WITH_COMPLEX(Sinh)
DEFINE_SPARSE_UNARY_KERNEL_WITH_COMPLEX(Asin)
DEFINE_SPARSE_UNARY_KERNEL_WITH_COMPLEX(Asinh)
DEFINE_SPARSE_UNARY_KERNEL_WITH_COMPLEX(Atan)
DEFINE_SPARSE_UNARY_KERNEL_WITH_COMPLEX(Atanh)
DEFINE_SPARSE_UNARY_KERNEL_WITH_COMPLEX(Expm1)
DEFINE_SPARSE_UNARY_KERNEL_WITH_COMPLEX(Log1p)
DEFINE_SPARSE_UNARY_KERNEL_WITH_COMPLEX(Square)
DEFINE_SPARSE_UNARY_KERNEL_WITH_COMPLEX(Tanh)
template <typename T, typename Context>
void ScaleCooKernel(const Context& dev_ctx,
const SparseCooTensor& x,
float scale,
float bias,
bool bias_after_scale,
SparseCooTensor* out) {
EmptyLikeCooKernel<T, Context>(dev_ctx, x, out);
phi::ScaleKernel<T, Context>(dev_ctx,
x.non_zero_elements(),
scale,
bias,
bias_after_scale,
out->mutable_non_zero_elements());
out->SetIndicesDict(x.GetIndicesDict());
out->SetKmaps(x.GetKmaps());
}
template <typename T, typename Context>
void ScaleCsrKernel(const Context& dev_ctx,
const SparseCsrTensor& x,
float scale,
float bias,
bool bias_after_scale,
SparseCsrTensor* out) {
EmptyLikeCsrKernel<T, Context>(dev_ctx, x, out);
phi::ScaleKernel<T, Context>(dev_ctx,
x.non_zero_elements(),
scale,
bias,
bias_after_scale,
out->mutable_non_zero_elements());
}
template <typename T, typename Context>
void CastCooKernel(const Context& dev_ctx,
const SparseCooTensor& x,
DataType index_dtype,
DataType value_dtype,
SparseCooTensor* out) {
const DenseTensor& x_indices = x.indices();
const DenseTensor& x_values = x.non_zero_elements();
DenseTensor* out_indices = out->mutable_indices();
DenseTensor* out_values = out->mutable_non_zero_elements();
if (index_dtype == DataType::UNDEFINED) {
*out_indices = x_indices;
} else {
MetaTensor meta(out_indices);
meta.set_dims(x_indices.dims());
meta.set_dtype(index_dtype);
PD_VISIT_INTEGRAL_TYPES(x_indices.dtype(), "CastCooKernel", [&] {
CastKernel<data_t, Context>(dev_ctx, x_indices, index_dtype, out_indices);
});
}
if (value_dtype == DataType::UNDEFINED) {
phi::Copy(dev_ctx, x_values, dev_ctx.GetPlace(), false, out_values);
} else {
MetaTensor meta(out_values);
meta.set_dims(x_values.dims());
CastKernel<T, Context>(dev_ctx, x_values, value_dtype, out_values);
}
out->SetIndicesDict(x.GetIndicesDict());
out->SetKmaps(x.GetKmaps());
}
template <typename T, typename Context>
void CastCsrKernel(const Context& dev_ctx,
const SparseCsrTensor& x,
DataType index_dtype,
DataType value_dtype,
SparseCsrTensor* out) {
const DenseTensor& x_crows = x.crows();
const DenseTensor& x_cols = x.cols();
const DenseTensor& x_values = x.non_zero_elements();
DenseTensor* out_crows = out->mutable_crows();
DenseTensor* out_cols = out->mutable_cols();
DenseTensor* out_values = out->mutable_non_zero_elements();
if (index_dtype == DataType::UNDEFINED) {
*out_crows = x_crows;
*out_cols = x_cols;
} else {
MetaTensor crows_meta(out_crows);
crows_meta.set_dims(x_crows.dims());
crows_meta.set_dtype(index_dtype);
PD_VISIT_INTEGRAL_TYPES(x_crows.dtype(), "CastCsrKernel", [&] {
CastKernel<data_t, Context>(dev_ctx, x_crows, index_dtype, out_crows);
});
MetaTensor cols_meta(out_cols);
cols_meta.set_dims(x_cols.dims());
cols_meta.set_dtype(index_dtype);
PD_VISIT_INTEGRAL_TYPES(x_cols.dtype(), "CastCsrKernel", [&] {
CastKernel<data_t, Context>(dev_ctx, x_cols, index_dtype, out_cols);
});
}
if (value_dtype == DataType::UNDEFINED) {
phi::Copy(dev_ctx, x_values, dev_ctx.GetPlace(), false, out_values);
} else {
MetaTensor meta(out_values);
meta.set_dims(x_values.dims());
CastKernel<T, Context>(dev_ctx, x_values, value_dtype, out_values);
}
}
template <typename T, typename Context>
void IsnanCooKernel(const Context& dev_ctx,
const SparseCooTensor& x,
SparseCooTensor* out) {
*(out->mutable_indices()) = x.indices();
const DenseTensor& x_values = x.non_zero_elements();
DenseTensor* out_values = out->mutable_non_zero_elements();
MetaTensor meta(out_values);
meta.set_dims(x_values.dims());
meta.set_dtype(DataType::BOOL);
phi::IsnanKernel<T, Context>(
dev_ctx, x.non_zero_elements(), out->mutable_non_zero_elements());
out->SetIndicesDict(x.GetIndicesDict());
out->SetKmaps(x.GetKmaps());
}
template <typename T, typename Context>
void IsnanCsrKernel(const Context& dev_ctx,
const SparseCsrTensor& x,
SparseCsrTensor* out) {
const DenseTensor& x_crows = x.crows();
const DenseTensor& x_cols = x.cols();
const DenseTensor& x_values = x.non_zero_elements();
DenseTensor* out_crows = out->mutable_crows();
DenseTensor* out_cols = out->mutable_cols();
DenseTensor* out_values = out->mutable_non_zero_elements();
*out_crows = x_crows;
*out_cols = x_cols;
MetaTensor meta(out_values);
meta.set_dims(x_values.dims());
meta.set_dtype(DataType::BOOL);
phi::IsnanKernel<T, Context>(
dev_ctx, x.non_zero_elements(), out->mutable_non_zero_elements());
}
} // namespace sparse
} // namespace phi