test_inplace_abn_op.py 8.1 KB
Newer Older
K
Kaipeng Deng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#   Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# 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.

import unittest
import numpy as np
import os
import paddle.fluid.core as core
import paddle.fluid as fluid
from paddle.fluid import compiler
H
hong 已提交
21
import paddle
K
Kaipeng Deng 已提交
22 23 24 25


class TestInplaceANBOpTraining(unittest.TestCase):
    def setUp(self):
26
        self.dtype = np.float32 if core.is_compiled_with_rocm() else np.float64
K
Kaipeng Deng 已提交
27 28 29 30 31 32
        self.N = 4
        self.C = 5
        self.H = 7
        self.W = 9
        self.dshape = [self.N, self.C, self.H, self.W]

33 34 35 36 37 38 39 40 41 42 43
    def build_program(
        self,
        place,
        layout,
        seed,
        only_forward=False,
        activation="identity",
        alpha=1.0,
        use_cuda=False,
        inplace=False,
    ):
K
Kaipeng Deng 已提交
44 45 46 47 48 49
        main = fluid.Program()
        startup = fluid.Program()
        main.random_seed = seed
        startup.random_seed = seed
        with fluid.unique_name.guard():
            with fluid.program_guard(main, startup):
50 51 52 53 54 55 56
                data = fluid.layers.data(
                    name='input',
                    shape=self.dshape,
                    dtype=self.dtype,
                    append_batch_size=False,
                    stop_gradient=False,
                )
K
Kaipeng Deng 已提交
57 58 59 60 61 62 63 64 65 66
                if inplace:
                    bn = fluid.layers.inplace_abn(
                        data,
                        act=activation,
                        param_attr=fluid.ParamAttr(name='bn_scale'),
                        bias_attr=fluid.ParamAttr(name='bn_bias'),
                        moving_mean_name='bn_moving_mean',
                        moving_variance_name='bn_moving_variance',
                        data_layout=layout,
                        is_test=only_forward,
67 68
                        act_alpha=alpha,
                    )
K
Kaipeng Deng 已提交
69 70 71 72 73 74 75 76 77
                else:
                    bn = fluid.layers.batch_norm(
                        data,
                        param_attr=fluid.ParamAttr(name='bn_scale'),
                        bias_attr=fluid.ParamAttr(name='bn_bias'),
                        moving_mean_name='bn_moving_mean',
                        moving_variance_name='bn_moving_variance',
                        data_layout=layout,
                        is_test=only_forward,
78 79
                        in_place=inplace,
                    )
K
Kaipeng Deng 已提交
80 81 82 83 84 85
                    if activation == 'leaky_relu':
                        bn = fluid.layers.leaky_relu(bn, alpha)
                    if activation == 'elu':
                        bn = fluid.layers.elu(bn, alpha)

                # NOTE: in inplace mode input and output of bn
86
                # may have same name, multiply 1. to generate
K
Kaipeng Deng 已提交
87
                # a new Variable for fetch
88
                bn = bn * 1.0
K
Kaipeng Deng 已提交
89 90 91 92 93 94 95 96 97 98 99

                sigmoid = fluid.layers.sigmoid(bn)
                out = fluid.layers.reduce_sum(sigmoid)
                if not only_forward:
                    sgd_opt = fluid.optimizer.SGD(learning_rate=0.0)
                    sgd_opt.backward(out)
        return main, startup, [out, bn]

    def compare(self, place, layout, only_forward, activation, alpha, use_cuda):
        seed = 10
        os.environ['FLAGS_cudnn_deterministic'] = "1"
100
        data = np.random.random(size=self.dshape).astype(self.dtype) * 4.0 - 2
K
Kaipeng Deng 已提交
101 102 103 104

        fetch_outs = []
        fetch_names = []
        for inplace in [False, True]:
105 106 107 108 109 110 111 112 113
            main, startup, outs = self.build_program(
                place,
                layout,
                seed,
                only_forward,
                activation,
                alpha,
                inplace=inplace,
            )
K
Kaipeng Deng 已提交
114 115 116 117
            exe = fluid.Executor(place)
            exe.run(startup)

            fetch_name = [v.name for v in outs] + [
118 119 120 121
                'bn_moving_mean',
                'bn_moving_variance',
                'bn_scale',
                'bn_bias',
K
Kaipeng Deng 已提交
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
            ]
            if not only_forward:
                others = [
                    'inplace_abn_0.tmp_0' if inplace else 'batch_norm_0.tmp_0',
                    'inplace_abn_0.tmp_1' if inplace else 'batch_norm_0.tmp_1',
                    'bn_scale@GRAD',
                    'bn_bias@GRAD',
                    'input@GRAD',
                ]
                fetch_name += others
            for nm in fetch_name:
                fv = fluid.framework._get_var(str(nm), program=main)
                fv.persistable = True

            build_strategy = fluid.BuildStrategy()
137 138 139
            build_strategy.sync_batch_norm = (
                use_cuda and fluid.core.get_cuda_device_count() > 1
            )
K
Kaipeng Deng 已提交
140 141 142 143 144 145
            build_strategy.enable_inplace = inplace
            exec_strategy = fluid.ExecutionStrategy()
            exec_strategy.num_threads = 1 if os.name == 'nt' else 0
            comp_prog1 = compiler.CompiledProgram(main).with_data_parallel(
                outs[0].name if not only_forward else None,
                build_strategy=build_strategy,
146 147 148 149 150
                exec_strategy=exec_strategy,
            )
            bn_fetches = exe.run(
                program=main, feed={'input': data}, fetch_list=fetch_name
            )
K
Kaipeng Deng 已提交
151 152 153
            fetch_outs.append(bn_fetches)
            fetch_names.append(fetch_name)

154 155 156
        for bn_val, inplace_abn_val, name1, name2 in zip(
            *(fetch_outs + fetch_names)
        ):
157 158 159 160 161
            np.testing.assert_allclose(
                bn_val,
                inplace_abn_val,
                rtol=1e-05,
                atol=0.01,
162 163 164 165 166 167 168 169 170 171 172 173 174
                err_msg='Output ('
                + name1
                + ':'
                + name2
                + ') has diff on {} with {} layout and {} activation. \n'.format(
                    place, layout, activation
                )
                + '\nBN     '
                + str(bn_val)
                + '\n'
                + 'Inplace ABN '
                + str(inplace_abn_val),
            )
K
Kaipeng Deng 已提交
175 176 177

    def test_op(self):
        use_cudas = [False, True] if core.is_compiled_with_cuda() else [False]
178
        # use_cudas = [False]
K
Kaipeng Deng 已提交
179 180 181 182
        for use_cuda in use_cudas:
            place = core.CUDAPlace(0) if use_cuda else core.CPUPlace()
            layouts = ["NCHW", "NHWC"]
            for layout in layouts:
183 184 185
                for activation, alpha in zip(
                    [None, 'elu', 'leaky_relu'], [0.0, 1.0, 0.02]
                ):
K
Kaipeng Deng 已提交
186
                    for infer_only in [True, False]:
187 188 189 190 191 192 193 194
                        self.compare(
                            place,
                            layout,
                            infer_only,
                            activation,
                            alpha,
                            use_cuda,
                        )
K
Kaipeng Deng 已提交
195 196 197 198

    def test_all_branches(self):
        seed = 10
        os.environ['FLAGS_cudnn_deterministic'] = "1"
199
        data = np.random.random(size=self.dshape).astype(self.dtype) * 4.0 - 2
K
Kaipeng Deng 已提交
200 201 202 203 204 205 206 207
        use_cudas = [False, True] if core.is_compiled_with_cuda() else [False]
        alpha = 0.1
        layouts = ["NCHW", "NHWC"]
        for use_cuda in use_cudas:
            place = core.CUDAPlace(0) if use_cuda else core.CPUPlace()
            for layout in layouts:
                for activation in ['identity', 'leaky_relu']:
                    main, startup, outs = self.build_program(
208 209 210 211 212 213 214 215 216
                        place,
                        layout,
                        seed,
                        False,
                        activation,
                        alpha,
                        use_cuda,
                        True,
                    )
K
Kaipeng Deng 已提交
217 218 219 220 221 222
                    exe = fluid.Executor(place)
                    exe.run(startup)
                    exe.run(program=main, feed={'input': data})


if __name__ == '__main__':
H
hong 已提交
223
    paddle.enable_static()
K
Kaipeng Deng 已提交
224
    unittest.main()