chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:40:42 +08:00
commit e25996e7db
15472 changed files with 3536181 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
// 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/common/type_traits.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/complex_functors.h"
#include "paddle/phi/kernels/impl/abs_grad_kernel_impl.h"
using phi::dtype::complex;
PD_REGISTER_KERNEL(abs_grad,
CPU,
ALL_LAYOUT,
phi::AbsGradKernel,
float,
double,
int,
int64_t,
complex<float>,
complex<double>) {
kernel->InputAt(1).SetDataType(phi::dtype::ToReal(kernel_key.dtype()));
}
PD_REGISTER_KERNEL(abs_double_grad,
CPU,
ALL_LAYOUT,
phi::AbsDoubleGradKernel,
float,
double,
int,
int64_t,
complex<float>,
complex<double>) {
kernel->InputAt(1).SetDataType(phi::dtype::ToReal(kernel_key.dtype()));
}
+52
View File
@@ -0,0 +1,52 @@
// 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/abs_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/complex_functors.h"
#include "paddle/phi/kernels/funcs/for_range.h"
namespace phi {
template <typename T, typename Context>
PADDLE_API void AbsKernel(const Context& dev_ctx,
const DenseTensor& x,
DenseTensor* out) {
auto numel = x.numel();
auto* x_data = x.data<T>();
dev_ctx.template Alloc<dtype::Real<T>>(
out, size_t(x.numel() * sizeof(dtype::Real<T>)));
auto* out_data = out->data<dtype::Real<T>>();
funcs::ForRange<Context> for_range(dev_ctx, numel);
funcs::AbsFunctor<T> functor(x_data, out_data, numel);
for_range(functor);
}
} // namespace phi
PD_REGISTER_KERNEL(abs,
CPU,
ALL_LAYOUT,
phi::AbsKernel,
float,
double,
int,
int64_t,
phi::complex64,
phi::complex128) {
kernel->OutputAt(0).SetDataType(phi::dtype::ToReal(kernel_key.dtype()));
}
@@ -0,0 +1,37 @@
// 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/accuracy_check_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/accuracy_check_kernel_impl.h"
PD_REGISTER_KERNEL(accuracy_check,
CPU,
ALL_LAYOUT,
phi::AccuracyCheckKernel,
float,
double,
int,
int64_t,
uint8_t,
int8_t,
int16_t,
bool,
phi::float16,
phi::bfloat16,
phi::complex64,
phi::complex128) {}
+102
View File
@@ -0,0 +1,102 @@
// 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/accuracy_kernel.h"
#include <algorithm>
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
namespace phi {
template <typename T, typename Context>
void AccuracyKernel(const Context& dev_ctx,
const DenseTensor& inference,
const DenseTensor& indices,
const DenseTensor& label,
DenseTensor* accuracy,
DenseTensor* correct,
DenseTensor* total) {
int* correct_data = dev_ctx.template Alloc<int>(correct);
int* total_data = dev_ctx.template Alloc<int>(total);
float* accuracy_data = dev_ctx.template Alloc<float>(accuracy);
const int64_t* indices_data = indices.data<int64_t>();
const int64_t* label_data = label.data<int64_t>();
PADDLE_ENFORCE_EQ(
inference.dims().size(),
2,
common::errors::InvalidArgument(
"Rank(Input) of AccuracyOp must be 2, with shape "
"[sample_number, class_dim], But received rank(Input) is %d",
inference.dims().size()));
size_t num_samples = inference.dims()[0];
size_t class_dim = inference.dims()[1];
*accuracy_data = 0.0f;
PADDLE_ENFORCE_GT(label.dims().size(),
0,
common::errors::InvalidArgument(
"Rank(Label) of AccuracyOp must greater than 0, "
"But received rank(Label) is %d",
label.dims().size()));
PADDLE_ENFORCE_GE(label.dims()[0],
inference.dims()[0],
common::errors::InvalidArgument(
"num_samples(%d) of Label should less than "
"or equal to num_samples(%d) of Input",
label.dims()[0],
num_samples));
if (num_samples == 0) {
return;
}
int num_correct = 0;
// assume inference is already the topk of the output
for (size_t i = 0; i < num_samples; ++i) {
PADDLE_ENFORCE_GE(
label_data[i],
0,
common::errors::InvalidArgument(
"label of AccuracyOp must >= 0, But received label[%d] is %d",
i,
label_data[i]));
for (size_t j = 0; j < class_dim; ++j) {
if (indices_data[i * class_dim + j] == label_data[i]) {
++num_correct;
break;
}
}
}
*correct_data = num_correct;
*total_data = static_cast<int>(num_samples);
*accuracy_data =
static_cast<float>(num_correct) / static_cast<float>(num_samples);
}
} // namespace phi
// TODO(add supported dtype.)
PD_REGISTER_KERNEL(
accuracy, CPU, ALL_LAYOUT, phi::AccuracyKernel, float, double) {
kernel->InputAt(1).SetDataType(phi::DataType::INT64);
kernel->InputAt(2).SetDataType(phi::DataType::INT64);
kernel->OutputAt(0).SetDataType(phi::DataType::FLOAT32);
kernel->OutputAt(1).SetDataType(phi::DataType::INT32);
kernel->OutputAt(2).SetDataType(phi::DataType::INT32);
}
@@ -0,0 +1,598 @@
/* 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/activation_grad_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/full_kernel.h"
#include "paddle/phi/kernels/impl/activation_grad_impl.h"
namespace phi {
#define DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(name, functor_class) \
template <typename T, typename Context> \
void name##GradKernel(const Context& dev_ctx, \
const DenseTensor& x, \
const DenseTensor& dout, \
DenseTensor* dx) { \
funcs::functor_class<T> functor; \
ActivationGradImpl<T, Context, funcs::functor_class<T>>( \
dev_ctx, &x, nullptr, &dout, dx, functor); \
}
#define DEFINE_CPU_ACT_GRAD_KERNEL_WITH_ONE_ATTRS_DEPX( \
name, functor_class, attr) \
template <typename T, typename Context> \
void name##GradKernel(const Context& dev_ctx, \
const DenseTensor& x, \
const DenseTensor& dout, \
float attr, \
DenseTensor* dx) { \
funcs::functor_class<T> functor; \
auto attrs = functor.GetAttrs(); \
*(attrs[0].second) = attr; \
ActivationGradImpl<T, Context, funcs::functor_class<T>>( \
dev_ctx, &x, nullptr, &dout, dx, functor); \
}
#define DEFINE_CPU_ACT_GRAD_KERNEL_WITH_ONE_DOUBLE_ATTRS_DEPX( \
name, functor_class, attr) \
template <typename T, typename Context> \
void name##GradKernel(const Context& dev_ctx, \
const DenseTensor& x, \
const DenseTensor& dout, \
double attr, \
DenseTensor* dx) { \
funcs::functor_class<T> functor; \
auto attrs = functor.GetAttrs(); \
*(attrs[0].second) = attr; \
ActivationGradImpl<T, Context, funcs::functor_class<T>>( \
dev_ctx, &x, nullptr, &dout, dx, functor); \
}
#define DEFINE_CPU_ACT_GRAD_KERNEL_WITH_TWO_ATTRS_DEPX( \
name, functor_class, attr1, attr2) \
template <typename T, typename Context> \
void name##GradKernel(const Context& dev_ctx, \
const DenseTensor& x, \
const DenseTensor& dout, \
float attr1, \
float attr2, \
DenseTensor* dx) { \
funcs::functor_class<T> functor; \
auto attrs = functor.GetAttrs(); \
*(attrs[0].second) = attr1; \
*(attrs[1].second) = attr2; \
ActivationGradImpl<T, Context, funcs::functor_class<T>>( \
dev_ctx, &x, nullptr, &dout, dx, functor); \
}
#define DEFINE_CPU_ACT_GRAD_KERNEL_WITH_TWO_DOUBLE_ATTRS_DEPX( \
name, functor_class, attr1, attr2) \
template <typename T, typename Context> \
void name##GradKernel(const Context& dev_ctx, \
const DenseTensor& x, \
const DenseTensor& dout, \
double attr1, \
double attr2, \
DenseTensor* dx) { \
funcs::functor_class<T> functor; \
auto attrs = functor.GetAttrs(); \
*(attrs[0].second) = attr1; \
*(attrs[1].second) = attr2; \
ActivationGradImpl<T, Context, funcs::functor_class<T>>( \
dev_ctx, &x, nullptr, &dout, dx, functor); \
}
#define DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPOUT(name, functor_class) \
template <typename T, typename Context> \
void name##GradKernel(const Context& dev_ctx, \
const DenseTensor& out, \
const DenseTensor& dout, \
DenseTensor* dx) { \
funcs::functor_class<T> functor; \
ActivationGradImpl<T, Context, funcs::functor_class<T>>( \
dev_ctx, nullptr, &out, &dout, dx, functor); \
}
#define DEFINE_CPU_ACT_GRAD_KERNEL_WITH_ONE_ATTRS_DEPOUT( \
name, functor_class, attr) \
template <typename T, typename Context> \
void name##GradKernel(const Context& dev_ctx, \
const DenseTensor& out, \
const DenseTensor& dout, \
float attr, \
DenseTensor* dx) { \
funcs::functor_class<T> functor; \
auto attrs = functor.GetAttrs(); \
*(attrs[0].second) = attr; \
ActivationGradImpl<T, Context, funcs::functor_class<T>>( \
dev_ctx, nullptr, &out, &dout, dx, functor); \
}
#define DEFINE_CPU_ACT_GRAD_KERNEL_WITH_TWO_ATTRS_DEPOUT( \
name, functor_class, attr1, attr2) \
template <typename T, typename Context> \
void name##GradKernel(const Context& dev_ctx, \
const DenseTensor& out, \
const DenseTensor& dout, \
float attr1, \
float attr2, \
DenseTensor* dx) { \
funcs::functor_class<T> functor; \
auto attrs = functor.GetAttrs(); \
*(attrs[0].second) = attr1; \
*(attrs[1].second) = attr2; \
ActivationGradImpl<T, Context, funcs::functor_class<T>>( \
dev_ctx, nullptr, &out, &dout, dx, functor); \
}
#define DEFINE_CPU_ACTIVATION_GRAD_KERNEL_NODEP(name, functor_class) \
template <typename T, typename Context> \
void name##GradKernel( \
const Context& dev_ctx, const DenseTensor& dout, DenseTensor* dx) { \
funcs::functor_class<T> functor; \
ActivationGradImpl<T, Context, funcs::functor_class<T>>( \
dev_ctx, nullptr, nullptr, &dout, dx, functor); \
}
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Cos, CosGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Tan, TanGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Acos, AcosGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Sin, SinGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Asin, AsinGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Atan, AtanGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Sinh, SinhGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Cosh, CoshGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Asinh, AsinhGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Acosh, AcoshGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Atanh, AtanhGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(TanhShrink, TanhShrinkGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Square, SquareGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPOUT(Exp, ExpGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPOUT(Expm1, Expm1GradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPOUT(Reciprocal, ReciprocalGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPOUT(Sqrt, SqrtGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPOUT(Rsqrt, RsqrtGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPOUT(Relu6, Relu6GradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Softsign, SoftsignGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(LogSigmoid, LogSigmoidGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Log, LogGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Log2, Log2GradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Log10, Log10GradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Log1p, Log1pGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPX(Swish, SwishGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPOUT(Relu, ReluGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPOUT(Tanh, TanhGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_DEPOUT(Sigmoid, SigmoidGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_NODEP(Rint, ZeroGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_NODEP(Round, ZeroGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_NODEP(Floor, ZeroGradFunctor);
DEFINE_CPU_ACTIVATION_GRAD_KERNEL_NODEP(Ceil, ZeroGradFunctor);
DEFINE_CPU_ACT_GRAD_KERNEL_WITH_ONE_DOUBLE_ATTRS_DEPX(LeakyRelu,
LeakyReluGradFunctor,
alpha);
DEFINE_CPU_ACT_GRAD_KERNEL_WITH_ONE_ATTRS_DEPX(SoftShrink,
SoftShrinkGradFunctor,
lambda);
DEFINE_CPU_ACT_GRAD_KERNEL_WITH_ONE_ATTRS_DEPX(HardShrink,
HardShrinkGradFunctor,
threshold);
DEFINE_CPU_ACT_GRAD_KERNEL_WITH_ONE_ATTRS_DEPX(Mish,
MishGradFunctor,
threshold);
DEFINE_CPU_ACT_GRAD_KERNEL_WITH_ONE_ATTRS_DEPX(Celu, CELUGradFunctor, alpha);
DEFINE_CPU_ACT_GRAD_KERNEL_WITH_TWO_ATTRS_DEPX(HardTanh,
HardTanhGradFunctor,
t_min,
t_max);
DEFINE_CPU_ACT_GRAD_KERNEL_WITH_TWO_ATTRS_DEPX(STanh,
STanhGradFunctor,
scale_a,
scale_b);
DEFINE_CPU_ACT_GRAD_KERNEL_WITH_TWO_DOUBLE_ATTRS_DEPX(Softplus,
SoftplusGradFunctor,
beta,
threshold);
DEFINE_CPU_ACT_GRAD_KERNEL_WITH_TWO_ATTRS_DEPOUT(HardSigmoid,
HardSigmoidGradFunctor,
slope,
offset);
DEFINE_CPU_ACT_GRAD_KERNEL_WITH_TWO_ATTRS_DEPX(ThresholdedRelu,
ThresholdedReluGradFunctor,
threshold,
value);
template <typename T, typename Context>
void SiluGradKernel(const Context& dev_ctx,
const DenseTensor& x,
const DenseTensor& out,
const DenseTensor& dout,
DenseTensor* dx) {
funcs::SiluGradFunctor<T> functor;
ActivationGradImpl<T, Context, funcs::SiluGradFunctor<T>>(
dev_ctx, &x, &out, &dout, dx, functor);
}
template <typename T, typename Context>
void EluGradKernel(const Context& dev_ctx,
const DenseTensor& x,
const DenseTensor& out,
const DenseTensor& dout,
float alpha,
DenseTensor* dx) {
dev_ctx.template Alloc<T>(dx);
if (dx->numel() == 0) {
return;
}
auto x_flatten =
EigenVector<T>::Flatten(GET_DATA_SAFELY(&x, "Input", "X", "elu_grad"));
auto out_flatten = EigenVector<T>::Flatten(
GET_DATA_SAFELY(&out, "Input", "Out", "elu_grad"));
auto dout_flatten = EigenVector<T>::Flatten(
GET_DATA_SAFELY(&dout, "Input", "dOut", "elu_grad"));
auto dx_flatten =
EigenVector<T>::Flatten(GET_DATA_SAFELY(dx, "Output", "dX", "elu_grad"));
auto* place = dev_ctx.eigen_device();
if (alpha > 0) {
funcs::ELUGradFunctor<T> functor;
functor.alpha = alpha;
functor(*place, x_flatten, out_flatten, dout_flatten, dx_flatten);
} else {
funcs::ELUGradNegativeAlphaFunctor<T> functor;
functor.alpha = alpha;
functor(*place, x_flatten, out_flatten, dout_flatten, dx_flatten);
}
}
template <typename T, typename Context>
void HardSwishGradKernel(const Context& dev_ctx,
const DenseTensor& x,
const DenseTensor& dout,
DenseTensor* dx) {
funcs::HardSwishGradFunctor<T> functor;
float threshold = 6;
float scale = 6;
float offset = 3;
auto attrs = functor.GetAttrs();
*(attrs[0].second) = threshold;
*(attrs[1].second) = scale;
*(attrs[2].second) = offset;
ActivationGradImpl<T, Context, funcs::HardSwishGradFunctor<T>>(
dev_ctx, &x, nullptr, &dout, dx, functor);
}
template <typename T, typename Context>
void PowGradKernel(const Context& dev_ctx,
const DenseTensor& x,
const DenseTensor& dout,
const Scalar& factor,
DenseTensor* dx) {
if (factor.to<float>() == 0) {
std::vector<int64_t> vec_dims = vectorize(dx->dims());
Full<T, Context>(dev_ctx, vec_dims, static_cast<T>(0), dx);
return;
}
PADDLE_ENFORCE_NOT_NULL(
dx,
errors::InvalidArgument("The output DenseTensor dx can not be nullptr"));
dev_ctx.template Alloc<T>(dx);
auto dout_flatten = EigenVector<T>::Flatten(
GET_DATA_SAFELY(&dout, "Input", "Out@GRAD", "PowGrad"));
auto dx_flatten = EigenVector<T>::Flatten(
GET_DATA_SAFELY(dx, "Output", "X@GRAD", "PowGrad"));
auto x_flatten =
EigenVector<T>::Flatten(GET_DATA_SAFELY(&x, "Input", "X", "PowGrad"));
auto* place = dev_ctx.eigen_device();
funcs::PowGradFunctor<T> functor;
auto attrs = functor.GetAttrs();
*(attrs[0].second) = factor.to<float>();
functor(*place, x_flatten, nullptr, dout_flatten, dx_flatten);
}
} // namespace phi
PD_REGISTER_KERNEL(
relu_grad, CPU, ALL_LAYOUT, phi::ReluGradKernel, float, double) {}
#define PD_REGISTER_ACTIVATION_GRAD_KERNEL(name, func) \
PD_REGISTER_KERNEL(name, CPU, ALL_LAYOUT, phi::func, float, double) {}
#define PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(name, func) \
PD_REGISTER_KERNEL(name, \
CPU, \
ALL_LAYOUT, \
phi::func, \
float, \
double, \
phi::complex64, \
phi::complex128) {}
#define PD_REGISTER_ACTIVATION_DOUBLE_GRAD_KERNEL(name, func) \
PD_REGISTER_KERNEL( \
name, CPU, ALL_LAYOUT, phi::func, float, double, phi::float16) {}
#define PD_REGISTER_ACTIVATION_DOUBLE_GRAD_KERNEL_WITH_COMPLEX(name, func) \
PD_REGISTER_KERNEL(name, \
CPU, \
ALL_LAYOUT, \
phi::func, \
float, \
double, \
phi::float16, \
phi::complex64, \
phi::complex128) {}
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(sin_grad, SinGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(cos_grad, CosGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(tan_grad, TanGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(acos_grad, AcosGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(asin_grad, AsinGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(atan_grad, AtanGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(sinh_grad, SinhGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(cosh_grad, CoshGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(asinh_grad, AsinhGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(acosh_grad, AcoshGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(atanh_grad, AtanhGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(tanh_grad, TanhGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL(hardtanh_grad, HardTanhGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL(leaky_relu_grad, LeakyReluGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL(thresholded_relu_grad,
ThresholdedReluGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL(relu6_grad, Relu6GradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL(softshrink_grad, SoftShrinkGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL(hard_shrink_grad, HardShrinkGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL(tanh_shrink_grad, TanhShrinkGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL(elu_grad, EluGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(silu_grad, SiluGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL(mish_grad, MishGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(stanh_grad, STanhGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(reciprocal_grad,
ReciprocalGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(sqrt_grad, SqrtGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL(rsqrt_grad, RsqrtGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(softplus_grad,
SoftplusGradKernel)
PD_REGISTER_ACTIVATION_DOUBLE_GRAD_KERNEL(relu_double_grad,
ReluDoubleGradKernel)
PD_REGISTER_ACTIVATION_DOUBLE_GRAD_KERNEL_WITH_COMPLEX(tanh_double_grad,
TanhDoubleGradKernel)
PD_REGISTER_ACTIVATION_DOUBLE_GRAD_KERNEL(leaky_relu_double_grad,
LeakyReluDoubleGradKernel)
PD_REGISTER_ACTIVATION_DOUBLE_GRAD_KERNEL(elu_double_grad, EluDoubleGradKernel)
PD_REGISTER_ACTIVATION_DOUBLE_GRAD_KERNEL(sqrt_double_grad,
SqrtDoubleGradKernel)
PD_REGISTER_ACTIVATION_DOUBLE_GRAD_KERNEL(rsqrt_double_grad,
RsqrtDoubleGradKernel)
PD_REGISTER_ACTIVATION_DOUBLE_GRAD_KERNEL_WITH_COMPLEX(softplus_double_grad,
SoftplusDoubleGradKernel)
PD_REGISTER_KERNEL(tanh_triple_grad,
CPU,
ALL_LAYOUT,
phi::TanhTripleGradKernel,
float,
double,
phi::float16,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(exp_grad,
CPU,
ALL_LAYOUT,
phi::ExpGradKernel,
float,
double,
int,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(expm1_grad,
CPU,
ALL_LAYOUT,
phi::Expm1GradKernel,
float,
double,
phi::float16,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(
logit_grad, CPU, ALL_LAYOUT, phi::LogitGradKernel, float, double) {}
PD_REGISTER_KERNEL(square_grad,
CPU,
ALL_LAYOUT,
phi::SquareGradKernel,
float,
double,
int,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(square_double_grad,
CPU,
ALL_LAYOUT,
phi::SquareDoubleGradKernel,
float,
double,
phi::float16,
int,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(sin_double_grad,
CPU,
ALL_LAYOUT,
phi::SinDoubleGradKernel,
float,
double,
phi::float16,
int,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(sin_triple_grad,
CPU,
ALL_LAYOUT,
phi::SinTripleGradKernel,
float,
double,
phi::float16,
int,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(cos_double_grad,
CPU,
ALL_LAYOUT,
phi::CosDoubleGradKernel,
float,
double,
phi::float16,
int,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(cos_triple_grad,
CPU,
ALL_LAYOUT,
phi::CosTripleGradKernel,
float,
double,
phi::float16,
int,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(softsign_grad,
SoftsignGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(sigmoid_grad, SigmoidGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(sigmoid_double_grad,
SigmoidDoubleGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(sigmoid_triple_grad,
SigmoidTripleGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL(hardsigmoid_grad, HardSigmoidGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(logsigmoid_grad,
LogSigmoidGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(log_grad, LogGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(log2_grad, Log2GradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(log10_grad, Log10GradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(log1p_grad, Log1pGradKernel)
PD_REGISTER_ACTIVATION_DOUBLE_GRAD_KERNEL_WITH_COMPLEX(log_double_grad,
LogDoubleGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL_WITH_COMPLEX(hardswish_grad,
HardSwishGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL(swish_grad, SwishGradKernel)
PD_REGISTER_ACTIVATION_GRAD_KERNEL(celu_grad, CeluGradKernel)
PD_REGISTER_ACTIVATION_DOUBLE_GRAD_KERNEL(celu_double_grad,
CeluDoubleGradKernel)
PD_REGISTER_KERNEL(rint_grad,
CPU,
ALL_LAYOUT,
phi::RintGradKernel,
float,
double,
int,
int64_t) {}
PD_REGISTER_KERNEL(round_grad,
CPU,
ALL_LAYOUT,
phi::RoundGradKernel,
float,
double,
int,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(pow_grad,
CPU,
ALL_LAYOUT,
phi::PowGradKernel,
float,
double,
int,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(pow_double_grad,
CPU,
ALL_LAYOUT,
phi::PowDoubleGradKernel,
float,
double,
int,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(pow_triple_grad,
CPU,
ALL_LAYOUT,
phi::PowTripleGradKernel,
float,
double,
int,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(ceil_grad,
CPU,
ALL_LAYOUT,
phi::CeilGradKernel,
float,
double,
uint8_t,
int8_t,
int16_t,
int,
int64_t,
phi::float16,
phi::bfloat16) {}
PD_REGISTER_KERNEL(floor_grad,
CPU,
ALL_LAYOUT,
phi::FloorGradKernel,
float,
double,
uint8_t,
int8_t,
int16_t,
int,
int64_t,
phi::float16,
phi::bfloat16) {}
+484
View File
@@ -0,0 +1,484 @@
/* 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/activation_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/full_kernel.h"
#include "paddle/phi/kernels/funcs/activation_functor.h"
#include "paddle/phi/kernels/impl/activation_impl.h"
namespace phi {
#define DEFINE_CPU_ACTIVATION_KERNEL(name, functor_class) \
template <typename T, typename Context> \
void name##Kernel( \
const Context& dev_ctx, const DenseTensor& x, DenseTensor* out) { \
funcs::functor_class<T> functor; \
ActivationImpl<T, T, Context, funcs::functor_class<T>>( \
dev_ctx, x, out, functor); \
}
#define DEFINE_CPU_ACTIVATION_KERNEL_WITH_INT_IN_FLOAT_OUT(name, \
functor_class) \
template <typename T, typename Context> \
void name##Kernel( \
const Context& dev_ctx, const DenseTensor& x, DenseTensor* out) { \
funcs::functor_class<T> functor; \
using U = \
typename std::conditional_t<std::is_integral<T>::value, float, T>; \
ActivationImpl<T, U, Context, funcs::functor_class<T>>( \
dev_ctx, x, out, functor); \
}
#define DEFINE_CPU_ACT_KERNEL_WITH_ONE_ATTRS(name, functor_class, attr) \
template <typename T, typename Context> \
void name##Kernel(const Context& dev_ctx, \
const DenseTensor& x, \
float attr, \
DenseTensor* out) { \
funcs::functor_class<T> functor; \
auto attrs = functor.GetAttrs(); \
*(attrs[0].second) = attr; \
ActivationImpl<T, T, Context, funcs::functor_class<T>>( \
dev_ctx, x, out, functor); \
}
#define DEFINE_CPU_ACT_KERNEL_WITH_ONE_DOUBLE_ATTRS(name, functor_class, attr) \
template <typename T, typename Context> \
void name##Kernel(const Context& dev_ctx, \
const DenseTensor& x, \
double attr, \
DenseTensor* out) { \
funcs::functor_class<T> functor; \
auto attrs = functor.GetAttrs(); \
*(attrs[0].second) = attr; \
ActivationImpl<T, T, Context, funcs::functor_class<T>>( \
dev_ctx, x, out, functor); \
}
#define DEFINE_CPU_ACT_KERNEL_WITH_TWO_ATTRS( \
name, functor_class, attr1, attr2) \
template <typename T, typename Context> \
void name##Kernel(const Context& dev_ctx, \
const DenseTensor& x, \
float attr1, \
float attr2, \
DenseTensor* out) { \
funcs::functor_class<T> functor; \
auto attrs = functor.GetAttrs(); \
*(attrs[0].second) = attr1; \
*(attrs[1].second) = attr2; \
ActivationImpl<T, T, Context, funcs::functor_class<T>>( \
dev_ctx, x, out, functor); \
}
#define DEFINE_CPU_ACT_KERNEL_WITH_TWO_DOUBLE_ATTRS( \
name, functor_class, attr1, attr2) \
template <typename T, typename Context> \
void name##Kernel(const Context& dev_ctx, \
const DenseTensor& x, \
double attr1, \
double attr2, \
DenseTensor* out) { \
funcs::functor_class<T> functor; \
auto attrs = functor.GetAttrs(); \
*(attrs[0].second) = attr1; \
*(attrs[1].second) = attr2; \
ActivationImpl<T, T, Context, funcs::functor_class<T>>( \
dev_ctx, x, out, functor); \
}
// Specialized Sin kernel with vectorized Sleef implementation for float/double
// This ensures high precision computation
template <typename T, typename Context>
void SinKernel(const Context& dev_ctx, const DenseTensor& x, DenseTensor* out) {
if constexpr (std::is_same<T, float>::value ||
std::is_same<T, double>::value) {
// Use vectorized Sleef path for float/double for high precision
VectorizedSinImpl<T, Context>(dev_ctx, x, out);
} else {
// Use generic path for other types (float16, bfloat16, complex)
funcs::SinFunctor<T> functor;
ActivationImpl<T, T, Context, funcs::SinFunctor<T>>(
dev_ctx, x, out, functor);
}
}
// Specialized Cos kernel with vectorized Sleef implementation for float/double
template <typename T, typename Context>
void CosKernel(const Context& dev_ctx, const DenseTensor& x, DenseTensor* out) {
if constexpr (std::is_same<T, float>::value ||
std::is_same<T, double>::value) {
// Use vectorized Sleef path for float/double for high precision
VectorizedCosImpl<T, Context>(dev_ctx, x, out);
} else {
// Use generic path for other types (float16, bfloat16, complex)
funcs::CosFunctor<T> functor;
ActivationImpl<T, T, Context, funcs::CosFunctor<T>>(
dev_ctx, x, out, functor);
}
}
DEFINE_CPU_ACTIVATION_KERNEL(Tan, TanFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Asin, AsinFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Atan, AtanFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Acos, AcosFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Sinh, SinhFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Cosh, CoshFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Asinh, AsinhFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Acosh, AcoshFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Atanh, AtanhFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Relu, ReluCPUFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Tanh, TanhFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(TanhShrink, TanhShrinkFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Silu, SiluFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Reciprocal, ReciprocalFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Square, SquareFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Sqrt, SqrtFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Rsqrt, RsqrtFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Softsign, SoftsignFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Sigmoid, SigmoidFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(LogSigmoid, LogSigmoidFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Floor, FloorFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Ceil, CeilFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Negative, NegativeFunctor)
DEFINE_CPU_ACTIVATION_KERNEL(Rint, RintFunctor)
DEFINE_CPU_ACTIVATION_KERNEL_WITH_INT_IN_FLOAT_OUT(Log, LogFunctor)
DEFINE_CPU_ACTIVATION_KERNEL_WITH_INT_IN_FLOAT_OUT(Log2, Log2Functor)
DEFINE_CPU_ACTIVATION_KERNEL_WITH_INT_IN_FLOAT_OUT(Log10, Log10Functor)
DEFINE_CPU_ACTIVATION_KERNEL_WITH_INT_IN_FLOAT_OUT(Log1p, Log1pFunctor)
DEFINE_CPU_ACTIVATION_KERNEL_WITH_INT_IN_FLOAT_OUT(Expm1, Expm1Functor)
// Specialized Exp kernel with vectorized MKL VML/Sleef implementation
// for float/double. This ensures high precision computation.
template <typename T, typename Context>
void ExpKernel(const Context& dev_ctx, const DenseTensor& x, DenseTensor* out) {
if constexpr (std::is_same<T, float>::value ||
std::is_same<T, double>::value) {
// Use vectorized MKL VML/Sleef path for float/double for high precision
VectorizedExpImpl<T, Context>(dev_ctx, x, out);
} else {
// Use generic path for other types (int, int64, float16, complex)
funcs::ExpFunctor<T> functor;
using U = typename std::conditional_t<std::is_integral<T>::value, float, T>;
ActivationImpl<T, U, Context, funcs::ExpFunctor<T>>(
dev_ctx, x, out, functor);
}
}
DEFINE_CPU_ACT_KERNEL_WITH_ONE_DOUBLE_ATTRS(LeakyRelu, LeakyReluFunctor, alpha)
DEFINE_CPU_ACT_KERNEL_WITH_ONE_ATTRS(Mish, MishFunctor, threshold)
DEFINE_CPU_ACT_KERNEL_WITH_ONE_ATTRS(HardShrink, HardShrinkFunctor, threshold)
DEFINE_CPU_ACT_KERNEL_WITH_ONE_ATTRS(SoftShrink, SoftShrinkFunctor, lambda)
DEFINE_CPU_ACT_KERNEL_WITH_ONE_ATTRS(Elu, ELUFunctor, alpha)
DEFINE_CPU_ACT_KERNEL_WITH_ONE_ATTRS(Celu, CELUFunctor, alpha)
DEFINE_CPU_ACT_KERNEL_WITH_TWO_ATTRS(HardTanh, HardTanhFunctor, t_min, t_max)
DEFINE_CPU_ACT_KERNEL_WITH_TWO_ATTRS(STanh, STanhFunctor, scale_a, scale_b)
DEFINE_CPU_ACT_KERNEL_WITH_TWO_DOUBLE_ATTRS(Softplus,
SoftplusFunctor,
beta,
threshold)
DEFINE_CPU_ACT_KERNEL_WITH_TWO_ATTRS(HardSigmoid,
HardSigmoidFunctor,
slope,
offset)
DEFINE_CPU_ACT_KERNEL_WITH_TWO_ATTRS(ThresholdedRelu,
ThresholdedReluFunctor,
threshold,
value)
template <typename T, typename Context>
void HardSwishKernel(const Context& dev_ctx,
const DenseTensor& x,
DenseTensor* out) {
funcs::HardSwishFunctor<T> functor;
float threshold = 6;
float scale = 6;
float offset = 3;
auto attrs = functor.GetAttrs();
*(attrs[0].second) = threshold;
*(attrs[1].second) = scale;
*(attrs[2].second) = offset;
ActivationImpl<T, T, Context, funcs::HardSwishFunctor<T>>(
dev_ctx, x, out, functor);
}
template <typename T, typename Context>
void SwishKernel(const Context& dev_ctx,
const DenseTensor& x,
DenseTensor* out) {
funcs::SwishFunctor<T> functor;
auto attrs = functor.GetAttrs();
*(attrs[0].second) = 1.0;
ActivationImpl<T, T, Context, funcs::SwishFunctor<T>>(
dev_ctx, x, out, functor);
}
template <typename T, typename Context>
void Relu6Kernel(const Context& dev_ctx,
const DenseTensor& x,
DenseTensor* out) {
funcs::Relu6Functor<T> functor;
auto attrs = functor.GetAttrs();
*(attrs[0].second) = 6.0;
ActivationImpl<T, T, Context, funcs::Relu6Functor<T>>(
dev_ctx, x, out, functor);
}
template <typename T, typename Context>
void RoundKernel(const Context& dev_ctx,
const DenseTensor& x,
const int decimals,
DenseTensor* out) {
funcs::RoundFunctor<T> functor;
auto attrs = functor.GetAttrs();
*(attrs[0].second) = decimals;
ActivationImpl<T, T, Context, funcs::RoundFunctor<T>>(
dev_ctx, x, out, functor);
}
template <typename T, typename Context>
void PowKernel(const Context& dev_ctx,
const DenseTensor& x,
const Scalar& factor,
DenseTensor* out) {
PADDLE_ENFORCE_NOT_NULL(
out, errors::InvalidArgument("Output Out should not be nullptr"));
dev_ctx.template Alloc<T>(out);
if (factor.to<float>() == 0) {
std::vector<int64_t> vec_dims = vectorize(out->dims());
Full<T, Context>(dev_ctx, vec_dims, static_cast<T>(1), out);
return;
}
if (factor.to<float>() == 1) {
Copy<Context>(dev_ctx, x, dev_ctx.GetPlace(), false, out);
return;
}
auto x_flatten =
EigenVector<T>::Flatten(GET_DATA_SAFELY(&x, "Input", "X", "Activation"));
auto out_flatten = EigenVector<T>::Flatten(
GET_DATA_SAFELY(out, "Output", "Out", "Activation"));
auto* place = dev_ctx.eigen_device();
funcs::PowFunctor<T> functor;
auto attrs = functor.GetAttrs();
*(attrs[0].second) = factor.to<float>();
functor(*place, x_flatten, out_flatten);
}
} // namespace phi
PD_REGISTER_KERNEL(relu, CPU, ALL_LAYOUT, phi::ReluKernel, float, double) {}
#define PD_REGISTER_ACTIVATION_KERNEL(name, func) \
PD_REGISTER_KERNEL(name, CPU, ALL_LAYOUT, phi::func, float, double) {}
#define PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(name, func) \
PD_REGISTER_KERNEL(name, \
CPU, \
ALL_LAYOUT, \
phi::func, \
float, \
double, \
phi::complex64, \
phi::complex128) {}
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(sin, SinKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(cos, CosKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(tan, TanKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(acos, AcosKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(asin, AsinKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(atan, AtanKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(sinh, SinhKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(cosh, CoshKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(asinh, AsinhKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(acosh, AcoshKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(atanh, AtanhKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(tanh, TanhKernel)
PD_REGISTER_ACTIVATION_KERNEL(hardtanh, HardTanhKernel)
PD_REGISTER_ACTIVATION_KERNEL(leaky_relu, LeakyReluKernel)
PD_REGISTER_ACTIVATION_KERNEL(thresholded_relu, ThresholdedReluKernel)
PD_REGISTER_ACTIVATION_KERNEL(hard_shrink, HardShrinkKernel)
PD_REGISTER_ACTIVATION_KERNEL(softshrink, SoftShrinkKernel)
PD_REGISTER_ACTIVATION_KERNEL(tanh_shrink, TanhShrinkKernel)
PD_REGISTER_ACTIVATION_KERNEL(elu, EluKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(silu, SiluKernel)
PD_REGISTER_ACTIVATION_KERNEL(mish, MishKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(stanh, STanhKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(reciprocal, ReciprocalKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(sqrt, SqrtKernel)
PD_REGISTER_ACTIVATION_KERNEL(rsqrt, RsqrtKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(softplus, SoftplusKernel)
PD_REGISTER_ACTIVATION_KERNEL(logit, LogitKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(softsign, SoftsignKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(sigmoid, SigmoidKernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(logsigmoid, LogSigmoidKernel)
PD_REGISTER_ACTIVATION_KERNEL(hardsigmoid, HardSigmoidKernel)
PD_REGISTER_ACTIVATION_KERNEL(swish, SwishKernel)
PD_REGISTER_ACTIVATION_KERNEL(relu6, Relu6Kernel)
PD_REGISTER_ACTIVATION_KERNEL_WITH_COMPLEX(hardswish, HardSwishKernel)
PD_REGISTER_ACTIVATION_KERNEL(celu, CeluKernel)
PD_REGISTER_KERNEL(
rint, CPU, ALL_LAYOUT, phi::RintKernel, int, int64_t, float, double) {}
PD_REGISTER_KERNEL(round,
CPU,
ALL_LAYOUT,
phi::RoundKernel,
int,
int64_t,
float,
double,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(exp,
CPU,
ALL_LAYOUT,
phi::ExpKernel,
float,
double,
int,
int64_t,
phi::float16,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(expm1,
CPU,
ALL_LAYOUT,
phi::Expm1Kernel,
float,
double,
int,
int64_t,
phi::float16,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(square,
CPU,
ALL_LAYOUT,
phi::SquareKernel,
float,
double,
int,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(log,
CPU,
ALL_LAYOUT,
phi::LogKernel,
float,
double,
int,
int64_t,
phi::float16,
phi::bfloat16,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(log2,
CPU,
ALL_LAYOUT,
phi::Log2Kernel,
float,
double,
int,
int64_t,
phi::float16,
phi::bfloat16,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(log10,
CPU,
ALL_LAYOUT,
phi::Log10Kernel,
float,
double,
int,
int64_t,
phi::float16,
phi::bfloat16,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(log1p,
CPU,
ALL_LAYOUT,
phi::Log1pKernel,
float,
double,
int,
int64_t,
phi::float16,
phi::bfloat16,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(negative,
CPU,
ALL_LAYOUT,
phi::NegativeKernel,
float,
double,
int16_t,
int,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(pow,
CPU,
ALL_LAYOUT,
phi::PowKernel,
float,
double,
int,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(ceil,
CPU,
ALL_LAYOUT,
phi::CeilKernel,
float,
double,
uint8_t,
int8_t,
int16_t,
int,
int64_t,
phi::float16,
phi::bfloat16) {}
PD_REGISTER_KERNEL(floor,
CPU,
ALL_LAYOUT,
phi::FloorKernel,
float,
double,
uint8_t,
int8_t,
int16_t,
int,
int64_t,
phi::float16,
phi::bfloat16) {}
+22
View File
@@ -0,0 +1,22 @@
// 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/adadelta_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/adadelta_kernel_impl.h"
PD_REGISTER_KERNEL(
adadelta, CPU, ALL_LAYOUT, phi::AdadeltaKernel, float, double) {}
+118
View File
@@ -0,0 +1,118 @@
// 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/adagrad_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/math_function.h"
#include "paddle/phi/kernels/funcs/selected_rows_functor.h"
#include "paddle/phi/kernels/impl/adagrad_kernel_impl.h"
namespace phi {
namespace {
size_t FindPos(const std::vector<int64_t>& rows, int64_t value) {
return std::find(rows.begin(), rows.end(), value) - rows.begin();
}
} // namespace
template <typename T>
struct DenseAdagradFunctor<CPUContext, T> {
void operator()(const CPUContext& dev_ctx,
const DenseTensor& param_t,
const DenseTensor& grad_t,
const DenseTensor& moment_t,
const DenseTensor& learning_rate,
const optional<DenseTensor>& master_param,
float epsilon_t,
bool multi_precision,
DenseTensor* param_out_tensor,
DenseTensor* moment_out_tensor,
DenseTensor* master_param_outs) {
dev_ctx.template Alloc<T>(param_out_tensor);
dev_ctx.template Alloc<T>(moment_out_tensor);
T epsilon = static_cast<T>(epsilon_t);
auto param = EigenVector<T>::Flatten(param_t);
auto grad = EigenVector<T>::Flatten(grad_t);
auto moment = EigenVector<T>::Flatten(moment_t);
auto param_out = EigenVector<T>::Flatten(*param_out_tensor);
auto moment_out = EigenVector<T>::Flatten(*moment_out_tensor);
auto place = *dev_ctx.eigen_device();
moment_out.device(place) = moment + grad * grad;
Eigen::DSizes<int, 1> m_dsize(static_cast<int>(moment_out_tensor->numel()));
auto* lr = learning_rate.data<T>();
param_out.device(place) =
param - lr[0] * grad / (moment_out.sqrt() + epsilon);
}
};
template <typename T>
struct SparseAdagradFunctor<CPUContext, T> {
void operator()(const CPUContext& dev_ctx,
const SelectedRows& grad,
const DenseTensor& learning_rate,
T epsilon,
DenseTensor* moment,
DenseTensor* param) {
// 1. g_m.rows = set(g.rows)
auto grad_width = grad.value().dims()[1];
funcs::scatter::MergeAdd<CPUContext, T> merge_func;
auto grad_merge = merge_func(dev_ctx, grad);
auto& merge_rows = grad_merge.rows();
auto* grad_merge_data = grad_merge.mutable_value()->template data<T>();
// 2. m += g_m * g_m
auto grad_square = SquareSelectedRows<CPUContext, T>(dev_ctx, grad_merge);
funcs::SelectedRowsAddToTensor<CPUContext, T> functor;
functor(dev_ctx, grad_square, moment);
// 3. update parameter
auto* lr = learning_rate.data<T>();
auto* param_data = param->data<T>();
auto* moment_data = moment->data<T>();
for (size_t i = 0; i < merge_rows.size(); i++) {
for (int64_t j = 0; j < grad_width; j++) {
param_data[merge_rows[i] * grad_width + j] -=
lr[0] * grad_merge_data[i * grad_width + j] /
(std::sqrt(moment_data[merge_rows[i] * grad_width + j]) + epsilon);
}
}
}
};
template struct SparseAdagradFunctor<CPUContext, float>;
template struct SparseAdagradFunctor<CPUContext, double>;
template struct DenseAdagradFunctor<CPUContext, float>;
template struct DenseAdagradFunctor<CPUContext, double>;
} // namespace phi
PD_REGISTER_KERNEL(
adagrad, CPU, ALL_LAYOUT, phi::AdagradDenseKernel, float, double) {}
PD_REGISTER_KERNEL(adagrad_dense_param_sparse_grad,
CPU,
ALL_LAYOUT,
phi::AdagradSparseKernel,
float,
double) {}
+316
View File
@@ -0,0 +1,316 @@
// 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/adam_kernel.h"
#include <vector>
#include "glog/logging.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/core/tensor_utils.h"
#include "paddle/phi/kernels/funcs/adam_functors.h"
#include "paddle/phi/kernels/funcs/jit/kernels.h"
PD_DECLARE_int32(inner_op_parallelism);
namespace phi {
template <typename T, typename Context>
PADDLE_API void AdamDenseKernel(const Context& dev_ctx,
const DenseTensor& param,
const DenseTensor& grad,
const DenseTensor& learning_rate,
const DenseTensor& moment1,
const DenseTensor& moment2,
const optional<DenseTensor>& moment2_max,
const DenseTensor& beta1_pow,
const DenseTensor& beta2_pow,
const optional<DenseTensor>& master_param,
const optional<DenseTensor>& skip_update,
const Scalar& beta1,
const Scalar& beta2,
const Scalar& epsilon,
bool lazy_mode,
int64_t min_row_size_to_use_multithread,
bool multi_precision,
bool use_global_beta_pow,
bool amsgrad,
DenseTensor* param_out,
DenseTensor* moment1_out,
DenseTensor* moment2_out,
DenseTensor* moment2_max_out,
DenseTensor* beta1_pow_out,
DenseTensor* beta2_pow_out,
DenseTensor* master_param_outs) {
VLOG(4) << "use_global_beta_pow:" << use_global_beta_pow;
bool skip_update_ = false;
if (skip_update.is_initialized()) {
PADDLE_ENFORCE_EQ(
skip_update->numel(),
1,
errors::InvalidArgument("Input(SkipUpdate) size must be 1, but get %d",
skip_update->numel()));
std::vector<bool> skip_update_vec;
TensorToVector(*skip_update, dev_ctx, &skip_update_vec);
skip_update_ = skip_update_vec[0];
}
// skip_update=true, just copy input to output, and TensorCopy will call
// mutable_data
if (skip_update_) {
VLOG(4) << "Adam skip update";
Copy(dev_ctx, param, dev_ctx.GetPlace(), false, param_out);
Copy(dev_ctx, moment1, dev_ctx.GetPlace(), false, moment1_out);
Copy(dev_ctx, moment2, dev_ctx.GetPlace(), false, moment2_out);
if (amsgrad) {
Copy(dev_ctx,
moment2_max.get(),
dev_ctx.GetPlace(),
false,
moment2_max_out);
}
if (!use_global_beta_pow) {
Copy(dev_ctx, beta1_pow, beta1_pow.place(), false, beta1_pow_out);
Copy(dev_ctx, beta2_pow, beta2_pow.place(), false, beta2_pow_out);
}
return;
}
T beta1_ = beta1.to<T>();
T beta2_ = beta2.to<T>();
T epsilon_ = epsilon.to<T>();
VLOG(3) << "beta1_pow.numel() : " << beta1_pow.numel();
VLOG(3) << "beta2_pow.numel() : " << beta2_pow.numel();
VLOG(3) << "param.numel(): " << param.numel();
PADDLE_ENFORCE_EQ(
beta1_pow_out->numel(),
1,
errors::InvalidArgument("beta1 pow output size should be 1, but received "
"value is:%d.",
beta1_pow_out->numel()));
PADDLE_ENFORCE_EQ(
beta2_pow_out->numel(),
1,
errors::InvalidArgument("beta2 pow output size should be 1, but received "
"value is:%d.",
beta2_pow_out->numel()));
T beta1_p = beta1_pow.data<T>()[0];
T beta2_p = beta2_pow.data<T>()[0];
if (!use_global_beta_pow) {
dev_ctx.template Alloc<T>(beta1_pow_out)[0] = beta1_ * beta1_p;
dev_ctx.template Alloc<T>(beta2_pow_out)[0] = beta2_ * beta2_p;
}
T* param_out_ptr = dev_ctx.template Alloc<T>(param_out);
T* mom1_out_ptr = dev_ctx.template Alloc<T>(moment1_out);
T* mom2_out_ptr = dev_ctx.template Alloc<T>(moment2_out);
T* mom2_max_out_ptr =
amsgrad ? dev_ctx.template Alloc<T>(moment2_max_out) : nullptr;
T learning_rate_ = static_cast<T>(learning_rate.data<double>()[0]) *
(sqrt(1 - beta2_p) / (1 - beta1_p));
T eps = epsilon_ * sqrt(1 - beta2_p);
jit::adam_attr_t attr(beta1_, beta2_, amsgrad);
int64_t numel = param.numel();
const T* param_ptr = param.data<T>();
const T* mom1_ptr = moment1.data<T>();
const T* mom2_ptr = moment2.data<T>();
const T* mom2_max_ptr = amsgrad ? moment2_max.get().data<T>() : nullptr;
const T* grad_ptr = grad.data<T>();
auto adam = jit::KernelFuncs<jit::AdamTuple<T>, CPUPlace>::Cache().At(attr);
static constexpr int64_t chunk_size = 512;
#ifdef PADDLE_WITH_MKLML
#pragma omp parallel for
#endif
for (int64_t i = 0; i < numel / chunk_size; ++i) {
const int64_t offset = i * chunk_size;
const T* mom2_max_in_data = amsgrad ? mom2_max_ptr + offset : nullptr;
T* mom2_max_out_data = amsgrad ? mom2_max_out_ptr + offset : nullptr;
adam(beta1_,
beta2_,
-learning_rate_,
eps,
chunk_size,
grad_ptr + offset,
mom1_ptr + offset,
mom2_ptr + offset,
mom2_max_in_data,
param_ptr + offset,
mom1_out_ptr + offset,
mom2_out_ptr + offset,
mom2_max_out_data,
param_out_ptr + offset,
amsgrad);
}
if (numel % chunk_size != 0) {
const int64_t offset = (numel / chunk_size) * chunk_size;
const int64_t tail_numel = numel % chunk_size;
const T* mom2_max_in_data = amsgrad ? mom2_max_ptr + offset : nullptr;
T* mom2_max_out_data = amsgrad ? mom2_max_out_ptr + offset : nullptr;
adam(beta1_,
beta2_,
-learning_rate_,
eps,
tail_numel,
grad_ptr + offset,
mom1_ptr + offset,
mom2_ptr + offset,
mom2_max_in_data,
param_ptr + offset,
mom1_out_ptr + offset,
mom2_out_ptr + offset,
mom2_max_out_data,
param_out_ptr + offset,
amsgrad);
}
}
template <typename T, typename Context>
void MergedAdamKernel(
const Context& dev_ctx,
const std::vector<const DenseTensor*>& param,
const std::vector<const DenseTensor*>& grad,
const std::vector<const DenseTensor*>& learning_rate,
const std::vector<const DenseTensor*>& moment1,
const std::vector<const DenseTensor*>& moment2,
const optional<std::vector<const DenseTensor*>>& moment2_max,
const std::vector<const DenseTensor*>& beta1_pow,
const std::vector<const DenseTensor*>& beta2_pow,
const optional<std::vector<const DenseTensor*>>& master_param,
const Scalar& beta1,
const Scalar& beta2,
const Scalar& epsilon,
bool multi_precision,
bool use_global_beta_pow,
bool amsgrad,
std::vector<DenseTensor*> param_out,
std::vector<DenseTensor*> moment1_out,
std::vector<DenseTensor*> moment2_out,
std::vector<DenseTensor*> moment2_max_out,
std::vector<DenseTensor*> beta1_pow_out,
std::vector<DenseTensor*> beta2_pow_out,
std::vector<DenseTensor*> master_param_out) {
size_t param_num = param.size();
PADDLE_ENFORCE_EQ(
param_num,
grad.size(),
errors::InvalidArgument("The size of Input(grad) must be equal to "
"Input(param), but got the size of Input(grad) "
"is %d, the size of Input(param) is %d.",
grad.size(),
param_num));
PADDLE_ENFORCE_EQ(
param_num,
learning_rate.size(),
errors::InvalidArgument(
"The size of Input(learning_rate) must be equal to "
"Input(param), but got the size of Input(learning_rate) "
"is %d, the size of Input(param) is %d.",
learning_rate.size(),
param_num));
PADDLE_ENFORCE_EQ(param_num,
moment1.size(),
errors::InvalidArgument(
"The size of Input(moment1) must be equal to "
"Input(param), but got the size of Input(moment1) "
"is %d, the size of Input(param) is %d.",
moment1.size(),
param_num));
PADDLE_ENFORCE_EQ(param_num,
moment2.size(),
errors::InvalidArgument(
"The size of Input(moment2) must be equal to "
"Input(param), but got the size of Input(moment2) "
"is %d, the size of Input(param) is %d.",
moment2.size(),
param_num));
PADDLE_ENFORCE_EQ(param_num,
beta1_pow.size(),
errors::InvalidArgument(
"The size of Input(beta1_pow) must be equal to "
"Input(param), but got the size of Input(beta1_pow) "
"is %d, the size of Input(param) is %d.",
beta1_pow.size(),
param_num));
PADDLE_ENFORCE_EQ(param_num,
beta2_pow.size(),
errors::InvalidArgument(
"The size of Input(beta2_pow) must be equal to "
"Input(param), but got the size of Input(beta2_pow) "
"is %d, the size of Input(param) is %d.",
beta2_pow.size(),
param_num));
T beta1_ = beta1.to<T>();
T beta2_ = beta2.to<T>();
T epsilon_ = epsilon.to<T>();
for (size_t idx = 0; idx < param_num; idx++) {
const T* mom2_max_in_data =
amsgrad ? moment2_max.get()[idx]->data<T>() : nullptr;
T* mom2_max_out_data =
amsgrad ? dev_ctx.template Alloc<T>(moment2_max_out[idx]) : nullptr;
const T lr_val = static_cast<T>(learning_rate[idx]->data<double>()[0]);
funcs::AdamFunctor<T, funcs::CPUAdam> functor(
beta1_,
beta2_,
epsilon_,
beta1_pow[idx]->data<T>(),
beta2_pow[idx]->data<T>(),
moment1[idx]->data<T>(),
dev_ctx.template Alloc<T>(moment1_out[idx]),
moment2[idx]->data<T>(),
dev_ctx.template Alloc<T>(moment2_out[idx]),
mom2_max_in_data,
mom2_max_out_data,
&lr_val,
grad[idx]->data<T>(),
param[idx]->data<T>(),
dev_ctx.template Alloc<T>(param_out[idx]),
amsgrad);
functor(param[idx]->numel());
if (!use_global_beta_pow) {
dev_ctx.template Alloc<T>(beta1_pow_out[idx])[0] =
beta1_ * beta1_pow[idx]->data<T>()[0];
dev_ctx.template Alloc<T>(beta2_pow_out[idx])[0] =
beta2_ * beta2_pow[idx]->data<T>()[0];
}
}
}
} // namespace phi
PD_REGISTER_KERNEL(adam, CPU, ALL_LAYOUT, phi::AdamDenseKernel, float, double) {
kernel->InputAt(2).SetDataType(phi::DataType::FLOAT64);
}
PD_REGISTER_KERNEL(
merged_adam, CPU, ALL_LAYOUT, phi::MergedAdamKernel, float, double) {
kernel->InputAt(2).SetDataType(phi::DataType::FLOAT64);
}
+21
View File
@@ -0,0 +1,21 @@
// 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/adamax_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/adamax_kernel_impl.h"
PD_REGISTER_KERNEL(adamax, CPU, ALL_LAYOUT, phi::AdamaxKernel, float, double) {}
+219
View File
@@ -0,0 +1,219 @@
// 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/adamw_kernel.h"
#include <vector>
#include "glog/logging.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/core/tensor_utils.h"
#include "paddle/phi/kernels/adam_kernel.h"
#include "paddle/phi/kernels/funcs/adam_functors.h"
#include "paddle/phi/kernels/funcs/jit/kernels.h"
namespace phi {
template <typename T, typename Context>
PADDLE_API void AdamwDenseKernel(const Context& dev_ctx,
const DenseTensor& param,
const DenseTensor& grad,
const DenseTensor& learning_rate,
const DenseTensor& moment1,
const DenseTensor& moment2,
const optional<DenseTensor>& moment2_max,
const DenseTensor& beta1_pow,
const DenseTensor& beta2_pow,
const optional<DenseTensor>& master_param,
const optional<DenseTensor>& skip_update,
const Scalar& beta1,
const Scalar& beta2,
const Scalar& epsilon,
double lr_ratio,
double coeff,
bool with_decay,
bool lazy_mode,
int64_t min_row_size_to_use_multithread,
bool multi_precision,
bool use_global_beta_pow,
bool amsgrad,
DenseTensor* param_out,
DenseTensor* moment1_out,
DenseTensor* moment2_out,
DenseTensor* moment2_max_out,
DenseTensor* beta1_pow_out,
DenseTensor* beta2_pow_out,
DenseTensor* master_param_outs) {
bool skip_update_ = false;
if (skip_update.is_initialized()) {
PADDLE_ENFORCE_EQ(
skip_update->numel(),
1,
errors::InvalidArgument("Input(SkipUpdate) size must be 1, but get %d",
skip_update->numel()));
std::vector<bool> skip_update_vec;
TensorToVector(*skip_update, dev_ctx, &skip_update_vec);
skip_update_ = skip_update_vec[0];
}
VLOG(3) << "Skip update" << skip_update_;
if (skip_update_ || !with_decay) {
AdamDenseKernel<T, Context>(dev_ctx,
param,
grad,
learning_rate,
moment1,
moment2,
moment2_max,
beta1_pow,
beta2_pow,
master_param,
skip_update,
beta1,
beta2,
epsilon,
lazy_mode,
min_row_size_to_use_multithread,
multi_precision,
use_global_beta_pow,
amsgrad,
param_out,
moment1_out,
moment2_out,
moment2_max_out,
beta1_pow_out,
beta2_pow_out,
master_param_outs);
return;
}
T beta1_ = beta1.to<T>();
T beta2_ = beta2.to<T>();
T epsilon_ = epsilon.to<T>();
T coeff_ = static_cast<T>(coeff);
T lr_ratio_ = static_cast<T>(lr_ratio);
VLOG(3) << "beta1_pow.numel() : " << beta1_pow.numel();
VLOG(3) << "beta2_pow.numel() : " << beta2_pow.numel();
VLOG(3) << "param.numel(): " << param.numel();
PADDLE_ENFORCE_EQ(
beta1_pow_out->numel(),
1,
errors::InvalidArgument("beta1 pow output size should be 1, but received "
"value is:%d.",
beta1_pow_out->numel()));
PADDLE_ENFORCE_EQ(
beta2_pow_out->numel(),
1,
errors::InvalidArgument("beta2 pow output size should be 1, but received "
"value is:%d.",
beta2_pow_out->numel()));
T beta1_p = beta1_pow.data<T>()[0];
T beta2_p = beta2_pow.data<T>()[0];
if (!use_global_beta_pow) {
dev_ctx.template Alloc<T>(beta1_pow_out)[0] = beta1_ * beta1_p;
dev_ctx.template Alloc<T>(beta2_pow_out)[0] = beta2_ * beta2_p;
}
T* param_out_ptr = dev_ctx.template Alloc<T>(param_out);
T* mom1_out_ptr = dev_ctx.template Alloc<T>(moment1_out);
T* mom2_out_ptr = dev_ctx.template Alloc<T>(moment2_out);
T* mom2_max_out_ptr =
amsgrad ? dev_ctx.template Alloc<T>(moment2_max_out) : nullptr;
T old_lr = static_cast<T>(learning_rate.data<double>()[0]);
T learning_rate_ = static_cast<T>(learning_rate.data<double>()[0]) *
(sqrt(1 - beta2_p) / (1 - beta1_p));
T eps = epsilon_ * sqrt(1 - beta2_p);
jit::adamw_attr_t attr(beta1_, beta2_, coeff_, amsgrad);
int64_t numel = param.numel();
const T* param_ptr = param.data<T>();
const T* mom1_ptr = moment1.data<T>();
const T* mom2_ptr = moment2.data<T>();
const T* mom2_max_ptr = amsgrad ? moment2_max.get().data<T>() : nullptr;
const T* grad_ptr = grad.data<T>();
auto adamw = jit::KernelFuncs<jit::AdamWTuple<T>, CPUPlace>::Cache().At(attr);
static constexpr int64_t chunk_size = 512;
#ifdef PADDLE_WITH_MKLML
#pragma omp parallel for
#endif
for (int64_t i = 0; i < numel / chunk_size; ++i) {
const int64_t offset = i * chunk_size;
const T* mom2_max_in_data = amsgrad ? mom2_max_ptr + offset : nullptr;
T* mom2_max_out_data = amsgrad ? mom2_max_out_ptr + offset : nullptr;
adamw(beta1_,
beta2_,
-learning_rate_,
eps,
old_lr,
lr_ratio_,
coeff_,
chunk_size,
grad_ptr + offset,
mom1_ptr + offset,
mom2_ptr + offset,
mom2_max_in_data,
param_ptr + offset,
mom1_out_ptr + offset,
mom2_out_ptr + offset,
mom2_max_out_data,
param_out_ptr + offset,
amsgrad);
}
if (numel % chunk_size != 0) {
const int64_t offset = (numel / chunk_size) * chunk_size;
const int64_t tail_numel = numel % chunk_size;
const T* mom2_max_in_data = amsgrad ? mom2_max_ptr + offset : nullptr;
T* mom2_max_out_data = amsgrad ? mom2_max_out_ptr + offset : nullptr;
adamw(beta1_,
beta2_,
-learning_rate_,
eps,
old_lr,
lr_ratio_,
coeff_,
tail_numel,
grad_ptr + offset,
mom1_ptr + offset,
mom2_ptr + offset,
mom2_max_in_data,
param_ptr + offset,
mom1_out_ptr + offset,
mom2_out_ptr + offset,
mom2_max_out_data,
param_out_ptr + offset,
amsgrad);
}
}
} // namespace phi
PD_REGISTER_KERNEL(
adamw, CPU, ALL_LAYOUT, phi::AdamwDenseKernel, float, double) {
kernel->InputAt(2).SetDataType(phi::DataType::FLOAT64);
kernel->InputAt(9).SetBackend(phi::Backend::ALL_BACKEND);
}
+154
View File
@@ -0,0 +1,154 @@
// 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/common/amp_type_traits.h"
#include "paddle/phi/kernels/impl/add_n_kernel_impl.h"
#include "glog/logging.h"
namespace phi {
template <typename T, typename Context>
void AddNKernel(const Context& dev_ctx,
const std::vector<const TensorBase*>& x,
DenseTensor* out) {
size_t in_num = x.size();
dev_ctx.template Alloc<T>(out);
if (out && out->numel() == 0) {
return;
}
bool in_place = false;
if (!x.empty() && x[0]->initialized() && DenseTensor::classof(x[0])) {
if ((static_cast<const DenseTensor*>(x[0]))->Holder() == out->Holder()) {
in_place = true;
if (in_num == 1) {
return;
}
}
}
// using MT to keep precision
using MT = typename MPTypeTrait<T>::Type;
auto& place = *dev_ctx.eigen_device();
if constexpr (std::is_same_v<MT, T>) {
// compute in out
auto result = EigenVector<T>::Flatten(*out);
if (!in_place) {
funcs::SetConstant<Context, T> constant_functor;
constant_functor(dev_ctx, out, static_cast<T>(0));
}
funcs::SelectedRowsAddToTensor<Context, T> functor;
size_t start = in_place ? 1 : 0;
for (size_t i = start; i < in_num; i++) {
if (DenseTensor::classof(x[i])) {
auto& in_t = *(static_cast<const DenseTensor*>(x[i]));
if (!in_t.initialized() || in_t.numel() == 0) {
continue;
}
auto in = EigenVector<T>::Flatten(in_t);
result.device(place) = result + in;
} else if (SelectedRows::classof(x[i])) {
auto& in_t = *(static_cast<const SelectedRows*>(x[i]));
functor(dev_ctx, in_t, out);
} else {
PADDLE_THROW(common::errors::InvalidArgument(
"Expected type of Input(X) of %d-th must be Tensor, "
"SelectedRows. But got "
"unsupported type: %s.",
i,
x[i]->type_info().name()));
}
}
} else {
// compute in temp_out by using MT
DenseTensor temp_out;
temp_out.Resize(out->dims());
dev_ctx.template Alloc<MT>(&temp_out);
auto result_mp = EigenVector<MT>::Flatten(temp_out);
// set temp_out
funcs::SetConstant<Context, MT> constant_functor;
if (in_place && DenseTensor::classof(x[0]) && x[0]->initialized()) {
auto& in_0 = *(static_cast<const DenseTensor*>(x[0]));
if (in_0.numel()) {
auto in_0_e = EigenVector<T>::Flatten(in_0).template cast<MT>();
result_mp.device(place) = in_0_e;
} else {
constant_functor(dev_ctx, &temp_out, static_cast<MT>(0));
}
} else {
constant_functor(dev_ctx, &temp_out, static_cast<MT>(0));
}
funcs::SelectedRowsAddToTensor<Context, MT> functor;
size_t start = in_place ? 1 : 0;
for (size_t i = start; i < in_num; i++) {
if (DenseTensor::classof(x[i])) {
auto& in_t = *(static_cast<const DenseTensor*>(x[i]));
if (!in_t.initialized() || in_t.numel() == 0) {
continue;
}
auto in = EigenVector<T>::Flatten(in_t).template cast<MT>();
result_mp.device(place) = result_mp + in;
} else if (SelectedRows::classof(x[i])) {
auto& in_t = *(static_cast<const SelectedRows*>(x[i]));
functor(dev_ctx, in_t, &temp_out);
} else {
PADDLE_THROW(common::errors::InvalidArgument(
"Expected type of Input(X) of %d-th must be Tensor, "
"SelectedRows. But got "
"unsupported type: %s.",
i,
x[i]->type_info().name()));
}
}
// cast back to T, and copy to out
auto result = EigenVector<T>::Flatten(*out);
result.device(place) = result_mp.template cast<T>();
}
}
} // namespace phi
PD_REGISTER_KERNEL(add_n,
CPU,
ALL_LAYOUT,
phi::AddNKernel,
float,
double,
int,
phi::bfloat16,
phi::float16,
int64_t,
phi::complex64,
phi::complex128) {}
PD_REGISTER_KERNEL(add_n_array,
CPU,
ALL_LAYOUT,
phi::AddNArrayKernel,
float,
double,
int,
phi::bfloat16,
phi::float16,
int64_t,
phi::complex64,
phi::complex128) {}
@@ -0,0 +1,44 @@
// 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/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
namespace phi {
template <typename T, typename Context>
void AddPositionEncodingGradKernel(const Context& dev_ctx,
const DenseTensor& x_in,
const DenseTensor& out_grad,
float alpha,
float beta,
DenseTensor* x_grad) {
auto* dOut = &out_grad;
auto dout = EigenVector<T>::Flatten(*dOut);
auto* dX = x_grad;
dev_ctx.template Alloc<T>(dX);
auto dx = EigenVector<T>::Flatten(*dX);
auto* place = dev_ctx.eigen_device();
dx.device(*place) = dout * static_cast<T>(alpha);
}
} // namespace phi
PD_REGISTER_KERNEL(add_position_encoding_grad,
CPU,
ALL_LAYOUT,
phi::AddPositionEncodingGradKernel,
float,
double) {}
@@ -0,0 +1,104 @@
// 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/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
namespace phi {
template <typename T, typename Context>
void AddPositionEncodingKernel(const Context& dev_ctx,
const DenseTensor& x_in,
float alpha,
float beta,
DenseTensor* out) {
auto* X = &x_in;
auto& x_lod = X->lod();
auto* src_ptr = X->data<T>();
auto* dst_ptr = dev_ctx.template Alloc<T>(out);
auto x_dim = X->dims();
int64_t batch_size = 0;
int64_t max_seq_len = 0;
int64_t enc_size = 0;
if (x_lod.empty()) {
PADDLE_ENFORCE_EQ(x_dim.size(),
3,
common::errors::InvalidArgument(
"The input(X)'s dimension of AddPositionEncodingOp "
"should be equal to "
"3, but received %d. ",
x_dim.size()));
batch_size = x_dim[0];
max_seq_len = x_dim[1];
enc_size = x_dim[2];
} else {
PADDLE_ENFORCE_EQ(x_dim.size(),
2,
common::errors::InvalidArgument(
"The input(X)'s dimension of AddPositionEncodingOp "
"should be equal to "
"2, but received %d. ",
x_dim.size()));
PADDLE_ENFORCE_EQ(x_lod.size(),
1,
common::errors::InvalidArgument(
"The input(X)'s lod level of AddPositionEncodingOp "
"should be equal to "
"1, but received %d. ",
x_lod.size()));
batch_size = x_lod[0].size() - 1;
max_seq_len = -1;
enc_size = x_dim[1];
}
PADDLE_ENFORCE_EQ(enc_size % 2,
0,
common::errors::InvalidArgument(
"The input(X)'s feature size of "
"AddPositionEncodingOp only support even, "
"but received an odd number: %d. ",
enc_size));
const int64_t half_size = enc_size / 2;
for (int64_t i = 0; i < batch_size; ++i) {
const int64_t max_length =
x_lod.empty() ? max_seq_len : x_lod[0][i + 1] - x_lod[0][i];
for (int64_t j = 0; j < max_length; ++j) {
for (int64_t k = 0; k < half_size; ++k) {
const double val =
(half_size > 1)
? j / pow(10000.0, static_cast<double>(k) / (half_size - 1))
: j / 10000.0;
dst_ptr[k] = src_ptr[k] * alpha + sin(val) * beta;
dst_ptr[half_size + k] =
src_ptr[half_size + k] * alpha + cos(val) * beta;
}
src_ptr += enc_size;
dst_ptr += enc_size;
}
}
}
} // namespace phi
PD_REGISTER_KERNEL(add_position_encoding,
CPU,
ALL_LAYOUT,
phi::AddPositionEncodingKernel,
float,
double) {}
@@ -0,0 +1,22 @@
/* 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/addmm_grad_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/addmm_grad_kernel_impl.h"
PD_REGISTER_KERNEL(
addmm_grad, CPU, ALL_LAYOUT, phi::AddmmGradKernel, float, double) {}
+21
View File
@@ -0,0 +1,21 @@
/* 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/addmm_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/addmm_kernel_impl.h"
PD_REGISTER_KERNEL(addmm, CPU, ALL_LAYOUT, phi::AddmmKernel, float, double) {}
@@ -0,0 +1,132 @@
// 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_grad_kernel.h"
#include <string>
#include <unordered_map>
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
namespace phi {
template <typename T>
using EigenArrayMap =
Eigen::Map<Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic>>;
template <typename T>
using ConstEigenArrayMap =
Eigen::Map<const Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic>>;
template <typename T>
using EigenVectorArrayMap = Eigen::Map<Eigen::Array<T, Eigen::Dynamic, 1>>;
template <typename T>
using ConstEigenVectorArrayMap =
Eigen::Map<const Eigen::Array<T, Eigen::Dynamic, 1>>;
template <typename T, typename Context>
void AffineChannelGradKernel(const Context& dev_ctx,
const DenseTensor& x_in,
const DenseTensor& scale_in,
const DenseTensor& bias_in,
const DenseTensor& out_grad,
const std::string& data_layout,
DenseTensor* x_grad,
DenseTensor* scale_grad,
DenseTensor* bias_grad) {
auto* x = &x_in;
auto* scale = &scale_in;
auto* dy = &out_grad;
auto* dx = x_grad;
auto* dscale = scale_grad;
auto* dbias = bias_grad;
const DataLayout layout = StringToDataLayout(data_layout);
auto dims = x->dims();
int N = static_cast<int>(dims[0]);
int C = static_cast<int>(layout == DataLayout::NCHW ? dims[1]
: dims[dims.size() - 1]);
int HxW = static_cast<int>(x->numel() / N / C);
auto* dy_d = dy->data<T>();
auto* scale_d = scale->data<T>();
ConstEigenVectorArrayMap<T> scale_e(scale_d, C);
T* dx_d = dx ? dev_ctx.template Alloc<T>(dx) : nullptr;
T* dscale_d = dscale ? dev_ctx.template Alloc<T>(dscale) : nullptr;
T* dbias_d = dbias ? dev_ctx.template Alloc<T>(dbias) : nullptr;
EigenVectorArrayMap<T> dscale_e(dscale_d, C);
EigenVectorArrayMap<T> dbias_e(dbias_d, C);
if (layout == DataLayout::NCHW) {
// compute dscale and dbias
int64_t stride = static_cast<int64_t>(C) * HxW;
auto* original_dy_d = dy_d;
if (dscale && dbias) {
auto* x_d = x->data<T>();
for (int i = 0; i < N; i++) {
ConstEigenArrayMap<T> x_e(x_d, HxW, C);
ConstEigenArrayMap<T> dy_e(dy_d, HxW, C);
if (i == 0) {
dscale_e = (x_e * dy_e).colwise().sum();
} else {
dscale_e += (x_e * dy_e).colwise().sum();
}
if (i == 0) {
dbias_e = dy_e.colwise().sum();
} else {
dbias_e += dy_e.colwise().sum();
}
x_d += stride;
dy_d += stride;
}
}
// compute dx
if (dx) {
dy_d = original_dy_d;
for (int i = 0; i < N; i++) {
ConstEigenArrayMap<T> dy_e(dy_d, HxW, C);
EigenArrayMap<T> dx_e(dx_d, HxW, C);
dx_e = dy_e.rowwise() * scale_e.transpose();
dy_d += stride;
dx_d += stride;
}
}
} else {
int64_t num = static_cast<int64_t>(N) * HxW;
ConstEigenArrayMap<T> dy_e(dy_d, C, num);
// compute dscale and dbias
if (dscale && dbias) {
auto* x_d = x->data<T>();
ConstEigenArrayMap<T> x_e(x_d, C, num);
dscale_e = (x_e * dy_e).rowwise().sum();
dbias_e = dy_e.rowwise().sum();
}
// compute dx
if (dx) {
EigenArrayMap<T> dx_e(dx_d, C, num);
dx_e = dy_e.colwise() * scale_e;
}
}
}
} // namespace phi
PD_REGISTER_KERNEL(affine_channel_grad,
CPU,
ALL_LAYOUT,
phi::AffineChannelGradKernel,
float,
double) {}
@@ -0,0 +1,83 @@
// 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 <string>
#include <unordered_map>
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
namespace phi {
template <typename T>
using EigenArrayMap =
Eigen::Map<Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic>>;
template <typename T>
using ConstEigenArrayMap =
Eigen::Map<const Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic>>;
template <typename T>
using EigenVectorArrayMap = Eigen::Map<Eigen::Array<T, Eigen::Dynamic, 1>>;
template <typename T>
using ConstEigenVectorArrayMap =
Eigen::Map<const Eigen::Array<T, Eigen::Dynamic, 1>>;
template <typename T, typename Context>
void AffineChannelKernel(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<T>(y);
const DataLayout layout = StringToDataLayout(data_layout);
auto dims = x->dims();
int N = static_cast<int>(dims[0]);
int C = static_cast<int>(layout == DataLayout::NCHW ? dims[1]
: dims[dims.size() - 1]);
int HxW = static_cast<int>(x->numel() / N / C);
auto* scale_d = scale->data<T>();
auto* bias_d = bias->data<T>();
ConstEigenVectorArrayMap<T> a_e(scale_d, C);
ConstEigenVectorArrayMap<T> b_e(bias_d, C);
auto* x_d = x->data<T>();
auto* y_d = y->data<T>();
if (layout == DataLayout::NCHW) {
int64_t stride = static_cast<int64_t>(C) * HxW;
for (int i = 0; i < N; i++) {
ConstEigenArrayMap<T> x_e(x_d, HxW, C);
EigenArrayMap<T> y_e(y_d, HxW, C);
y_e = (x_e.rowwise() * a_e.transpose()).rowwise() + b_e.transpose();
x_d += stride;
y_d += stride;
}
} else {
int64_t num = static_cast<int64_t>(N) * HxW;
ConstEigenArrayMap<T> x_e(x_d, C, num);
EigenArrayMap<T> y_e(y_d, C, num);
y_e = (x_e.colwise() * a_e).colwise() + b_e;
}
}
} // namespace phi
PD_REGISTER_KERNEL(
affine_channel, CPU, ALL_LAYOUT, phi::AffineChannelKernel, float, double) {}
@@ -0,0 +1,146 @@
// 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/affine_grid_grad_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/common/int_array.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/affine_grid_utils.h"
namespace phi {
template <typename T>
struct Linspace<CPUContext, T> {
void operator()(T start,
T end,
int count,
bool align_corners,
DenseTensor* numbers,
const CPUContext& dev_ctx) {
numbers->Resize({count});
T* number_data = dev_ctx.template Alloc<T>(numbers);
T slice = (end - start) / (T)(count - 1);
if (!align_corners) {
slice = (end - start) / (T)count;
start *= (T)(count - 1) / (T)count;
}
for (int i = 0; i < count; ++i) {
number_data[i] = start + (T)i * slice;
}
}
};
template <typename T, typename Context>
void AffineGridGrad4DKernel(const Context& dev_ctx,
const DenseTensor& output_grad,
const IntArray& outputShape,
bool align_corners,
DenseTensor* input_grad) {
auto& theta_grad = input_grad;
int n = static_cast<int>(output_grad.dims()[0]);
auto& size_attr = outputShape.GetData();
int h = 0;
int w = 0;
h = static_cast<int>(size_attr[2]);
w = static_cast<int>(size_attr[3]);
theta_grad->Resize({n, 2, 3});
dev_ctx.template Alloc<T>(theta_grad);
funcs::SetConstant<Context, T>()(dev_ctx, theta_grad, static_cast<T>(0));
DenseTensor grid;
GetIdxMap4D<Context, T>(n, h, w, align_corners, &grid, dev_ctx);
// output = grid * theta.T
// TODO(wanghaoshuang): Refine batched matrix multiply
auto blas = funcs::GetBlas<Context, T>(dev_ctx);
for (int i = 0; i < n; ++i) {
DenseTensor sliced_grid = grid.Slice(i, i + 1).Resize(
{static_cast<int64_t>(h) * static_cast<int64_t>(w), 3});
DenseTensor sliced_out_grad = output_grad.Slice(i, i + 1).Resize(
{static_cast<int64_t>(h) * static_cast<int64_t>(w), 2});
DenseTensor sliced_theta_grad = theta_grad->Slice(i, i + 1).Resize({2, 3});
blas.MatMul(sliced_out_grad,
true,
sliced_grid,
false,
T(1),
&sliced_theta_grad,
T(0));
}
}
template <typename T, typename Context>
void AffineGridGrad5DKernel(const Context& dev_ctx,
const DenseTensor& output_grad,
const IntArray& outputShape,
bool align_corners,
DenseTensor* input_grad) {
auto& theta_grad = input_grad;
int n = static_cast<int>(output_grad.dims()[0]);
auto& size_attr = outputShape.GetData();
int d = 0;
int h = 0;
int w = 0;
d = static_cast<int>(size_attr[2]);
h = static_cast<int>(size_attr[3]);
w = static_cast<int>(size_attr[4]);
theta_grad->Resize({n, 3, 4});
dev_ctx.template Alloc<T>(theta_grad);
funcs::SetConstant<Context, T>()(dev_ctx, theta_grad, static_cast<T>(0));
DenseTensor grid;
GetIdxMap5D<Context, T>(n, d, h, w, align_corners, &grid, dev_ctx);
auto blas = funcs::GetBlas<Context, T>(dev_ctx);
for (int i = 0; i < n; ++i) {
DenseTensor sliced_grid = grid.Slice(i, i + 1).Resize(
{static_cast<int64_t>(d) * static_cast<int64_t>(h) *
static_cast<int64_t>(w),
4});
DenseTensor sliced_out_grad = output_grad.Slice(i, i + 1).Resize(
{static_cast<int64_t>(d) * static_cast<int64_t>(h) *
static_cast<int64_t>(w),
3});
DenseTensor sliced_theta_grad = theta_grad->Slice(i, i + 1).Resize({3, 4});
blas.MatMul(sliced_out_grad,
true,
sliced_grid,
false,
T(1),
&sliced_theta_grad,
T(0));
}
}
template <typename T, typename Context>
void AffineGridGradKernel(const Context& dev_ctx,
const DenseTensor& output_grad,
const IntArray& outputShape,
bool align_corners,
DenseTensor* input_grad) {
auto& size_attr = outputShape.GetData();
if (size_attr.size() == 4) {
AffineGridGrad4DKernel<T, Context>(
dev_ctx, output_grad, outputShape, align_corners, input_grad);
} else {
AffineGridGrad5DKernel<T, Context>(
dev_ctx, output_grad, outputShape, align_corners, input_grad);
}
}
} // namespace phi
PD_REGISTER_KERNEL(affine_grid_grad,
CPU,
ALL_LAYOUT,
phi::AffineGridGradKernel,
float,
double){};
@@ -0,0 +1,132 @@
// 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/affine_grid_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/common/int_array.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/affine_grid_utils.h"
namespace phi {
template <typename T>
struct Linspace<CPUContext, T> {
void operator()(T start,
T end,
int count,
bool align_corners,
DenseTensor* numbers,
const CPUContext& dev_ctx) {
numbers->Resize({count});
T* number_data = dev_ctx.template Alloc<T>(numbers);
T slice = (end - start) / (T)(count - 1);
if (!align_corners) {
slice = (end - start) / (T)count;
start *= (T)(count - 1) / (T)count;
}
for (int i = 0; i < count; ++i) {
number_data[i] = start + (T)i * slice;
}
}
};
template <typename T, typename Context>
void AffineGrid4DKernel(const Context& dev_ctx,
const DenseTensor& input,
const IntArray& outputShape,
bool align_corners,
DenseTensor* output) {
auto* theta = &input;
int n = static_cast<int>(theta->dims()[0]);
auto& size_attr = outputShape.GetData();
int h = 0;
int w = 0;
h = static_cast<int>(size_attr[2]);
w = static_cast<int>(size_attr[3]);
output->Resize({n, h, w, 2});
dev_ctx.template Alloc<T>(output);
funcs::SetConstant<Context, T>()(dev_ctx, output, static_cast<T>(0));
DenseTensor grid;
GetIdxMap4D<Context, T>(n, h, w, align_corners, &grid, dev_ctx);
// output = grid * theta.T
// TODO(wanghaoshuang): Refine batched matrix multiply
auto blas = funcs::GetBlas<Context, T>(dev_ctx);
for (int i = 0; i < n; ++i) {
DenseTensor sliced_grid = grid.Slice(i, i + 1).Resize(
{static_cast<int64_t>(h) * static_cast<int64_t>(w), 3});
DenseTensor sliced_theta = theta->Slice(i, i + 1).Resize({2, 3});
DenseTensor sliced_out = output->Slice(i, i + 1).Resize(
{static_cast<int64_t>(h) * static_cast<int64_t>(w), 2});
blas.MatMul(
sliced_grid, false, sliced_theta, true, T(1), &sliced_out, T(0));
}
}
template <typename T, typename Context>
void AffineGrid5DKernel(const Context& dev_ctx,
const DenseTensor& input,
const IntArray& outputShape,
bool align_corners,
DenseTensor* output) {
auto* theta = &input;
int n = static_cast<int>(theta->dims()[0]);
auto& size_attr = outputShape.GetData();
int d = 0;
int h = 0;
int w = 0;
d = static_cast<int>(size_attr[2]);
h = static_cast<int>(size_attr[3]);
w = static_cast<int>(size_attr[4]);
output->Resize({n, d, h, w, 3});
dev_ctx.template Alloc<T>(output);
funcs::SetConstant<Context, T>()(dev_ctx, output, static_cast<T>(0));
DenseTensor grid;
GetIdxMap5D<Context, T>(n, d, h, w, align_corners, &grid, dev_ctx);
auto blas = funcs::GetBlas<Context, T>(dev_ctx);
for (int i = 0; i < n; ++i) {
DenseTensor sliced_grid = grid.Slice(i, i + 1).Resize(
{static_cast<int64_t>(d) * static_cast<int64_t>(h) *
static_cast<int64_t>(w),
4});
DenseTensor sliced_theta = theta->Slice(i, i + 1).Resize({3, 4});
DenseTensor sliced_out = output->Slice(i, i + 1).Resize(
{static_cast<int64_t>(d) * static_cast<int64_t>(h) *
static_cast<int64_t>(w),
3});
blas.MatMul(
sliced_grid, false, sliced_theta, true, T(1), &sliced_out, T(0));
}
}
template <typename T, typename Context>
void AffineGridKernel(const Context& dev_ctx,
const DenseTensor& input,
const IntArray& outputShape,
bool align_corners,
DenseTensor* output) {
auto& size_attr = outputShape.GetData();
if (size_attr.size() == 4) {
AffineGrid4DKernel<T, Context>(
dev_ctx, input, outputShape, align_corners, output);
} else {
AffineGrid5DKernel<T, Context>(
dev_ctx, input, outputShape, align_corners, output);
}
}
} // namespace phi
PD_REGISTER_KERNEL(
affine_grid, CPU, ALL_LAYOUT, phi::AffineGridKernel, float, double){};
+111
View File
@@ -0,0 +1,111 @@
// Copyright (c) 2023 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/all_gather_kernel.h"
#include "paddle/phi/backends/all_context.h"
#include "paddle/phi/core/kernel_registry.h"
#if defined(PADDLE_WITH_GLOO)
#include "paddle/phi/core/distributed/gloo_comm_context.h"
#endif
#ifdef PADDLE_WITH_CUSTOM_DEVICE
#include "paddle/phi/core/distributed/xccl_comm_context.h"
#endif
namespace phi {
template <typename T, typename Context>
void AllGatherKernel(const Context& dev_ctx,
const DenseTensor& x,
int nranks,
DenseTensor* out) {
#if defined(PADDLE_WITH_GLOO)
dev_ctx.template Alloc<T>(out);
auto out_dims = x.dims();
out_dims[0] *= nranks;
out->Resize(out_dims);
auto comm_ctx =
static_cast<distributed::GlooCommContext*>(dev_ctx.GetCommContext());
PADDLE_ENFORCE_EQ(
nranks,
comm_ctx->GetSize(),
errors::InvalidArgument(
"nranks: %s should equal to %s", nranks, comm_ctx->GetSize()));
comm_ctx->AllGather(out, x);
#else
PADDLE_THROW(errors::Unavailable(
"PaddlePaddle should compile with GLOO by setting WITH_GLOO=ON"));
#endif
}
#ifdef PADDLE_WITH_CUSTOM_DEVICE
template <typename T>
void AllGatherKernel(const CustomContext& dev_ctx,
const DenseTensor& x,
int nranks,
DenseTensor* out) {
dev_ctx.template Alloc<T>(out);
auto out_dims = x.dims();
out_dims[0] *= nranks;
out->Resize(out_dims);
auto comm_ctx =
static_cast<distributed::XCCLCommContext*>(dev_ctx.GetCommContext());
PADDLE_ENFORCE_EQ(
nranks,
comm_ctx->GetSize(),
errors::InvalidArgument(
"nranks: %s should equal to %s", nranks, comm_ctx->GetSize()));
comm_ctx->AllGather(out, x, dev_ctx.stream());
}
#endif
} // namespace phi
PD_REGISTER_KERNEL(all_gather,
CPU,
ALL_LAYOUT,
phi::AllGatherKernel,
float,
double,
int,
bool,
int8_t,
uint8_t,
int16_t,
int64_t,
phi::float16,
phi::complex64,
phi::complex128) {}
#ifdef PADDLE_WITH_CUSTOM_DEVICE
PD_REGISTER_KERNEL(all_gather,
Custom,
ALL_LAYOUT,
phi::AllGatherKernel,
float,
double,
int,
bool,
int8_t,
uint8_t,
int16_t,
int64_t,
phi::float16,
phi::complex64,
phi::complex128) {}
#endif
+103
View File
@@ -0,0 +1,103 @@
// Copyright (c) 2023 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/all_reduce_kernel.h"
#include "paddle/phi/backends/all_context.h"
#include "paddle/phi/core/kernel_registry.h"
#if defined(PADDLE_WITH_GLOO)
#include "paddle/phi/core/distributed/gloo_comm_context.h"
#endif
#ifdef PADDLE_WITH_CUSTOM_DEVICE
#include "paddle/phi/core/distributed/xccl_comm_context.h"
#endif
namespace phi {
template <typename T, typename Context>
void AllReduceKernel(const Context& dev_ctx,
const DenseTensor& x,
int reduce_type,
DenseTensor* out) {
#if defined(PADDLE_WITH_GLOO)
out->Resize(x.dims());
dev_ctx.template Alloc<T>(out);
auto comm_ctx =
static_cast<distributed::GlooCommContext*>(dev_ctx.GetCommContext());
PADDLE_ENFORCE_NE(
comm_ctx,
nullptr,
errors::Unavailable("NCCLCommContext is nullptr, collective op should "
"has ring_id attr."));
comm_ctx->AllReduce(out, x, reduce_type);
#else
PADDLE_THROW(
errors::PreconditionNotMet("PaddlePaddle should compile with GPU."));
#endif
}
#ifdef PADDLE_WITH_CUSTOM_DEVICE
template <typename T>
void AllReduceKernel(const CustomContext& dev_ctx,
const DenseTensor& x,
int reduce_type,
DenseTensor* out) {
out->Resize(x.dims());
dev_ctx.template Alloc<T>(out);
auto comm_ctx =
static_cast<distributed::XCCLCommContext*>(dev_ctx.GetCommContext());
PADDLE_ENFORCE_NE(
comm_ctx,
nullptr,
errors::Unavailable("XCCLCommContext is nullptr, collective op should "
"has ring_id attr."));
comm_ctx->AllReduce(
out, x, ccl::ToXCCLReduceOp(reduce_type), dev_ctx.stream());
}
#endif
} // namespace phi
PD_REGISTER_KERNEL(all_reduce,
CPU,
ALL_LAYOUT,
phi::AllReduceKernel,
float,
double,
int,
bool,
int8_t,
uint8_t,
int16_t,
int64_t,
phi::float16) {}
#ifdef PADDLE_WITH_CUSTOM_DEVICE
PD_REGISTER_KERNEL(all_reduce,
Custom,
ALL_LAYOUT,
phi::AllReduceKernel,
float,
double,
int,
bool,
int8_t,
uint8_t,
int64_t,
phi::float16) {}
#endif
@@ -0,0 +1,97 @@
// Copyright (c) 2023 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/all_to_all_kernel.h"
#include "paddle/phi/backends/all_context.h"
#include "paddle/phi/core/kernel_registry.h"
#ifdef PADDLE_WITH_CUSTOM_DEVICE
#include "paddle/phi/core/distributed/xccl_comm_context.h"
#endif
namespace phi {
template <typename T, typename Context>
void AllToAllKernel(const Context& dev_ctx UNUSED,
const DenseTensor& x UNUSED,
DenseTensor* out UNUSED) {
PADDLE_THROW(
errors::Unimplemented("Unimplemented cpu kernel for all_to_all."));
}
#ifdef PADDLE_WITH_CUSTOM_DEVICE
template <typename T>
void AllToAllKernel(const CustomContext& dev_ctx,
const DenseTensor& x,
DenseTensor* out) {
out->Resize(x.dims());
dev_ctx.template Alloc<T>(out);
auto comm_ctx =
static_cast<distributed::XCCLCommContext*>(dev_ctx.GetCommContext());
int nranks = comm_ctx->GetSize();
int rank = comm_ctx->GetRank();
int send_numel = x.numel() / nranks;
std::vector<void*> sendbuf, recvbuf;
std::vector<size_t> sendsize(send_numel, nranks);
std::vector<DataType> sendtype(x.dtype(), nranks);
for (auto i = 0; i < nranks; ++i) {
sendbuf.push_back(x.data<T>() + i * send_numel);
recvbuf.push_back(out->data<T>() + i * send_numel);
}
DeviceManager::CCLAllToAll(dev_ctx.GetPlace().GetDeviceType(),
const_cast<const void**>(sendbuf.data()),
sendsize.data(),
sendtype.data(),
recvbuf.data(),
sendsize.data(),
sendtype.data(),
rank,
nranks,
comm_ctx->GetXcclComm(),
dev_ctx.stream());
}
#endif
} // namespace phi
PD_REGISTER_KERNEL(all_to_all,
CPU,
ALL_LAYOUT,
phi::AllToAllKernel,
float,
double,
int,
bool,
int8_t,
uint8_t,
int16_t,
int64_t,
phi::float16) {}
#ifdef PADDLE_WITH_CUSTOM_DEVICE
PD_REGISTER_KERNEL(all_to_all,
Custom,
ALL_LAYOUT,
phi::AllToAllKernel,
float,
double,
int,
bool,
int8_t,
int16_t,
uint8_t,
int64_t,
phi::float16) {}
#endif
+107
View File
@@ -0,0 +1,107 @@
// 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/allclose_kernel.h"
#include <cmath>
#include <type_traits>
#include "glog/logging.h"
#include "paddle/phi/core/enforce.h"
#include "paddle/phi/core/kernel_registry.h"
namespace phi {
template <typename T, typename Context>
void AllCloseKernel(const Context& dev_ctx,
const DenseTensor& x,
const DenseTensor& y,
const Scalar& rtol,
const Scalar& atol,
bool equal_nan,
DenseTensor* out) {
if (x.numel() == 0 || y.numel() == 0) {
auto* out_data = dev_ctx.template Alloc<bool>(out);
*out_data = true;
return;
}
double rtol_v = NAN, atol_v = NAN;
if (rtol.dtype() == DataType::FLOAT64) {
rtol_v = rtol.to<double>();
} else if (rtol.dtype() == DataType::FLOAT32) {
rtol_v = rtol.to<float>();
} else {
PADDLE_THROW(common::errors::InvalidArgument(
"Input (Rtol) type must be double or float, but get %s.",
rtol.dtype()));
}
if (atol.dtype() == DataType::FLOAT64) {
atol_v = atol.to<double>();
} else if (atol.dtype() == DataType::FLOAT32) {
atol_v = atol.to<float>();
} else {
PADDLE_THROW(common::errors::InvalidArgument(
"Input (Atol) type must be double or float, but get %s.",
atol.dtype()));
}
VLOG(3) << "rtol and atol is : " << rtol_v << " " << atol_v;
auto* in_a = x.data<T>();
auto* in_b = y.data<T>();
auto* out_data = dev_ctx.template Alloc<bool>(out);
*out_data = true;
auto num = x.numel();
if (std::is_same<T, int32_t>::value || std::is_same<T, int64_t>::value ||
std::is_same<T, bool>::value) {
for (int64_t i = 0; i < num; ++i) {
const double a = static_cast<double>(in_a[i]),
b = static_cast<double>(in_b[i]);
double left = (a > b ? a - b : b - a);
double right = atol_v + (b > 0 ? rtol_v * b : (-rtol_v) * b);
double diff = (left > right ? left - right : right - left);
bool val = a == b || left <= right || diff <= 1e-15;
*out_data &= val;
}
} else {
for (int64_t i = 0; i < num; ++i) {
const T a = in_a[i], b = in_b[i];
bool val = false;
if (std::isnan(static_cast<double>(a)) ||
std::isnan(static_cast<double>(b))) {
val = equal_nan && std::isnan(static_cast<double>(a)) ==
std::isnan(static_cast<double>(b));
} else {
T left = (a > b ? a - b : b - a);
T right = atol_v + (b > 0 ? rtol_v * b : (-rtol_v) * b);
T diff = (left > right ? left - right : right - left);
val = a == b || left <= right || diff <= 1e-15;
}
*out_data &= val;
}
}
}
} // namespace phi
PD_REGISTER_KERNEL(allclose,
CPU,
ALL_LAYOUT,
phi::AllCloseKernel,
float,
double,
bool,
int,
int64_t) {
kernel->OutputAt(0).SetDataType(phi::DataType::BOOL);
}
+126
View File
@@ -0,0 +1,126 @@
// 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/amp_kernel.h"
#include <cmath>
#include "paddle/phi/common/amp_type_traits.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/empty_kernel.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
#include "paddle/phi/kernels/impl/amp_kernel_impl.h"
#include "paddle/phi/kernels/isfinite_kernel.h"
#include "paddle/phi/kernels/reduce_all_kernel.h"
namespace phi {
// Utils
template <typename T, bool IsFoundInfOnCPU>
class UpdateLossScalingFunctor<CPUContext, T, IsFoundInfOnCPU> {
public:
void operator()(const CPUContext& dev_ctx UNUSED,
const bool* found_inf_data,
const T* pre_loss_scaling_data,
const int* good_in_data,
const int* bad_in_data,
const int incr_every_n_steps,
const int decr_every_n_nan_or_inf,
const float incr_ratio,
const float decr_ratio,
T* updated_loss_scaling_data,
int* good_out_data,
int* bad_out_data) const {
PADDLE_ENFORCE_EQ(
IsFoundInfOnCPU,
true,
common::errors::InvalidArgument(
"The Input(FoundInfinite) should be on the CPUPlace."));
Update<T>(found_inf_data,
pre_loss_scaling_data,
good_in_data,
bad_in_data,
incr_every_n_steps,
decr_every_n_nan_or_inf,
incr_ratio,
decr_ratio,
updated_loss_scaling_data,
good_out_data,
bad_out_data);
}
};
// Kernels
template <typename T, typename Context>
void CheckFiniteAndUnscaleKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& xs,
const DenseTensor& scale,
std::vector<DenseTensor*> outs,
DenseTensor* found_infinite) {
const T* scale_data = scale.data<T>();
bool* found_inf_data = dev_ctx.template Alloc<bool>(found_infinite);
*found_inf_data = false;
DenseTensor is_finite = Empty<bool>(dev_ctx, {1});
bool* is_finite_data = is_finite.template data<bool>();
auto& dev = *dev_ctx.eigen_device();
T inverse_scale = 1.0 / *scale_data;
for (size_t i = 0; i < xs.size(); ++i) {
const auto* x = xs[i];
auto* out = outs[i];
dev_ctx.template Alloc<T>(out);
if (!(*found_inf_data)) {
DenseTensor tmp;
tmp.Resize(x->dims());
IsfiniteKernel<T, Context>(dev_ctx, *x, &tmp);
std::vector<int64_t> dims(x->dims().size());
std::iota(dims.begin(), dims.end(), 0);
AllKernel<bool, Context>(dev_ctx, tmp, dims, false, &is_finite);
*found_inf_data = !(*is_finite_data);
}
auto eigen_out = EigenVector<T>::Flatten(*out);
auto eigen_in = EigenVector<T>::Flatten(*x);
if (!(*found_inf_data)) {
eigen_out.device(dev) = eigen_in * inverse_scale;
} else {
eigen_out.device(dev) = eigen_in * static_cast<T>(0);
}
}
}
} // namespace phi
PD_REGISTER_KERNEL(check_finite_and_unscale,
CPU,
ALL_LAYOUT,
phi::CheckFiniteAndUnscaleKernel,
float,
double) {
kernel->OutputAt(1).SetDataType(phi::DataType::BOOL);
}
PD_REGISTER_KERNEL(update_loss_scaling,
CPU,
ALL_LAYOUT,
phi::UpdateLossScalingKernel,
float,
double) {
kernel->OutputAt(2).SetDataType(phi::DataType::INT32);
kernel->OutputAt(3).SetDataType(phi::DataType::INT32);
}
@@ -0,0 +1,30 @@
// 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/angle_grad_kernel.h"
#include "paddle/phi/kernels/impl/angle_grad_kernel_impl.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
PD_REGISTER_KERNEL(angle_grad,
CPU,
ALL_LAYOUT,
phi::AngleGradKernel,
float,
double,
phi::complex64,
phi::complex128) {
kernel->InputAt(1).SetDataType(phi::dtype::ToReal(kernel_key.dtype()));
}
+31
View File
@@ -0,0 +1,31 @@
// 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/angle_kernel.h"
#include "paddle/phi/kernels/impl/angle_kernel_impl.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
PD_REGISTER_KERNEL(angle,
CPU,
ALL_LAYOUT,
phi::AngleKernel,
float,
double,
phi::complex64,
phi::complex128) {
kernel->OutputAt(0).SetDataType(phi::DataType::UNDEFINED);
}
+125
View File
@@ -0,0 +1,125 @@
/* 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/arange_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/common/amp_type_traits.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/range_function.h"
namespace phi {
template <typename T, typename Context>
void ArangeFunc(const Context& dev_ctx,
const T& start_value,
const T& end_value,
const T& step_value,
DenseTensor* out) {
int64_t size = 0;
funcs::GetSize(start_value, end_value, step_value, &size);
out->Resize({size});
T* out_data = dev_ctx.template Alloc<T>(out);
T value = start_value;
for (int64_t i = 0; i < size; ++i) {
out_data[i] = value;
value += step_value;
}
}
template <typename T, typename Context>
void ArangeTensorKernel(const Context& dev_ctx,
const DenseTensor& start,
const DenseTensor& end,
const DenseTensor& step,
DenseTensor* out) {
int64_t size = 0;
using MPType = typename phi::dtype::MPTypeTrait<T>::Type;
bool any_float = phi::IsFloatingType(start.dtype()) ||
phi::IsFloatingType(end.dtype()) ||
phi::IsFloatingType(step.dtype());
Scalar start_scalar(start);
Scalar end_scalar(end);
Scalar step_scalar(step);
if (any_float) {
double sv = start_scalar.to<double>();
double ev = end_scalar.to<double>();
double stv = step_scalar.to<double>();
funcs::GetSize<double>(sv, ev, stv, &size);
} else {
int64_t sv = start_scalar.to<int64_t>();
int64_t ev = end_scalar.to<int64_t>();
int64_t stv = step_scalar.to<int64_t>();
funcs::GetSize<int64_t>(sv, ev, stv, &size);
}
MPType start_value = start_scalar.to<MPType>();
MPType step_value = step_scalar.to<MPType>();
out->Resize({size});
T* out_data = dev_ctx.template Alloc<T>(out);
MPType value = start_value;
for (int64_t i = 0; i < size; ++i) {
out_data[i] = static_cast<T>(value);
value += step_value;
}
}
template <typename T, typename Context>
void ArangeKernel(const Context& dev_ctx,
const Scalar& start,
const Scalar& end,
const Scalar& step,
DenseTensor* out) {
bool any_float = phi::IsFloatingType(start.dtype()) ||
phi::IsFloatingType(end.dtype()) ||
phi::IsFloatingType(step.dtype());
int64_t size = 0;
using MPType = typename phi::dtype::MPTypeTrait<T>::Type;
if (any_float) {
double sv = start.to<double>();
double ev = end.to<double>();
double stv = step.to<double>();
funcs::GetSize<double>(sv, ev, stv, &size);
} else {
int64_t sv = start.to<int64_t>();
int64_t ev = end.to<int64_t>();
int64_t stv = step.to<int64_t>();
funcs::GetSize<int64_t>(sv, ev, stv, &size);
}
MPType start_value = start.to<MPType>();
MPType step_value = step.to<MPType>();
out->Resize({size});
T* out_data = dev_ctx.template Alloc<T>(out);
MPType value = start_value;
for (int64_t i = 0; i < size; ++i) {
out_data[i] = static_cast<T>(value);
value += step_value;
}
}
} // namespace phi
PD_REGISTER_KERNEL(arange_tensor,
CPU,
ALL_LAYOUT,
phi::ArangeTensorKernel,
float,
double,
int,
int64_t) {}
PD_REGISTER_KERNEL(
arange, CPU, ALL_LAYOUT, phi::ArangeKernel, float, double, int, int64_t) {}
@@ -0,0 +1,224 @@
// 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/arg_min_max_kernel.h"
#include "paddle/common/ddim.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/core/utils/data_type.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
#include "paddle/phi/kernels/funcs/math_function.h"
namespace phi {
enum ArgMinMaxType { kArgMin, kArgMax };
template <typename Context,
typename T,
typename Tout,
int64_t Rank,
ArgMinMaxType argMinMaxValue>
struct ArgMinMaxFunctor {};
#define DECLARE_ARG_MIN_MAX_FUNCTOR(eigen_op_type, enum_argminmax_value) \
template <typename Context, typename T, typename Tout, int64_t Rank> \
struct ArgMinMaxFunctor<Context, T, Tout, Rank, enum_argminmax_value> { \
void operator()(const Context& dev_ctx, \
const DenseTensor& in, \
DenseTensor* out, \
DDim x_dims, \
DDim out_dims, \
int64_t axis, \
bool keepdims, \
bool flatten) { \
auto in_eigen = EigenTensor<T, Rank>::From(in, x_dims); \
if (flatten) { \
auto out_eigen = EigenTensor<Tout, 0>::From(*out, out_dims); \
out_eigen.device(*(dev_ctx.eigen_device())) = \
in_eigen.eigen_op_type(axis).template cast<Tout>(); \
} else { \
if (keepdims) { \
auto out_eigen = EigenTensor<Tout, Rank>::From(*out, out_dims); \
out_eigen.device(*(dev_ctx.eigen_device())) = \
in_eigen.eigen_op_type(axis).template cast<Tout>(); \
} else { \
auto out_eigen = EigenTensor<Tout, Rank - 1>::From(*out, out_dims); \
out_eigen.device(*(dev_ctx.eigen_device())) = \
in_eigen.eigen_op_type(axis).template cast<Tout>(); \
} \
} \
} \
}
DECLARE_ARG_MIN_MAX_FUNCTOR(argmin, ArgMinMaxType::kArgMin);
DECLARE_ARG_MIN_MAX_FUNCTOR(argmax, ArgMinMaxType::kArgMax);
template <typename Context, typename T, ArgMinMaxType EnumArgMinMaxValue>
struct VisitDataArgMinMaxFunctor {
const Context& dev_ctx;
const DenseTensor& x;
int64_t axis;
bool keepdims;
bool flatten;
DenseTensor* out;
explicit VisitDataArgMinMaxFunctor(const Context& dev_ctx,
const DenseTensor& x,
int64_t axis,
bool keepdims,
bool flatten,
DenseTensor* out)
: dev_ctx(dev_ctx),
x(x),
axis(axis),
keepdims(keepdims),
flatten(flatten),
out(out) {}
template <typename Tout>
void apply() const {
dev_ctx.template Alloc<Tout>(out);
if (x.numel() == 0) return;
// if flatten, will construct the new dims for the calculation
DDim x_dims;
DDim out_dims;
int new_axis = axis;
if (flatten) {
// always reduce 1D -> 0D
x_dims = make_ddim({x.numel()});
out_dims = make_ddim({});
new_axis = 0;
} else {
x_dims = x.dims();
out_dims = out->dims();
if (axis < 0) new_axis = axis + x_dims.size();
}
#define CALL_ARG_MINMAX_FUNCTOR(rank) \
ArgMinMaxFunctor<Context, T, Tout, rank, EnumArgMinMaxValue> functor##rank; \
functor##rank(dev_ctx, x, out, x_dims, out_dims, new_axis, keepdims, flatten)
switch (x_dims.size()) {
case 0:
funcs::set_constant(dev_ctx, out, static_cast<Tout>(0));
return;
case 1:
CALL_ARG_MINMAX_FUNCTOR(1);
break;
case 2:
CALL_ARG_MINMAX_FUNCTOR(2);
break;
case 3:
CALL_ARG_MINMAX_FUNCTOR(3);
break;
case 4:
CALL_ARG_MINMAX_FUNCTOR(4);
break;
case 5:
CALL_ARG_MINMAX_FUNCTOR(5);
break;
case 6:
CALL_ARG_MINMAX_FUNCTOR(6);
break;
default:
PADDLE_ENFORCE_LE(
x_dims.size(),
6,
common::errors::InvalidArgument(
"%s operator doesn't supports tensors whose ranks are greater "
"than 6.",
(EnumArgMinMaxValue == kArgMin ? "argmin" : "argmax")));
break;
#undef CALL_ARG_MINMAX_FUNCTOR
}
}
};
template <typename Context, typename T, ArgMinMaxType EnumArgMinMaxValue>
void ArgMinMaxKernel(const Context& dev_ctx,
const DenseTensor& x,
const Scalar& axis,
bool keepdims,
bool flatten,
DataType dtype,
DenseTensor* out) {
PADDLE_ENFORCE_GE(
x.numel(),
0,
common::errors::InvalidArgument(
"argmin/argmax input numel must > 0, bug got %d", x.numel()));
if (dtype == DataType::UNDEFINED) {
VisitDataTypeTiny(
DataType::INT64,
VisitDataArgMinMaxFunctor<Context, T, EnumArgMinMaxValue>(
dev_ctx, x, axis.to<int64_t>(), keepdims, flatten, out));
return;
}
VisitDataTypeTiny(
dtype,
VisitDataArgMinMaxFunctor<Context, T, EnumArgMinMaxValue>(
dev_ctx, x, axis.to<int64_t>(), keepdims, flatten, out));
}
template <typename T, typename Context>
void ArgMinKernel(const Context& dev_ctx,
const DenseTensor& x,
const Scalar& axis,
bool keepdims,
bool flatten,
DataType dtype,
DenseTensor* out) {
ArgMinMaxKernel<Context, T, ArgMinMaxType::kArgMin>(
dev_ctx, x, axis, keepdims, flatten, dtype, out);
}
template <typename T, typename Context>
void ArgMaxKernel(const Context& dev_ctx,
const DenseTensor& x,
const Scalar& axis,
bool keepdims,
bool flatten,
DataType dtype,
DenseTensor* out) {
ArgMinMaxKernel<Context, T, ArgMinMaxType::kArgMax>(
dev_ctx, x, axis, keepdims, flatten, dtype, out);
}
} // namespace phi
PD_REGISTER_KERNEL(argmin,
CPU,
ALL_LAYOUT,
phi::ArgMinKernel,
float,
double,
int32_t,
int64_t,
int16_t,
uint8_t) {
kernel->OutputAt(0).SetDataType(phi::DataType::UNDEFINED);
}
PD_REGISTER_KERNEL(argmax,
CPU,
ALL_LAYOUT,
phi::ArgMaxKernel,
float,
double,
int32_t,
int64_t,
int16_t,
uint8_t) {
kernel->OutputAt(0).SetDataType(phi::DataType::UNDEFINED);
}
@@ -0,0 +1,144 @@
// 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/argsort_grad_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
#include "paddle/phi/kernels/funcs/eigen/eigen_function.h"
#include "paddle/phi/kernels/transpose_kernel.h"
namespace phi {
template <typename T, typename Type>
static void FullAssign(Type input_height,
Type input_width,
int input_dim,
const DenseTensor* input,
const DenseTensor* indices,
T* t_out) {
#ifdef PADDLE_WITH_MKLML
#pragma omp parallel for
#endif
for (Type i = 0; i < input_height; ++i) {
if (input_dim == 1) {
auto e_input = EigenVector<T>::Flatten(*input);
auto e_indices = EigenVector<Type>::Flatten(*indices);
for (Type j = 0; j < input_width; ++j) {
t_out[i * input_width + e_indices(j)] = e_input(j);
}
} else {
auto e_input = EigenMatrix<T>::Reshape(*input, input_dim - 1);
auto e_indices = EigenMatrix<Type>::Reshape(*indices, input_dim - 1);
for (Type j = 0; j < input_width; ++j) {
t_out[i * input_width + e_indices(i, j)] = e_input(i, j);
}
}
}
}
template <typename T, typename Context>
void ArgsortGradKernel(const Context& dev_ctx,
const DenseTensor& indices,
const DenseTensor& input,
const DenseTensor& out_grad,
int axis,
bool descending UNUSED,
bool stable UNUSED,
DenseTensor* in_grad) {
auto in_dims = indices.dims();
auto rank = input.dims().size();
axis = (axis < 0) ? (in_dims.size() + axis) : axis;
dev_ctx.template Alloc<T>(in_grad);
auto dxt = EigenVector<T>::Flatten(*in_grad);
auto& place = *dev_ctx.eigen_device();
dxt.device(place) = dxt.constant(static_cast<T>(0));
if (out_grad.numel() == 0) return;
if (rank == 0) {
Copy<Context>(dev_ctx, out_grad, dev_ctx.GetPlace(), false, in_grad);
return;
}
// Do full assign
if (axis == -1 || axis + 1 == in_dims.size()) {
const int64_t input_height =
common::product(slice_ddim(in_dims, 0, in_dims.size() - 1));
const int64_t input_width = in_dims[in_dims.size() - 1];
FullAssign<T, int64_t>(input_height,
input_width,
in_dims.size(),
&out_grad,
&indices,
in_grad->data<T>());
} else {
// If not full assign do transpose
std::vector<int> trans;
for (int i = 0; i < axis; i++) {
trans.push_back(i);
}
trans.push_back(in_dims.size() - 1);
for (int i = axis + 1; i < in_dims.size() - 1; i++) {
trans.push_back(i);
}
trans.push_back(axis);
DDim trans_dims(in_dims);
for (size_t i = 0; i < trans.size(); i++) {
trans_dims[static_cast<int>(i)] = in_dims[trans[i]];
}
DenseTensor trans_dO;
trans_dO.Resize(trans_dims);
dev_ctx.template Alloc<T>(&trans_dO);
DenseTensor trans_ind;
trans_ind.Resize(trans_dims);
dev_ctx.template Alloc<int64_t>(&trans_ind);
TransposeKernel<T, Context>(dev_ctx, out_grad, trans, &trans_dO);
TransposeKernel<int64_t, Context>(dev_ctx, indices, trans, &trans_ind);
const int64_t input_height =
common::product(slice_ddim(trans_dims, 0, trans_dims.size() - 1));
const int64_t input_width = trans_dims[trans_dims.size() - 1];
DenseTensor tmp_out;
tmp_out.Resize(trans_dims);
T* t_out = dev_ctx.template Alloc<T>(&tmp_out);
FullAssign<T, int64_t>(input_height,
input_width,
in_dims.size(),
&trans_dO,
&trans_ind,
t_out);
// transpose back
TransposeKernel<T, Context>(dev_ctx, tmp_out, trans, in_grad);
}
}
} // namespace phi
PD_REGISTER_KERNEL(argsort_grad,
CPU,
ALL_LAYOUT,
phi::ArgsortGradKernel,
float,
double,
phi::float16,
phi::bfloat16,
uint8_t,
int16_t,
int,
int64_t) {}
+197
View File
@@ -0,0 +1,197 @@
// 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/argsort_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
#include "paddle/phi/kernels/funcs/eigen/eigen_function.h"
#include "paddle/phi/kernels/funcs/math_function.h"
#include "paddle/phi/kernels/transpose_kernel.h"
namespace phi {
template <typename T, typename Type>
static void FullSort(Type input_height,
Type input_width,
int input_dim,
const DenseTensor* input,
T* t_out,
Type* t_indices,
bool descending,
bool stable) {
#ifdef PADDLE_WITH_MKLML
#pragma omp parallel for
#endif
for (Type i = 0; i < input_height; ++i) {
std::vector<std::pair<T, Type>> col_vec;
col_vec.reserve(input_width);
if (input_dim == 1) {
auto e_input = EigenVector<T>::Flatten(*input);
for (Type j = 0; j < input_width; ++j) {
col_vec.push_back(std::pair<T, Type>(e_input(j), j));
}
} else {
auto e_input = EigenMatrix<T>::Reshape(*input, input_dim - 1);
for (Type j = 0; j < input_width; ++j) {
col_vec.push_back(std::pair<T, Type>(e_input(i, j), j));
}
}
if (stable) {
std::stable_sort(
col_vec.begin(),
col_vec.end(),
[&](const std::pair<T, Type>& l, const std::pair<T, Type>& r) {
if (descending)
return (std::isnan(static_cast<double>(l.first)) &&
!std::isnan(static_cast<double>(r.first))) ||
(l.first > r.first);
else
return (!std::isnan(static_cast<double>(l.first)) &&
std::isnan(static_cast<double>(r.first))) ||
(l.first < r.first);
});
} else {
std::sort(col_vec.begin(),
col_vec.end(),
[&](const std::pair<T, Type>& l, const std::pair<T, Type>& r) {
if (descending)
return (std::isnan(static_cast<double>(l.first)) &&
!std::isnan(static_cast<double>(r.first))) ||
(l.first > r.first);
else
return (!std::isnan(static_cast<double>(l.first)) &&
std::isnan(static_cast<double>(r.first))) ||
(l.first < r.first);
});
}
for (Type j = 0; j < input_width; ++j) {
t_out[i * input_width + j] = col_vec[j].first;
t_indices[i * input_width + j] = col_vec[j].second;
}
}
}
template <typename T, typename Context>
void ArgsortKernel(const Context& dev_ctx,
const DenseTensor& input,
int axis,
bool descending,
bool stable,
DenseTensor* output,
DenseTensor* indices) {
auto in_dims = input.dims();
auto rank = in_dims.size();
if (input.numel() == 0) {
output->Resize(in_dims);
indices->Resize(in_dims);
dev_ctx.template Alloc<T>(output);
dev_ctx.template Alloc<int64_t>(indices);
return;
}
axis = (axis < 0) ? (in_dims.size() + axis) : axis;
T* out_data = dev_ctx.template Alloc<T>(output);
// For 0D Tensor
if (rank == 0) {
Copy<Context>(dev_ctx, input, dev_ctx.GetPlace(), false, output);
dev_ctx.template Alloc<int64_t>(indices);
funcs::set_constant(dev_ctx, indices, static_cast<int64_t>(0));
return;
}
// Do full sort
if (axis == -1 || axis + 1 == in_dims.size()) {
const int64_t input_height =
common::product(slice_ddim(in_dims, 0, in_dims.size() - 1));
const int64_t input_width = in_dims[in_dims.size() - 1];
int64_t* ids_data = dev_ctx.template Alloc<int64_t>(indices);
FullSort<T, int64_t>(input_height,
input_width,
in_dims.size(),
&input,
out_data,
ids_data,
descending,
stable);
} else {
// If not full sort do transpose
std::vector<int> trans;
for (int i = 0; i < axis; i++) {
trans.push_back(i);
}
trans.push_back(in_dims.size() - 1);
for (int i = axis + 1; i < in_dims.size() - 1; i++) {
trans.push_back(i);
}
trans.push_back(axis);
DDim trans_dims(in_dims);
for (size_t i = 0; i < trans.size(); i++) {
trans_dims[static_cast<int>(i)] = in_dims[trans[i]];
}
DenseTensor trans_inp;
trans_inp.Resize(trans_dims);
dev_ctx.template Alloc<T>(&trans_inp);
// Do transpose
TransposeKernel<T, Context>(dev_ctx, input, trans, &trans_inp);
const int64_t input_height =
common::product(slice_ddim(trans_dims, 0, trans_dims.size() - 1));
const int64_t input_width = trans_dims[trans_dims.size() - 1];
DenseTensor tmp_out;
tmp_out.Resize(trans_dims);
T* t_out = dev_ctx.template Alloc<T>(&tmp_out);
DenseTensor tmp_indices;
tmp_indices.Resize(trans_dims);
auto* t_ind = dev_ctx.template Alloc<int64_t>(&tmp_indices);
FullSort<T, int64_t>(input_height,
input_width,
in_dims.size(),
&trans_inp,
t_out,
t_ind,
descending,
stable);
dev_ctx.template Alloc<int64_t>(indices);
TransposeKernel<int64_t, Context>(dev_ctx, tmp_indices, trans, indices);
// transpose back
TransposeKernel<T, Context>(dev_ctx, tmp_out, trans, output);
}
}
} // namespace phi
PD_REGISTER_KERNEL(argsort,
CPU,
ALL_LAYOUT,
phi::ArgsortKernel,
float,
double,
int,
int64_t,
int16_t,
uint8_t,
phi::float16,
phi::bfloat16) {
kernel->OutputAt(1).SetDataType(phi::DataType::INT64);
}
@@ -0,0 +1,25 @@
// 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/as_complex_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/common/type_traits.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/as_complex_impl.h"
PD_REGISTER_KERNEL(
as_complex, CPU, ALL_LAYOUT, phi::AsComplexKernel, float, double) {
kernel->OutputAt(0).SetDataType(phi::dtype::ToComplex(kernel_key.dtype()));
}
+28
View File
@@ -0,0 +1,28 @@
// 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/as_real_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/as_real_impl.h"
PD_REGISTER_KERNEL(as_real,
CPU,
ALL_LAYOUT,
phi::AsRealKernel,
phi::complex64,
phi::complex128) {
kernel->OutputAt(0).SetDataType(phi::DataType::UNDEFINED);
}
+73
View File
@@ -0,0 +1,73 @@
// 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/asgd_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
#include "paddle/phi/kernels/funcs/jit/kernels.h"
namespace phi {
template <typename T, typename Context>
void ASGDKernelCPUImpl(const Context& dev_ctx,
const DenseTensor& param,
const DenseTensor& grad,
const DenseTensor& learning_rate,
const DenseTensor& d,
const DenseTensor& y,
const DenseTensor& n,
DenseTensor* param_out,
DenseTensor* d_out,
DenseTensor* y_out) {
auto param_eigen = EigenVector<T>::Flatten(param);
auto grad_eigen = EigenVector<T>::Flatten(grad);
auto d_eigen = EigenVector<T>::Flatten(d);
auto y_eigen = EigenVector<T>::Flatten(y);
auto param_out_eigen = EigenVector<T>::Flatten(*param_out);
auto d_out_eigen = EigenVector<T>::Flatten(*d_out);
auto y_out_eigen = EigenVector<T>::Flatten(*y_out);
T learning_rate_T = learning_rate.data<T>()[0];
T n_T = n.data<T>()[0];
d_out_eigen = d_eigen - y_eigen + grad_eigen;
y_out_eigen = grad_eigen;
param_out_eigen = param_eigen - (learning_rate_T / n_T) * d_out_eigen;
}
template <typename T, typename Context>
void ASGDKernel(const Context& dev_ctx,
const DenseTensor& param,
const DenseTensor& grad,
const DenseTensor& learning_rate,
const DenseTensor& d,
const DenseTensor& y,
const DenseTensor& n,
const optional<DenseTensor>& master_param UNUSED,
bool multi_precision UNUSED,
DenseTensor* param_out,
DenseTensor* d_out,
DenseTensor* y_out,
DenseTensor* master_param_out UNUSED) {
dev_ctx.template Alloc<T>(param_out);
dev_ctx.template Alloc<T>(d_out);
dev_ctx.template Alloc<T>(y_out);
ASGDKernelCPUImpl<T, Context>(
dev_ctx, param, grad, learning_rate, d, y, n, param_out, d_out, y_out);
}
} // namespace phi
PD_REGISTER_KERNEL(asgd, CPU, ALL_LAYOUT, phi::ASGDKernel, float, double) {}
@@ -0,0 +1,34 @@
// Copyright (c) 2023 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/assign_pos_kernel.h"
#include "paddle/common/errors.h"
#include "paddle/phi/core/kernel_registry.h"
namespace phi {
template <typename T, typename Context>
void AssignPosKernel(const Context& dev_ctx,
const DenseTensor& x,
const DenseTensor& cum_count,
const DenseTensor& eff_num_len,
DenseTensor* out) {
PADDLE_THROW(common::errors::Unavailable(
"Do not support assign pos op for cpu kernel now."));
}
} // namespace phi
PD_REGISTER_KERNEL(
assign_pos, CPU, ALL_LAYOUT, phi::AssignPosKernel, int, int64_t) {}
@@ -0,0 +1,25 @@
// 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/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/atan2_grad_kernel_impl.h"
PD_REGISTER_KERNEL(atan2_grad,
CPU,
ALL_LAYOUT,
phi::Atan2GradKernel,
float,
double,
phi::float16) {}
+29
View File
@@ -0,0 +1,29 @@
// 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/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/atan2_kernel_impl.h"
PD_REGISTER_KERNEL(atan2,
CPU,
ALL_LAYOUT,
phi::Atan2Kernel,
float,
double,
phi::float16,
int,
int64_t) {
kernel->OutputAt(0).SetDataType(phi::DataType::UNDEFINED);
}
@@ -0,0 +1,233 @@
// 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 <string>
#include "paddle/phi/backends/cpu/cpu_info.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/blas/blas.h"
#include "paddle/phi/kernels/funcs/cpu_vec.h"
#include "paddle/phi/kernels/funcs/fc_functor.h"
#include "paddle/utils/optional.h"
namespace phi {
// y[i] = (x[i] + bias[0]) > 0 ? (x[i] + bias[0]) : 0;
template <typename T>
inline void bias_relu(const int n, const T* x, const T* bias, T* y) {
if (bias) {
funcs::vec_add_bias<T, backends::cpu::avx>(n, *bias, x, y);
funcs::vec_relu<T, backends::cpu::avx>(n, y, y);
} else {
funcs::vec_relu<T, backends::cpu::avx>(n, x, y);
}
}
template <typename T>
inline void vec_softmax(const int n, const T* x, T* y) {
T scalar = x[0];
// max
for (int i = 1; i < n; ++i) {
scalar = scalar < x[i] ? x[i] : scalar;
}
funcs::vec_add_bias<T, backends::cpu::avx>(n, -scalar, x, y); // sub
funcs::vec_exp<T>(n, y, y); // exp
// sum
scalar = T(0);
for (int i = 0; i < n; ++i) {
scalar += y[i];
}
funcs::vec_scal<T>(n, static_cast<T>(1) / scalar, y); // scale
}
template <typename T, typename Context>
void AttentionLSTMKernel(const Context& dev_ctx,
const DenseTensor& x_in,
const DenseTensor& c0_in,
const optional<DenseTensor>& h0_in,
const DenseTensor& attention_weight_in,
const optional<DenseTensor>& attention_bias_in,
const optional<DenseTensor>& attention_scalar_in,
const optional<DenseTensor>& attention_scalar_bias_in,
const DenseTensor& lstm_weight_in,
const DenseTensor& lstm_bias_in,
const std::string& gate_activation,
const std::string& cell_activation,
const std::string& candidate_activation,
DenseTensor* hidden,
DenseTensor* cell,
DenseTensor* attentioned_x,
DenseTensor* attention_fc_out,
DenseTensor* lstm_x,
DenseTensor* lstm_out) {
auto* x = &x_in;
auto* h0 = h0_in.get_ptr();
auto* c0 = &c0_in;
auto* atten_w = &attention_weight_in;
auto* atten_b = attention_bias_in.get_ptr();
auto* atten_scalar = attention_scalar_in.get_ptr();
auto* atten_scalar_bias = attention_scalar_bias_in.get_ptr();
auto* lstm_w = &lstm_weight_in;
auto* lstm_b = &lstm_bias_in;
auto* hidden_out = hidden;
auto* cell_out = cell;
auto* atted_x = attentioned_x;
auto* fc_out = attention_fc_out;
// some shape should be reshape here since infershape can not get lod info
auto x_lod = x->lod();
const int N = static_cast<int>(x_lod[0].size() - 1); // batch size
auto x_dims = x->dims(); // T x M
auto w_dims = lstm_w->dims(); // (D+M) x 4D
const int total_T = static_cast<int>(x_dims[0]);
const int M = static_cast<int>(x_dims[1]); // x frame size
const int D = static_cast<int>(w_dims[1] / 4); // gate frame size
const int D2 = static_cast<int>(D * 2);
const int D3 = static_cast<int>(D * 3);
const int D4 = static_cast<int>(w_dims[1]);
int max_seq_len = static_cast<int>(x_lod[0][1]);
for (int i = 1; i < N; ++i) {
int len = static_cast<int>(x_lod[0][i + 1] - x_lod[0][i]);
max_seq_len = max_seq_len < len ? len : max_seq_len;
}
PADDLE_ENFORCE_EQ(
x_lod.size(),
1UL,
common::errors::InvalidArgument("Input(X)'s lod size must be 1."));
PADDLE_ENFORCE_EQ(
c0->dims()[0],
N,
common::errors::InvalidArgument("C0 dims should be %d x %d.", N, D));
fc_out->Resize({max_seq_len, 1});
std::function<void(const int, const T*, T*)> act_gate, act_cell, act_cand;
auto& act_gate_str = gate_activation;
auto& act_cell_str = cell_activation;
auto& act_cand_str = candidate_activation;
if (backends::cpu::MayIUse(backends::cpu::avx)) {
funcs::VecActivations<T, backends::cpu::avx> act_functor;
act_gate = act_functor(act_gate_str);
act_cell = act_functor(act_cell_str);
act_cand = act_functor(act_cand_str);
} else {
funcs::VecActivations<T, backends::cpu::isa_any> act_functor;
act_gate = act_functor(act_gate_str);
act_cell = act_functor(act_cell_str);
act_cand = act_functor(act_cand_str);
}
const T* x_data = x->data<T>();
const T* h0_data = h0 ? h0->data<T>() : NULL;
const T* c0_data = c0->data<T>();
const T* lstm_w_data = lstm_w->data<T>();
const T* lstm_b_data = lstm_b->data<T>();
const T* atten_w_data = atten_w->data<T>();
const T* atten_b_data = atten_b ? atten_b->data<T>() : NULL;
const T* atten_scalar_data = atten_scalar ? atten_scalar->data<T>() : NULL;
const T* atten_scalar_bias_data =
atten_scalar_bias ? atten_scalar_bias->data<T>() : NULL;
T* hidden_out_data = dev_ctx.template Alloc<T>(hidden_out);
T* cell_out_data = dev_ctx.template Alloc<T>(cell_out);
T* atted_x_data = dev_ctx.template Alloc<T>(atted_x);
T* fc_out_data = dev_ctx.template Alloc<T>(fc_out);
T* lstm_x_data = dev_ctx.template Alloc<T>(lstm_x);
T* lstm_out_data = dev_ctx.template Alloc<T>(lstm_out);
// x(TxM) * fc (Mx1) part of atten_wgt(M+D)x1
auto blas = funcs::GetBlas<CPUContext, T>(dev_ctx);
funcs::FCFunctor<Context, T> fc;
fc(dev_ctx, total_T, 1, M, x_data, atten_w_data, atted_x_data, atten_b_data);
const T* cur_atten_x_data = atted_x_data;
const T* cur_x_data = x_data;
const T* prev_cell_data = NULL;
const T* prev_hidden_data = NULL;
T* cur_cell_out_data = cell_out_data;
T* cur_hidden_out_data = hidden_out_data;
for (int i = 0; i < N; ++i) {
int seq_len = static_cast<int>(x_lod[0][i + 1] - x_lod[0][i]);
prev_cell_data = c0_data + i * D;
prev_hidden_data = h0_data ? h0_data + i * D : NULL;
for (int step = 0; step < seq_len; ++step) {
/// 1. compute attention vector
// 1a. prev_cell(1xD) * fc(D) rest part of atten_wgt
T prev_cell_bias = blas.DOT(D, prev_cell_data, atten_w_data + M);
// 1b. add cell bias and relu
bias_relu<T>(seq_len, cur_atten_x_data, &prev_cell_bias, fc_out_data);
// 1c. fc scalar
if (atten_scalar_data) {
blas.SCAL(seq_len, *atten_scalar_data, fc_out_data);
bias_relu<T>(seq_len, fc_out_data, atten_scalar_bias_data, fc_out_data);
}
// 1d. softmax
vec_softmax<T>(seq_len, fc_out_data, fc_out_data);
// mul x(seq_len*M) and sum pool
fc(dev_ctx, 1, M, seq_len, fc_out_data, cur_x_data, lstm_x_data);
/// 2. compute LSTM step
// lstm weight : concat[forget , input , output , tilde]
// shape : (D + M) x (4 * D)
// fc inputX(1xM) * weightX(M*(4D)) => 1 x 4D
blas.MatMul(1, D4, M, lstm_x_data, lstm_w_data + D * D4, lstm_out_data);
if (prev_hidden_data) {
blas.GEMM(CblasNoTrans,
CblasNoTrans,
1,
D4,
D,
static_cast<T>(1),
prev_hidden_data,
D,
lstm_w_data,
D4,
static_cast<T>(1),
lstm_out_data,
D4);
}
// since input is 1xM, so can use add bias
blas.VADD(D4, lstm_b_data, lstm_out_data, lstm_out_data);
// gate act: sigmoid
act_gate(D3, lstm_out_data, lstm_out_data);
// candidate act: tanh
act_cand(D, lstm_out_data + D3, lstm_out_data + D3);
// a = forget * prev_cell
blas.VMUL(D, lstm_out_data, prev_cell_data, lstm_out_data);
// b = input * tilde
blas.VMUL(D, lstm_out_data + D, lstm_out_data + D3, lstm_out_data + D);
// cell_out = a + b
blas.VADD(D, lstm_out_data, lstm_out_data + D, cur_cell_out_data);
// state act tanh(cell_out) * output_gate
act_cell(D, cur_cell_out_data, lstm_out_data);
blas.VMUL(D, lstm_out_data, lstm_out_data + D2, cur_hidden_out_data);
prev_hidden_data = cur_hidden_out_data;
prev_cell_data = cur_cell_out_data;
cur_cell_out_data = cur_cell_out_data + D;
cur_hidden_out_data = cur_hidden_out_data + D;
}
cur_x_data = cur_x_data + seq_len * M;
cur_atten_x_data = cur_atten_x_data + seq_len;
}
}
} // namespace phi
PD_REGISTER_KERNEL(
attention_lstm, CPU, ALL_LAYOUT, phi::AttentionLSTMKernel, float, double) {}
+250
View File
@@ -0,0 +1,250 @@
// 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/auc_kernel.h"
#include <glog/logging.h>
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
namespace phi {
inline static double trapezoidArea(double X1, double X2, double Y1, double Y2) {
return (X1 > X2 ? (X1 - X2) : (X2 - X1)) * (Y1 + Y2) / 2.0;
}
inline static size_t compute_max_bytes(int64_t *dest,
const long *src, // NOLINT
const int num_thresholds,
const int slide_steps) {
return reinterpret_cast<const char *>(src + (num_thresholds + 1) *
(slide_steps + 1)) -
reinterpret_cast<const char *>(dest);
}
template <typename T>
void statAuc(const DenseTensor &label,
const DenseTensor &predict,
const int num_thresholds,
const int slide_steps,
int64_t *origin_stat_pos,
int64_t *origin_stat_neg,
const bool is_fake_data) {
size_t batch_size = predict.dims()[0];
size_t inference_width = predict.dims()[1];
const T *inference_data = predict.data<T>();
const auto *label_data = label.data<int64_t>();
const int bucket_length = num_thresholds + 1;
if (slide_steps == 0) {
for (size_t i = 0; i < batch_size; i++) {
// if predict_data[i] has dim of 2, then predict_data[i][1] is pos prob
// if predict_data[i] has dim of 1, then predict_data[i][0] is pos prob
auto predict_data =
inference_data[i * inference_width + (inference_width - 1)];
PADDLE_ENFORCE_LE(predict_data,
1,
common::errors::PreconditionNotMet(
"The predict data must less or equal 1."));
PADDLE_ENFORCE_GE(predict_data,
0,
common::errors::PreconditionNotMet(
"The predict data must gather or equal 0."));
uint32_t binIdx = static_cast<uint32_t>(predict_data * num_thresholds);
if (label_data[i] > 0) {
origin_stat_pos[binIdx] += 1;
} else if (label_data[i] == 0) {
origin_stat_neg[binIdx] += 1;
}
}
return;
}
// the last number of origin_stat_pos store the index should be used in
// current step
int cur_step_index =
static_cast<int>(origin_stat_pos[(slide_steps + 1) * bucket_length]) %
slide_steps;
int cur_step_begin = cur_step_index * bucket_length;
int sum_step_begin = slide_steps * bucket_length;
for (int i = 0; i < bucket_length; ++i) {
origin_stat_pos[sum_step_begin + i] -= origin_stat_pos[cur_step_begin + i];
origin_stat_neg[sum_step_begin + i] -= origin_stat_neg[cur_step_begin + i];
}
std::memset(
origin_stat_pos + cur_step_begin, 0, bucket_length * sizeof(int64_t));
std::memset(
origin_stat_neg + cur_step_begin, 0, bucket_length * sizeof(int64_t));
for (size_t i = 0; i < batch_size; i++) {
// if predict_data[i] has dim of 2, then predict_data[i][1] is pos prob
// if predict_data[i] has dim of 1, then predict_data[i][0] is pos prob
auto predict_data =
inference_data[i * inference_width + (inference_width - 1)];
PADDLE_ENFORCE_LE(predict_data,
1,
common::errors::PreconditionNotMet(
"The predict data must less or equal 1."));
PADDLE_ENFORCE_GE(predict_data,
0,
common::errors::PreconditionNotMet(
"The predict data must gather or equal 0."));
uint32_t binIdx = static_cast<uint32_t>(predict_data * num_thresholds);
if (label_data[i] > 0) {
origin_stat_pos[cur_step_begin + binIdx] += 1;
} else if (label_data[i] == 0) {
origin_stat_neg[cur_step_begin + binIdx] += 1;
}
}
if (!is_fake_data) {
for (int i = 0; i < bucket_length; ++i) {
origin_stat_pos[sum_step_begin + i] +=
origin_stat_pos[cur_step_begin + i];
origin_stat_neg[sum_step_begin + i] +=
origin_stat_neg[cur_step_begin + i];
}
}
}
inline static void calcAuc(const int64_t *stat_pos,
const int64_t *stat_neg,
int num_thresholds,
double *auc) {
*auc = 0.0f;
double totPos = 0.0;
double totNeg = 0.0;
double totPosPrev = 0.0;
double totNegPrev = 0.0;
int idx = num_thresholds;
while (idx >= 0) {
totPosPrev = totPos;
totNegPrev = totNeg;
totPos += static_cast<double>(stat_pos[idx]);
totNeg += static_cast<double>(stat_neg[idx]);
*auc += trapezoidArea(totNeg, totNegPrev, totPos, totPosPrev);
--idx;
}
if (totPos > 0.0 && totNeg > 0.0) {
*auc = *auc / totPos / totNeg;
}
}
template <typename T, typename Context>
void AucKernel(const Context &dev_ctx,
const DenseTensor &input,
const DenseTensor &label,
const DenseTensor &stat_pos,
const DenseTensor &stat_neg,
const optional<DenseTensor> &ins_tag_weight,
const std::string &curve,
int num_thresholds,
int slide_steps,
DenseTensor *auc,
DenseTensor *stat_pos_out,
DenseTensor *stat_neg_out) {
// Only use output var for now, make sure it's persistable and
// not cleaned up for each batch.
auto *origin_stat_pos = dev_ctx.template Alloc<int64_t>(stat_pos_out);
auto *origin_stat_neg = dev_ctx.template Alloc<int64_t>(stat_neg_out);
auto *auc_value = dev_ctx.template Alloc<double>(auc);
// Just for pass UT, since UT's input & output cannot be set same var
auto *stat_pos_in_tensor = &stat_pos;
auto *stat_neg_in_tensor = &stat_neg;
auto *pos_in_data = stat_pos.data<int64_t>();
auto *neg_in_data = stat_neg.data<int64_t>();
bool is_fake_data = false;
if (ins_tag_weight.get_ptr() != nullptr) {
const auto *ins_tag_weight_data = ins_tag_weight->data<float>();
VLOG(4) << "auc ins_tag_weight = " << ins_tag_weight_data[0];
if (ins_tag_weight_data[0] == 0) {
is_fake_data = true;
}
}
size_t required_bytes =
((1 + slide_steps) * (num_thresholds + 1) + (slide_steps > 0 ? 1 : 0)) *
sizeof(int64_t);
if (stat_pos_in_tensor != stat_pos_out) {
size_t max_bytes = compute_max_bytes(
origin_stat_pos,
reinterpret_cast<const long *>(pos_in_data), // NOLINT
num_thresholds,
slide_steps);
PADDLE_ENFORCE_LE(required_bytes,
max_bytes,
common::errors::PreconditionNotMet(
"The number of bytes to be copied %d must be less "
"than or equal to the maximum number of bytes %d. ",
required_bytes,
max_bytes));
memcpy(
origin_stat_pos,
pos_in_data,
((1 + slide_steps) * (num_thresholds + 1) + (slide_steps > 0 ? 1 : 0)) *
sizeof(int64_t));
}
if (stat_neg_in_tensor != stat_neg_out) {
size_t max_bytes = compute_max_bytes(
origin_stat_neg,
reinterpret_cast<const long *>(neg_in_data), // NOLINT
num_thresholds,
slide_steps);
PADDLE_ENFORCE_LE(required_bytes,
max_bytes,
common::errors::PreconditionNotMet(
"The number of bytes to be copied %d must be less "
"than or equal to the maximum number of bytes %d. ",
required_bytes,
max_bytes));
memcpy(
origin_stat_neg,
neg_in_data,
((1 + slide_steps) * (num_thresholds + 1) + (slide_steps > 0 ? 1 : 0)) *
sizeof(int64_t));
}
// when calculate global_auc && is fake data, just do nothing
if (slide_steps == 0 && is_fake_data) {
return;
}
statAuc<T>(label,
input,
num_thresholds,
slide_steps,
origin_stat_pos,
origin_stat_neg,
is_fake_data);
int sum_offset = slide_steps * (num_thresholds + 1);
calcAuc(origin_stat_pos + sum_offset,
origin_stat_neg + sum_offset,
num_thresholds,
auc_value);
if (slide_steps) {
origin_stat_pos[(slide_steps + 1) * (num_thresholds + 1)] += 1;
origin_stat_neg[(slide_steps + 1) * (num_thresholds + 1)] += 1;
}
}
} // namespace phi
PD_REGISTER_KERNEL(auc, CPU, ALL_LAYOUT, phi::AucKernel, float) {
kernel->OutputAt(0).SetDataType(phi::DataType::FLOAT64);
kernel->OutputAt(1).SetDataType(phi::DataType::INT64);
kernel->OutputAt(2).SetDataType(phi::DataType::INT64);
}
@@ -0,0 +1,60 @@
/* 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/average_accumulates_kernel.h"
#include "paddle/phi/kernels/impl/average_accumulates_kernel_impl.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
namespace phi {
template <>
void GetAccumulators<CPUContext>(const CPUContext& dev_ctx,
const DenseTensor& in_num_accumulates,
const DenseTensor& in_old_num_accumulates,
const DenseTensor& in_num_updates,
int64_t* num_updates,
int64_t* num_accumulates,
int64_t* old_num_accumulates) {
*old_num_accumulates = in_old_num_accumulates.data<int64_t>()[0];
*num_accumulates = in_num_accumulates.data<int64_t>()[0];
*num_updates = in_num_updates.data<int64_t>()[0];
}
template <>
void SetAccumulators<CPUContext>(const CPUContext& dev_ctx,
int64_t num_updates,
int64_t num_accumulates,
int64_t old_num_accumulates,
DenseTensor* out_num_accumulates,
DenseTensor* out_old_num_accumulates,
DenseTensor* out_num_updates) {
out_old_num_accumulates->data<int64_t>()[0] = old_num_accumulates;
out_num_accumulates->data<int64_t>()[0] = num_accumulates;
out_num_updates->data<int64_t>()[0] = num_updates;
}
} // namespace phi
PD_REGISTER_KERNEL(average_accumulates,
CPU,
ALL_LAYOUT,
phi::AverageAccumulatesKernel,
float,
double) {
kernel->OutputAt(3).SetDataType(phi::DataType::INT64);
kernel->OutputAt(4).SetDataType(phi::DataType::INT64);
kernel->OutputAt(5).SetDataType(phi::DataType::INT64);
}
@@ -0,0 +1,22 @@
/* 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/phi/kernels/baddbmm_grad_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/baddbmm_grad_kernel_impl.h"
PD_REGISTER_KERNEL(
baddbmm_grad, CPU, ALL_LAYOUT, phi::BaddbmmGradKernel, float, double) {}
+22
View File
@@ -0,0 +1,22 @@
/* 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/phi/kernels/baddbmm_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/baddbmm_kernel_impl.h"
PD_REGISTER_KERNEL(
baddbmm, CPU, ALL_LAYOUT, phi::BaddbmmKernel, float, double) {}
+45
View File
@@ -0,0 +1,45 @@
// 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/barrier_kernel.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/distributed/comm_context_manager.h"
#include "paddle/phi/core/kernel_registry.h"
#if defined(PADDLE_WITH_GLOO)
#include "paddle/phi/core/distributed/gloo_comm_context.h"
#endif
namespace phi {
template <typename T, typename Context>
void BarrierKernel(const Context &dev_ctx,
const DenseTensor &x,
DenseTensor *out) {
#if defined(PADDLE_WITH_GLOO)
auto comm_ctx =
static_cast<distributed::GlooCommContext *>(dev_ctx.GetCommContext());
PADDLE_ENFORCE_NE(comm_ctx,
nullptr,
::common::errors::Unavailable(
"NCCLCommContext is nullptr, collective op should "
"has ring_id attr."));
comm_ctx->Barrier();
#else
PADDLE_THROW(common::errors::Unavailable(
"PaddlePaddle should compile with GLOO by setting WITH_GLOO=ON"));
#endif
}
} // namespace phi
PD_REGISTER_KERNEL(barrier, CPU, ALL_LAYOUT, phi::BarrierKernel, int) {}
+35
View File
@@ -0,0 +1,35 @@
// 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/core/kernel_registry.h"
namespace phi {
template <typename T, typename Context>
void BatchFCKernel(const Context &dev_ctx,
const DenseTensor &input,
const DenseTensor &w,
const DenseTensor &bias,
DenseTensor *out) {
PADDLE_ENFORCE_EQ(
(dev_ctx.GetPlace().GetType() == AllocationType::GPU) ||
(dev_ctx.GetPlace().GetType() == AllocationType::CUSTOM),
true,
common::errors::Unimplemented("BatchFC only supports GPU now."));
}
} // namespace phi
PD_REGISTER_KERNEL(
batch_fc, CPU, ALL_LAYOUT, phi::BatchFCKernel, float, double) {}
@@ -0,0 +1,693 @@
// 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 "glog/logging.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/batch_norm_kernel.h"
#include "paddle/phi/kernels/full_kernel.h"
#include "paddle/phi/kernels/funcs/batch_norm_utils.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
#include "paddle/phi/kernels/funcs/math_function.h"
namespace phi {
template <typename T>
using EigenArrayMap =
Eigen::Map<Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic>>;
template <typename T>
using ConstEigenArrayMap =
Eigen::Map<const Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic>>;
template <typename T>
using EigenVectorArrayMap = Eigen::Map<Eigen::Array<T, Eigen::Dynamic, 1>>;
template <typename T>
using ConstEigenVectorArrayMap =
Eigen::Map<const Eigen::Array<T, Eigen::Dynamic, 1>>;
template <typename T, typename Context>
void BatchNormGradFunctor(const Context& dev_ctx,
const DenseTensor& x,
const optional<DenseTensor>& scale,
const optional<DenseTensor>& bias,
const optional<DenseTensor>& mean,
const optional<DenseTensor>& variance,
const DenseTensor& saved_mean,
const DenseTensor& saved_variance,
const optional<DenseTensor>& reserve_space,
const DenseTensor& y_grad,
float momentum,
float epsilon,
const std::string& data_layout_str,
bool is_test,
bool use_global_stats,
bool trainable_statistics,
bool is_inplace,
DenseTensor* x_grad,
DenseTensor* scale_grad,
DenseTensor* bias_grad) {
const auto* d_y = &y_grad;
DataLayout data_layout = StringToDataLayout(data_layout_str);
auto* d_x = x_grad;
auto* d_scale = scale_grad;
auto* d_bias = bias_grad;
use_global_stats = is_test || use_global_stats;
// batch_norm with inplace as false will take X as grad input, which
// is same as cuDNN batch_norm backward calculation, batch_norm
// with inplace as true only take Y as input and X should be calculate
// by inverse operation of batch_norm on Y
if (is_inplace) {
if (d_x) {
PADDLE_ENFORCE_EQ(d_x,
d_y,
common::errors::InvalidArgument(
"X@GRAD and Y@GRAD inplaced in non-inplace mode"));
}
} else {
if (d_x) {
PADDLE_ENFORCE_NE(d_x,
d_y,
common::errors::InvalidArgument(
"X@GRAD and Y@GRAD inplaced in non-inplace mode"));
}
}
// Get the size for each dimension.
// NCHW [batch_size, in_channels, in_height, in_width]
const auto& x_dims = x.dims();
PADDLE_ENFORCE_GE(
x_dims.size(),
2,
common::errors::InvalidArgument(
"The size of input X's dimensions should be larger than 1."
"But received: the size of input X's dimensions is [%d]",
x_dims.size()));
PADDLE_ENFORCE_LE(
x_dims.size(),
5,
common::errors::InvalidArgument(
"The size of input X's dimensions should be less than 6."
"But received: the size of input X's dimensions is [%d]",
x_dims.size()));
const int64_t N = x_dims[0];
const int64_t C =
data_layout == DataLayout::NCHW ? x_dims[1] : x_dims[x_dims.size() - 1];
const int64_t sample_size = x.numel() / N / C;
const int64_t num_batch_channels = N * C;
const int64_t num_batch_spatial = N * sample_size;
// input dimension is 2 and the format is NCHW. The input can be regarded as
// NHWC format
if (x_dims.size() == 2 && data_layout == DataLayout::NCHW) {
data_layout = DataLayout::NHWC;
}
// init output
if (d_x) {
dev_ctx.template Alloc<T>(d_x);
}
const T* mean_data = nullptr;
const T* inv_var_data = nullptr;
DenseTensor inv_var_tensor;
if (use_global_stats) {
const auto* running_mean = mean.get_ptr();
const auto* running_variance = variance.get_ptr();
mean_data = running_mean->data<T>();
inv_var_tensor.Resize({C});
T* running_inv_var_data = dev_ctx.template Alloc<T>(&inv_var_tensor);
EigenVectorArrayMap<T> inv_var_tmp(running_inv_var_data, C);
ConstEigenVectorArrayMap<T> var_arr(running_variance->data<T>(), C);
inv_var_tmp = (var_arr + epsilon).sqrt().inverse();
inv_var_data = running_inv_var_data;
} else {
mean_data = saved_mean.data<T>();
inv_var_data = saved_variance.data<T>();
}
ConstEigenVectorArrayMap<T> mean_arr(mean_data, C);
ConstEigenVectorArrayMap<T> inv_var_arr(inv_var_data, C);
T* d_bias_data = nullptr;
T* d_scale_data = nullptr;
if (d_scale && d_bias) {
d_bias_data = dev_ctx.template Alloc<T>(d_bias);
d_scale_data = dev_ctx.template Alloc<T>(d_scale);
}
// d_bias = np.sum(d_y, axis=0)
// d_scale = np.sum((X - mean) / inv_std * dy, axis=0)
// d_x = (1. / N) * scale * inv_var * (N * d_y - np.sum(d_y, axis=0)
// - (X - mean) * inv_var * inv_var * np.sum(d_y * (X - mean), axis=0))
EigenVectorArrayMap<T> d_bias_arr(d_bias_data, C);
EigenVectorArrayMap<T> d_scale_arr(d_scale_data, C);
if (d_scale && d_bias) {
d_bias_arr.setZero();
d_scale_arr.setZero();
}
if (d_x && num_batch_spatial == 1 && !use_global_stats) {
Copy(dev_ctx, *d_y, dev_ctx.GetPlace(), false, d_x);
return;
}
auto* Scale = scale.get_ptr();
auto* Bias = bias.get_ptr();
Eigen::Array<T, Eigen::Dynamic, 1> scale_arr(C);
Eigen::Array<T, Eigen::Dynamic, 1> bias_arr(C);
if (Scale) {
scale_arr = ConstEigenVectorArrayMap<T>(Scale->data<T>(), C);
} else {
scale_arr.setOnes();
}
if (Bias) {
bias_arr = ConstEigenVectorArrayMap<T>(Bias->data<T>(), C);
} else {
bias_arr.setZero();
}
int64_t scale_coeff = use_global_stats ? 1 : num_batch_spatial;
const auto scale_inv_var_nhw = scale_arr * inv_var_arr / scale_coeff;
DenseTensor dy_sum;
dy_sum.Resize({C});
auto dy_sum_data = dev_ctx.template Alloc<T>(&dy_sum);
EigenVectorArrayMap<T> dy_sum_arr(dy_sum_data, C);
DenseTensor dy_mul_x_sub_mean_mul_invstd_sum;
dy_mul_x_sub_mean_mul_invstd_sum.Resize({C});
auto dy_mul_x_sub_mean_mul_invstd_sum_data =
dev_ctx.template Alloc<T>(&dy_mul_x_sub_mean_mul_invstd_sum);
EigenVectorArrayMap<T> dy_mul_x_sub_mean_mul_invstd_sum_arr(
dy_mul_x_sub_mean_mul_invstd_sum_data, C);
dy_sum_arr.setZero();
dy_mul_x_sub_mean_mul_invstd_sum_arr.setZero();
// inplace calculation
// Y: ((x - est_mean) * (inv_var) * scale + bias
// formula transform ====>
// (x * inv_var * scale) + (bias - est_mean * inv_var * scale)
// X: (y - bias) / scale / (inv_var) + est_mean
// formula transform ====>
// (y - bias) / (scale * inv_var) + est_mean
switch (data_layout) {
case DataLayout::NCHW: {
if (is_inplace) {
auto px = x;
EigenArrayMap<T> x_data(
dev_ctx.template Alloc<T>(&px), sample_size, num_batch_channels);
ConstEigenArrayMap<T> y_data(
x.data<T>(), sample_size, num_batch_channels);
for (int64_t nc = 0; nc < num_batch_channels; ++nc) {
x_data.col(nc) = (y_data.col(nc) - bias_arr(nc % C)) /
scale_inv_var_nhw(nc % C) / scale_coeff +
mean_arr(nc % C);
}
}
ConstEigenArrayMap<T> x_arr(x.data<T>(), sample_size, num_batch_channels);
ConstEigenArrayMap<T> d_y_arr(
d_y->data<T>(), sample_size, num_batch_channels);
for (int64_t nc = 0; nc < num_batch_channels; ++nc) {
int c = nc % C;
dy_sum_arr(c) += d_y_arr.col(nc).sum();
dy_mul_x_sub_mean_mul_invstd_sum_arr(c) +=
((x_arr.col(nc) - mean_arr(c)) * inv_var_arr(c) * d_y_arr.col(nc))
.sum();
}
if (d_scale && d_bias) {
d_bias_arr = dy_sum_arr;
d_scale_arr = dy_mul_x_sub_mean_mul_invstd_sum_arr;
}
if (d_x) {
EigenArrayMap<T> d_x_arr(
dev_ctx.template Alloc<T>(d_x), sample_size, num_batch_channels);
if (!use_global_stats) {
for (int64_t nc = 0; nc < num_batch_channels; ++nc) {
int c = nc % C;
d_x_arr.col(nc) =
scale_inv_var_nhw(c) *
(d_y_arr.col(nc) * num_batch_spatial - dy_sum_arr(c) -
(x_arr.col(nc) - mean_arr[c]) *
dy_mul_x_sub_mean_mul_invstd_sum_arr(c) * inv_var_arr(c));
}
} else {
for (int64_t nc = 0; nc < num_batch_channels; ++nc) {
int c = nc % C;
d_x_arr.col(nc) = scale_inv_var_nhw(c) * d_y_arr.col(nc);
}
}
}
break;
}
case DataLayout::NHWC: {
if (is_inplace) {
auto px = x;
EigenArrayMap<T> x_data(
dev_ctx.template Alloc<T>(&px), C, num_batch_spatial);
ConstEigenArrayMap<T> y_data(x.data<T>(), C, num_batch_spatial);
for (int64_t nhw = 0; nhw < num_batch_spatial; nhw++) {
x_data.col(nhw) =
(y_data.col(nhw) - bias_arr) / scale_inv_var_nhw / scale_coeff +
mean_arr;
}
}
ConstEigenArrayMap<T> x_arr(x.data<T>(), C, num_batch_spatial);
ConstEigenArrayMap<T> d_y_arr(d_y->data<T>(), C, num_batch_spatial);
for (int64_t nhw = 0; nhw < num_batch_spatial; ++nhw) {
dy_sum_arr += d_y_arr.col(nhw);
dy_mul_x_sub_mean_mul_invstd_sum_arr +=
(x_arr.col(nhw) - mean_arr) * inv_var_arr * d_y_arr.col(nhw);
}
if (d_scale && d_bias) {
d_bias_arr = dy_sum_arr;
d_scale_arr = dy_mul_x_sub_mean_mul_invstd_sum_arr;
}
if (d_x) {
EigenArrayMap<T> d_x_arr(
dev_ctx.template Alloc<T>(d_x), C, num_batch_spatial);
if (!use_global_stats) {
for (int64_t nhw = 0; nhw < num_batch_spatial; ++nhw) {
d_x_arr.col(nhw) =
scale_inv_var_nhw *
(d_y_arr.col(nhw) * num_batch_spatial - dy_sum_arr -
(x_arr.col(nhw) - mean_arr) *
dy_mul_x_sub_mean_mul_invstd_sum_arr * inv_var_arr);
}
} else {
for (int64_t nhw = 0; nhw < num_batch_spatial; ++nhw) {
d_x_arr.col(nhw) = scale_inv_var_nhw * d_y_arr.col(nhw);
}
}
}
break;
}
default:
PADDLE_THROW(common::errors::InvalidArgument("Unknown storage order: %s",
data_layout_str));
}
}
template <typename T, typename Context>
void BatchNormGradKernel(const Context& dev_ctx,
const DenseTensor& x,
const optional<DenseTensor>& scale,
const optional<DenseTensor>& bias,
const optional<DenseTensor>& mean,
const optional<DenseTensor>& variance,
const DenseTensor& saved_mean,
const DenseTensor& saved_variance,
const optional<DenseTensor>& reserve_space,
const DenseTensor& y_grad,
float momentum,
float epsilon,
const std::string& data_layout,
bool is_test,
bool use_global_stats,
bool trainable_statistics,
DenseTensor* x_grad,
DenseTensor* scale_grad,
DenseTensor* bias_grad) {
if (x.numel() == 0) {
dev_ctx.template Alloc<T>(x_grad);
if (scale_grad)
Full<T, Context>(dev_ctx, scale_grad->dims(), 0, scale_grad);
if (bias_grad) Full<T, Context>(dev_ctx, bias_grad->dims(), 0, bias_grad);
return;
}
BatchNormGradFunctor<T, Context>(dev_ctx,
x,
scale,
bias,
mean,
variance,
saved_mean,
saved_variance,
reserve_space,
y_grad,
momentum,
epsilon,
data_layout,
is_test,
use_global_stats,
trainable_statistics,
false,
x_grad,
scale_grad,
bias_grad);
}
template <typename T, typename Context>
void BatchNormDoubleGradKernel(const Context& dev_ctx,
const DenseTensor& x,
const optional<DenseTensor>& scale,
const optional<DenseTensor>& mean,
const optional<DenseTensor>& variance,
const DenseTensor& saved_mean,
const DenseTensor& saved_variance,
const DenseTensor& y_grad,
const optional<DenseTensor>& x_grad_grad,
const optional<DenseTensor>& scale_grad_grad,
const optional<DenseTensor>& bias_grad_grad,
float momentum,
float epsilon,
const std::string& data_layout_str,
bool is_test,
bool use_global_stats,
bool trainable_statistics,
DenseTensor* x_grad,
DenseTensor* scale_grad,
DenseTensor* y_grad_grad) {
const auto* X = &x;
const auto* Scale = scale.get_ptr();
const auto* dY = &y_grad;
const auto* Saved_mean = &saved_mean;
const auto* Saved_variance = &saved_variance;
PADDLE_ENFORCE_EQ(is_test,
false,
common::errors::InvalidArgument(
"`is_test = True` CANNOT be used in train program. If "
"you want to use global status in pre_train model, "
"please set `use_global_stats = True`"));
const auto data_layout = StringToDataLayout(data_layout_str);
const auto* ddX = x_grad_grad.get_ptr();
const auto* ddScale = scale_grad_grad.get_ptr();
const auto* ddBias = bias_grad_grad.get_ptr();
auto* dX = x_grad;
auto* dScale = scale_grad;
auto* ddY = y_grad_grad;
dev_ctx.template Alloc<T>(dX);
dev_ctx.template Alloc<T>(ddY);
const auto& x_dims = X->dims();
const int64_t C =
data_layout == DataLayout::NCHW ? x_dims[1] : x_dims[x_dims.size() - 1];
const int64_t sample_size = X->numel() / C;
funcs::SetConstant<Context, T> set_constant;
const T* mean_data = Saved_mean->data<T>();
const T* inv_var_data = Saved_variance->data<T>();
DenseTensor inv_var_tensor;
if (use_global_stats) {
const auto* running_mean = mean.get_ptr();
const auto* running_variance = variance.get_ptr();
mean_data = running_mean->data<T>();
inv_var_tensor.Resize({C});
T* running_inv_var_data = dev_ctx.template Alloc<T>(&inv_var_tensor);
EigenVectorArrayMap<T> inv_var_tmp(running_inv_var_data, C);
ConstEigenVectorArrayMap<T> var_arr(running_variance->data<T>(), C);
inv_var_tmp = (var_arr + epsilon).sqrt().inverse();
inv_var_data = running_inv_var_data;
}
// transpose NCHW -> NHWC for easy calculate
DenseTensor transformed_x(X->type());
DenseTensor transformed_dy(dY->type());
DenseTensor transformed_ddx(ddX->type());
DenseTensor transformed_dx(dX->type());
DenseTensor transformed_ddy(ddY->type());
if (data_layout == DataLayout::NCHW && x_dims.size() > 2) {
VLOG(3) << "Transform batchnorm output from NCHW to NHWC";
// Input DenseTensor
ResizeToChannelLast<Context, T>(dev_ctx, X, &transformed_x);
TransToChannelLast<Context, T>(dev_ctx, X, &transformed_x);
ResizeToChannelLast<Context, T>(dev_ctx, dY, &transformed_dy);
TransToChannelLast<Context, T>(dev_ctx, dY, &transformed_dy);
ResizeToChannelLast<Context, T>(dev_ctx, ddX, &transformed_ddx);
TransToChannelLast<Context, T>(dev_ctx, ddX, &transformed_ddx);
// Output DenseTensor
ResizeToChannelLast<Context, T>(dev_ctx, dX, &transformed_dx);
ResizeToChannelLast<Context, T>(dev_ctx, ddY, &transformed_ddy);
} else {
transformed_x.ShareDataWith(*X);
transformed_dy.ShareDataWith(*dY);
transformed_ddx.ShareDataWith(*ddX);
transformed_dx.ShareDataWith(*dX);
transformed_ddy.ShareDataWith(*ddY);
}
ConstEigenArrayMap<T> x_arr(transformed_x.data<T>(), C, sample_size);
ConstEigenVectorArrayMap<T> mean_arr(mean_data, C);
ConstEigenVectorArrayMap<T> inv_var_arr(inv_var_data, C);
DenseTensor mean_tile;
mean_tile.Resize({C, sample_size});
EigenArrayMap<T> mean_tile_data(
dev_ctx.template Alloc<T>(&mean_tile), C, sample_size);
DenseTensor inv_var_tile;
inv_var_tile.Resize({C, sample_size});
EigenArrayMap<T> inv_var_tile_data(
dev_ctx.template Alloc<T>(&inv_var_tile), C, sample_size);
mean_tile_data = mean_arr.replicate(1, sample_size);
inv_var_tile_data = inv_var_arr.replicate(1, sample_size);
DenseTensor Scale_data;
if (!Scale) {
Scale_data.Resize({C});
dev_ctx.template Alloc<T>(&Scale_data);
set_constant(dev_ctx, &Scale_data, static_cast<T>(1));
}
ConstEigenVectorArrayMap<T> scale_arr(
Scale ? Scale->data<T>() : Scale_data.data<T>(), C);
DenseTensor scale_tile;
scale_tile.Resize({C, sample_size});
EigenArrayMap<T> scale_tile_data(
dev_ctx.template Alloc<T>(&scale_tile), C, sample_size);
scale_tile_data = scale_arr.replicate(1, sample_size);
ConstEigenArrayMap<T> dy_arr(transformed_dy.data<T>(), C, sample_size);
ConstEigenArrayMap<T> ddx_arr(transformed_ddx.data<T>(), C, sample_size);
DenseTensor x_sub_mean_mul_invstd;
x_sub_mean_mul_invstd.Resize({C, sample_size});
EigenArrayMap<T> x_sub_mean_mul_invstd_arr(
dev_ctx.template Alloc<T>(&x_sub_mean_mul_invstd), C, sample_size);
x_sub_mean_mul_invstd_arr = (x_arr - mean_tile_data) * inv_var_tile_data;
if (dX) {
dev_ctx.template Alloc<T>(dX);
EigenArrayMap<T> dx_arr(
dev_ctx.template Alloc<T>(&transformed_dx), C, sample_size);
dx_arr.setZero();
if (use_global_stats) {
// math: dx = (ddscale * dy) * inv_var
if (ddScale) {
ConstEigenVectorArrayMap<T> ddscale_arr(ddScale->data<T>(), C);
DenseTensor ddscale_tile;
ddscale_tile.Resize({C, sample_size});
EigenArrayMap<T> ddscale_tile_data(
dev_ctx.template Alloc<T>(&ddscale_tile), C, sample_size);
ddscale_tile_data = ddscale_arr.replicate(1, sample_size);
dx_arr = dy_arr * ddscale_tile_data * inv_var_tile_data;
}
} else {
// math: dx = scale * ((x - mean) * inv_var / NxHxW * (np.mean(ddx,
// axis=(n,h,w)) *
// np.sum(dy, axis=(n,h,w)) -
// np.sum(dy * ddx, axis=(n,h,w)) + 3 * np.mean(dy * (x -
// mean),
// axis=(n,h,w)) * inv_var.pow(2) *
// np.sum(ddx * (x - mean), axis=(n,h,w))) + inv_var.pow(3) /
// NxHxW *
// np.sum(ddx * (x - mean)) *
// (np.mean(dy, axis=(n,h,w)) - dy) + inv_var.pow(3) / NxHxW *
// np.sum(dy,
// axis=(n,h,w)) * (x - mean) *
// (np.mean(ddx, axis=(n,h,w)) - ddx)) + ddr * (dy * inv_var -
// inv_var
// *
// np.mean(dy, axis=(n,h,w)) -
// inv_var.pow(3) * (x - mean) * np.mean(dy * (x - mean),
// axis=(n,h,w)))
if (ddX) {
dx_arr +=
(x_sub_mean_mul_invstd_arr * inv_var_tile_data * inv_var_tile_data /
sample_size)
.colwise() *
(ddx_arr.rowwise().sum() * dy_arr.rowwise().sum() / sample_size -
(dy_arr * ddx_arr).rowwise().sum() +
3. * (dy_arr * x_sub_mean_mul_invstd_arr).rowwise().sum() *
(ddx_arr * x_sub_mean_mul_invstd_arr).rowwise().sum() /
sample_size);
dx_arr += (inv_var_tile_data * inv_var_tile_data).colwise() *
(ddx_arr * x_sub_mean_mul_invstd_arr).rowwise().sum() /
sample_size * (dy_arr.rowwise().sum() / sample_size - dy_arr);
dx_arr += (inv_var_tile_data * inv_var_tile_data).colwise() *
(dy_arr * x_sub_mean_mul_invstd_arr).rowwise().sum() /
sample_size *
(ddx_arr.rowwise().sum() / sample_size - ddx_arr);
dx_arr = scale_tile_data * dx_arr;
}
if (ddScale) {
ConstEigenVectorArrayMap<T> ddscale_arr(ddScale->data<T>(), C);
DenseTensor ddscale_tile;
ddscale_tile.Resize({C, sample_size});
EigenArrayMap<T> ddscale_tile_data(
dev_ctx.template Alloc<T>(&ddscale_tile), C, sample_size);
ddscale_tile_data = ddscale_arr.replicate(1, sample_size);
dx_arr +=
(dy_arr * inv_var_tile_data -
(dy_arr.rowwise().sum().replicate(1, sample_size) / sample_size) *
inv_var_tile_data -
x_sub_mean_mul_invstd_arr * inv_var_tile_data *
(dy_arr * x_sub_mean_mul_invstd_arr)
.rowwise()
.sum()
.replicate(1, sample_size) /
sample_size) *
ddscale_tile_data;
}
}
if (data_layout == DataLayout::NCHW) {
VLOG(3) << "Transform batchnorm output from NHWC to NCHW";
TransToChannelFirst<Context, T>(dev_ctx, &transformed_dx, dX);
}
}
if (dScale) {
EigenVectorArrayMap<T> dscale_arr(dev_ctx.template Alloc<T>(dScale), C);
dscale_arr.setZero();
if (use_global_stats) {
// math: dscale = np.sum(ddx * dy, axis=(n,h,w)) * inv_var
if (ddX) {
dscale_arr = (ddx_arr * dy_arr * inv_var_tile_data).rowwise().sum();
}
} else {
// math: dscale = inv_var * (dy - np.mean(dy, axis=(n,h,w) - (x-mean) *
// inv_var.pow(2) * np.mean(dy * (x-mean), axis=(n,h,w)))) *
// ddx
if (ddX) {
DenseTensor first_grad;
first_grad.Resize({C, sample_size});
EigenArrayMap<T> first_grad_arr(
dev_ctx.template Alloc<T>(&first_grad), C, sample_size);
first_grad_arr.setZero();
first_grad_arr +=
inv_var_tile_data *
(dy_arr -
dy_arr.rowwise().sum().replicate(1, sample_size) / sample_size -
x_sub_mean_mul_invstd_arr *
(dy_arr * x_sub_mean_mul_invstd_arr)
.rowwise()
.sum()
.replicate(1, sample_size) /
sample_size);
dscale_arr = (first_grad_arr * ddx_arr).rowwise().sum();
}
}
}
if (ddY) {
dev_ctx.template Alloc<T>(ddY);
EigenArrayMap<T> ddy_arr(
dev_ctx.template Alloc<T>(&transformed_ddy), C, sample_size);
ddy_arr.setZero();
if (use_global_stats) { // NOLINT
// math: ddy = r * ddx * inv_var + ddbias +
// ddscale * (x - mean) * inv_var
if (ddX) {
ddy_arr = scale_tile_data * ddx_arr * inv_var_tile_data;
}
} else {
// math: ddy = (x - mean) * inv_var * ddscale + ddbias +
// scale * inv_var * (ddx - (x - mean) * inv_var.pow(2) *
// np.mean(ddx * (x - mean), axis=(n,h,w)))
if (ddX) {
ddy_arr +=
scale_tile_data * inv_var_tile_data *
(ddx_arr -
ddx_arr.rowwise().sum().replicate(1, sample_size) / sample_size -
x_sub_mean_mul_invstd_arr *
(ddx_arr * x_sub_mean_mul_invstd_arr)
.rowwise()
.sum()
.replicate(1, sample_size) /
sample_size);
}
}
if (ddScale) {
ConstEigenVectorArrayMap<T> ddscale_arr(ddScale->data<T>(), C);
DenseTensor ddscale_tile;
ddscale_tile.Resize({C, sample_size});
EigenArrayMap<T> ddscale_tile_data(
dev_ctx.template Alloc<T>(&ddscale_tile), C, sample_size);
ddscale_tile_data = ddscale_arr.replicate(1, sample_size);
ddy_arr += x_sub_mean_mul_invstd_arr * ddscale_tile_data;
}
if (ddBias) {
ConstEigenVectorArrayMap<T> ddbias_arr(ddBias->data<T>(), C);
DenseTensor ddbias_tile;
ddbias_tile.Resize({C, sample_size});
EigenArrayMap<T> ddbias_tile_data(
dev_ctx.template Alloc<T>(&ddbias_tile), C, sample_size);
ddbias_tile_data = ddbias_arr.replicate(1, sample_size);
ddy_arr += ddbias_tile_data;
}
if (data_layout == DataLayout::NCHW) {
VLOG(3) << "Transform batchnorm output from NHWC to NCHW";
TransToChannelFirst<Context, T>(dev_ctx, &transformed_ddy, ddY);
}
}
}
} // namespace phi
PD_DECLARE_BN_GRAD_FUNCTOR(float, CPU);
PD_DECLARE_BN_GRAD_FUNCTOR(double, CPU);
PD_REGISTER_KERNEL(
batch_norm_grad, CPU, ALL_LAYOUT, phi::BatchNormGradKernel, float, double) {
}
PD_REGISTER_KERNEL(batch_norm_double_grad,
CPU,
ALL_LAYOUT,
phi::BatchNormDoubleGradKernel,
float,
double) {}
+287
View File
@@ -0,0 +1,287 @@
// 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/batch_norm_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
namespace phi {
template <typename T>
using EigenArrayMap =
Eigen::Map<Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic>>;
template <typename T>
using ConstEigenArrayMap =
Eigen::Map<const Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic>>;
template <typename T>
using EigenVectorArrayMap = Eigen::Map<Eigen::Array<T, Eigen::Dynamic, 1>>;
template <typename T>
using ConstEigenVectorArrayMap =
Eigen::Map<const Eigen::Array<T, Eigen::Dynamic, 1>>;
template <typename T, typename Context>
void BatchNormKernel(const Context& dev_ctx,
const DenseTensor& x,
const DenseTensor& mean,
const DenseTensor& variance,
const optional<DenseTensor>& scale,
const optional<DenseTensor>& bias,
bool is_test,
float momentum,
float epsilon,
const std::string& data_layout_str,
bool use_global_stats,
bool trainable_statistics,
DenseTensor* y,
DenseTensor* mean_out,
DenseTensor* variance_out,
DenseTensor* saved_mean,
DenseTensor* saved_variance,
DenseTensor* reserve_space) {
if (x.numel() == 0) {
dev_ctx.template Alloc<T>(y);
if (mean_out) dev_ctx.template Alloc<T>(mean_out);
if (variance_out) dev_ctx.template Alloc<T>(variance_out);
if (saved_mean) dev_ctx.template Alloc<T>(saved_mean);
if (saved_variance) dev_ctx.template Alloc<T>(saved_variance);
if (reserve_space) {
// infermeta dim is -1.
reserve_space->Resize({0});
dev_ctx.template Alloc<T>(reserve_space);
}
return;
}
bool test_mode = is_test && (!trainable_statistics);
bool global_stats = test_mode || use_global_stats;
auto data_layout = StringToDataLayout(data_layout_str);
const auto& x_dims = x.dims();
PADDLE_ENFORCE_GE(
x_dims.size(),
2,
common::errors::InvalidArgument(
"The size of input X's dimensions should be larger than 1."
"But received: the size of input X's dimensions is [%d]",
x_dims.size()));
PADDLE_ENFORCE_LE(
x_dims.size(),
5,
common::errors::InvalidArgument(
"The size of input X's dimensions should be less than 6."
"But received: the size of input X's dimensions is [%d]",
x_dims.size()));
const int64_t N = x_dims[0];
const int64_t C =
data_layout == DataLayout::NCHW ? x_dims[1] : x_dims[x_dims.size() - 1];
const int64_t sample_size = x.numel() / N / C;
const int64_t num_batch_channels = static_cast<int64_t>(N) * C;
const int64_t num_batch_spatial = static_cast<int64_t>(N) * sample_size;
// alloc memory
dev_ctx.template Alloc<T>(y);
dev_ctx.template Alloc<T>(mean_out);
dev_ctx.template Alloc<T>(variance_out);
dev_ctx.template Alloc<T>(saved_mean);
dev_ctx.template Alloc<T>(saved_variance);
if (reserve_space != nullptr) {
reserve_space->Resize({0});
dev_ctx.template Alloc<T>(reserve_space);
}
// input dimension is 2 and the format is NCHW. The input can be regarded
// as NHWC format
if (x_dims.size() == 2 && data_layout == DataLayout::NCHW) {
data_layout = DataLayout::NHWC;
}
if (!global_stats) {
// saved_xx is use just in this batch of data
EigenVectorArrayMap<T> saved_mean_e(dev_ctx.template Alloc<T>(saved_mean),
C);
EigenVectorArrayMap<T> saved_variance_e(
dev_ctx.template Alloc<T>(saved_variance), C);
saved_mean_e.setZero();
saved_variance_e.setZero();
EigenVectorArrayMap<uint8_t> reserve_space_e(
dev_ctx.template Alloc<uint8_t>(reserve_space), 0);
reserve_space_e.setZero();
EigenVectorArrayMap<T> running_mean_arr(dev_ctx.template Alloc<T>(mean_out),
C);
EigenVectorArrayMap<T> running_var_arr(
dev_ctx.template Alloc<T>(variance_out), C);
if (num_batch_spatial == 1) {
// Only 1 element in normalization dimension,
// we skip the batch norm calculation, let y = x.
Copy(dev_ctx, x, dev_ctx.GetPlace(), false, y);
return;
}
switch (data_layout) {
case DataLayout::NCHW: {
ConstEigenArrayMap<T> x_arr(
x.data<T>(), sample_size, num_batch_channels);
for (int64_t nc = 0; nc < num_batch_channels; ++nc) {
saved_mean_e(nc % C) += x_arr.col(nc).sum();
}
saved_mean_e /= num_batch_spatial;
for (int64_t nc = 0; nc < num_batch_channels; ++nc) {
saved_variance_e(nc % C) +=
(x_arr.col(nc) - saved_mean_e(nc % C)).matrix().squaredNorm();
}
saved_variance_e /= num_batch_spatial;
break;
}
case DataLayout::NHWC: {
ConstEigenArrayMap<T> x_arr(x.data<T>(), C, num_batch_spatial);
for (int64_t i = 0; i < num_batch_spatial; ++i) {
saved_mean_e += x_arr.col(i);
}
saved_mean_e /= num_batch_spatial;
for (int64_t i = 0; i < num_batch_spatial; ++i) {
saved_variance_e +=
(x_arr.col(i) - saved_mean_e) * (x_arr.col(i) - saved_mean_e);
}
saved_variance_e /= num_batch_spatial;
break;
}
default:
PADDLE_THROW(common::errors::InvalidArgument(
"Unknown storage order: %s", data_layout_str));
}
// if MomentumTensor is set, use MomentumTensor value, momentum
// is only used in this training branch
running_mean_arr =
running_mean_arr * momentum + saved_mean_e * (1. - momentum);
running_var_arr =
running_var_arr * momentum + saved_variance_e * (1. - momentum);
} else {
const auto* est_mean = &mean;
const auto* est_var = &variance;
PADDLE_ENFORCE_EQ(
est_mean->dims().size(),
1UL,
common::errors::InvalidArgument(
"The size of mean's dimensions must equal to 1."
"But received: the size of mean's dimensions mean is [%d],"
"the dimensions of mean is [%s].",
est_mean->dims().size(),
est_mean->dims()));
PADDLE_ENFORCE_EQ(
est_var->dims().size(),
1UL,
common::errors::InvalidArgument(
"The size of variance's dimensions must equal to 1."
"But received: the size of variance's dimensions is [%d],"
"the dimensions of variance is [%s].",
est_var->dims().size(),
est_var->dims()));
PADDLE_ENFORCE_EQ(
est_mean->dims()[0],
C,
common::errors::InvalidArgument(
"The first dimension of mean must equal to the number of "
"Channels, which is [%d]. But received: the first dimension "
"of mean is [%d], the dimensions of mean is [%s].",
C,
est_mean->dims()[0],
est_mean->dims()));
PADDLE_ENFORCE_EQ(
est_var->dims()[0],
C,
common::errors::InvalidArgument(
"The first dimension of variance must equal to the number "
"of Channels, which is [%d]. But received: the first dimension of "
"variance is [%d], the dimensions of variance is [%s].",
C,
est_var->dims()[0],
est_var->dims()));
}
// use SavedMean and SavedVariance to do normalize
Eigen::Array<T, Eigen::Dynamic, 1> inv_std(C);
if (global_stats) { // NOLINT
ConstEigenVectorArrayMap<T> var_arr(variance.data<T>(), C);
inv_std = (var_arr + epsilon).sqrt().inverse();
} else {
EigenVectorArrayMap<T> saved_inv_std(saved_variance->data<T>(), C);
// inverse SavedVariance first, gradient will use it too.
saved_inv_std = (saved_inv_std + epsilon).inverse().sqrt();
inv_std = saved_inv_std;
}
ConstEigenVectorArrayMap<T> mean_arr(
global_stats ? mean.data<T>() : saved_mean->data<T>(), C);
// ((x - est_mean) * (inv_var) * scale + bias
// formula transform ====>
// (x * inv_var * scale) + (bias - est_mean * inv_var * scale)
auto* Scale = scale.get_ptr();
auto* Bias = bias.get_ptr();
Eigen::Array<T, Eigen::Dynamic, 1> new_scale(C);
Eigen::Array<T, Eigen::Dynamic, 1> new_bias(C);
if (Scale && Bias) { // NOLINT
ConstEigenVectorArrayMap<T> scale_arr(Scale->data<T>(), C);
ConstEigenVectorArrayMap<T> bias_arr(Bias->data<T>(), C);
new_scale = inv_std * scale_arr;
new_bias = bias_arr - mean_arr * inv_std * scale_arr;
} else if (Scale) {
ConstEigenVectorArrayMap<T> scale_arr(Scale->data<T>(), C);
new_scale = inv_std * scale_arr;
new_bias = -(mean_arr * inv_std * scale_arr);
} else if (Bias) {
ConstEigenVectorArrayMap<T> bias_arr(Bias->data<T>(), C);
new_scale = inv_std;
new_bias = bias_arr - mean_arr * inv_std;
} else {
new_scale = inv_std;
new_bias = -(mean_arr * inv_std);
}
switch (data_layout) {
case DataLayout::NCHW: {
EigenArrayMap<T> y_arr(
dev_ctx.template Alloc<T>(y), sample_size, num_batch_channels);
ConstEigenArrayMap<T> x_arr(x.data<T>(), sample_size, num_batch_channels);
for (int64_t nc = 0; nc < num_batch_channels; ++nc) {
y_arr.col(nc) = x_arr.col(nc) * new_scale(nc % C) + new_bias(nc % C);
}
break;
}
case DataLayout::NHWC: {
EigenArrayMap<T>(dev_ctx.template Alloc<T>(y), C, num_batch_spatial) =
(ConstEigenArrayMap<T>(x.data<T>(), C, num_batch_spatial).colwise() *
new_scale)
.colwise() +
new_bias;
break;
}
default:
PADDLE_THROW(common::errors::InvalidArgument("Unknown storage order: %d",
data_layout));
}
}
} // namespace phi
PD_REGISTER_KERNEL(
batch_norm, CPU, ALL_LAYOUT, phi::BatchNormKernel, float, double) {
kernel->OutputAt(5).SetDataType(phi::DataType::UINT8);
}
@@ -0,0 +1,48 @@
// 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/bce_loss_grad_kernel.h"
#include <algorithm> // for max
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
namespace phi {
template <typename T, typename Context>
void BCELossGradKernel(const Context& dev_ctx,
const DenseTensor& input,
const DenseTensor& label,
const DenseTensor& out_grad,
DenseTensor* input_grad) {
auto dx_data = dev_ctx.template Alloc<T>(input_grad);
auto dout_data = out_grad.data<T>();
auto x_data = input.data<T>();
auto label_data = label.data<T>();
int x_numel = static_cast<int>(input.numel());
// dx = dout * ((x - label)/(x - x^2))
for (int i = 0; i < x_numel; ++i) {
dx_data[i] =
dout_data[i] * ((x_data[i] - label_data[i]) /
std::max((static_cast<T>(1) - x_data[i]) * x_data[i],
static_cast<T>(1e-12)));
}
}
} // namespace phi
PD_REGISTER_KERNEL(
bce_loss_grad, CPU, ALL_LAYOUT, phi::BCELossGradKernel, float, double) {}
+59
View File
@@ -0,0 +1,59 @@
// 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/bce_loss_kernel.h"
#include <algorithm> // for max
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/math.h"
namespace phi {
template <typename T, typename Context>
void BCELossKernel(const Context& dev_ctx,
const DenseTensor& input,
const DenseTensor& label,
DenseTensor* out) {
auto x_data = input.data<T>();
auto label_data = label.data<T>();
auto out_data = dev_ctx.template Alloc<T>(out);
auto x_numel = input.numel();
// out = -(label * ln(x) + (1 - label) * ln(1 - x)) = (label - 1) * ln(1 -
// x) - label * ln(x)
for (int64_t i = 0; i < x_numel; ++i) {
PADDLE_ENFORCE_GE(
x_data[i],
static_cast<T>(0),
common::errors::InvalidArgument(
"Illegal input, input must be greater than or equal to 0"));
PADDLE_ENFORCE_LE(
x_data[i],
static_cast<T>(1),
common::errors::InvalidArgument(
"Illegal input, input must be less than or equal to 1"));
out_data[i] =
(label_data[i] - static_cast<T>(1)) *
std::max(funcs::real_log(static_cast<T>(1) - x_data[i]),
(T)(-100)) -
label_data[i] * std::max(funcs::real_log(x_data[i]), (T)(-100));
}
}
} // namespace phi
PD_REGISTER_KERNEL(
bce_loss, CPU, ALL_LAYOUT, phi::BCELossKernel, float, double) {}
@@ -0,0 +1,30 @@
// 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/common/data_type.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/beam_search_decode_kernel_impl.h"
PD_REGISTER_KERNEL(beam_search_decode,
CPU,
ALL_LAYOUT,
phi::BeamSearchDecodeOpKernel,
float,
double,
phi::float16,
int,
int64_t) {
kernel->OutputAt(0).SetDataType(phi::DataType::INT64);
kernel->OutputAt(1).SetDataType(phi::DataType::INT64);
}
@@ -0,0 +1,25 @@
// 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/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/beam_search_kernel_impl.h"
PD_REGISTER_KERNEL(beam_search,
CPU,
ALL_LAYOUT,
phi::BeamSearchOpKernel,
float,
double,
int,
int64_t) {}
@@ -0,0 +1,57 @@
// 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/bernoulli_kernel.h"
#include <random>
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
namespace phi {
template <typename T>
inline T BernoulliFunctor(T p, T rand) {
PADDLE_ENFORCE_LE(p,
1.0,
common::errors::OutOfRange(
"The probability should be <= 1, but got %f", p));
PADDLE_ENFORCE_GE(p,
0.0,
common::errors::OutOfRange(
"The probability should be >= 0, but got %f", p));
return static_cast<T>(rand < p);
}
template <typename T, typename Context>
void BernoulliKernel(const Context& dev_ctx,
const DenseTensor& x,
DenseTensor* out) {
auto numel = x.numel();
auto* x_data = x.data<T>();
T* out_data = dev_ctx.template Alloc<T>(out);
std::uniform_real_distribution<T> dist(0.0, 1.0);
auto gen_ptr = dev_ctx.GetGenerator();
auto engine = gen_ptr->GetCPUEngine();
for (int64_t i = 0; i < numel; ++i) {
out_data[i] = BernoulliFunctor(x_data[i], dist(*engine));
}
}
} // namespace phi
PD_REGISTER_KERNEL(
bernoulli, CPU, ALL_LAYOUT, phi::BernoulliKernel, float, double) {}
@@ -0,0 +1,21 @@
// 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/bilinear_grad_kernel.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/bilinear_grad_kernel_impl.h"
PD_REGISTER_KERNEL(
bilinear_grad, CPU, ALL_LAYOUT, phi::BilinearGradKernel, float, double) {}
+21
View File
@@ -0,0 +1,21 @@
// 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/bilinear_kernel.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/bilinear_kernel_impl.h"
PD_REGISTER_KERNEL(
bilinear, CPU, ALL_LAYOUT, phi::BilinearKernel, float, double) {}
+119
View File
@@ -0,0 +1,119 @@
// 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/bincount_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/full_kernel.h"
#include "paddle/phi/kernels/funcs/math_function.h"
namespace phi {
template <typename Context, typename T, typename InputT>
void BincountInner(const Context& dev_ctx,
const DenseTensor& x,
const optional<DenseTensor>& weights,
int64_t minlength,
DenseTensor* out) {
const DenseTensor* input = &x;
DenseTensor* output = out;
const InputT* input_data = input->data<InputT>();
auto input_numel = input->numel();
if (input_data == nullptr) {
DDim out_dim{minlength};
output->Resize(out_dim);
// Since minlength may >0 , so fill with 0.
Full<int64_t, Context>(dev_ctx, output->dims(), 0, output);
return;
}
PADDLE_ENFORCE_GE(
*std::min_element(input_data, input_data + input_numel),
static_cast<InputT>(0),
common::errors::InvalidArgument(
"The elements in input tensor must be non-negative ints"));
int64_t output_size = static_cast<int64_t>(*std::max_element(
input_data, input_data + input_numel)) +
1L;
output_size = std::max(output_size, minlength);
DDim out_dim{output_size};
output->Resize(out_dim);
bool has_weights = weights.is_initialized();
if (has_weights) {
const T* weights_data = weights->data<T>();
if (weights->dtype() == DataType::FLOAT32) {
float* output_data = dev_ctx.template Alloc<float>(output);
funcs::SetConstant<Context, float>()(
dev_ctx, output, static_cast<float>(0));
for (int64_t i = 0; i < input_numel; i++) {
output_data[input_data[i]] += static_cast<float>(weights_data[i]);
}
} else {
double* output_data = dev_ctx.template Alloc<double>(output);
funcs::SetConstant<Context, double>()(
dev_ctx, output, static_cast<double>(0));
for (int64_t i = 0; i < input_numel; i++) {
output_data[input_data[i]] += static_cast<double>(weights_data[i]);
}
}
} else {
int64_t* output_data = dev_ctx.template Alloc<int64_t>(output);
funcs::SetConstant<Context, int64_t>()(
dev_ctx, output, static_cast<int64_t>(0));
for (int64_t i = 0; i < input_numel; i++) {
output_data[input_data[i]] += 1L;
}
}
}
template <typename T, typename Context>
void BincountKernel(const Context& dev_ctx,
const DenseTensor& x,
const optional<DenseTensor>& weights,
const Scalar& minlength,
DenseTensor* out) {
int64_t int_minlength = minlength.to<int64_t>();
PADDLE_ENFORCE_GE(int_minlength,
0,
common::errors::InvalidArgument(
"The minlength should be greater than or equal to 0."
"But received minlength is %d",
int_minlength));
if (x.dtype() == DataType::INT32) {
BincountInner<Context, T, int>(dev_ctx, x, weights, int_minlength, out);
} else if (x.dtype() == DataType::INT64) {
BincountInner<Context, T, int64_t>(dev_ctx, x, weights, int_minlength, out);
}
}
} // namespace phi
PD_REGISTER_KERNEL(bincount,
CPU,
ALL_LAYOUT,
phi::BincountKernel,
float,
double,
int,
int64_t) {
kernel->OutputAt(0).SetDataType(phi::DataType::UNDEFINED);
}
+44
View File
@@ -0,0 +1,44 @@
// Copyright (c) 2023 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/binomial_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/binomial_functor.h"
namespace phi {
template <typename T, typename Context>
void BinomialKernel(const Context& dev_ctx,
const DenseTensor& count,
const DenseTensor& prob,
DenseTensor* out) {
auto numel = count.numel();
auto* count_data = count.data<T>();
auto* prob_data = prob.data<T>();
int64_t* out_data = dev_ctx.template Alloc<int64_t>(out);
for (int64_t i = 0; i < numel; ++i) {
out_data[i] =
funcs::BinomialFunctor<T>(dev_ctx, count_data[i], prob_data[i]);
}
}
} // namespace phi
PD_REGISTER_KERNEL(
binomial, CPU, ALL_LAYOUT, phi::BinomialKernel, float, double) {
kernel->OutputAt(0).SetDataType(phi::DataType::INT64);
}
@@ -0,0 +1,216 @@
// 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/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/math_function.h"
namespace phi {
template <class T>
bool DistPairDescend(std::tuple<int, int, T> pair1,
std::tuple<int, int, T> pair2) {
return std::get<2>(pair1) > std::get<2>(pair2);
}
// The match_indices must be initialized to -1 at first.
// The match_dist must be initialized to 0 at first.
template <typename T>
void BipartiteMatch(const DenseTensor& dist,
int* match_indices,
T* match_dist) {
PADDLE_ENFORCE_EQ(
dist.dims().size(),
2,
common::errors::InvalidArgument("The rank of dist must be 2."));
int64_t row = dist.dims()[0];
int64_t col = dist.dims()[1];
auto* dist_data = dist.data<T>();
// Test result: When row==130 the speed of these two methods almost the same
if (row >= 130) {
std::vector<std::tuple<int, int, T>> match_pair;
for (int64_t i = 0; i < row; ++i) {
for (int64_t j = 0; j < col; ++j) {
match_pair.push_back(std::make_tuple(i, j, dist_data[i * col + j]));
}
}
std::sort(match_pair.begin(), match_pair.end(), DistPairDescend<T>);
std::vector<int> row_indices(row, -1);
int64_t idx = 0;
for (int64_t k = 0; k < row * col; ++k) {
int64_t i = std::get<0>(match_pair[k]);
int64_t j = std::get<1>(match_pair[k]);
T dist = std::get<2>(match_pair[k]);
if (idx >= row) {
break;
}
if (match_indices[j] == -1 && row_indices[i] == -1 && dist > 0) {
match_indices[j] = static_cast<int>(i);
row_indices[i] = static_cast<int>(j);
match_dist[j] = dist;
idx += 1;
}
}
} else {
constexpr T kEPS = static_cast<T>(1e-6);
std::vector<int> row_pool;
for (int i = 0; i < row; ++i) {
row_pool.push_back(i);
}
while (!row_pool.empty()) {
int max_idx = -1;
int max_row_idx = -1;
T max_dist = -1;
for (int64_t j = 0; j < col; ++j) {
if (match_indices[j] != -1) {
continue;
}
for (auto m : row_pool) {
// distance is 0 between m-th row and j-th column
if (dist_data[m * col + j] < kEPS) {
continue;
}
if (dist_data[m * col + j] > max_dist) {
max_idx = static_cast<int>(j);
max_row_idx = m;
max_dist = dist_data[m * col + j];
}
}
}
if (max_idx == -1) {
// Cannot find good match.
break;
} else {
PADDLE_ENFORCE_EQ(
match_indices[max_idx],
-1,
common::errors::InvalidArgument(
"The match_indices must be initialized to -1 at [%d].",
max_idx));
match_indices[max_idx] = max_row_idx;
match_dist[max_idx] = max_dist;
// Erase the row index.
row_pool.erase(
std::find(row_pool.begin(), row_pool.end(), max_row_idx));
}
}
}
}
template <typename T>
void ArgMaxMatch(const DenseTensor& dist,
int* match_indices,
T* match_dist,
T overlap_threshold) {
constexpr T kEPS = static_cast<T>(1e-6);
int64_t row = dist.dims()[0];
int64_t col = dist.dims()[1];
auto* dist_data = dist.data<T>();
for (int64_t j = 0; j < col; ++j) {
if (match_indices[j] != -1) {
// the j-th column has been matched to one entity.
continue;
}
int max_row_idx = -1;
T max_dist = -1;
for (int i = 0; i < row; ++i) {
T dist = dist_data[i * col + j];
if (dist < kEPS) {
// distance is 0 between m-th row and j-th column
continue;
}
if (dist >= overlap_threshold && dist > max_dist) {
max_row_idx = i;
max_dist = dist;
}
}
if (max_row_idx != -1) {
PADDLE_ENFORCE_EQ(
match_indices[j],
-1,
common::errors::InvalidArgument(
"The match_indices must be initialized to -1 at [%d].", j));
match_indices[j] = max_row_idx;
match_dist[j] = max_dist;
}
}
}
template <typename T, typename Context>
void BipartiteMatchKernel(const Context& dev_ctx,
const DenseTensor& dist_mat_in,
const std::string& match_type,
float dist_threshold,
DenseTensor* col_to_row_match_indices,
DenseTensor* col_to_row_match_dist) {
auto* dist_mat = &dist_mat_in;
auto* match_indices = col_to_row_match_indices;
auto* match_dist = col_to_row_match_dist;
auto col = dist_mat->dims()[1];
int64_t n = dist_mat->lod().empty()
? 1
: static_cast<int64_t>(dist_mat->lod().back().size() - 1);
if (!dist_mat->lod().empty()) {
PADDLE_ENFORCE_EQ(
dist_mat->lod().size(),
1UL,
common::errors::InvalidArgument("Only support 1 level of LoD."));
}
match_indices->Resize({n, col});
dev_ctx.template Alloc<int>(match_indices);
match_dist->Resize({n, col});
dev_ctx.template Alloc<T>(match_dist);
funcs::SetConstant<CPUContext, int> iset;
iset(dev_ctx, match_indices, static_cast<int>(-1));
funcs::SetConstant<CPUContext, T> tset;
tset(dev_ctx, match_dist, static_cast<T>(0));
int* indices = match_indices->data<int>();
T* dist = match_dist->data<T>();
auto type = match_type;
auto threshold = dist_threshold;
if (n == 1) {
BipartiteMatch<T>(*dist_mat, indices, dist);
if (type == "per_prediction") {
ArgMaxMatch<T>(*dist_mat, indices, dist, threshold);
}
} else {
auto lod = dist_mat->lod().back();
for (size_t i = 0; i < lod.size() - 1; ++i) {
if (lod[i + 1] > lod[i]) {
DenseTensor one_ins = dist_mat->Slice(static_cast<int64_t>(lod[i]),
static_cast<int64_t>(lod[i + 1]));
BipartiteMatch<T>(one_ins, indices + i * col, dist + i * col);
if (type == "per_prediction") {
ArgMaxMatch<T>(one_ins, indices + i * col, dist + i * col, threshold);
}
}
}
}
}
} // namespace phi
PD_REGISTER_KERNEL(bipartite_match,
CPU,
ALL_LAYOUT,
phi::BipartiteMatchKernel,
float,
double) {
kernel->OutputAt(0).SetDataType(phi::DataType::INT32);
}
+157
View File
@@ -0,0 +1,157 @@
/* 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/bitwise_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/bitwise_functors.h"
#include "paddle/phi/kernels/funcs/elementwise_base.h"
#include "paddle/phi/common/transform.h"
namespace phi {
#define DEFINE_BITWISE_KERNEL(op_type) \
template <typename T, typename Context> \
void Bitwise##op_type##Kernel(const Context& dev_ctx, \
const DenseTensor& x, \
const DenseTensor& y, \
DenseTensor* out) { \
funcs::Bitwise##op_type##Functor<T> func; \
funcs::ElementwiseCompute<funcs::Bitwise##op_type##Functor<T>, T>( \
dev_ctx, x, y, func, out); \
}
DEFINE_BITWISE_KERNEL(And)
DEFINE_BITWISE_KERNEL(Or)
DEFINE_BITWISE_KERNEL(Xor)
#undef DEFINE_BITWISE_KERNEL
#define DEFINE_BITWISE_KERNEL_WITH_INVERSE(op_type) \
template <typename T, typename Context> \
void Bitwise##op_type##Kernel(const Context& dev_ctx, \
const DenseTensor& x, \
const DenseTensor& y, \
bool is_arithmetic, \
DenseTensor* out) { \
auto x_dims = x.dims(); \
auto y_dims = y.dims(); \
if (x_dims.size() >= y_dims.size()) { \
if (is_arithmetic) { \
funcs::Bitwise##op_type##ArithmeticFunctor<T> func; \
funcs::ElementwiseCompute< \
funcs::Bitwise##op_type##ArithmeticFunctor<T>, \
T>(dev_ctx, x, y, func, out); \
} else { \
funcs::Bitwise##op_type##LogicFunctor<T> func; \
funcs::ElementwiseCompute<funcs::Bitwise##op_type##LogicFunctor<T>, \
T>(dev_ctx, x, y, func, out); \
} \
} else { \
if (is_arithmetic) { \
funcs::InverseBitwise##op_type##ArithmeticFunctor<T> inv_func; \
funcs::ElementwiseCompute< \
funcs::InverseBitwise##op_type##ArithmeticFunctor<T>, \
T>(dev_ctx, x, y, inv_func, out); \
} else { \
funcs::InverseBitwise##op_type##LogicFunctor<T> inv_func; \
funcs::ElementwiseCompute< \
funcs::InverseBitwise##op_type##LogicFunctor<T>, \
T>(dev_ctx, x, y, inv_func, out); \
} \
} \
}
DEFINE_BITWISE_KERNEL_WITH_INVERSE(LeftShift)
DEFINE_BITWISE_KERNEL_WITH_INVERSE(RightShift)
#undef DEFINE_BITWISE_KERNEL_WITH_INVERSE
template <typename T, typename Context>
void BitwiseNotKernel(const Context& dev_ctx,
const DenseTensor& x,
DenseTensor* out) {
const T* x_data = x.data<T>();
T* out_data = dev_ctx.template Alloc<T>(out);
size_t numel = x.numel();
funcs::BitwiseNotFunctor<T> func;
Transform<Context> trans;
trans(dev_ctx, x_data, x_data + numel, out_data, func);
}
} // namespace phi
PD_REGISTER_KERNEL(bitwise_and,
CPU,
ALL_LAYOUT,
phi::BitwiseAndKernel,
bool,
uint8_t,
int8_t,
int16_t,
int,
int64_t) {}
PD_REGISTER_KERNEL(bitwise_or,
CPU,
ALL_LAYOUT,
phi::BitwiseOrKernel,
bool,
uint8_t,
int8_t,
int16_t,
int,
int64_t) {}
PD_REGISTER_KERNEL(bitwise_xor,
CPU,
ALL_LAYOUT,
phi::BitwiseXorKernel,
bool,
uint8_t,
int8_t,
int16_t,
int,
int64_t) {}
PD_REGISTER_KERNEL(bitwise_not,
CPU,
ALL_LAYOUT,
phi::BitwiseNotKernel,
bool,
uint8_t,
int8_t,
int16_t,
int,
int64_t) {}
PD_REGISTER_KERNEL(bitwise_left_shift,
CPU,
ALL_LAYOUT,
phi::BitwiseLeftShiftKernel,
uint8_t,
int8_t,
int16_t,
int,
int64_t) {}
PD_REGISTER_KERNEL(bitwise_right_shift,
CPU,
ALL_LAYOUT,
phi::BitwiseRightShiftKernel,
uint8_t,
int8_t,
int16_t,
int,
int64_t) {}
+22
View File
@@ -0,0 +1,22 @@
// 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/bmm_grad_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/bmm_grad_kernel_impl.h"
PD_REGISTER_KERNEL(
bmm_grad, CPU, ALL_LAYOUT, phi::BmmGradKernel, float, double) {}
+21
View File
@@ -0,0 +1,21 @@
// 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/bmm_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/bmm_kernel_impl.h"
PD_REGISTER_KERNEL(bmm, CPU, ALL_LAYOUT, phi::BmmKernel, float, double) {}
+19
View File
@@ -0,0 +1,19 @@
// 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/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/box_clip_kernel_impl.h"
PD_REGISTER_KERNEL(
box_clip, CPU, ALL_LAYOUT, phi::BoxClipKernel, float, double) {}
+288
View File
@@ -0,0 +1,288 @@
// 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/box_coder_kernel.h"
#include <array>
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/full_kernel.h"
#include "paddle/phi/kernels/funcs/math_function.h"
#include "paddle/phi/kernels/impl/box_coder.h"
namespace phi {
template <typename T>
void EncodeCenterSize(const DenseTensor *target_box,
const DenseTensor *prior_box,
const DenseTensor *prior_box_var,
const bool normalized,
const std::vector<float> variance,
T *output) {
int64_t row = target_box->dims()[0];
int64_t col = prior_box->dims()[0];
int64_t len = prior_box->dims()[1];
#ifdef PADDLE_WITH_MKLML
#pragma omp parallel for collapse(2)
#endif
for (int64_t i = 0; i < row; ++i) {
for (int64_t j = 0; j < col; ++j) {
auto *target_box_data = target_box->data<T>();
auto *prior_box_data = prior_box->data<T>();
size_t offset = i * col * len + j * len;
T prior_box_width = prior_box_data[j * len + 2] -
prior_box_data[j * len] + (normalized == false);
T prior_box_height = prior_box_data[j * len + 3] -
prior_box_data[j * len + 1] + (normalized == false);
T prior_box_center_x = prior_box_data[j * len] + prior_box_width / 2;
T prior_box_center_y = prior_box_data[j * len + 1] + prior_box_height / 2;
T target_box_center_x =
(target_box_data[i * len + 2] + target_box_data[i * len]) / 2;
T target_box_center_y =
(target_box_data[i * len + 3] + target_box_data[i * len + 1]) / 2;
T target_box_width = target_box_data[i * len + 2] -
target_box_data[i * len] + (normalized == false);
T target_box_height = target_box_data[i * len + 3] -
target_box_data[i * len + 1] +
(normalized == false);
output[offset] =
(target_box_center_x - prior_box_center_x) / prior_box_width;
output[offset + 1] =
(target_box_center_y - prior_box_center_y) / prior_box_height;
output[offset + 2] =
std::log(std::fabs(target_box_width / prior_box_width));
output[offset + 3] =
std::log(std::fabs(target_box_height / prior_box_height));
}
}
if (prior_box_var) {
const T *prior_box_var_data = prior_box_var->data<T>();
#ifdef PADDLE_WITH_MKLML
#pragma omp parallel for collapse(3)
#endif
for (int64_t i = 0; i < row; ++i) {
for (int64_t j = 0; j < col; ++j) {
for (int k = 0; k < 4; ++k) {
size_t offset = i * col * len + j * len;
int prior_var_offset = static_cast<int>(j * len);
output[offset + k] /= prior_box_var_data[prior_var_offset + k];
}
}
}
} else if (!(variance.empty())) {
#ifdef PADDLE_WITH_MKLML
#pragma omp parallel for collapse(3)
#endif
for (int64_t i = 0; i < row; ++i) {
for (int64_t j = 0; j < col; ++j) {
for (int k = 0; k < 4; ++k) {
size_t offset = i * col * len + j * len;
output[offset + k] /= static_cast<T>(variance[k]);
}
}
}
}
}
template <typename T, int axis, int var_size>
void DecodeCenterSize(const DenseTensor *target_box,
const DenseTensor *prior_box,
const DenseTensor *prior_box_var,
const bool normalized,
std::vector<float> variance,
T *output) {
int64_t row = target_box->dims()[0];
int64_t col = target_box->dims()[1];
int64_t len = target_box->dims()[2];
#ifdef PADDLE_WITH_MKLML
#pragma omp parallel for collapse(2)
#endif
for (int64_t i = 0; i < row; ++i) {
for (int64_t j = 0; j < col; ++j) {
auto *target_box_data = target_box->data<T>();
auto *prior_box_data = prior_box->data<T>();
std::array<T, 4> var_data{1., 1., 1., 1.};
T *var_ptr = var_data.data();
size_t offset = i * col * len + j * len;
int prior_box_offset = axis == 0 ? j * len : i * len;
T prior_box_width = prior_box_data[prior_box_offset + 2] -
prior_box_data[prior_box_offset] +
(normalized == false);
T prior_box_height = prior_box_data[prior_box_offset + 3] -
prior_box_data[prior_box_offset + 1] +
(normalized == false);
T prior_box_center_x =
prior_box_data[prior_box_offset] + prior_box_width / 2;
T prior_box_center_y =
prior_box_data[prior_box_offset + 1] + prior_box_height / 2;
T target_box_center_x = 0, target_box_center_y = 0;
T target_box_width = 0, target_box_height = 0;
int prior_var_offset = axis == 0 ? j * len : i * len;
if (var_size == 2) {
std::memcpy(var_ptr,
prior_box_var->data<T>() + prior_var_offset,
4 * sizeof(T));
} else if (var_size == 1) {
var_ptr = reinterpret_cast<T *>(variance.data());
}
T box_var_x = *var_ptr;
T box_var_y = *(var_ptr + 1);
T box_var_w = *(var_ptr + 2);
T box_var_h = *(var_ptr + 3);
target_box_center_x =
box_var_x * target_box_data[offset] * prior_box_width +
prior_box_center_x;
target_box_center_y =
box_var_y * target_box_data[offset + 1] * prior_box_height +
prior_box_center_y;
target_box_width =
std::exp(box_var_w * target_box_data[offset + 2]) * prior_box_width;
target_box_height =
std::exp(box_var_h * target_box_data[offset + 3]) * prior_box_height;
output[offset] = target_box_center_x - target_box_width / 2;
output[offset + 1] = target_box_center_y - target_box_height / 2;
output[offset + 2] =
target_box_center_x + target_box_width / 2 - (normalized == false);
output[offset + 3] =
target_box_center_y + target_box_height / 2 - (normalized == false);
}
}
}
template <typename T, typename Context>
void BoxCoderKernel(const Context &dev_ctx,
const DenseTensor &prior_box,
const optional<DenseTensor> &prior_box_var,
const DenseTensor &target_box,
const std::string &code_type_str,
bool normalized,
int axis,
const std::vector<float> &variance,
DenseTensor *output_box) {
// prior_box and prior_box_var have the same shape, so do not judge
// prior_box_var
if (prior_box.numel() == 0 || target_box.numel() == 0) {
Full<T, Context>(dev_ctx, output_box->dims(), 0, output_box);
return;
}
if (!target_box.lod().empty()) {
PADDLE_ENFORCE_EQ(target_box.lod().size(),
1UL,
common::errors::InvalidArgument(
"Input(TargetBox) of BoxCoder operator "
"supports LoD with only one level. But received "
"level = %d",
target_box.lod().size()));
}
if (prior_box_var) {
PADDLE_ENFORCE_EQ(variance.empty(),
true,
common::errors::InvalidArgument(
"Input 'PriorBoxVar' and attribute 'variance' "
"of BoxCoder operator should not be used at the "
"same time."));
}
if (!(variance.empty())) {
PADDLE_ENFORCE_EQ(static_cast<int>(variance.size()),
4,
common::errors::InvalidArgument(
"Size of attribute 'variance' of BoxCoder "
"operator should be 4. But received "
"size = %d",
variance.size()));
}
auto code_type = funcs::GetBoxCodeType(code_type_str);
auto row = target_box.dims()[0];
auto col = prior_box.dims()[0];
if (code_type == funcs::BoxCodeType::kDecodeCenterSize) {
col = target_box.dims()[1];
}
auto len = prior_box.dims()[1];
output_box->Resize({row, col, len});
dev_ctx.template Alloc<T>(output_box);
T *output = output_box->data<T>();
if (code_type == funcs::BoxCodeType::kEncodeCenterSize) {
EncodeCenterSize<T>(&target_box,
&prior_box,
prior_box_var.get_ptr(),
normalized,
variance,
output);
} else if (code_type == funcs::BoxCodeType::kDecodeCenterSize) {
if (prior_box_var) {
if (axis == 0) {
DecodeCenterSize<T, 0, 2>(&target_box,
&prior_box,
prior_box_var.get_ptr(),
normalized,
variance,
output);
} else {
DecodeCenterSize<T, 1, 2>(&target_box,
&prior_box,
prior_box_var.get_ptr(),
normalized,
variance,
output);
}
} else if (!(variance.empty())) {
if (axis == 0) {
DecodeCenterSize<T, 0, 1>(&target_box,
&prior_box,
prior_box_var.get_ptr(),
normalized,
variance,
output);
} else {
DecodeCenterSize<T, 1, 1>(&target_box,
&prior_box,
prior_box_var.get_ptr(),
normalized,
variance,
output);
}
} else {
if (axis == 0) {
DecodeCenterSize<T, 0, 0>(&target_box,
&prior_box,
prior_box_var.get_ptr(),
normalized,
variance,
output);
} else {
DecodeCenterSize<T, 1, 0>(&target_box,
&prior_box,
prior_box_var.get_ptr(),
normalized,
variance,
output);
}
}
}
}
} // namespace phi
PD_REGISTER_KERNEL(
box_coder, CPU, ALL_LAYOUT, phi::BoxCoderKernel, float, double) {}
@@ -0,0 +1,68 @@
// Copyright (c) 2023 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/broadcast_kernel.h"
#include "paddle/phi/backends/all_context.h"
#include "paddle/phi/core/kernel_registry.h"
#if defined(PADDLE_WITH_GLOO)
#include "paddle/phi/core/distributed/gloo_comm_context.h"
#endif
namespace phi {
template <typename T, typename Context>
void BroadcastKernel(const Context& dev_ctx,
const DenseTensor& x,
int root,
DenseTensor* out) {
PADDLE_ENFORCE_GT(x.numel(),
0,
common::errors::InvalidArgument(
"Tensor need be broadcast must not empty."));
#if defined(PADDLE_WITH_GLOO)
dev_ctx.template Alloc<T>(out);
auto comm_context =
static_cast<distributed::GlooCommContext*>(dev_ctx.GetCommContext());
PADDLE_ENFORCE_NE(
comm_context,
nullptr,
errors::Unavailable("NCCLCommContext is nullptr, collective op should "
"has ring_id attr."));
comm_context->Broadcast(out, x, root);
#else
PADDLE_THROW(errors::Unavailable(
"PaddlePaddle should compile with GLOO by setting WITH_GLOO=ON"));
#endif
}
} // namespace phi
PD_REGISTER_KERNEL(broadcast,
CPU,
ALL_LAYOUT,
phi::BroadcastKernel,
float,
double,
int,
bool,
int8_t,
uint8_t,
int16_t,
int64_t,
phi::float16,
phi::complex64,
phi::complex128) {}
@@ -0,0 +1,209 @@
// 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/broadcast_tensors_grad_kernel.h"
#include <vector>
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/enforce.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/full_kernel.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
#include "paddle/phi/kernels/funcs/eigen/eigen_function.h"
#include "paddle/phi/kernels/funcs/math_function.h"
#define SWITCH_RESHAPE_DIMS(n) \
case n: { \
Eigen::DSizes<int64_t, n> reshape_dims; \
for (size_t i = 0; i < reshape_dims_vec.size(); ++i) { \
reshape_dims[i] = reshape_dims_vec[i]; \
} \
dX.device(place) = \
dOut.reshape(reshape_dims).sum(reduce_dims).reshape(dX.dimensions()); \
break; \
}
#define UPPER_SWITCH_REDUCE_DIMS(m) \
case m: { \
Eigen::DSizes<int64_t, m> reduce_dims; \
for (size_t i = 0; i < reduce_dims_vec.size(); ++i) { \
reduce_dims[i] = reduce_dims_vec[i]; \
} \
switch (reshape_size) {
#define LOWER_SWITCH_REDUCE_DIMS \
default: { \
PADDLE_THROW(errors::InvalidArgument( \
"Detected reshape size: %d out of range. " \
"Minimum value should be larger than reduce size %d. " \
"While maximum supported is: 5", \
reshape_size, \
reduce_size)); \
} \
} \
break; \
}
namespace phi {
template <typename T, typename Context>
void BroadcastTensorsGradKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& inputs,
const std::vector<const DenseTensor*>& dout,
std::vector<DenseTensor*> dx) {
(void)inputs;
// Find reduce dimensions
const auto& in_tensors = dout;
auto& out_tensors = dx;
size_t num_ins = in_tensors.size();
if (dout[0] && dout[0]->numel() == 0) {
for (auto dx : out_tensors) {
if (dx) Full<T, Context>(dev_ctx, dx->dims(), 0, dx);
}
return;
}
PADDLE_ENFORCE_GT(
num_ins,
1,
errors::InvalidArgument(
"Expected at least 2 input tensors, but only received %d.",
in_tensors.size()));
PADDLE_ENFORCE_EQ(num_ins,
out_tensors.size(),
errors::InvalidArgument(
"BroadcastTensorsOp expects equal number of inputs and "
"outputs, but received: %d inputs v.s %d outputs",
num_ins,
out_tensors.size()));
// For each In-Out tensor pair,
// Prepare and apply broadcast dims array
for (size_t i = 0; i < num_ins; i++) {
const auto* input_tensor = in_tensors[i];
auto* output_tensor = out_tensors[i];
const auto& input_dims = input_tensor->dims();
const auto& output_dims = output_tensor->dims();
int in_rank = input_dims.size();
int out_rank = output_dims.size();
// BroadcastTensorsGrad is simply a reduce_sum along broadcasted axes
// Here we perform the following Eigen operations:
// dOut(Flattened) -> reshape(reshape_dims) -> reduce(reduce_dims) ->
// reshape(dX_shape) -> dX
// Note the last "reshape(dX_shape)" will be performed implicitly,
// and we only need to collect reduce_dims and reshape_dims
std::vector<int> reduce_dims_vec;
std::vector<int> reshape_dims_vec;
for (int j = 0; j < in_rank; j++) {
int out_axis = out_rank - j - 1;
int in_axis = in_rank - j - 1;
reshape_dims_vec.push_back(static_cast<int>(input_dims[j]));
if (out_axis < 0 || output_dims[out_axis] != input_dims[in_axis]) {
reduce_dims_vec.push_back(in_axis);
}
}
size_t reduce_size = reduce_dims_vec.size();
size_t reshape_size = reshape_dims_vec.size();
bool just_copy = (reduce_dims_vec.empty());
dev_ctx.template Alloc<T>(output_tensor);
if (just_copy) {
// If this turns out to be a No-Op, simply perform a tensor copy
Copy(dev_ctx, *input_tensor, dev_ctx.GetPlace(), false, output_tensor);
} else {
PADDLE_ENFORCE_GE(
reduce_dims_vec.size(),
1,
errors::InvalidArgument("The number of dimensions of the input "
"'Out@GRAD' for Op(broadcast_tensors)"
" must be greater than or equal to 1, but "
"the value received is %d.",
reduce_dims_vec.size()));
PADDLE_ENFORCE_LE(
reduce_dims_vec.size(),
5,
errors::InvalidArgument(
"The number of dimensions of the input 'Out@GRAD' "
"for Op(broadcast_tensors) must be less than or equal "
"to 5, but the value received is %d.",
reduce_dims_vec.size()));
// Overall:
// dOut(Flattened) -> reshape(reshape_dims) -> reduce(reduce_dims) ->
// reshape(dX_shape) -> dX
auto dX = EigenVector<T>::Flatten(*output_tensor);
auto dOut = EigenVector<T>::Flatten(*input_tensor);
auto& place = *dev_ctx.eigen_device();
// Expand ReduceSize and ReshapeSize into static values
switch (reduce_size) {
UPPER_SWITCH_REDUCE_DIMS(1)
SWITCH_RESHAPE_DIMS(1)
SWITCH_RESHAPE_DIMS(2)
SWITCH_RESHAPE_DIMS(3)
SWITCH_RESHAPE_DIMS(4)
SWITCH_RESHAPE_DIMS(5)
LOWER_SWITCH_REDUCE_DIMS
UPPER_SWITCH_REDUCE_DIMS(2)
SWITCH_RESHAPE_DIMS(2)
SWITCH_RESHAPE_DIMS(3)
SWITCH_RESHAPE_DIMS(4)
SWITCH_RESHAPE_DIMS(5)
LOWER_SWITCH_REDUCE_DIMS
UPPER_SWITCH_REDUCE_DIMS(3)
SWITCH_RESHAPE_DIMS(3)
SWITCH_RESHAPE_DIMS(4)
SWITCH_RESHAPE_DIMS(5)
LOWER_SWITCH_REDUCE_DIMS
UPPER_SWITCH_REDUCE_DIMS(4)
SWITCH_RESHAPE_DIMS(4)
SWITCH_RESHAPE_DIMS(5)
LOWER_SWITCH_REDUCE_DIMS
UPPER_SWITCH_REDUCE_DIMS(5)
SWITCH_RESHAPE_DIMS(5)
LOWER_SWITCH_REDUCE_DIMS
default: {
PADDLE_THROW(
errors::InvalidArgument("Detected reduce size: %d out of range. "
"While maximum supported is: 5",
reduce_size));
}
}
}
}
}
} // namespace phi
PD_REGISTER_KERNEL(broadcast_tensors_grad,
CPU,
ALL_LAYOUT,
phi::BroadcastTensorsGradKernel,
int,
int64_t,
float,
double,
phi::float16,
phi::complex64,
phi::complex128) {}
@@ -0,0 +1,31 @@
// 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/broadcast_tensors_kernel.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/broadcast_tensors_kernel_impl.h"
PD_REGISTER_KERNEL(broadcast_tensors,
CPU,
ALL_LAYOUT,
phi::BroadcastTensorsKernel,
bool,
int,
int64_t,
float,
double,
phi::float16,
phi::complex64,
phi::complex128) {}
+44
View File
@@ -0,0 +1,44 @@
// 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/c_concat_kernel.h"
#include "paddle/phi/core/kernel_registry.h"
namespace phi {
template <typename T, typename Context>
void CConcatKernel(const Context &dev_ctx UNUSED,
const DenseTensor &x UNUSED,
int rank UNUSED,
int nranks UNUSED,
int ring_id UNUSED,
bool use_calc_stream UNUSED,
bool use_model_parallel UNUSED,
DenseTensor *out UNUSED) {
PADDLE_THROW(common::errors::Unavailable(
"Do not support c_concat for cpu kernel now."));
}
} // namespace phi
PD_REGISTER_KERNEL(c_concat,
CPU,
ALL_LAYOUT,
phi::CConcatKernel,
float,
double,
int,
int64_t,
phi::float16) {}
@@ -0,0 +1,101 @@
// Copyright (c) 2023 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/c_embedding_grad_kernel.h"
#include "glog/logging.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
namespace phi {
template <typename TIds, typename TData>
void UpdateEmbedding(const TIds* ids,
size_t ids_len,
int64_t start_idx,
TData* table,
int64_t height,
int64_t width,
const TData* out) {
for (size_t i = 0; i < ids_len; i++) {
TIds id = ids[i];
int64_t local = id - start_idx;
if (local >= 0 && local < height) {
for (int64_t w = 0; w < width; w++) {
table[local * width + w] += out[i * width + w];
}
}
}
}
template <typename T, typename Context>
void CEmbeddingGradKernel(const Context& dev_ctx,
const DenseTensor& w,
const DenseTensor& ids,
const DenseTensor& out_grad,
int64_t start_index,
DenseTensor* w_grad) {
w_grad->Resize(w.dims());
T* table_grad_data = dev_ctx.template Alloc<T>(w_grad);
size_t table_t_mem_size = w.numel() * sizeof(w_grad->dtype());
size_t table_grad_t_mem_size = w_grad->numel() * sizeof(w_grad->dtype());
VLOG(10) << "table_dims:" << w.dims()
<< ", table_t memory_size:" << table_t_mem_size
<< ", table_grad_t memory_size:" << table_grad_t_mem_size
<< ", start_index:" << start_index;
memset(table_grad_data, 0, table_grad_t_mem_size);
const T* d_output_data = out_grad.data<T>();
const int64_t height = w.dims()[0];
const int64_t width = w.dims()[1];
const auto& index_type = ids.dtype();
if (index_type == DataType::INT32) {
UpdateEmbedding(ids.data<int32_t>(),
ids.numel(),
start_index,
table_grad_data,
height,
width,
d_output_data);
} else if (index_type == DataType::INT64) {
UpdateEmbedding(ids.data<int64_t>(),
ids.numel(),
start_index,
table_grad_data,
height,
width,
d_output_data);
} else {
PADDLE_THROW(common::errors::Unavailable(
"CPU c_embedding ids only support int32 or int64."));
}
}
} // namespace phi
PD_REGISTER_KERNEL(c_embedding_grad,
CPU,
ALL_LAYOUT,
phi::CEmbeddingGradKernel,
float,
double,
phi::float16,
phi::complex64,
phi::complex128) {}
@@ -0,0 +1,90 @@
// Copyright (c) 2023 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/c_embedding_kernel.h"
#include "glog/logging.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
namespace phi {
template <typename TIds, typename TData>
void GetIdsEmbedding(const TIds* ids,
size_t ids_len,
int64_t start_idx,
const TData* table,
int64_t height,
int64_t width,
TData* out) {
for (size_t i = 0; i < ids_len; i++) {
TIds id = ids[i];
int64_t local = id - start_idx;
if (local >= 0 && local < height) {
memcpy(out + i * width, table + local * width, width * sizeof(TData));
} else {
memset(out + i * width, 0, width * sizeof(TData));
}
}
}
template <typename T, typename Context>
void CEmbeddingKernel(const Context& dev_ctx,
const DenseTensor& w,
const DenseTensor& ids,
int64_t start_index,
int64_t vocab_size,
DenseTensor* out) {
VLOG(10) << "table_dims:" << w.dims();
const T* table_data = w.data<T>();
T* output_data = dev_ctx.template Alloc<T>(out);
const int64_t height = w.dims()[0];
const int64_t width = w.dims()[1];
const auto& index_type = ids.dtype();
if (index_type == DataType::INT32) {
GetIdsEmbedding(ids.data<int32_t>(),
ids.numel(),
start_index,
table_data,
height,
width,
output_data);
} else if (index_type == DataType::INT64) {
GetIdsEmbedding(ids.data<int64_t>(),
ids.numel(),
start_index,
table_data,
height,
width,
output_data);
} else {
PADDLE_THROW(common::errors::Unavailable(
"CPU c_embedding ids only support int32 or int64."));
}
}
} // namespace phi
PD_REGISTER_KERNEL(c_embedding,
CPU,
ALL_LAYOUT,
phi::CEmbeddingKernel,
float,
double,
phi::float16,
phi::complex64,
phi::complex128) {}
@@ -0,0 +1,43 @@
/* Copyright (c) 2023 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/c_identity_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
namespace phi {
template <typename T, typename Context>
void CIdentityKernel(const Context& dev_ctx,
const DenseTensor& x,
int ring_id,
bool use_calc_stream,
bool use_model_parallel,
DenseTensor* out) {
PADDLE_THROW(
errors::Unavailable("Do not support c_identity for cpu kernel now."));
}
} // namespace phi
PD_REGISTER_KERNEL(c_identity,
CPU,
ALL_LAYOUT,
phi::CIdentityKernel,
float,
double,
int,
int64_t,
phi::float16) {}
@@ -0,0 +1,63 @@
// 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 <algorithm>
#include <utility>
#include <vector>
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/kernel_registry.h"
#if defined(PADDLE_WITH_GLOO)
#include "paddle/phi/core/distributed/gloo_comm_context.h"
#endif
namespace phi {
template <typename T, typename Context>
void CScatterOpCPUKernel(const Context &dev_ctx,
const DenseTensor &x,
int ring_id,
int root,
int nranks,
bool use_calc_stream,
DenseTensor *out) {
#if defined(PADDLE_WITH_GLOO)
auto in = &x;
auto root_id = root;
auto comm_ctx =
static_cast<distributed::GlooCommContext *>(dev_ctx.GetCommContext());
PADDLE_ENFORCE_NE(comm_ctx,
nullptr,
::common::errors::Unavailable(
"NCCLCommContext is nullptr, collective op should "
"has ring_id attr."));
comm_ctx->Scatter(out, *in, root_id);
#else
PADDLE_THROW(common::errors::Unavailable(
"PaddlePaddle should compile with GLOO by setting WITH_GLOO=ON"));
#endif
}
} // namespace phi
PD_REGISTER_KERNEL(c_scatter,
CPU,
ALL_LAYOUT,
phi::CScatterOpCPUKernel,
float,
double,
int,
int64_t,
phi::float16) {}
@@ -0,0 +1,40 @@
// 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/core/dense_tensor.h"
#include "paddle/phi/core/kernel_registry.h"
namespace phi {
template <typename T, typename Context>
void CSoftmaxWithCrossEntropyKernel(const Context &dev_ctx UNUSED,
const DenseTensor &logits UNUSED,
const DenseTensor &label UNUSED,
int64_t ignore_index UNUSED,
int rank UNUSED,
int nranks UNUSED,
DenseTensor *softmax UNUSED,
DenseTensor *loss UNUSED) {
PADDLE_THROW(common::errors::Unavailable(
"Do not support c_softmax_with_cross_entropy for cpu kernel now."));
}
} // namespace phi
PD_REGISTER_KERNEL(c_softmax_with_cross_entropy,
CPU,
ALL_LAYOUT,
phi::CSoftmaxWithCrossEntropyKernel,
float,
double,
phi::float16) {}
@@ -0,0 +1,44 @@
// 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/core/dense_tensor.h"
#include "paddle/phi/core/kernel_registry.h"
namespace phi {
template <typename T, typename Context>
void CSoftmaxWithMultiLabelCrossEntropyKernel(const Context &dev_ctx UNUSED,
const DenseTensor &logits UNUSED,
const DenseTensor &label UNUSED,
const DenseTensor &smooth_weight
UNUSED,
int64_t ignore_index UNUSED,
bool sum_multi_label_loss UNUSED,
int rank UNUSED,
int nranks UNUSED,
DenseTensor *softmax UNUSED,
DenseTensor *loss UNUSED) {
PADDLE_THROW(common::errors::Unavailable(
"Do not support c_softmax_with_multi_label_cross_entropy for cpu kernel "
"now."));
}
} // namespace phi
PD_REGISTER_KERNEL(c_softmax_with_multi_label_cross_entropy,
CPU,
ALL_LAYOUT,
phi::CSoftmaxWithMultiLabelCrossEntropyKernel,
float,
double,
phi::float16) {}
+41
View File
@@ -0,0 +1,41 @@
// Copyright (c) 2023 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/c_split_kernel.h"
#include "paddle/phi/core/kernel_registry.h"
namespace phi {
template <typename T, typename Context>
void CSplitKernel(const Context& dev_ctx,
const DenseTensor& x,
int rank,
int nranks,
bool use_model_parallel,
DenseTensor* out) {
PADDLE_THROW(common::errors::Unavailable(
"Do not support c_split for cpu kernel now."));
}
} // namespace phi
PD_REGISTER_KERNEL(c_split,
CPU,
ALL_LAYOUT,
phi::CSplitKernel,
float,
double,
int,
int64_t,
phi::float16) {}
+128
View File
@@ -0,0 +1,128 @@
// 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/backends/cpu/cpu_context.h"
#include "paddle/phi/common/transform.h"
namespace phi {
template <typename InT, typename OutT>
struct CastOpTransformFunctor {
HOSTDEVICE OutT operator()(InT in) const { return static_cast<OutT>(in); }
};
template <>
struct CastOpTransformFunctor<::phi::dtype::float8_e5m2, ::phi::complex64> {
HOSTDEVICE ::phi::complex64 operator()(::phi::dtype::float8_e5m2 in) const {
return ::phi::complex64(static_cast<float>(in));
}
};
template <>
struct CastOpTransformFunctor<::phi::dtype::float8_e5m2, ::phi::complex128> {
HOSTDEVICE ::phi::complex128 operator()(::phi::dtype::float8_e5m2 in) const {
return ::phi::complex128(static_cast<double>(in));
}
};
template <>
struct CastOpTransformFunctor<::phi::dtype::float8_e4m3fn, ::phi::complex64> {
HOSTDEVICE ::phi::complex64 operator()(::phi::dtype::float8_e4m3fn in) const {
return ::phi::complex64(static_cast<float>(in));
}
};
template <>
struct CastOpTransformFunctor<::phi::dtype::float8_e4m3fn, ::phi::complex128> {
HOSTDEVICE ::phi::complex128 operator()(
::phi::dtype::float8_e4m3fn in) const {
return ::phi::complex128(static_cast<double>(in));
}
};
template <>
struct CastOpTransformFunctor<::phi::dtype::bfloat16, ::phi::complex64> {
HOSTDEVICE ::phi::complex64 operator()(::phi::dtype::bfloat16 in) const {
return ::phi::complex64(static_cast<float>(in));
}
};
template <>
struct CastOpTransformFunctor<::phi::dtype::bfloat16, ::phi::complex128> {
HOSTDEVICE ::phi::complex128 operator()(::phi::dtype::bfloat16 in) const {
return ::phi::complex128(static_cast<double>(in));
}
};
template <>
struct CastOpTransformFunctor<::phi::dtype::float16, ::phi::complex64> {
HOSTDEVICE ::phi::complex64 operator()(::phi::dtype::float16 in) const {
return ::phi::complex64(static_cast<float>(in));
}
};
template <>
struct CastOpTransformFunctor<::phi::dtype::float16, ::phi::complex128> {
HOSTDEVICE ::phi::complex128 operator()(::phi::dtype::float16 in) const {
return ::phi::complex128(static_cast<double>(in));
}
};
template <typename InT, typename OutT>
void CastKernelImpl(const CPUContext& dev_ctx,
const DenseTensor& x,
DataType out_dtype,
DenseTensor* out) {
auto* in_begin = x.data<InT>();
auto numel = x.numel();
auto* in_end = in_begin + numel;
auto* out_begin = dev_ctx.Alloc<OutT>(out);
out->set_type(out_dtype);
phi::Transform<CPUContext> trans;
trans(dev_ctx,
in_begin,
in_end,
out_begin,
CastOpTransformFunctor<InT, OutT>());
}
template <typename InT, typename OutT>
void CastInplaceKernelImpl(const CPUContext& dev_ctx,
const DenseTensor& x,
DataType out_dtype,
DenseTensor* out) {
auto numel = x.numel();
auto* in_begin = new InT[numel];
auto* in_end = in_begin + numel;
auto* data_origin = x.data<InT>();
memcpy(in_begin, data_origin, sizeof(InT) * numel);
auto* out_begin = dev_ctx.Alloc<OutT>(out);
out->set_type(out_dtype);
phi::Transform<CPUContext> trans;
trans(dev_ctx,
in_begin,
in_end,
out_begin,
CastOpTransformFunctor<InT, OutT>());
delete[] in_begin;
}
} // namespace phi
+89
View File
@@ -0,0 +1,89 @@
// Copyright (c) 2021 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/core/kernel_registry.h"
#include "paddle/phi/core/visit_type.h"
#include "paddle/phi/kernels/cpu/cast_impl.h"
namespace phi {
template <typename T, typename Context>
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;
}
if (out->IsSharedWith(x)) {
PD_VISIT_ALL_CPU_TYPES(out_dtype, "CastInplaceKernelImpl", ([&] {
CastInplaceKernelImpl<T, data_t>(
dev_ctx, x, out_dtype, out);
}));
} else {
PD_VISIT_ALL_CPU_TYPES(out_dtype, "CastKernelImpl", ([&] {
CastKernelImpl<T, data_t>(
dev_ctx, x, out_dtype, out);
}));
}
}
#ifdef _WIN32
INSTANTIATE_CAST_KERNEL(float, CPUContext)
INSTANTIATE_CAST_KERNEL(double, CPUContext)
INSTANTIATE_CAST_KERNEL(int, CPUContext)
INSTANTIATE_CAST_KERNEL(int64_t, CPUContext)
INSTANTIATE_CAST_KERNEL(uint8_t, CPUContext)
INSTANTIATE_CAST_KERNEL(uint16_t, CPUContext)
INSTANTIATE_CAST_KERNEL(uint32_t, CPUContext)
INSTANTIATE_CAST_KERNEL(uint64_t, CPUContext)
INSTANTIATE_CAST_KERNEL(bool, CPUContext)
INSTANTIATE_CAST_KERNEL(int16_t, CPUContext)
INSTANTIATE_CAST_KERNEL(float16, CPUContext)
INSTANTIATE_CAST_KERNEL(bfloat16, CPUContext)
#endif
} // namespace phi
PD_REGISTER_KERNEL(cast,
CPU,
ALL_LAYOUT,
phi::CastKernel,
float,
double,
int,
int64_t,
int16_t,
bool,
int8_t,
uint8_t,
uint16_t,
uint32_t,
uint64_t,
phi::float8_e4m3fn,
phi::float8_e5m2,
phi::float16,
phi::bfloat16,
phi::complex64,
phi::complex128) {
kernel->OutputAt(0).SetDataType(phi::DataType::UNDEFINED);
}
@@ -0,0 +1,26 @@
// 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/channel_shuffle_grad_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h"
PD_REGISTER_KERNEL(channel_shuffle_grad,
CPU,
ALL_LAYOUT,
phi::ChannelShuffleGradKernel,
float,
double) {}
@@ -0,0 +1,26 @@
// 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/channel_shuffle_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h"
PD_REGISTER_KERNEL(channel_shuffle,
CPU,
ALL_LAYOUT,
phi::ChannelShuffleKernel,
float,
double) {}
@@ -0,0 +1,85 @@
/* Copyright (c) 2023 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/check_numerics_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/check_numerics_utils.h"
namespace phi {
template <typename T, typename Context>
void CheckNumericsKernel(const Context& dev_ctx,
const DenseTensor& tensor,
const std::string& op_type,
const std::string& var_name,
const int check_nan_inf_level,
const int stack_height_limit,
const std::string& output_dir,
DenseTensor* stats,
DenseTensor* values) {
// stats stores the checking result of num_nan, num_inf and num_zero.
stats->Resize({static_cast<int64_t>(3)});
int64_t* stats_ptr = dev_ctx.template Alloc<int64_t>(stats);
// values stores the max_value, min_value and mean_value.
values->Resize({static_cast<int64_t>(3)});
float* values_ptr = dev_ctx.template Alloc<float>(values);
if (tensor.numel() == 0) {
stats_ptr[0] = 0;
stats_ptr[1] = 0;
stats_ptr[2] = 0;
values_ptr[0] = static_cast<float>(0);
values_ptr[1] = static_cast<float>(0);
values_ptr[2] = static_cast<float>(0);
return;
}
std::string cpu_hint_str =
funcs::GetCpuHintString<T>(op_type, var_name, tensor.place());
funcs::CheckNumericsCpuImpl(tensor.data<T>(),
tensor.numel(),
cpu_hint_str,
check_nan_inf_level,
"cpu",
output_dir,
stats_ptr,
values_ptr);
}
#ifdef _WIN32
INSTANTIATE_CHECKNUMBERICS_KERNEL(float, CPUContext)
INSTANTIATE_CHECKNUMBERICS_KERNEL(double, CPUContext)
INSTANTIATE_CHECKNUMBERICS_KERNEL(float16, CPUContext)
INSTANTIATE_CHECKNUMBERICS_KERNEL(bfloat16, CPUContext)
INSTANTIATE_CHECKNUMBERICS_KERNEL(complex64, CPUContext)
INSTANTIATE_CHECKNUMBERICS_KERNEL(complex128, CPUContext)
INSTANTIATE_CHECKNUMBERICS_KERNEL(float8_e4m3fn, CPUContext)
INSTANTIATE_CHECKNUMBERICS_KERNEL(float8_e5m2, CPUContext)
#endif
} // namespace phi
PD_REGISTER_KERNEL(check_numerics,
CPU,
ALL_LAYOUT,
phi::CheckNumericsKernel,
float,
double,
phi::float16,
phi::bfloat16,
phi::complex64,
phi::complex128,
phi::float8_e4m3fn,
phi::float8_e5m2) {}
@@ -0,0 +1,22 @@
// 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/cholesky_grad_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/cholesky_grad_kernel_impl.h"
PD_REGISTER_KERNEL(
cholesky_grad, CPU, ALL_LAYOUT, phi::CholeskyGradKernel, float, double) {}
+86
View File
@@ -0,0 +1,86 @@
/* 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/cholesky_kernel.h"
#include "Eigen/Cholesky"
#include "Eigen/Core"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
namespace phi {
template <typename T, typename Context>
void CholeskyKernel(const Context& dev_ctx,
const DenseTensor& x,
bool upper,
DenseTensor* out) {
using EigenMatrix =
Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using InputMatrixMap = Eigen::Map<const EigenMatrix>;
using OutputMatrixMap = Eigen::Map<EigenMatrix>;
if (out->numel() == 0) {
dev_ctx.template Alloc<T>(out);
return;
}
auto& dims = x.dims();
int batch_count = 1;
for (int i = 0; i < dims.size() - 2; i++) {
batch_count *= static_cast<int>(dims[i]);
}
auto m = dims[dims.size() - 1];
const auto* x_data = x.data<T>();
auto* out_data = dev_ctx.template Alloc<T>(out);
// Cholesky decomposition for each matrix, maybe can use multi threads
for (int i = 0; i < batch_count; i++) {
auto input = InputMatrixMap(x_data + i * m * m, m, m);
auto output = OutputMatrixMap(out_data + i * m * m, m, m);
if (upper) {
Eigen::LLT<
Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>,
Eigen::UpLoType::Upper>
llt_decomposition(input);
PADDLE_ENFORCE_EQ(llt_decomposition.info(),
Eigen::Success,
errors::InvalidArgument(
"Cholesky decomposition was not successful. The "
"%d-th input matrice "
"might not be not be positive definite.",
i));
output = llt_decomposition.matrixU();
} else {
Eigen::LLT<
Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>,
Eigen::UpLoType::Lower>
llt_decomposition(input);
PADDLE_ENFORCE_EQ(llt_decomposition.info(),
Eigen::Success,
errors::InvalidArgument(
"Cholesky decomposition was not successful. The "
"%d-th input matrice "
"might not be not be positive definite.",
i));
output = llt_decomposition.matrixL();
}
}
}
} // namespace phi
PD_REGISTER_KERNEL(
cholesky, CPU, ALL_LAYOUT, phi::CholeskyKernel, float, double) {}
@@ -0,0 +1,24 @@
// 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/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/cholesky_solve_grad_kernel_impl.h"
PD_REGISTER_KERNEL(cholesky_solve_grad,
CPU,
ALL_LAYOUT,
phi::CholeskySolveGradKernel,
float,
double) {}
@@ -0,0 +1,41 @@
// 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/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/lapack/lapack_function.h"
#include "paddle/phi/kernels/impl/cholesky_solve_kernel_impl.h"
namespace phi {
template <typename T>
class CholeskySolveFunctor<T, CPUContext> {
public:
void operator()(const CPUContext &dev_ctx,
bool upper,
int M,
int N,
T *Adata,
int lda,
T *Bdata,
int *devInfo) {
char uplo = upper ? 'U' : 'L';
funcs::lapackCholeskySolve<T>(uplo, M, N, Adata, lda, Bdata, lda, devInfo);
}
};
} // namespace phi
PD_REGISTER_KERNEL(
cholesky_solve, CPU, ALL_LAYOUT, phi::CholeskySolveKernel, float, double) {}
@@ -0,0 +1,27 @@
// 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/chunk_eval_kernel.h"
#include "paddle/phi/kernels/impl/chunk_eval_kernel_impl.h"
PD_REGISTER_KERNEL(
chunk_eval, CPU, ALL_LAYOUT, phi::ChunkEvalKernel, float, int64_t) {
kernel->InputAt(0).SetDataType(phi::DataType::INT64);
kernel->InputAt(1).SetDataType(phi::DataType::INT64);
kernel->InputAt(2).SetDataType(phi::DataType::INT64);
kernel->OutputAt(3).SetDataType(phi::DataType::INT64);
kernel->OutputAt(4).SetDataType(phi::DataType::INT64);
kernel->OutputAt(5).SetDataType(phi::DataType::INT64);
}
@@ -0,0 +1,129 @@
// Copyright (c) 2021 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 <map>
#include <set>
#include <vector>
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/generator.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/class_center_sample_kernel.h"
namespace phi {
template <typename T, typename Context>
void ClassCenterSampleKernel(const Context& dev_ctx,
const DenseTensor& label,
int num_classes,
int num_samples,
int ring_id,
int rank,
int nranks,
bool fix_seed,
int seed,
DenseTensor* remapped_label,
DenseTensor* sampled_local_class_center) {
PADDLE_ENFORCE_GT(num_classes,
0,
errors::InvalidArgument(
"The value 'num_classes' for Op(class_center_sample) "
"must be greater than 0, "
"but the value given is %d.",
num_classes));
PADDLE_ENFORCE_GT(num_samples,
0,
errors::InvalidArgument(
"The value 'num_samples' for Op(class_center_sample) "
"must be greater than 0, "
"but the value given is %d.",
num_samples));
PADDLE_ENFORCE_LE(num_samples,
num_classes,
errors::InvalidArgument(
"The value 'num_samples' for Op(class_center_sample) "
"must be less than or equal to %d, "
"but the value given is %d.",
num_classes,
num_samples));
int64_t numel = label.numel();
auto* label_ptr = label.data<T>();
// get unique positive class center by ascending
std::set<T, std::less<T>> unique_label; // NOLINT
for (int64_t i = 0; i < numel; ++i) {
unique_label.insert(label_ptr[i]);
}
// construct a lookup table and get sampled_local_class_center
std::vector<T> actual_sampled;
std::map<T, T> new_class_dict;
T idx = 0;
for (auto& t : unique_label) {
new_class_dict[t] = idx;
actual_sampled.push_back(t);
idx++;
}
if (!fix_seed) {
std::random_device rnd;
seed = static_cast<int>(rnd());
}
std::uniform_int_distribution<T> dist(0, num_classes - 1);
std::shared_ptr<std::mt19937_64> engine;
if (seed) {
engine = std::make_shared<std::mt19937_64>();
engine->seed(seed);
} else {
engine = dev_ctx.GetGenerator()->GetCPUEngine();
}
// sample negative class center randomly
while (unique_label.size() < static_cast<size_t>(num_samples)) {
T neg = dist(*engine);
if (unique_label.find(neg) == unique_label.end()) {
unique_label.insert(neg);
// unorder for negative class center
actual_sampled.push_back(neg);
}
}
int actual_num_samples = unique_label.size();
sampled_local_class_center->Resize({actual_num_samples});
T* sampled_local_class_center_ptr =
dev_ctx.template Alloc<T>(sampled_local_class_center);
idx = 0;
for (auto& t : actual_sampled) {
sampled_local_class_center_ptr[idx] = t;
idx++;
}
// remap the input label to sampled class
auto* remapped_label_ptr = dev_ctx.template Alloc<T>(remapped_label);
for (int64_t i = 0; i < numel; ++i) {
remapped_label_ptr[i] = new_class_dict[label_ptr[i]];
}
}
} // namespace phi
PD_REGISTER_KERNEL(class_center_sample,
CPU,
ALL_LAYOUT,
phi::ClassCenterSampleKernel,
int64_t,
int) {}
@@ -0,0 +1,34 @@
// 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/clip_by_norm_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/clip_by_norm_kernel_impl.h"
namespace phi {
template <typename T, typename Context>
void ClipByNormKernel(const Context& dev_ctx,
const DenseTensor& in,
float max_norm,
DenseTensor* output) {
ClipByNormFunctor<T, Context>(dev_ctx, in, max_norm, output);
}
} // namespace phi
PD_REGISTER_KERNEL(
clip_by_norm, CPU, ALL_LAYOUT, phi::ClipByNormKernel, float) {}
@@ -0,0 +1,28 @@
// 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/clip_grad_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/clip_grad_kernel_impl.h"
PD_REGISTER_KERNEL(clip_grad,
CPU,
ALL_LAYOUT,
phi::ClipGradKernel,
float,
double,
int,
int64_t) {}
+22
View File
@@ -0,0 +1,22 @@
// 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/clip_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/clip_kernel_impl.h"
PD_REGISTER_KERNEL(
clip, CPU, ALL_LAYOUT, phi::ClipKernel, float, double, int, int64_t) {}
@@ -0,0 +1,26 @@
// 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/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/collect_fpn_proposals_kernel_impl.h"
PD_REGISTER_KERNEL(collect_fpn_proposals,
CPU,
ALL_LAYOUT,
phi::CollectFpnProposalsOpKernel,
float,
double) {
kernel->InputAt(2).SetDataType(phi::DataType::INT32);
kernel->OutputAt(1).SetDataType(phi::DataType::INT32);
}
+134
View File
@@ -0,0 +1,134 @@
// 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/compare_kernel.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/elementwise_base.h"
#include "paddle/phi/kernels/impl/compare_kernel_impl.h"
namespace phi {
template <typename T,
typename Context,
typename Functor,
typename InverseFunctor>
inline void CompareKernelImpl(const Context& dev_ctx,
const DenseTensor& x,
const DenseTensor& y,
int axis,
DenseTensor* out) {
dev_ctx.template Alloc<bool>(out);
if (x.dims().size() >= y.dims().size()) {
funcs::ElementwiseCompute<Functor, T, bool>(
dev_ctx, x, y, Functor(), out, axis);
} else {
funcs::ElementwiseCompute<InverseFunctor, T, bool>(
dev_ctx, x, y, InverseFunctor(), out, axis);
}
}
template <typename T,
typename Context,
typename Functor,
typename InverseFunctor>
inline void InplaceCompareKernelImpl(const Context& dev_ctx,
const DenseTensor& x,
const DenseTensor& y,
int axis,
DenseTensor* out) {
auto x_origin = x;
out->set_type(DataType::BOOL);
dev_ctx.template Alloc<bool>(out);
if (x_origin.dims().size() >= y.dims().size()) {
funcs::ElementwiseCompute<Functor, T, bool>(
dev_ctx, x_origin, y, Functor(), out, axis);
} else {
funcs::ElementwiseCompute<InverseFunctor, T, bool>(
dev_ctx, x_origin, y, InverseFunctor(), out, axis);
}
}
template <typename T, typename Context, typename Functor>
inline void CompareAllKernelImpl(const Context& dev_ctx,
const DenseTensor& x,
const DenseTensor& y,
DenseTensor* out) {
bool* out_data = dev_ctx.template Alloc<bool>(out);
if (x.dims() != y.dims()) {
out_data[0] = false;
} else if (x.numel() == 0) { // shape equal and numel is 0, return true
out_data[0] = true;
} else {
DenseTensor tmp;
tmp.Resize(x.dims());
dev_ctx.template Alloc<bool>(&tmp);
if (x.numel() == 1 && y.numel() == 1) {
bool* tmp_data = tmp.data<bool>();
tmp_data[0] = Functor()(x.data<T>()[0], y.data<T>()[0]);
} else {
funcs::ElementwiseCompute<Functor, T, bool>(
dev_ctx, x, y, Functor(), &tmp, 0);
}
auto tmp_flat = EigenVector<bool>::Flatten(tmp);
auto out_es = EigenScalar<bool>::From(*out);
auto& place = *dev_ctx.eigen_device();
auto reduce_dim = Eigen::array<int, 1>({{0}});
out_es.device(place) = tmp_flat.all(reduce_dim);
}
}
} // namespace phi
PD_REGISTER_KERNEL(equal_all,
CPU,
ALL_LAYOUT,
phi::EqualAllKernel,
bool,
int,
int64_t,
float,
double) {
kernel->OutputAt(0).SetDataType(phi::DataType::BOOL);
}
#define PD_REGISTER_COMPLEX_COMPARE_KERNEL(name, func) \
PD_REGISTER_KERNEL(name, \
CPU, \
ALL_LAYOUT, \
phi::func##Kernel, \
bool, \
int, \
uint8_t, \
int8_t, \
int16_t, \
int64_t, \
phi::complex64, \
phi::complex128, \
float, \
double, \
phi::float16, \
phi::bfloat16) { \
kernel->OutputAt(0).SetDataType(phi::DataType::BOOL); \
}
PD_REGISTER_COMPLEX_COMPARE_KERNEL(less_than, LessThan)
PD_REGISTER_COMPLEX_COMPARE_KERNEL(less_equal, LessEqual)
PD_REGISTER_COMPLEX_COMPARE_KERNEL(greater_than, GreaterThan)
PD_REGISTER_COMPLEX_COMPARE_KERNEL(greater_equal, GreaterEqual)
PD_REGISTER_COMPLEX_COMPARE_KERNEL(equal, Equal)
PD_REGISTER_COMPLEX_COMPARE_KERNEL(not_equal, NotEqual)
@@ -0,0 +1,41 @@
// 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/complex_grad_kernel.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/complex_grad_kernel_impl.h"
PD_REGISTER_KERNEL(real_grad,
CPU,
ALL_LAYOUT,
phi::RealGradKernel,
phi::complex64,
phi::complex128) {
kernel->InputAt(0).SetDataType(phi::dtype::ToReal(kernel_key.dtype()));
}
PD_REGISTER_KERNEL(imag_grad,
CPU,
ALL_LAYOUT,
phi::ImagGradKernel,
phi::complex64,
phi::complex128) {
kernel->InputAt(0).SetDataType(phi::dtype::ToReal(kernel_key.dtype()));
}
PD_REGISTER_KERNEL(
complex_grad, CPU, ALL_LAYOUT, phi::ComplexGradKernel, float, double) {
kernel->InputAt(2).SetDataType(phi::dtype::ToComplex(kernel_key.dtype()));
}
+45
View File
@@ -0,0 +1,45 @@
// Copyright (c) 2021 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/complex_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/complex_kernel_impl.h"
PD_REGISTER_KERNEL(conj,
CPU,
ALL_LAYOUT,
phi::ConjKernel,
phi::complex64,
phi::complex128,
float,
double,
int,
int64_t) {}
PD_REGISTER_KERNEL(
real, CPU, ALL_LAYOUT, phi::RealKernel, phi::complex64, phi::complex128) {
kernel->OutputAt(0).SetDataType(phi::dtype::ToReal(kernel_key.dtype()));
}
PD_REGISTER_KERNEL(
imag, CPU, ALL_LAYOUT, phi::ImagKernel, phi::complex64, phi::complex128) {
kernel->OutputAt(0).SetDataType(phi::dtype::ToReal(kernel_key.dtype()));
}
PD_REGISTER_KERNEL(
complex, CPU, ALL_LAYOUT, phi::ComplexKernel, float, double) {
kernel->OutputAt(0).SetDataType(phi::dtype::ToComplex(kernel_key.dtype()));
}
@@ -0,0 +1,37 @@
// 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/concat_grad_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/concat_grad_kernel_impl.h"
PD_REGISTER_KERNEL(concat_grad,
CPU,
ALL_LAYOUT,
phi::ConcatGradKernel,
double,
float,
bool,
int64_t,
int,
int8_t,
int16_t,
uint8_t,
phi::float16,
phi::float8_e4m3fn,
phi::float8_e5m2,
phi::complex64,
phi::complex128) {}
+134
View File
@@ -0,0 +1,134 @@
// 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/concat_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/common/scalar.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/core/lod_utils.h"
#include "paddle/phi/kernels/funcs/concat_and_split_functor.h"
#include "paddle/phi/kernels/funcs/concat_funcs.h"
#include "paddle/phi/kernels/funcs/strided_memcpy.h"
namespace phi {
template <typename T, typename Context>
void ConcatKernel(const Context& dev_ctx,
const std::vector<const DenseTensor*>& x,
const Scalar& axis_scalar,
DenseTensor* out) {
int64_t axis = axis_scalar.to<int64_t>();
axis = funcs::ComputeAxis(axis, x[0]->dims().size());
std::vector<DDim> x_dims;
x_dims.reserve(x.size());
for (auto item : x) {
x_dims.push_back(item->dims());
}
DDim out_dims = funcs::ComputeAndCheckShape(true, x_dims, axis);
out->Resize(out_dims);
dev_ctx.template Alloc<T>(out);
if (out->numel() == 0) {
return;
}
// If axis is 0, the lod of the output is not the same as inputs.
if (axis == 0 && !x[0]->lod().empty()) {
size_t lod_size_0 = x[0]->lod().size();
size_t lod_size = lod_size_0;
for (size_t i = 1; i < x.size(); ++i) {
if (!x[i]->lod().empty()) {
PADDLE_ENFORCE_EQ(
x[i]->lod().size(),
lod_size_0,
common::errors::Unimplemented(
"The lod level of all input DenseTensors should be same. "
"Maybe different lod level of input DenseTensors can concat,"
"it is not supported currently. The lod level of %dth input "
"is %d and first input is %d.",
i,
x[i]->lod().size(),
lod_size_0));
} else {
lod_size = 0;
break;
}
}
if (lod_size) {
auto* out_lod = out->mutable_lod();
for (size_t i = 1; i < x.size(); ++i) {
auto in_lod = ConvertToLengthBasedLegacyLoD(x[i]->lod());
AppendLegacyLoD(out_lod, in_lod);
}
}
}
// Sometimes direct copies will be faster, this maybe need deeply analysis.
if (axis == 0 && x.size() < 10) {
size_t output_offset = 0;
for (const auto* in : x) {
if (in->numel() == 0UL) {
continue;
}
auto in_stride = common::stride_numel(in->dims());
auto out_stride = common::stride_numel(out->dims());
funcs::StridedNumelCopyWithAxis<T, Context>(
dev_ctx,
axis,
out->data<T>() + output_offset,
out_stride,
in->data<T>(),
in_stride,
in_stride[static_cast<int>(axis)]);
output_offset += in_stride[static_cast<int>(axis)];
}
} else {
// TODO(chenweihang): concat functor support vector<DenseTensor*> input
std::vector<DenseTensor> inputs;
inputs.reserve(x.size());
for (auto item : x) {
if (item->numel() > 0) {
inputs.emplace_back(*item);
} else {
continue;
}
}
funcs::ConcatFunctor<Context, T> functor;
functor(dev_ctx, inputs, axis, out);
}
}
} // namespace phi
PD_REGISTER_KERNEL(concat,
CPU,
ALL_LAYOUT,
phi::ConcatKernel,
float,
double,
bool,
int64_t,
int,
uint8_t,
int8_t,
int16_t,
phi::float16,
phi::bfloat16,
phi::float8_e4m3fn,
phi::float8_e5m2,
phi::complex64,
phi::complex128) {}
+303
View File
@@ -0,0 +1,303 @@
/* Copyright (c) 2023 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/contiguous_kernel.h"
#include <set>
#include <vector>
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/dense_tensor_iterator.h"
#include "paddle/phi/kernels/funcs/math_function.h"
#include "paddle/phi/kernels/impl/transpose_grad_kernel_impl.h"
#if defined(PADDLE_WITH_OPENMP)
#include <omp.h>
#endif
namespace phi {
inline int64_t DivUp(const int64_t& x, const int64_t& y) {
return (x + y - 1) / y;
}
inline void DealWithStride(const DenseTensorIterator& iter, int64_t* strides) {
for (int dim = 0; dim < iter.ndim(); dim++) {
for (int arg = 0; arg < iter.ntensors(); arg++) {
*strides++ = iter.strides(arg)[dim];
}
}
if (iter.ndim() < 2) {
std::fill_n(strides, (2 - iter.ndim()) * iter.ntensors(), 0);
}
}
template <typename T>
inline void FallbackContiguous(const DDim& input_dims,
const DDim& input_stride,
const int64_t numel,
const T* input_data,
T* output_data) {
int rank = input_dims.size();
auto dims = input_dims;
for (int64_t i = 0; i < numel; i++) {
int64_t input_offset = 0;
int64_t index_tmp = i;
for (int dim = rank - 1; dim >= 0; --dim) {
int64_t mod = index_tmp % dims[dim];
index_tmp = index_tmp / dims[dim];
input_offset += mod * input_stride[dim];
}
output_data[i] = input_data[input_offset];
}
}
inline bool OnlyTransposed(const DDim& shape,
const DDim& stride,
const uint64_t& offset) {
if (offset != 0) {
return false;
}
DDim x_stride = stride;
DDim x_shape = shape;
std::set<int> visited_idx;
for (int i = 0; i < stride.size(); i++) {
int64_t max_num = 0;
int max_idx = -1;
for (int j = 0; j < stride.size(); j++) {
if (visited_idx.count(j)) {
continue;
}
if (stride[j] < 1) {
return false;
}
if (stride[j] > max_num) {
max_num = stride[j];
max_idx = j;
}
}
if (max_idx == -1) {
return false;
}
if (i != 0 && x_stride[i - 1] == max_num) {
return false;
}
visited_idx.insert(max_idx);
x_stride[i] = max_num;
x_shape[i] = shape[max_idx];
}
if (DenseTensorMeta::calc_strides(x_shape) == x_stride) {
return true;
} else {
return false;
}
}
inline bool FastContiguousJudge(const std::vector<int64_t>& coalesce_shape,
const DenseTensor& input) {
if (coalesce_shape.size() > 3 || input.dims().size() == 0) return false;
auto x_meta = input.meta();
if (coalesce_shape.size() == 3 &&
!OnlyTransposed(x_meta.dims, x_meta.strides, x_meta.offset))
return false;
return true;
}
inline bool FastTransposeCopyValid(const DenseTensor& self,
const DenseTensor& src) {
constexpr int64_t MIN_NUMEL = 360;
return src.numel() != 0 && src.dims().size() == 2 && src.strides()[0] == 1 &&
src.strides()[1] == src.dims()[0] &&
self.dims().size() == src.dims().size() && self.numel() >= MIN_NUMEL;
}
template <typename T, typename Context>
void ContiguousKernel(const Context& dev_ctx,
const DenseTensor& input,
DenseTensor* out) {
DenseTensorMeta meta = input.meta();
meta.strides = meta.calc_strides(meta.dims);
meta.offset = 0;
out->set_meta(meta);
const T* input_data = input.data<T>();
T* output_data = dev_ctx.template Alloc<T>(out);
auto numel = input.numel();
if (numel == 0) {
return;
}
if (IsComplexType(input.dtype())) {
FallbackContiguous<T>(
input.dims(), input.strides(), numel, input_data, output_data);
return;
}
#if defined(_WIN32)
FallbackContiguous<T>(
input.dims(), input.strides(), numel, input_data, output_data);
return;
#else
if (FastTransposeCopyValid(*out, input)) {
constexpr int64_t TRANS_NUMEL = 60;
void* trans_buffer =
malloc(SizeOf(input.dtype()) * TRANS_NUMEL * TRANS_NUMEL);
const T* tmp_src_ptr = input_data;
T* tmp_out_ptr = output_data;
T* tmp_buf_ptr = reinterpret_cast<T*>(trans_buffer);
int64_t dim0 = out->dims()[0];
int64_t dim1 = out->dims()[1];
for (int64_t d0 = 0; d0 < dim0; d0 += TRANS_NUMEL) {
for (int64_t d1 = 0; d1 < dim1; d1 += TRANS_NUMEL) {
const T* src_ptr_inter = tmp_src_ptr + d0 + d1 * dim0;
T* out_ptr_inter = tmp_out_ptr + d1 + d0 * dim1;
int nr = std::min(dim0 - d0, TRANS_NUMEL);
int nc = std::min(dim1 - d1, TRANS_NUMEL);
for (int c = 0; c < nc; c++) {
memcpy(tmp_buf_ptr + c * TRANS_NUMEL,
src_ptr_inter + c * dim0,
nr * sizeof(T));
}
int rc_max = std::max(nr, nc);
int rc_min = std::min(nr, nc);
for (int r = 0; r < rc_max; r++) {
int end = std::min(r, rc_min);
for (int c = 0; c < end; c++) {
T tmp = tmp_buf_ptr[r + TRANS_NUMEL * c];
tmp_buf_ptr[r + TRANS_NUMEL * c] = tmp_buf_ptr[r * TRANS_NUMEL + c];
tmp_buf_ptr[r * TRANS_NUMEL + c] = tmp;
}
}
for (int r = 0; r < nr; r++) {
memcpy(out_ptr_inter + r * dim1,
tmp_buf_ptr + r * TRANS_NUMEL,
nc * sizeof(T));
}
}
}
free(trans_buffer);
} else {
#if defined(PADDLE_WITH_OPENMP)
DenseTensorIteratorConfig config;
config.add_output(*out);
config.add_const_input(input);
config.is_alloc_out_ = true;
DenseTensorIterator iter = config.build();
if (!FastContiguousJudge(iter.shape(), input)) {
FallbackContiguous<T>(
input.dims(), input.strides(), numel, input_data, output_data);
return;
}
std::vector<int64_t> tmp_strides(
iter.ntensors() * static_cast<size_t>(std::max(iter.ndim(), 2)));
DealWithStride(iter, tmp_strides.data());
std::vector<int64_t> out_stride(tmp_strides.begin() + iter.ntensors(),
tmp_strides.end());
const int64_t& iter_numel = iter.numel();
const char* in_ptr = reinterpret_cast<const char*>(input_data);
char* out_ptr = reinterpret_cast<char*>(output_data);
int64_t end = iter_numel;
int64_t begin = 0;
int64_t grain_size = 32768;
int64_t* whole_stride = tmp_strides.data();
#pragma omp parallel
{
int64_t num_threads = omp_get_num_threads();
if (grain_size > 0) {
num_threads = std::min(num_threads, DivUp((end - begin), grain_size));
}
int64_t tid = omp_get_thread_num();
int64_t chunk_size = DivUp((end - begin), num_threads);
int64_t begin_tid = begin + tid * chunk_size;
if (begin_tid < end) {
int64_t range_start = begin_tid;
int64_t range_end = std::min(end, chunk_size + begin_tid);
auto dimiter = DimIter(iter.shape(), range_start, range_end);
while (!dimiter.iter_to_end()) {
const auto v_ndim = dimiter.values.size();
const char* tmp_in_data = in_ptr;
char* tmp_out_data = out_ptr;
for (size_t dim = 0; dim < v_ndim; dim++) {
int64_t value = dimiter.values[dim];
tmp_out_data += value * whole_stride[dim * iter.ntensors() + 0];
tmp_in_data += value * whole_stride[dim * iter.ntensors() + 1];
}
auto step = dimiter.iter_for_step();
for (int64_t i = 0; i < step[1]; i++) {
for (int64_t j = 0; j < step[0]; j++) {
const char* real_in_ptr = tmp_in_data + j * whole_stride[1];
char* real_out_ptr = tmp_out_data + j * whole_stride[0];
*reinterpret_cast<T*>(real_out_ptr) =
*reinterpret_cast<const T*>(real_in_ptr);
}
tmp_in_data = tmp_in_data + out_stride[1];
tmp_out_data = tmp_out_data + out_stride[0];
}
dimiter.iter_to_next(step);
}
}
}
#else
FallbackContiguous<T>(
input.dims(), input.strides(), numel, input_data, output_data);
#endif
}
#endif
}
} // namespace phi
PD_REGISTER_KERNEL(contiguous,
CPU,
ALL_LAYOUT,
phi::ContiguousKernel,
bool,
uint8_t,
uint16_t,
uint32_t,
uint64_t,
int8_t,
int16_t,
int32_t,
int64_t,
float,
double,
phi::float16,
phi::bfloat16,
phi::complex64,
phi::complex128,
phi::float8_e4m3fn,
phi::float8_e5m2) {}
+137
View File
@@ -0,0 +1,137 @@
// 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/conv_grad_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/conv_grad_kernel_impl.h"
namespace phi {
template <typename T, typename Context>
void DepthwiseConvGradKernel(const Context& dev_ctx,
const DenseTensor& input,
const DenseTensor& filter,
const DenseTensor& out_grad,
const std::vector<int>& strides,
const std::vector<int>& paddings,
const std::string& padding_algorithm,
int groups,
const std::vector<int>& dilations,
const std::string& data_format,
DenseTensor* input_grad,
DenseTensor* filter_grad) {
ConvGradKernel<T>(dev_ctx,
input,
filter,
out_grad,
strides,
paddings,
padding_algorithm,
dilations,
groups,
data_format,
input_grad,
filter_grad);
}
template <typename T, typename Context>
void Conv3DGradKernel(const Context& dev_ctx,
const DenseTensor& input,
const DenseTensor& filter,
const DenseTensor& out_grad,
const std::vector<int>& strides,
const std::vector<int>& paddings,
const std::string& padding_algorithm,
int groups,
const std::vector<int>& dilations,
const std::string& data_format,
DenseTensor* input_grad,
DenseTensor* filter_grad) {
ConvGradKernel<T>(dev_ctx,
input,
filter,
out_grad,
strides,
paddings,
padding_algorithm,
dilations,
groups,
data_format,
input_grad,
filter_grad);
}
template <typename T, typename Context>
void Conv3DDoubleGradKernel(const Context& dev_ctx,
const DenseTensor& input,
const DenseTensor& filter,
const DenseTensor& out_grad,
const optional<DenseTensor>& input_grad_grad,
const optional<DenseTensor>& filter_grad_grad,
const std::vector<int>& strides,
const std::vector<int>& paddings_t,
const std::string& padding_algorithm,
int groups,
const std::vector<int>& dilations_t,
const std::string& data_format,
DenseTensor* input_grad,
DenseTensor* filter_grad,
DenseTensor* out_grad_grad) {
ConvGradGradKernel<T>(dev_ctx,
input,
filter,
out_grad,
input_grad_grad,
filter_grad_grad,
strides,
paddings_t,
padding_algorithm,
dilations_t,
groups,
data_format,
input_grad,
filter_grad,
out_grad_grad);
}
} // namespace phi
PD_REGISTER_KERNEL(
conv2d_grad, CPU, ALL_LAYOUT, phi::ConvGradKernel, float, double) {}
PD_REGISTER_KERNEL(depthwise_conv2d_grad,
CPU,
ALL_LAYOUT,
phi::DepthwiseConvGradKernel,
float,
double) {}
PD_REGISTER_KERNEL(
conv3d_grad, CPU, ALL_LAYOUT, phi::Conv3DGradKernel, float, double) {}
PD_REGISTER_KERNEL(conv2d_double_grad,
CPU,
ALL_LAYOUT,
phi::ConvGradGradKernel,
float,
double) {}
PD_REGISTER_KERNEL(conv3d_double_grad,
CPU,
ALL_LAYOUT,
phi::Conv3DDoubleGradKernel,
float,
double) {}
+103
View File
@@ -0,0 +1,103 @@
// 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/conv_kernel.h"
#include "paddle/phi/backends/cpu/cpu_context.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/conv_kernel_impl.h"
namespace phi {
template <typename T, typename Context>
void ConvKernel(const Context& dev_ctx,
const DenseTensor& input,
const DenseTensor& filter,
const std::vector<int>& strides,
const std::vector<int>& paddings,
const std::string& padding_algorithm,
const std::vector<int>& dilations,
int groups,
const std::string& data_format,
DenseTensor* out) {
ConvKernelImpl<T>(dev_ctx,
input,
filter,
strides,
paddings,
padding_algorithm,
groups,
dilations,
data_format,
out);
}
template <typename T, typename Context>
void DepthwiseConvKernel(const Context& dev_ctx,
const DenseTensor& input,
const DenseTensor& filter,
const std::vector<int>& strides,
const std::vector<int>& paddings,
const std::string& padding_algorithm,
int groups,
const std::vector<int>& dilations,
const std::string& data_format,
DenseTensor* out) {
ConvKernelImpl<T>(dev_ctx,
input,
filter,
strides,
paddings,
padding_algorithm,
groups,
dilations,
data_format,
out);
}
template <typename T, typename Context>
void Conv3DKernel(const Context& dev_ctx,
const DenseTensor& input,
const DenseTensor& filter,
const std::vector<int>& strides,
const std::vector<int>& paddings,
const std::string& padding_algorithm,
int groups,
const std::vector<int>& dilations,
const std::string& data_format,
DenseTensor* out) {
ConvKernelImpl<T>(dev_ctx,
input,
filter,
strides,
paddings,
padding_algorithm,
groups,
dilations,
data_format,
out);
}
} // namespace phi
PD_REGISTER_KERNEL(conv2d, CPU, ALL_LAYOUT, phi::ConvKernel, float, double) {}
PD_REGISTER_KERNEL(depthwise_conv2d,
CPU,
ALL_LAYOUT,
phi::DepthwiseConvKernel,
float,
double) {}
PD_REGISTER_KERNEL(conv3d, CPU, ALL_LAYOUT, phi::Conv3DKernel, float, double) {}
@@ -0,0 +1,70 @@
// 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/conv_transpose_grad_kernel.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/conv_transpose_grad_kernel_impl.h"
namespace phi {
template <typename T, typename Context>
void DepthwiseConv2dTransposeGradKernel(const Context& dev_ctx,
const DenseTensor& x,
const DenseTensor& filter,
const DenseTensor& dout,
const std::vector<int>& strides,
const std::vector<int>& paddings,
const std::vector<int>& output_padding,
const IntArray& output_size,
const std::string& padding_algorithm,
int groups,
const std::vector<int>& dilations,
const std::string& data_format,
DenseTensor* dx,
DenseTensor* dfilter) {
ConvTransposeGradRawKernel<T, Context>(dev_ctx,
x,
filter,
dout,
strides,
paddings,
padding_algorithm,
groups,
dilations,
data_format,
dx,
dfilter);
}
} // namespace phi
PD_REGISTER_KERNEL(conv2d_transpose_grad,
CPU,
ALL_LAYOUT,
phi::Conv2dTransposeGradKernel,
float,
double) {}
PD_REGISTER_KERNEL(conv3d_transpose_grad,
CPU,
ALL_LAYOUT,
phi::Conv3dTransposeGradKernel,
float,
double) {}
PD_REGISTER_KERNEL(depthwise_conv2d_transpose_grad,
CPU,
ALL_LAYOUT,
phi::DepthwiseConv2dTransposeGradKernel,
float,
double) {}
@@ -0,0 +1,66 @@
// 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/conv_transpose_kernel.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/impl/conv_transpose_kernel_impl.h"
namespace phi {
template <typename T, typename Context>
void DepthwiseConv2dTransposeKernel(const Context& dev_ctx,
const DenseTensor& x,
const DenseTensor& filter,
const std::vector<int>& strides,
const std::vector<int>& paddings,
const std::vector<int>& output_padding,
const IntArray& output_size,
const std::string& padding_algorithm,
int groups,
const std::vector<int>& dilations,
const std::string& data_format,
DenseTensor* out) {
ConvTransposeRawKernel<T, Context>(dev_ctx,
x,
filter,
strides,
paddings,
padding_algorithm,
groups,
dilations,
data_format,
out);
}
} // namespace phi
PD_REGISTER_KERNEL(conv2d_transpose,
CPU,
ALL_LAYOUT,
phi::Conv2dTransposeKernel,
float,
double) {}
PD_REGISTER_KERNEL(conv3d_transpose,
CPU,
ALL_LAYOUT,
phi::Conv3dTransposeKernel,
float,
double) {}
PD_REGISTER_KERNEL(depthwise_conv2d_transpose,
CPU,
ALL_LAYOUT,
phi::DepthwiseConv2dTransposeKernel,
float,
double) {}
+297
View File
@@ -0,0 +1,297 @@
// 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/common/ddim.h"
#include "paddle/phi/core/meta_tensor.h"
namespace phi {
template <typename T = int>
inline void UpdatePaddingAndDilation(std::vector<T>* paddings,
std::vector<T>* dilation,
const std::string padding_algorithm,
const DDim data_dims,
const std::vector<T>& strides,
const std::vector<T>& ksize) {
// set padding size == data_dims.size() * 2
auto data_shape = vectorize<T>(data_dims);
if (static_cast<int>(paddings->size()) == data_dims.size()) {
for (int i = 0; i < data_dims.size(); ++i) {
T copy_pad = *(paddings->begin() + 2 * i);
paddings->insert(paddings->begin() + 2 * i + 1, copy_pad);
}
} else {
PADDLE_ENFORCE_EQ(
data_dims.size() * 2,
paddings->size(),
common::errors::InvalidArgument(
"Attribute padding's size should be the same or twice as the "
"input's dimension. "
"But received: padding's size is %d, padding is [%s]; input's "
"dimension is %d, input's shape is [%s].",
paddings->size(),
make_ddim(*paddings),
data_dims.size(),
data_dims));
}
// when padding_algorithm is "VALID" or "SAME"
if (padding_algorithm == "SAME") {
for (int i = 0; i < data_dims.size(); ++i) {
T out_size = (data_dims[i] + strides[i] - 1) / strides[i];
T pad_sum =
std::max((out_size - 1) * strides[i] + ksize[i] - data_shape[i],
static_cast<T>(0));
T pad_0 = pad_sum / 2;
T pad_1 = pad_sum - pad_0;
*(paddings->begin() + i * 2) = pad_0;
*(paddings->begin() + i * 2 + 1) = pad_1;
// dilation
*(dilation->begin() + i) = 1;
}
} else if (padding_algorithm == "VALID") {
for (auto it = paddings->begin(); it != paddings->end(); it++) {
*it = 0;
}
}
}
inline int ConvOutSize(int input_size,
int filter_size,
int dilation,
int pad_left,
int pad_right,
int stride) {
const int64_t dkernel =
static_cast<int64_t>(dilation) * (filter_size - 1) + 1;
const int64_t output_size =
(static_cast<int64_t>(input_size) + pad_left + pad_right - dkernel) /
stride +
1;
PADDLE_ENFORCE_GT(
output_size,
0,
common::errors::InvalidArgument(
"The output's size is expected to be greater than 0. "
"But received: output's size is %ld. The output's size is "
"computed by ((input_size + pad_left + pad_right - "
"(dilation * (filter_size - 1) + 1)) / stride + 1), where "
"input_size is %d, padding is (%d, %d), filter_size is %d, "
"dilation is %d, stride is %d.",
output_size,
input_size,
pad_left,
pad_right,
filter_size,
dilation,
stride));
PADDLE_ENFORCE_LE_INT_MAX(output_size, "conv output size");
return static_cast<int>(output_size);
}
inline std::vector<int64_t> ComputeOutputShape(
const MetaTensor& input,
const MetaTensor& filter,
const MetaTensor& bias,
const std::vector<int>& strides,
const std::vector<int>& paddings,
const std::string& padding_algorithm,
const std::vector<int>& dilations,
int groups,
const std::string& data_format,
bool channel_last,
MetaConfig config) {
auto in_dims = input.dims();
auto filter_dims = filter.dims();
int dilation_size = dilations.size();
for (int i = 0; i < dilation_size; ++i) {
PADDLE_ENFORCE_GT(
dilations[i],
0,
common::errors::InvalidArgument(
"The dilation of Op(Conv) should be larger than 0, but received "
"dilation is %d.",
dilations[i]));
}
PADDLE_ENFORCE_EQ(
in_dims.size() == 4 || in_dims.size() == 5,
true,
common::errors::InvalidArgument(
"The input of Op(Conv) should be a 4-D or 5-D Tensor. But "
"received: input's dimension is %u, input's shape is [%s].",
in_dims.size(),
in_dims));
PADDLE_ENFORCE_EQ(
in_dims.size(),
filter_dims.size(),
common::errors::InvalidArgument(
"The input's dimension and filter's dimension of "
"Op(Conv) should be equal. But received: the input's shape is "
"[%s], "
"the input's dimension is %d; the filter's shape is [%s], "
"the filter's dimension is %d.",
in_dims,
in_dims.size(),
filter_dims,
filter_dims.size()));
int stride_size = strides.size();
for (int i = 0; i < stride_size; ++i) {
PADDLE_ENFORCE_GT(
strides[i],
0,
common::errors::InvalidArgument(
"The stride of Op(Conv) should be larger than 0, but received "
"stride is %d.",
strides[i]));
}
PADDLE_ENFORCE_EQ(
in_dims.size(),
strides.size() + 2U,
common::errors::InvalidArgument(
"The difference of input's dimension and Attr(strides)'s "
"length must be equal to 2 for Op(Conv). "
"But received: input's dimension is %d, input's shape is [%s]; "
"Attr(stride)'s length is %d, Attr(stride) is [%s]; "
"difference of input's dimension and Attr(strides)'s length = %u.",
in_dims.size(),
in_dims,
strides.size(),
make_ddim(strides),
in_dims.size() - stride_size));
const auto input_channels =
channel_last ? in_dims[in_dims.size() - 1] : in_dims[1];
if (config.is_runtime) {
PADDLE_ENFORCE_EQ(
input_channels,
(channel_last ? filter_dims[filter_dims.size() - 1] : filter_dims[1]) *
groups,
common::errors::InvalidArgument(
"The number of input's channels should be equal to filter's "
"channels "
"* groups for Op(Conv). But received: the input's channels is %d, "
"the input's shape is [%s]; the filter's channels is %d, the "
"filter's shape is [%s]; the groups is %d, the data_format is %s. "
"The error may come from wrong data_format setting.",
input_channels,
in_dims,
channel_last ? filter_dims[filter_dims.size() - 1] : filter_dims[1],
filter_dims,
groups,
data_format));
PADDLE_ENFORCE_EQ(
filter_dims[0] % groups,
0,
common::errors::InvalidArgument(
"The number of output's channels (filter's first dimension) of "
"Op(Conv) should be divided by groups. But received: "
"the output channels is %d, the filter's shape is [%s], "
"the groups is %d.",
filter_dims[0],
filter_dims,
groups));
PADDLE_ENFORCE_GT(
filter_dims[0],
0,
common::errors::InvalidArgument(
"the size of filter at axis 0 should be greater than 0"));
}
DDim in_data_dims;
if (channel_last) {
in_data_dims = slice_ddim(in_dims, 1, in_dims.size() - 1);
} else {
in_data_dims = slice_ddim(in_dims, 2, in_dims.size());
}
DDim filter_data_dims;
if (channel_last) {
filter_data_dims = slice_ddim(filter_dims, 1, filter_dims.size() - 1);
} else {
filter_data_dims = slice_ddim(filter_dims, 2, filter_dims.size());
}
std::vector<int64_t> ksize = vectorize<int64_t>(filter_data_dims);
std::vector<int64_t> paddings_vec(paddings.begin(), paddings.end());
std::vector<int64_t> dilations_vec(dilations.begin(), dilations.end());
std::vector<int64_t> strides_vec(strides.begin(), strides.end());
phi::UpdatePaddingAndDilation(&paddings_vec,
&dilations_vec,
padding_algorithm,
in_data_dims,
strides_vec,
ksize);
std::vector<int64_t> output_shape({in_dims[0]});
if (!channel_last) {
output_shape.push_back(filter_dims[0]);
}
for (int i = 0; i < in_data_dims.size(); ++i) {
if (!config.is_runtime &&
(in_data_dims[i] <= 0 || filter_dims[i + 2] <= 0)) {
output_shape.push_back(-1);
} else {
PADDLE_ENFORCE_LE_INT_MAX(in_data_dims[i], "conv input size");
PADDLE_ENFORCE_LE_INT_MAX(filter_data_dims[i], "conv filter size");
PADDLE_ENFORCE_LE_INT_MAX(paddings_vec[2 * i], "conv padding left");
PADDLE_ENFORCE_LE_INT_MAX(paddings_vec[2 * i + 1], "conv padding right");
output_shape.push_back(
ConvOutSize(static_cast<int>(in_data_dims[i]),
static_cast<int>(filter_data_dims[i]),
static_cast<int>(dilations_vec[i]),
static_cast<int>(paddings_vec[2 * i]),
static_cast<int>(paddings_vec[2 * i + 1]),
static_cast<int>(strides_vec[i])));
}
}
if (channel_last) {
output_shape.push_back(filter_dims[0]);
}
return output_shape;
}
inline bool IsExpand(const std::vector<int64_t>& filter_dim,
const std::vector<int>& strides,
const std::vector<int>& paddings,
const std::vector<int>& dilations) {
bool filter_1 = true, strides_1 = true, padding_0 = true, dilation_1 = true;
for (size_t j = 0; j < strides.size(); ++j) {
filter_1 = filter_1 && (filter_dim[j + 2] == 1);
strides_1 = strides_1 && (strides[j] == 1);
padding_0 = padding_0 && (paddings[j] == 0);
dilation_1 = dilation_1 && (dilations[j] == 1);
}
if (paddings.size() != strides.size()) {
for (size_t j = 0; j < paddings.size(); ++j) {
padding_0 = padding_0 && (paddings[j] == 0);
}
}
return !(filter_1 && strides_1 && padding_0 && dilation_1);
}
} // namespace phi
@@ -0,0 +1,47 @@
// 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 <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/correlation_funcs.h"
namespace phi {
template <typename T, typename Context>
void CorrelationKernel(const Context& dev_ctx,
const DenseTensor& input1,
const DenseTensor& input2,
int pad_size,
int kernel_size,
int max_displacement,
int stride1,
int stride2,
int corr_type_multiply,
DenseTensor* out) {
bool is_gpu_place = (dev_ctx.GetPlace().GetType() == AllocationType::GPU) ||
(dev_ctx.GetPlace().GetType() == AllocationType::CUSTOM);
PADDLE_ENFORCE_EQ(
is_gpu_place,
true,
common::errors::Unimplemented("Correlation only supports GPU now."));
}
} // namespace phi
PD_REGISTER_KERNEL(
correlation, CPU, ALL_LAYOUT, phi::CorrelationKernel, float, double) {}
@@ -0,0 +1,165 @@
// 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/crf_decoding_kernel.h"
#include "paddle/phi/core/kernel_registry.h"
#include "paddle/phi/kernels/funcs/eigen/common.h"
#include "paddle/phi/kernels/funcs/jit/kernels.h"
#include "paddle/phi/kernels/funcs/math_function.h"
namespace phi {
template <typename T, typename Context>
void Decode(const Context& dev_ctx,
const DenseTensor& emission_weights,
const DenseTensor& transition_weights,
DenseTensor* decoded_path) {
auto emission_dims = emission_weights.dims();
const size_t seq_len = emission_dims[0];
const size_t tag_num = emission_dims[1];
const T* x = emission_weights.data<T>();
const T* w = transition_weights.data<T>();
int64_t* path = decoded_path->data<int64_t>();
// alpha is a memo table. An element alpha(k, v) records the score of the
// best sequence of tags from position 1 to position k with v being the end
// tag.
DenseTensor alpha;
alpha.Resize(emission_dims);
T* alpha_value = dev_ctx.template Alloc<T>(&alpha);
DenseTensor track;
track.Resize(emission_dims);
int* track_value = dev_ctx.template Alloc<int>(&track);
auto ker =
jit::KernelFuncs<jit::CRFDecodingTuple<T>, CPUPlace>::Cache().At(tag_num);
ker(static_cast<int>(seq_len), x, w, alpha_value, track_value, tag_num);
T max_score = -std::numeric_limits<T>::max();
int max_i = 0;
for (size_t i = 0; i < tag_num; ++i) {
T score = alpha_value[(seq_len - 1) * tag_num + i] + w[tag_num + i];
if (score > max_score) {
max_score = score;
max_i = i;
}
}
path[seq_len - 1] = max_i;
for (int k = seq_len - 1; k >= 1; --k) {
path[k - 1] = max_i = track_value[k * tag_num + max_i];
}
}
// Slice() needs to be used in *.cc files, otherwise there is a error in
// test/custom_runtime/extension_header_test.cc
template <typename T, typename Context>
void CRFDecodingOpKernel(const Context& dev_ctx,
const DenseTensor& emission,
const DenseTensor& transition,
const optional<DenseTensor>& label,
const optional<DenseTensor>& length,
DenseTensor* viterbi_path) {
auto* emission_weights = &emission;
auto* transition_weights = &transition;
auto* label_p = label.get_ptr();
auto* decoded_path = viterbi_path;
int64_t* path = dev_ctx.template Alloc<int64_t>(decoded_path);
funcs::SetConstant<Context, int64_t>()(dev_ctx, decoded_path, 0);
bool has_length = length.get_ptr() != nullptr;
if (has_length) {
auto* length_p = length.get_ptr();
const size_t seq_num = length_p->numel();
const int64_t* length_data = length_p->data<int64_t>();
auto in_dims = emission_weights->dims();
DenseTensor emission_weights_tmp = *emission_weights;
emission_weights_tmp.Resize(
make_ddim({in_dims[0] * in_dims[1], in_dims[2]}));
decoded_path->Resize({in_dims[0] * in_dims[1], 1});
for (size_t i = 0; i < seq_num; ++i) {
if (length_data[i] == 0) continue;
int64_t start_pos = i * in_dims[1];
int64_t end_pos = start_pos + static_cast<int64_t>(length_data[i]);
DenseTensor decoded_path_one_seq =
decoded_path->Slice(start_pos, end_pos);
Decode<T, Context>(dev_ctx,
emission_weights_tmp.Slice(start_pos, end_pos),
*transition_weights,
&decoded_path_one_seq);
}
decoded_path->Resize({in_dims[0], in_dims[1]});
if (label) {
const int64_t* label_value = label_p->data<int64_t>();
for (size_t i = 0; i < seq_num; ++i) {
for (int64_t j = 0; j < in_dims[1]; ++j) {
int64_t start_pos = i * in_dims[1];
if (j < length_data[i]) {
path[start_pos + j] =
label_value[start_pos + j] == path[start_pos + j] ? 1 : 0;
} else {
path[start_pos + j] = 0;
}
}
}
}
} else {
PADDLE_ENFORCE_EQ(emission_weights->NumLevels(),
1UL,
common::errors::InvalidArgument(
"The Input(Emission) should be a sequence with lod "
"level 1. But received: lod level %u.",
emission_weights->NumLevels()));
auto lod = emission_weights->lod();
PADDLE_ENFORCE_GT(
lod.size(),
0,
common::errors::InvalidArgument(
"Input(Emission) must be a sequence. But received: lod level %u.",
lod.size()));
const size_t level = 0;
const size_t seq_num = lod[level].size() - 1;
for (size_t i = 0; i < seq_num; ++i) {
if (lod[level][i] == lod[level][i + 1]) continue;
int64_t start_pos = static_cast<int64_t>(lod[level][i]);
int64_t end_pos = static_cast<int64_t>(lod[level][i + 1]);
DenseTensor decoded_path_one_seq =
decoded_path->Slice(start_pos, end_pos);
Decode<T, Context>(dev_ctx,
emission_weights->Slice(start_pos, end_pos),
*transition_weights,
&decoded_path_one_seq);
}
if (label) {
PADDLE_ENFORCE_EQ(label_p->NumLevels(),
1UL,
common::errors::InvalidArgument(
"The Input(label) should be a sequence with lod "
"level 1. But received: lod level %u.",
label_p->NumLevels()));
const int64_t* label_value = label_p->data<int64_t>();
size_t numel = label->numel();
for (size_t i = 0; i < numel; ++i) {
path[i] = label_value[i] == path[i] ? 1 : 0;
}
}
}
}
} // namespace phi
PD_REGISTER_KERNEL(
crf_decoding, CPU, ALL_LAYOUT, phi::CRFDecodingOpKernel, float, double) {
kernel->OutputAt(0).SetDataType(phi::DataType::INT64);
}

Some files were not shown because too many files have changed in this diff Show More