test_cumsum_op.py 18.0 KB
Newer Older
1
#   Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
E
emailweixu 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14
#
# 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.

W
WangZhen 已提交
15 16
import os
import tempfile
17 18
import unittest

E
emailweixu 已提交
19
import numpy as np
W
wanghuancoder 已提交
20
from eager_op_test import OpTest, convert_float_to_uint16
21

22
import paddle
23
import paddle.inference as paddle_infer
24 25
from paddle import fluid
from paddle.fluid import core
26 27 28 29 30


class TestCumsumOp(unittest.TestCase):
    def run_cases(self):
        data_np = np.arange(12).reshape(3, 4)
Z
Zhou Wei 已提交
31
        data = paddle.to_tensor(data_np)
32 33 34

        y = paddle.cumsum(data)
        z = np.cumsum(data_np)
35
        np.testing.assert_array_equal(z, y.numpy())
36 37 38

        y = paddle.cumsum(data, axis=0)
        z = np.cumsum(data_np, axis=0)
39
        np.testing.assert_array_equal(z, y.numpy())
40 41 42

        y = paddle.cumsum(data, axis=-1)
        z = np.cumsum(data_np, axis=-1)
43
        np.testing.assert_array_equal(z, y.numpy())
44 45 46 47 48 49 50 51 52

        y = paddle.cumsum(data, dtype='float64')
        self.assertTrue(y.dtype == core.VarDesc.VarType.FP64)

        y = paddle.cumsum(data, dtype=np.int32)
        self.assertTrue(y.dtype == core.VarDesc.VarType.INT32)

        y = paddle.cumsum(data, axis=-2)
        z = np.cumsum(data_np, axis=-2)
53
        np.testing.assert_array_equal(z, y.numpy())
54 55 56 57

    def run_static(self, use_gpu=False):
        with fluid.program_guard(fluid.Program()):
            data_np = np.random.random((100, 100)).astype(np.float32)
58
            x = paddle.static.data('X', [100, 100])
59 60 61 62 63 64 65 66 67 68
            y = paddle.cumsum(x)
            y2 = paddle.cumsum(x, axis=0)
            y3 = paddle.cumsum(x, axis=-1)
            y4 = paddle.cumsum(x, dtype='float64')
            y5 = paddle.cumsum(x, dtype=np.int32)
            y6 = paddle.cumsum(x, axis=-2)

            place = fluid.CUDAPlace(0) if use_gpu else fluid.CPUPlace()
            exe = fluid.Executor(place)
            exe.run(fluid.default_startup_program())
69 70 71 72 73 74 75 76 77 78 79
            out = exe.run(
                feed={'X': data_np},
                fetch_list=[
                    y.name,
                    y2.name,
                    y3.name,
                    y4.name,
                    y5.name,
                    y6.name,
                ],
            )
80 81

            z = np.cumsum(data_np)
82
            np.testing.assert_allclose(z, out[0], rtol=1e-05)
83
            z = np.cumsum(data_np, axis=0)
84
            np.testing.assert_allclose(z, out[1], rtol=1e-05)
85
            z = np.cumsum(data_np, axis=-1)
86
            np.testing.assert_allclose(z, out[2], rtol=1e-05)
87 88 89
            self.assertTrue(out[3].dtype == np.float64)
            self.assertTrue(out[4].dtype == np.int32)
            z = np.cumsum(data_np, axis=-2)
90
            np.testing.assert_allclose(z, out[5], rtol=1e-05)
91 92

    def test_cpu(self):
93 94 95
        paddle.disable_static(paddle.fluid.CPUPlace())
        self.run_cases()
        paddle.enable_static()
96 97 98 99 100 101

        self.run_static()

    def test_gpu(self):
        if not fluid.core.is_compiled_with_cuda():
            return
102 103 104
        paddle.disable_static(paddle.fluid.CUDAPlace(0))
        self.run_cases()
        paddle.enable_static()
105 106 107 108 109

        self.run_static(use_gpu=True)

    def test_name(self):
        with fluid.program_guard(fluid.Program()):
110
            x = paddle.static.data('x', [3, 4])
111 112
            y = paddle.cumsum(x, name='out')
            self.assertTrue('out' in y.name)
E
emailweixu 已提交
113 114


W
wanghuancoder 已提交
115 116 117 118
def cumsum_wrapper(x, axis=-1, flatten=False, exclusive=False, reverse=False):
    return paddle._C_ops.cumsum(x, axis, flatten, exclusive, reverse)


E
emailweixu 已提交
119 120 121
class TestSumOp1(OpTest):
    def setUp(self):
        self.op_type = "cumsum"
G
GGBond8488 已提交
122
        self.prim_op_type = "prim"
W
wanghuancoder 已提交
123
        self.python_api = cumsum_wrapper
124
        self.public_python_api = paddle.cumsum
125 126 127 128 129 130 131 132 133
        self.set_enable_cinn()
        self.init_dtype()
        self.set_attrs_input_output()
        if self.dtype == np.uint16:
            self.inputs = {'X': convert_float_to_uint16(self.x)}
            self.outputs = {'Out': convert_float_to_uint16(self.out)}
        else:
            self.inputs = {'X': self.x}
            self.outputs = {'Out': self.out}
E
emailweixu 已提交
134 135

    def test_check_output(self):
136
        self.check_output()
E
emailweixu 已提交
137 138

    def test_check_grad(self):
G
GGBond8488 已提交
139
        self.check_grad(['X'], 'Out', check_prim=True)
E
emailweixu 已提交
140

141 142
    def init_dtype(self):
        self.dtype = self.dtype_ = np.float64
E
emailweixu 已提交
143

144
    def set_enable_cinn(self):
145
        pass
E
emailweixu 已提交
146

147 148 149 150
    def set_attrs_input_output(self):
        self.attrs = {'axis': 2}
        self.x = np.random.random((5, 6, 10)).astype(self.dtype_)
        self.out = self.x.cumsum(axis=2)
E
emailweixu 已提交
151 152


153 154 155 156 157
class TestSumOp2(TestSumOp1):
    def set_attrs_input_output(self):
        self.attrs = {'axis': -1, 'reverse': True}
        self.x = np.random.random((5, 6, 10)).astype(self.dtype_)
        self.out = np.flip(np.flip(self.x, axis=2).cumsum(axis=2), axis=2)
E
emailweixu 已提交
158 159


160 161 162 163 164
class TestSumOp3(TestSumOp1):
    def set_attrs_input_output(self):
        self.attrs = {'axis': 1}
        self.x = np.random.random((5, 6, 10)).astype(self.dtype_)
        self.out = self.x.cumsum(axis=1)
E
emailweixu 已提交
165 166


167 168
class TestSumOp4(TestSumOp1):
    def set_attrs_input_output(self):
E
emailweixu 已提交
169
        self.attrs = {'axis': 0}
170 171
        self.x = np.random.random((5, 6, 10)).astype(self.dtype_)
        self.out = self.x.cumsum(axis=0)
E
emailweixu 已提交
172 173


174 175 176 177
class TestSumOp5(TestSumOp1):
    def set_attrs_input_output(self):
        self.x = np.random.random((5, 20)).astype(self.dtype_)
        self.out = self.x.cumsum(axis=1)
E
emailweixu 已提交
178 179


180 181
class TestSumOp6(TestSumOp1):
    def set_attrs_input_output(self):
182
        self.attrs = {'axis': -1, 'flatten': True}
183 184
        self.x = np.random.random((5, 6, 5)).astype(self.dtype_)
        self.out = self.x.cumsum()
E
emailweixu 已提交
185 186


187 188
class TestSumOp7(TestSumOp1):
    def set_attrs_input_output(self):
189
        self.x = np.random.random(100).astype(self.dtype_)
190
        self.out = self.x.cumsum(axis=0)
E
emailweixu 已提交
191 192


193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
class TestCumsumFP16(unittest.TestCase):
    def check_main(self, x_np, dtype):
        paddle.disable_static()
        x = paddle.to_tensor(x_np.astype(dtype))
        x.stop_gradient = False
        y = paddle.cumsum(x, dtype=dtype)
        x_g = paddle.grad(y, [x])
        y_np = y.numpy().astype('float32')
        x_g_np = x_g[0].numpy().astype('float32')
        paddle.enable_static()
        return y_np, x_g_np

    def test_main(self):
        if not paddle.is_compiled_with_cuda():
            return

        np.random.seed(20)
        x_np = np.random.random([10, 12])
        y_np_1, x_g_np_1 = self.check_main(x_np, 'float16')
        y_np_2, x_g_np_2 = self.check_main(x_np, 'float32')

        np.testing.assert_allclose(y_np_1, y_np_2, rtol=1e-03)
        np.testing.assert_allclose(x_g_np_1, x_g_np_2, rtol=1e-03)


218
class TestSumOpExclusive1(OpTest):
E
emailweixu 已提交
219 220
    def setUp(self):
        self.op_type = "cumsum"
G
GGBond8488 已提交
221
        self.prim_op_type = "prim"
W
wanghuancoder 已提交
222
        self.python_api = cumsum_wrapper
223
        self.public_python_api = paddle.cumsum
224 225 226 227 228 229 230 231 232
        self.set_enable_cinn()
        self.init_dtype()
        self.set_attrs_input_output()
        if self.dtype == np.uint16:
            self.inputs = {'X': convert_float_to_uint16(self.x)}
            self.outputs = {'Out': convert_float_to_uint16(self.out)}
        else:
            self.inputs = {'X': self.x}
            self.outputs = {'Out': self.out}
E
emailweixu 已提交
233 234

    def test_check_output(self):
235
        self.check_output()
E
emailweixu 已提交
236

237
    def test_check_grad(self):
G
GGBond8488 已提交
238
        self.check_grad(['X'], 'Out', check_prim=True)
239

240 241
    def init_dtype(self):
        self.dtype = self.dtype_ = np.float64
242

243
    def set_enable_cinn(self):
244
        pass
245

246 247 248 249 250 251 252 253 254 255
    def set_attrs_input_output(self):
        self.attrs = {'axis': 2, 'exclusive': True}
        self.x = np.random.random((4, 5, 20)).astype(self.dtype_)
        self.out = np.concatenate(
            (
                np.zeros((4, 5, 1), dtype=self.dtype_),
                self.x[:, :, :-1].cumsum(axis=2),
            ),
            axis=2,
        )
256

257

258 259 260 261 262 263 264 265 266 267 268
class TestSumOpExclusive2(TestSumOpExclusive1):
    def set_attrs_input_output(self):
        self.attrs = {'axis': 2, 'exclusive': True}
        self.x = np.random.random((1, 1, 100)).astype(self.dtype_)
        self.out = np.concatenate(
            (
                np.zeros((1, 1, 1), dtype=self.dtype_),
                self.x[:, :, :-1].cumsum(axis=2),
            ),
            axis=2,
        )
269 270


271 272 273 274 275 276 277 278 279 280 281
class TestSumOpExclusive3(TestSumOpExclusive1):
    def set_attrs_input_output(self):
        self.attrs = {'axis': 2, 'exclusive': True}
        self.x = np.random.random((4, 5, 20)).astype(self.dtype_)
        self.out = np.concatenate(
            (
                np.zeros((4, 5, 1), dtype=self.dtype_),
                self.x[:, :, :-1].cumsum(axis=2),
            ),
            axis=2,
        )
282

283

284 285 286 287 288 289 290 291 292 293 294
class TestSumOpExclusive4(TestSumOpExclusive1):
    def set_attrs_input_output(self):
        self.attrs = {'axis': 2, 'exclusive': True}
        self.x = np.random.random((1, 1, 100)).astype(self.dtype_)
        self.out = np.concatenate(
            (
                np.zeros((1, 1, 1), dtype=self.dtype_),
                self.x[:, :, :-1].cumsum(axis=2),
            ),
            axis=2,
        )
295 296


297 298 299 300 301 302 303 304 305 306 307
class TestSumOpExclusive5(TestSumOpExclusive1):
    def set_attrs_input_output(self):
        self.attrs = {'axis': 2, 'exclusive': True}
        self.x = np.random.random((4, 5, 40)).astype(self.dtype_)
        self.out = np.concatenate(
            (
                np.zeros((4, 5, 1), dtype=self.dtype_),
                self.x[:, :, :-1].cumsum(axis=2),
            ),
            axis=2,
        )
308

309

310
class TestSumOpExclusiveFP16(OpTest):
311 312
    def setUp(self):
        self.op_type = "cumsum"
G
GGBond8488 已提交
313
        self.prim_op_type = "prim"
W
wanghuancoder 已提交
314
        self.python_api = cumsum_wrapper
315
        self.public_python_api = paddle.cumsum
316
        self.init_dtype()
317
        self.attrs = {'axis': 2, "exclusive": True}
318 319 320 321 322 323 324 325 326 327 328 329 330 331
        self.x = np.random.random((4, 5, 20)).astype(self.dtype)
        self.out = np.concatenate(
            (
                np.zeros((4, 5, 1), dtype=self.dtype),
                self.x[:, :, :-1].cumsum(axis=2),
            ),
            axis=2,
        )
        if self.dtype == np.uint16:
            self.inputs = {'X': convert_float_to_uint16(self.x)}
            self.outputs = {'Out': convert_float_to_uint16(self.out)}
        else:
            self.inputs = {'X': self.x}
            self.outputs = {'Out': self.out}
332 333 334 335

    def test_check_output(self):
        self.check_output()

336
    def test_check_grad(self):
G
GGBond8488 已提交
337
        self.check_grad(['X'], 'Out', check_prim=True)
338

339 340
    def init_dtype(self):
        self.dtype = np.float16
341

342 343

class TestSumOpReverseExclusive(OpTest):
344 345
    def setUp(self):
        self.op_type = "cumsum"
G
GGBond8488 已提交
346
        self.prim_op_type = "prim"
W
wanghuancoder 已提交
347
        self.python_api = cumsum_wrapper
348
        self.public_python_api = paddle.cumsum
349 350 351 352 353 354
        self.set_enable_cinn()
        self.init_dtype()
        self.attrs = {
            'axis': 2,
            'reverse': True,
            'exclusive': True,
355
        }
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
        self.x = np.random.random((4, 5, 6)).astype(self.dtype_)
        a = np.flip(self.x, axis=2)
        self.out = np.concatenate(
            (
                np.flip(a[:, :, :-1].cumsum(axis=2), axis=2),
                np.zeros((4, 5, 1), dtype=self.dtype_),
            ),
            axis=2,
        )
        if self.dtype == np.uint16:
            self.inputs = {'X': convert_float_to_uint16(self.x)}
            self.outputs = {'Out': convert_float_to_uint16(self.out)}
        else:
            self.inputs = {'X': self.x}
            self.outputs = {'Out': self.out}
371 372 373 374

    def test_check_output(self):
        self.check_output()

375
    def test_check_grad(self):
G
GGBond8488 已提交
376
        self.check_grad(['X'], 'Out', check_prim=True)
377

378 379
    def init_dtype(self):
        self.dtype = self.dtype_ = np.float64
380

381
    def set_enable_cinn(self):
382
        pass
383

E
emailweixu 已提交
384

385 386 387 388 389 390
def create_test_fp16_class(parent, max_relative_error=1e-2):
    class TestCumsumFP16Op(parent):
        def init_dtype(self):
            self.dtype = self.dtype_ = np.float16

        def set_enable_cinn(self):
391
            pass
392 393 394 395 396 397 398 399 400 401 402

        def test_check_output(self):
            self.check_output()

        def test_check_grad(self):
            self.check_grad(
                ['X'],
                'Out',
                check_prim=True,
            )

403
    cls_name = "{}_{}".format(parent.__name__, "Fp16")
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
    TestCumsumFP16Op.__name__ = cls_name
    globals()[cls_name] = TestCumsumFP16Op


create_test_fp16_class(TestSumOp1)
create_test_fp16_class(TestSumOp2)
create_test_fp16_class(TestSumOp3)
create_test_fp16_class(TestSumOp4)
create_test_fp16_class(TestSumOp5)
create_test_fp16_class(TestSumOp6)
create_test_fp16_class(TestSumOpExclusive1)
create_test_fp16_class(TestSumOpExclusive2)
create_test_fp16_class(TestSumOpExclusive3)
create_test_fp16_class(TestSumOpExclusive4)
create_test_fp16_class(TestSumOpExclusive5)
create_test_fp16_class(TestSumOpReverseExclusive)


def create_test_bf16_class(parent):
    @unittest.skipIf(
        not core.is_compiled_with_cuda()
        or not core.is_bfloat16_supported(core.CUDAPlace(0)),
        "core is not compiled with CUDA or not support bfloat16",
    )
    class TestCumsumBF16Op(parent):
        def init_dtype(self):
            self.dtype = np.uint16
            self.dtype_ = np.float32

        def set_enable_cinn(self):
            self.enable_cinn = False

        def test_check_output(self):
            place = paddle.CUDAPlace(0)
            self.check_output_with_place(place, check_prim=True)

        def test_check_grad(self):
            place = paddle.CUDAPlace(0)
            self.check_grad_with_place(place, ["X"], "Out", check_prim=True)

444
    cls_name = "{}_{}".format(parent.__name__, "BF16")
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
    TestCumsumBF16Op.__name__ = cls_name
    globals()[cls_name] = TestCumsumBF16Op


create_test_bf16_class(TestSumOp1)
create_test_bf16_class(TestSumOp2)
create_test_bf16_class(TestSumOp3)
create_test_bf16_class(TestSumOp4)
create_test_bf16_class(TestSumOp5)
create_test_bf16_class(TestSumOp6)
create_test_bf16_class(TestSumOpExclusive1)
create_test_bf16_class(TestSumOpExclusive2)
create_test_bf16_class(TestSumOpExclusive3)
create_test_bf16_class(TestSumOpExclusive4)
create_test_bf16_class(TestSumOpExclusive5)
create_test_bf16_class(TestSumOpReverseExclusive)
461

E
emailweixu 已提交
462

463 464
class BadInputTest(unittest.TestCase):
    def test_error(self):
465
        paddle.enable_static()
466 467 468
        with fluid.program_guard(fluid.Program()):

            def test_bad_x():
469
                data = [1, 2, 4]
470
                result = paddle.cumsum(data, axis=0)
471

472 473 474
            with self.assertRaises(TypeError):
                test_bad_x()
        paddle.disable_static()
475 476


W
WangZhen 已提交
477 478 479 480 481
class TestTensorAxis(unittest.TestCase):
    def setUp(self):
        paddle.seed(2022)
        self.temp_dir = tempfile.TemporaryDirectory()
        self.save_path = os.path.join(self.temp_dir.name, 'tensor_axis_cumsum')
482 483 484 485 486
        self.place = (
            paddle.CUDAPlace(0)
            if paddle.is_compiled_with_cuda()
            else paddle.CPUPlace()
        )
W
WangZhen 已提交
487 488 489 490 491 492

    def test_dygraph(self):
        paddle.disable_static()
        x = np.random.randn(5, 6)
        axis = 1
        np_out = np.cumsum(x, axis)
493 494 495
        pd_out = paddle.cumsum(
            paddle.to_tensor(x), axis=paddle.to_tensor([axis], dtype='int32')
        )
W
WangZhen 已提交
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
        np.testing.assert_allclose(np_out, pd_out.numpy())

    def test_static_and_infer(self):
        paddle.enable_static()
        np_x = np.random.randn(9, 10, 11).astype('float32')
        main_prog = paddle.static.Program()
        starup_prog = paddle.static.Program()
        with paddle.static.program_guard(main_prog, starup_prog):
            # run static
            x = paddle.static.data(shape=np_x.shape, name='x', dtype=np_x.dtype)
            linear = paddle.nn.Linear(np_x.shape[-1], np_x.shape[-1])
            linear_out = linear(x)
            relu_out = paddle.nn.functional.relu(linear_out)
            axis = paddle.full([1], 2, dtype='int64')
            out = paddle.cumsum(relu_out, axis=axis)
511
            loss = paddle.mean(out)
512
            sgd = paddle.optimizer.SGD(learning_rate=0.0)
513
            sgd.minimize(paddle.mean(out))
W
WangZhen 已提交
514 515 516 517 518 519 520

            exe = paddle.static.Executor(self.place)
            exe.run(starup_prog)
            static_out = exe.run(feed={'x': np_x}, fetch_list=[out])

            # run infer
            paddle.static.save_inference_model(self.save_path, [x], [out], exe)
521 522 523
            config = paddle_infer.Config(
                self.save_path + '.pdmodel', self.save_path + '.pdiparams'
            )
W
WangZhen 已提交
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
            if paddle.is_compiled_with_cuda():
                config.enable_use_gpu(100, 0)
            else:
                config.disable_gpu()

            predictor = paddle_infer.create_predictor(config)
            input_names = predictor.get_input_names()
            input_handle = predictor.get_input_handle(input_names[0])
            fake_input = np_x
            input_handle.reshape(np_x.shape)
            input_handle.copy_from_cpu(fake_input)
            predictor.run()
            output_names = predictor.get_output_names()
            output_handle = predictor.get_output_handle(output_names[0])
            infer_out = output_handle.copy_to_cpu()
            np.testing.assert_allclose(static_out[0], infer_out)


542 543
class TestCumSumOpFp16(unittest.TestCase):
    def test_fp16(self):
544
        paddle.enable_static()
545 546 547 548 549 550 551 552 553 554 555 556
        x_np = np.random.random((100, 100)).astype('float16')
        with paddle.static.program_guard(paddle.static.Program()):
            x = paddle.static.data(shape=[100, 100], name='x', dtype='float16')
            y1 = paddle.cumsum(x)
            y2 = paddle.cumsum(x, axis=0)
            y3 = paddle.cumsum(x, axis=-1)
            y4 = paddle.cumsum(x, axis=-2)
            if core.is_compiled_with_cuda():
                place = paddle.CUDAPlace(0)
                exe = paddle.static.Executor(place)
                exe.run(paddle.static.default_startup_program())
                out = exe.run(feed={'x': x_np}, fetch_list=[y1, y2, y3, y4])
557
        paddle.disable_static()
558 559


E
emailweixu 已提交
560 561
if __name__ == '__main__':
    unittest.main()