Skip to content

Commit da33f7b

Browse files
author
zhangkaihuo
authored
[Sparse]Sparse add support gpu (#45974)
1 parent 2d45f68 commit da33f7b

4 files changed

Lines changed: 175 additions & 1 deletion

File tree

paddle/phi/kernels/sparse/elementwise_grad_kernel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ limitations under the License. */
1515
#pragma once
1616

1717
#include "paddle/phi/core/dense_tensor.h"
18+
#include "paddle/phi/core/sparse_coo_tensor.h"
1819
#include "paddle/phi/core/sparse_csr_tensor.h"
1920
#include "paddle/phi/kernels/empty_kernel.h"
2021

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/* Copyright (c) 2022 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/sparse/elementwise_grad_kernel.h"
16+
#include "paddle/phi/core/kernel_registry.h"
17+
#include "paddle/phi/core/tensor_utils.h"
18+
#include "paddle/phi/kernels/sparse/empty_kernel.h"
19+
20+
namespace phi {
21+
namespace sparse {
22+
23+
template <typename T, typename Context>
24+
void ElementWiseAddCooGradKernel(const Context& dev_ctx,
25+
const SparseCooTensor& x,
26+
const SparseCooTensor& y,
27+
const SparseCooTensor& dout,
28+
SparseCooTensor* dx,
29+
SparseCooTensor* dy) {
30+
if (dx) {
31+
EmptyLikeCooKernel<T, Context>(dev_ctx, x, dx);
32+
Copy(dev_ctx, dout, dev_ctx.GetPlace(), false, dx);
33+
}
34+
35+
if (dy) {
36+
EmptyLikeCooKernel<T, Context>(dev_ctx, y, dy);
37+
Copy(dev_ctx, dout, dev_ctx.GetPlace(), false, dy);
38+
}
39+
}
40+
41+
} // namespace sparse
42+
} // namespace phi
43+
44+
PD_REGISTER_KERNEL(add_coo_coo_grad,
45+
GPU,
46+
ALL_LAYOUT,
47+
phi::sparse::ElementWiseAddCooGradKernel,
48+
float,
49+
double,
50+
int16_t,
51+
int,
52+
int64_t,
53+
phi::dtype::float16) {
54+
kernel->InputAt(0).SetDataLayout(phi::DataLayout::SPARSE_COO);
55+
kernel->InputAt(1).SetDataLayout(phi::DataLayout::SPARSE_COO);
56+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/* Copyright (c) 2022 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 <thrust/equal.h>
16+
#include <thrust/execution_policy.h>
17+
18+
#include "paddle/phi/kernels/elementwise_add_kernel.h"
19+
#include "paddle/phi/kernels/sparse/elementwise_kernel.h"
20+
#include "paddle/phi/kernels/sparse/empty_kernel.h"
21+
22+
#include "paddle/phi/core/enforce.h"
23+
#include "paddle/phi/core/kernel_registry.h"
24+
#include "paddle/phi/core/visit_type.h"
25+
26+
namespace phi {
27+
namespace sparse {
28+
29+
template <typename T, typename IntT>
30+
void ElementWiseAddCooGPUKernel(const GPUContext& dev_ctx,
31+
const SparseCooTensor& x,
32+
const SparseCooTensor& y,
33+
SparseCooTensor* out) {
34+
const auto& x_indices = x.indices();
35+
const auto& y_indices = y.indices();
36+
PADDLE_ENFORCE_EQ(
37+
x_indices.numel(),
38+
y_indices.numel(),
39+
phi::errors::PreconditionNotMet(
40+
"The numel of x.indices() and y.indices() should be equal"));
41+
const IntT* x_indices_ptr = x_indices.data<IntT>();
42+
const IntT* y_indices_ptr = y_indices.data<IntT>();
43+
#ifdef PADDLE_WITH_HIP
44+
bool is_same = thrust::equal(thrust::hip::par.on(dev_ctx.stream()),
45+
#else
46+
bool is_same = thrust::equal(thrust::cuda::par.on(dev_ctx.stream()),
47+
#endif
48+
x_indices_ptr,
49+
x_indices_ptr + x_indices.numel(),
50+
y_indices_ptr);
51+
PADDLE_ENFORCE_EQ(
52+
is_same,
53+
true,
54+
phi::errors::PreconditionNotMet(
55+
"Currently, ElementWiseAddCooKernel only supports the case "
56+
"where x and y have the same indices"));
57+
EmptyLikeCooKernel<T, GPUContext>(dev_ctx, x, out);
58+
phi::AddKernel<T, GPUContext>(
59+
dev_ctx, x.values(), y.values(), out->mutable_values());
60+
}
61+
62+
template <typename T, typename Context>
63+
void ElementWiseAddCooKernel(const Context& dev_ctx,
64+
const SparseCooTensor& x,
65+
const SparseCooTensor& y,
66+
SparseCooTensor* out) {
67+
PD_VISIT_BASE_INTEGRAL_TYPES(x.indices().dtype(), "VerifyIndices", ([&] {
68+
ElementWiseAddCooGPUKernel<T, data_t>(
69+
dev_ctx, x, y, out);
70+
}));
71+
}
72+
73+
} // namespace sparse
74+
} // namespace phi
75+
76+
PD_REGISTER_KERNEL(add_coo_coo,
77+
GPU,
78+
ALL_LAYOUT,
79+
phi::sparse::ElementWiseAddCooKernel,
80+
float,
81+
double,
82+
int16_t,
83+
int,
84+
int64_t,
85+
phi::dtype::float16) {
86+
kernel->InputAt(0).SetDataLayout(phi::DataLayout::SPARSE_COO);
87+
kernel->InputAt(1).SetDataLayout(phi::DataLayout::SPARSE_COO);
88+
}

python/paddle/fluid/tests/unittests/test_sparse_elementwise_op.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import numpy as np
2020
import paddle
21-
from paddle.fluid.framework import _test_eager_guard
21+
import paddle.incubate.sparse as sparse
2222

2323
op_list = [__add__, __sub__, __mul__, __truediv__]
2424

@@ -134,6 +134,35 @@ def test_support_dtypes_coo(self):
134134
for op in op_list:
135135
self.func_test_coo(op)
136136

137+
def test_add_same_indices(self):
138+
indices_data = [[0, 1], [0, 3]]
139+
values1_data = [[1.0], [2.0]]
140+
values2_data = [[1.0], [2.0]]
141+
shape = [2, 4, 2]
142+
143+
sp_a = sparse.sparse_coo_tensor(indices_data,
144+
values1_data,
145+
shape,
146+
stop_gradient=False)
147+
sp_b = sparse.sparse_coo_tensor(indices_data,
148+
values2_data,
149+
shape,
150+
stop_gradient=False)
151+
152+
values1 = paddle.to_tensor(values1_data, stop_gradient=False)
153+
values2 = paddle.to_tensor(values2_data, stop_gradient=False)
154+
155+
#c.values() = a.values() + b.values()
156+
sp_c = sparse.add(sp_a, sp_b)
157+
sp_c.backward()
158+
ref_c = values1 + values2
159+
ref_c.backward()
160+
np.testing.assert_allclose(sp_c.values().numpy(), ref_c.numpy())
161+
np.testing.assert_allclose(sp_a.grad.values().numpy(),
162+
values1.grad.numpy())
163+
np.testing.assert_allclose(sp_b.grad.values().numpy(),
164+
values2.grad.numpy())
165+
137166

138167
if __name__ == "__main__":
139168
paddle.device.set_device('cpu')

0 commit comments

Comments
 (0)