Skip to content

Commit d0d14d0

Browse files
xymyeahfrankwhzhang
authored andcommitted
[NPU] fix the grad kernel diff bug of gather op (PaddlePaddle#31757)
* fix gather grad kernel diff * fix gather grad kernel diff * fix gather review bug
1 parent 76903ce commit d0d14d0

File tree

2 files changed

+78
-62
lines changed

2 files changed

+78
-62
lines changed

paddle/fluid/operators/gather_op_npu.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,13 @@ class GatherGradOpNPUKernel : public framework::OpKernel<T> {
8787
namespace ops = paddle::operators;
8888
REGISTER_OP_NPU_KERNEL(
8989
gather, ops::GatherOpNPUKernel<paddle::platform::NPUDeviceContext, float>,
90+
ops::GatherOpNPUKernel<paddle::platform::NPUDeviceContext, double>,
9091
ops::GatherOpNPUKernel<paddle::platform::NPUDeviceContext,
9192
paddle::platform::float16>);
9293

9394
REGISTER_OP_NPU_KERNEL(
9495
gather_grad,
9596
ops::GatherGradOpNPUKernel<paddle::platform::NPUDeviceContext, float>,
97+
ops::GatherGradOpNPUKernel<paddle::platform::NPUDeviceContext, double>,
9698
ops::GatherGradOpNPUKernel<paddle::platform::NPUDeviceContext,
9799
paddle::platform::float16>);
Lines changed: 76 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
1+
# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
55
# You may obtain a copy of the License at
66
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
7+
# http://www.apache.org/licenses/LICENSE-2.0
88
#
99
# Unless required by applicable law or agreed to in writing, software
1010
# distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,101 +14,115 @@
1414

1515
from __future__ import print_function
1616

17-
import numpy as np
1817
import unittest
18+
import numpy as np
1919
import sys
2020
sys.path.append("..")
21-
from op_test import OpTest, _set_use_system_allocator
21+
from op_test import OpTest
2222
import paddle
2323
import paddle.fluid as fluid
24+
from paddle.framework import core
2425

2526
paddle.enable_static()
2627
SEED = 2021
2728

2829

30+
def gather_numpy(x, index, axis):
31+
x_transpose = np.swapaxes(x, 0, axis)
32+
tmp_gather = x_transpose[index, ...]
33+
gather = np.swapaxes(tmp_gather, 0, axis)
34+
return gather
35+
36+
2937
@unittest.skipIf(not paddle.is_compiled_with_npu(),
3038
"core is not compiled with NPU")
3139
class TestGatherOp(OpTest):
3240
def setUp(self):
3341
self.set_npu()
34-
self.op_type = "gather"
3542
self.place = paddle.NPUPlace(0)
36-
self.init_dtype()
37-
self.init_input_output()
38-
43+
self.op_type = "gather"
44+
self.config()
45+
xnp = np.random.random(self.x_shape).astype(self.x_type)
3946
self.inputs = {
40-
'X': OpTest.np_dtype_to_fluid_dtype(self.x),
41-
'Index': OpTest.np_dtype_to_fluid_dtype(self.index)
47+
'X': xnp,
48+
'Index': np.array(self.index).astype(self.index_type)
4249
}
43-
self.attrs = {'validate_indices': True}
44-
self.outputs = {'Out': self.out}
50+
self.outputs = {'Out': self.inputs["X"][self.inputs["Index"]]}
4551

4652
def set_npu(self):
4753
self.__class__.use_npu = True
4854

49-
def init_input_output(self):
50-
self.x = np.array([[1, 2], [3, 4], [5, 6]]).astype(self.dtype)
51-
self.index = np.array([1, 2]).astype(np.int)
52-
self.out = np.array([[3, 4], [5, 6]]).astype(self.dtype)
53-
54-
def init_dtype(self):
55-
self.dtype = np.float32
56-
5755
def test_check_output(self):
5856
self.check_output_with_place(self.place, check_dygraph=False)
5957

58+
def test_check_grad(self):
59+
self.check_grad_with_place(
60+
self.place, ['X'],
61+
'Out',
62+
max_relative_error=0.006,
63+
check_dygraph=False)
6064

61-
@unittest.skipIf(not paddle.is_compiled_with_npu(),
62-
"core is not compiled with NPU")
63-
class TestGatherAPI(unittest.TestCase):
64-
def test_name(self):
65-
with paddle.static.program_guard(paddle.static.Program()):
66-
x = paddle.static.data(name="x", shape=[3, 2], dtype="float32")
67-
index = paddle.static.data(name='index', shape=[1], dtype='int32')
68-
69-
out = paddle.gather(x, index, name='gather')
70-
self.assertEqual(('gather' in out.name), True)
65+
def config(self):
66+
"""
67+
For multi-dimension input
68+
"""
69+
self.x_shape = (10, 20)
70+
self.x_type = "float32"
71+
self.index = [1, 3, 5]
72+
self.index_type = "int32"
7173

72-
def test_static(self):
73-
with paddle.static.program_guard(paddle.static.Program()):
7474

75-
x_np = np.array([[1, 2], [3, 4], [5, 6]]).astype('float32')
76-
index_np = np.array([1, 2]).astype('int32')
77-
78-
x = paddle.static.data(name="x", shape=[3, 2], dtype='float32')
79-
index = paddle.static.data(name="index", shape=[2], dtype='int32')
75+
@unittest.skipIf(not paddle.is_compiled_with_npu(),
76+
"core is not compiled with NPU")
77+
class TestCase1(TestGatherOp):
78+
def config(self):
79+
"""
80+
For one dimension input
81+
"""
82+
self.x_shape = (100)
83+
self.x_type = "float32"
84+
self.index = [1, 3, 5]
85+
self.index_type = "int32"
8086

81-
z = paddle.gather(x, index)
8287

88+
@unittest.skipIf(not paddle.is_compiled_with_npu(),
89+
"core is not compiled with NPU")
90+
class API_TestGather(unittest.TestCase):
91+
def test_out1(self):
92+
with fluid.program_guard(fluid.Program(), fluid.Program()):
93+
data1 = fluid.layers.data('data1', shape=[-1, 2], dtype='float32')
94+
index = fluid.layers.data('index', shape=[-1, 1], dtype='int32')
95+
out = paddle.fluid.layers.gather(data1, index)
96+
place = paddle.NPUPlace(0)
97+
exe = fluid.Executor(place)
98+
input = np.array([[1, 2], [3, 4], [5, 6]])
99+
index_1 = np.array([1, 2])
100+
result, = exe.run(feed={"data1": input,
101+
"index": index_1},
102+
fetch_list=[out])
103+
expected_output = np.array([[3, 4], [5, 6]])
104+
self.assertTrue(np.allclose(result, expected_output))
105+
106+
def test_out2(self):
107+
with paddle.static.program_guard(paddle.static.Program(),
108+
paddle.static.Program()):
109+
x = paddle.fluid.data('x', shape=[-1, 2], dtype='float32')
110+
index = paddle.fluid.data('index', shape=[-1, 1], dtype='int32')
111+
out = paddle.gather(x, index)
83112
place = paddle.NPUPlace(0)
84113
exe = paddle.static.Executor(place)
85-
x_value, index_value, z_value = exe.run(
86-
feed={"x": x_np,
87-
"index": index_np}, fetch_list=[x, index, z])
88-
89-
z_expected = np.array([[3, 4], [5, 6]])
90-
self.assertEqual(
91-
(x_value == x_np).all(),
92-
True,
93-
msg="x_value = {}, but expected {}".format(x_value, x_np))
94-
self.assertEqual(
95-
(index_value == index_np).all(),
96-
True,
97-
msg="index_value = {}, but expected {}".format(index_value,
98-
index_np))
99-
self.assertEqual(
100-
(z_value == z_expected).all(),
101-
True,
102-
msg="z_value = {}, but expected {}".format(z_value, z_expected))
103-
104-
def test_backward(self):
105-
# TODO(ascendrc): Test backward after add grad npu op implemented.
106-
pass
114+
x_np = np.array([[1, 2], [3, 4], [5, 6]]).astype('float32')
115+
index_np = np.array([1, 1]).astype('int32')
116+
result, = exe.run(feed={"x": x_np,
117+
"index": index_np},
118+
fetch_list=[out])
119+
expected_output = gather_numpy(x_np, index_np, axis=0)
120+
self.assertTrue(np.allclose(result, expected_output))
107121

108122

109123
@unittest.skipIf(not paddle.is_compiled_with_npu(),
110124
"core is not compiled with NPU")
111-
class TestPowNet(unittest.TestCase):
125+
class TestGatherGrad(unittest.TestCase):
112126
def _test(self, run_npu=True):
113127
main_prog = paddle.static.Program()
114128
startup_prog = paddle.static.Program()
@@ -159,5 +173,5 @@ def test_npu(self):
159173
self.assertTrue(np.allclose(npu_loss, cpu_loss))
160174

161175

162-
if __name__ == '__main__':
176+
if __name__ == "__main__":
163177
unittest.main()

0 commit comments

Comments
 (0)