test_cumsum_op.py 18.4 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
        self.enable_cinn = True
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
        self.enable_cinn = True
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 318
        # TODO(thisjiang): set `True` after reduce+cast at shape=[4, 5, 20, 20], dim=[2]'s fusion bug has fixed
        self.enable_cinn = False
319
        self.attrs = {'axis': 2, "exclusive": True}
320 321 322 323 324 325 326 327 328 329 330 331 332 333
        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}
334 335 336 337

    def test_check_output(self):
        self.check_output()

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

341 342
    def init_dtype(self):
        self.dtype = np.float16
343

344 345

class TestSumOpReverseExclusive(OpTest):
346 347
    def setUp(self):
        self.op_type = "cumsum"
G
GGBond8488 已提交
348
        self.prim_op_type = "prim"
W
wanghuancoder 已提交
349
        self.python_api = cumsum_wrapper
350
        self.public_python_api = paddle.cumsum
351 352 353 354 355 356
        self.set_enable_cinn()
        self.init_dtype()
        self.attrs = {
            'axis': 2,
            'reverse': True,
            'exclusive': True,
357
        }
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
        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}
373 374 375 376

    def test_check_output(self):
        self.check_output()

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

380 381
    def init_dtype(self):
        self.dtype = self.dtype_ = np.float64
382

383
    def set_enable_cinn(self):
384
        self.enable_cinn = True
385

E
emailweixu 已提交
386

387 388 389 390 391 392
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):
393 394
            # TODO(thisjiang): set `pass` after reduce+cast at shape=[4, 5, 20, 20], dim=[2]'s fusion bug has fixed
            self.enable_cinn = False
395 396 397 398 399 400 401 402 403 404 405

        def test_check_output(self):
            self.check_output()

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

406
    cls_name = "{}_{}".format(parent.__name__, "Fp16")
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 444 445 446
    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)

447
    cls_name = "{}_{}".format(parent.__name__, "BF16")
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
    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)
464

E
emailweixu 已提交
465

466 467
class BadInputTest(unittest.TestCase):
    def test_error(self):
468
        paddle.enable_static()
469 470 471
        with fluid.program_guard(fluid.Program()):

            def test_bad_x():
472
                data = [1, 2, 4]
473
                result = paddle.cumsum(data, axis=0)
474

475 476 477
            with self.assertRaises(TypeError):
                test_bad_x()
        paddle.disable_static()
478 479


W
WangZhen 已提交
480 481 482 483 484
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')
485 486 487 488 489
        self.place = (
            paddle.CUDAPlace(0)
            if paddle.is_compiled_with_cuda()
            else paddle.CPUPlace()
        )
W
WangZhen 已提交
490 491 492 493 494 495

    def test_dygraph(self):
        paddle.disable_static()
        x = np.random.randn(5, 6)
        axis = 1
        np_out = np.cumsum(x, axis)
496 497 498
        pd_out = paddle.cumsum(
            paddle.to_tensor(x), axis=paddle.to_tensor([axis], dtype='int32')
        )
W
WangZhen 已提交
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
        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)
514
            loss = paddle.mean(out)
515
            sgd = paddle.optimizer.SGD(learning_rate=0.0)
516
            sgd.minimize(paddle.mean(out))
W
WangZhen 已提交
517 518 519 520 521 522 523

            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)
524 525 526
            config = paddle_infer.Config(
                self.save_path + '.pdmodel', self.save_path + '.pdiparams'
            )
W
WangZhen 已提交
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
            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)


545 546
class TestCumSumOpFp16(unittest.TestCase):
    def test_fp16(self):
547
        paddle.enable_static()
548 549 550 551 552 553 554 555 556 557 558 559
        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])
560
        paddle.disable_static()
561 562


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