Skip to content

Commit 3184c3c

Browse files
【Hackathon 5th No.1】 为 Paddle 新增 copysign API (#57785)
* add copysign op * fix codestyle * codestyle * fix test * fix std bug * merge init * merge init * merge init * add static cast * add std * static cast * static cast * copysignf * static cast to float input * float input * static cast to double input * fix * add inplace test * fix api * fix cast when grad * modify paddle.cast_ to cast_ * remove cast in python api * support fp16 && bf16 * set grad y to zero * fix en doc * support number input * add hostdevice * refactor kernel * fix nan when backward * add broadcast unit test * modify .cu * Update __init__.py * Update __init__.py * for ci test * static float * codestyle * static double * fix broadcast, try coverage * Delete paddle/phi/kernels/funcs/broadcast_function.h * remove unused * Update math.py * Update math.py * fix en doc * add test for output dtype, integer unsupported for now * update * update * fix * fix * add cast for input * fix * add pir test * fix doc * fix doc * fix doc * detail doc * adjust for MSVC * fix * Update python/paddle/tensor/math.py Co-authored-by: zachary sun <70642955+sunzhongkai588@users.noreply.github.com> * Update python/paddle/tensor/math.py Co-authored-by: zachary sun <70642955+sunzhongkai588@users.noreply.github.com> * fix doc output dtype, fix Equation * codestyle * codestyle * Update math.py --------- Co-authored-by: zachary sun <70642955+sunzhongkai588@users.noreply.github.com>
1 parent f178fb4 commit 3184c3c

File tree

13 files changed

+852
-0
lines changed

13 files changed

+852
-0
lines changed

paddle/phi/api/yaml/backward.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,17 @@
413413
func : conv3d_transpose_grad
414414
data_type : x
415415

416+
- backward_op : copysign_grad
417+
forward : copysign (Tensor x, Tensor y) -> Tensor(out)
418+
args : (Tensor x, Tensor y, Tensor out_grad)
419+
output : Tensor(x_grad), Tensor(y_grad)
420+
infer_meta :
421+
func : GeneralBinaryGradInferMeta
422+
param : [x, y]
423+
kernel :
424+
func : copysign_grad
425+
inplace : (out_grad -> x_grad)
426+
416427
- backward_op : cos_double_grad
417428
forward : cos_grad (Tensor x, Tensor grad_out) -> Tensor(grad_x)
418429
args : (Tensor x, Tensor grad_out, Tensor grad_x_grad)

paddle/phi/api/yaml/ops.yaml

100644100755
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,16 @@
578578
data_type : x
579579
backward : conv3d_transpose_grad
580580

581+
- op : copysign
582+
args : (Tensor x, Tensor y)
583+
output : Tensor(out)
584+
infer_meta :
585+
func : ElementwiseInferMeta
586+
kernel :
587+
func : copysign
588+
inplace: (x -> out)
589+
backward : copysign_grad
590+
581591
- op : cos
582592
args : (Tensor x)
583593
output : Tensor(out)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
2+
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#pragma once
16+
17+
#include "paddle/phi/core/dense_tensor.h"
18+
#include "paddle/phi/kernels/funcs/elementwise_base.h"
19+
#include "paddle/phi/kernels/funcs/elementwise_functor.h"
20+
21+
namespace phi {
22+
23+
using float16 = phi::dtype::float16;
24+
using bfloat16 = phi::dtype::bfloat16;
25+
26+
template <typename T>
27+
inline HOSTDEVICE auto copysign_func(const T& a, const T& b) {
28+
#ifdef WIN32
29+
using U = typename std::conditional_t<std::is_integral<T>::value, float, T>;
30+
return static_cast<T>(std::copysign(static_cast<U>(a), static_cast<U>(b)));
31+
#else
32+
return static_cast<T>(std::copysign(a, b));
33+
#endif
34+
}
35+
36+
inline HOSTDEVICE phi::dtype::float16 copysign_func(phi::dtype::float16 a,
37+
phi::dtype::float16 b) {
38+
return phi::dtype::raw_uint16_to_float16((a.x & 0x7fff) | (b.x & 0x8000));
39+
}
40+
41+
inline HOSTDEVICE phi::dtype::bfloat16 copysign_func(phi::dtype::bfloat16 a,
42+
phi::dtype::bfloat16 b) {
43+
return phi::dtype::raw_uint16_to_bfloat16((a.x & 0x7fff) | (b.x & 0x8000));
44+
}
45+
46+
template <typename T, typename Context>
47+
void CopySignGradKernel(const Context& dev_ctx,
48+
const DenseTensor& x,
49+
const DenseTensor& y,
50+
const DenseTensor& out_grad,
51+
DenseTensor* x_grad,
52+
DenseTensor* y_grad);
53+
} // namespace phi

paddle/phi/kernels/copysign_kernel.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
2+
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#pragma once
16+
17+
#include "paddle/phi/core/dense_tensor.h"
18+
#include "paddle/phi/kernels/funcs/broadcast_function.h"
19+
#include "paddle/phi/kernels/funcs/elementwise_base.h"
20+
namespace phi {
21+
22+
using float16 = phi::dtype::float16;
23+
using bfloat16 = phi::dtype::bfloat16;
24+
25+
template <typename T>
26+
inline HOSTDEVICE auto copysign_func(const T& a, const T& b) {
27+
#ifdef WIN32
28+
using U = typename std::conditional_t<std::is_integral<T>::value, float, T>;
29+
return static_cast<T>(std::copysign(static_cast<U>(a), static_cast<U>(b)));
30+
#else
31+
return static_cast<T>(std::copysign(a, b));
32+
#endif
33+
}
34+
35+
inline HOSTDEVICE phi::dtype::float16 copysign_func(phi::dtype::float16 a,
36+
phi::dtype::float16 b) {
37+
return phi::dtype::raw_uint16_to_float16((a.x & 0x7fff) | (b.x & 0x8000));
38+
}
39+
40+
inline HOSTDEVICE phi::dtype::bfloat16 copysign_func(phi::dtype::bfloat16 a,
41+
phi::dtype::bfloat16 b) {
42+
return phi::dtype::raw_uint16_to_bfloat16((a.x & 0x7fff) | (b.x & 0x8000));
43+
}
44+
45+
template <typename T>
46+
struct CopySignFunctor {
47+
inline HOSTDEVICE T operator()(const T a, const T b) const {
48+
return copysign_func(a, b);
49+
}
50+
};
51+
template <typename T>
52+
struct InverseCopySignFunctor {
53+
inline HOSTDEVICE T operator()(const T a, const T b) const {
54+
return copysign_func(b, a);
55+
}
56+
};
57+
58+
template <typename T, typename Context>
59+
void CopySignKernel(const Context& dev_ctx,
60+
const DenseTensor& x,
61+
const DenseTensor& y,
62+
DenseTensor* out);
63+
} // namespace phi
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "paddle/phi/kernels/copysign_grad_kernel.h"
16+
17+
#include "paddle/phi/backends/cpu/cpu_context.h"
18+
#include "paddle/phi/core/kernel_registry.h"
19+
#include "paddle/phi/kernels/cpu/elementwise_grad.h"
20+
21+
namespace phi {
22+
23+
template <typename T>
24+
HOSTDEVICE T compute_copysign_grad_dx(T x, T y, T out, T dout) {
25+
if (x == static_cast<T>(0))
26+
return x;
27+
else
28+
return static_cast<T>(dout * (phi::copysign_func(x, y) / x));
29+
}
30+
31+
template <typename T>
32+
struct CopySignGradDX {
33+
HOSTDEVICE T operator()(T x, T y, T out, T dout) const {
34+
return compute_copysign_grad_dx<T>(x, y, out, dout);
35+
}
36+
};
37+
38+
template <typename T>
39+
struct CopySignGradDY {
40+
HOSTDEVICE T operator()(T x, T y, T out, T dout) const {
41+
return static_cast<T>(0);
42+
}
43+
};
44+
45+
template <typename T, typename Context>
46+
void CopySignGradKernel(const Context& dev_ctx,
47+
const DenseTensor& x,
48+
const DenseTensor& y,
49+
const DenseTensor& out_grad,
50+
DenseTensor* x_grad,
51+
DenseTensor* y_grad) {
52+
funcs::ElementwiseGradPreProcess(out_grad, x_grad);
53+
int axis = -1;
54+
phi::funcs::
55+
ElemwiseGradCompute<Context, T, CopySignGradDX<T>, CopySignGradDY<T>>(
56+
dev_ctx,
57+
x,
58+
y,
59+
out_grad,
60+
out_grad,
61+
axis,
62+
x_grad,
63+
y_grad,
64+
CopySignGradDX<T>(),
65+
CopySignGradDY<T>());
66+
}
67+
} // namespace phi
68+
69+
PD_REGISTER_KERNEL(copysign_grad,
70+
CPU,
71+
ALL_LAYOUT,
72+
phi::CopySignGradKernel,
73+
bool,
74+
uint8_t,
75+
int8_t,
76+
int16_t,
77+
int,
78+
int64_t,
79+
float,
80+
double,
81+
phi::dtype::float16,
82+
phi::dtype::bfloat16) {}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "paddle/phi/kernels/copysign_kernel.h"
16+
17+
#include "paddle/phi/backends/cpu/cpu_context.h"
18+
#include "paddle/phi/core/kernel_registry.h"
19+
namespace phi {
20+
template <typename T, typename Context>
21+
void CopySignKernel(const Context& dev_ctx,
22+
const DenseTensor& x,
23+
const DenseTensor& y,
24+
DenseTensor* out) {
25+
dev_ctx.template Alloc<T>(out);
26+
auto x_dims = x.dims();
27+
auto y_dims = y.dims();
28+
if (x_dims.size() >= y_dims.size()) {
29+
funcs::ElementwiseCompute<phi::CopySignFunctor<T>, T>(
30+
dev_ctx, x, y, phi::CopySignFunctor<T>(), out);
31+
} else {
32+
funcs::ElementwiseCompute<phi::InverseCopySignFunctor<T>, T>(
33+
dev_ctx, x, y, phi::InverseCopySignFunctor<T>(), out);
34+
}
35+
}
36+
} // namespace phi
37+
38+
PD_REGISTER_KERNEL(copysign,
39+
CPU,
40+
ALL_LAYOUT,
41+
phi::CopySignKernel,
42+
bool,
43+
uint8_t,
44+
int8_t,
45+
int16_t,
46+
int,
47+
int64_t,
48+
float,
49+
double,
50+
phi::dtype::float16,
51+
phi::dtype::bfloat16) {}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "paddle/phi/kernels/copysign_grad_kernel.h"
16+
17+
#include "paddle/phi/backends/gpu/gpu_context.h"
18+
#include "paddle/phi/core/kernel_registry.h"
19+
#include "paddle/phi/kernels/gpu/elementwise_grad.h"
20+
21+
namespace phi {
22+
23+
template <typename T>
24+
struct CopySignGradXFunctor {
25+
inline HOSTDEVICE T operator()(const T x, const T y, const T dout) const {
26+
if (x == static_cast<T>(0)) return x;
27+
return dout * (phi::copysign_func(x, y) / x);
28+
}
29+
};
30+
31+
template <typename T>
32+
struct CopySignGradYFunctor {
33+
inline HOSTDEVICE T operator()(const T x, const T y, const T dout) const {
34+
return static_cast<T>(0);
35+
}
36+
};
37+
38+
template <typename InT, typename OutT>
39+
struct CopySignGradXYFunctor {
40+
inline HOSTDEVICE phi::Array<OutT, 2> operator()(const InT x,
41+
const InT y,
42+
const InT dout) {
43+
phi::Array<OutT, 2> outs;
44+
// dx
45+
if (x == static_cast<InT>(0))
46+
outs[0] = static_cast<OutT>(0);
47+
else
48+
outs[0] = static_cast<OutT>(dout * (phi::copysign_func(x, y)) / x);
49+
// dy = 0
50+
outs[1] = static_cast<OutT>(0);
51+
return outs;
52+
}
53+
};
54+
55+
template <typename T, typename Context>
56+
void CopySignGradKernel(const Context& dev_ctx,
57+
const DenseTensor& x,
58+
const DenseTensor& y,
59+
const DenseTensor& out_grad,
60+
DenseTensor* x_grad,
61+
DenseTensor* y_grad) {
62+
const auto place = dev_ctx.GetPlace();
63+
int axis = -1;
64+
if (x_grad != nullptr && y_grad != nullptr) {
65+
std::vector<const DenseTensor*> ins = {&x, &y, &out_grad};
66+
GetGradXAndYOut<T>(dev_ctx,
67+
place,
68+
axis,
69+
ins,
70+
out_grad,
71+
x_grad,
72+
y_grad,
73+
CopySignGradXYFunctor<T, T>());
74+
} else if (x_grad != nullptr && y_grad == nullptr) {
75+
std::vector<const DenseTensor*> ins = {&x, &y, &out_grad};
76+
GetGradXOrYOut<T>(
77+
dev_ctx, place, axis, ins, out_grad, x_grad, CopySignGradXFunctor<T>());
78+
} else if (y_grad != nullptr && x_grad == nullptr) {
79+
std::vector<const DenseTensor*> ins = {&x, &y, &out_grad};
80+
GetGradXOrYOut<T>(
81+
dev_ctx, place, axis, ins, out_grad, y_grad, CopySignGradYFunctor<T>());
82+
}
83+
}
84+
} // namespace phi
85+
86+
PD_REGISTER_KERNEL(copysign_grad,
87+
GPU,
88+
ALL_LAYOUT,
89+
phi::CopySignGradKernel,
90+
bool,
91+
uint8_t,
92+
int8_t,
93+
int16_t,
94+
int,
95+
int64_t,
96+
float,
97+
double,
98+
phi::dtype::float16,
99+
phi::dtype::bfloat16) {}

0 commit comments

Comments
 (0)