test_cumsum_op.py 18.1 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
        self.enable_cinn = True
318
        self.attrs = {'axis': 2, "exclusive": True}
319 320 321 322 323 324 325 326 327 328 329 330 331 332
        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}
333 334 335 336

    def test_check_output(self):
        self.check_output()

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

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

343 344

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

    def test_check_output(self):
        self.check_output()

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

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

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

E
emailweixu 已提交
385

386 387 388 389 390 391
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):
392
            self.enable_cinn = True
393 394 395 396 397 398 399 400 401 402 403

        def test_check_output(self):
            self.check_output()

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

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

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

E
emailweixu 已提交
463

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

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

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


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

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

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


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


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