pytorch

Форк
0
/
test_op_nnpi_fp16.py 
368 строк · 14.2 Кб
1
import numpy as np
2

3
import caffe2.python.fakelowp.init_shared_libs  # noqa
4
import datetime
5
from hypothesis import given, settings
6
from hypothesis import strategies as st
7
from caffe2.proto import caffe2_pb2
8
from caffe2.python import core
9
from caffe2.python import workspace
10
from caffe2.python.onnx.onnxifi import onnxifi_caffe2_net
11
from caffe2.python.fakelowp.test_utils import print_test_debug_info
12
from caffe2.python.fakelowp.test_utils import compute_ulp_error
13
import caffe2.python.serialized_test.serialized_test_util as serial
14

15
core.GlobalInit(["caffe2", "--caffe2_log_level=-3", "--glow_global_fp16=1"])
16

17
kEpsilon = 1e-8
18

19

20
class ArithmeticOpsTest(serial.SerializedTestCase):
21
    def _test_binary_op_graph(self, name, seed):
22
        np.random.seed(seed)
23
        workspace.ResetWorkspace()
24
        # First dimension is the batch size
25
        dims = np.concatenate((np.array([1]), np.random.randint(1, 20, size=3)))
26
        A = np.random.uniform(low=-100.0, high=100.0, size=dims).astype(np.float32)
27
        B = np.random.uniform(low=-100.0, high=100.0, size=dims).astype(np.float32)
28
        # Avoid dividing by 0
29
        B[np.abs(B) < 1e-3] = 1e-3
30
        print(A.shape, B.shape)
31
        pred_net = caffe2_pb2.NetDef()
32
        pred_net.name = "pred"
33
        pred_net.external_input.extend(["A", "B"])
34
        pred_net.external_output.append("C")
35
        pred_net.op.add().CopyFrom(
36
            core.CreateOperator(
37
                name,
38
                ["A", "B"],
39
                ["C"]
40
            )
41
        )
42
        pred_net_ref = caffe2_pb2.NetDef()
43
        pred_net_ref.name = "ref"
44
        pred_net_ref.external_input.extend(["A", "B"])
45
        pred_net_ref.external_output.append("C_ref")
46
        pred_net_ref.op.add().CopyFrom(
47
            core.CreateOperator(
48
                name + "FakeFp16",
49
                ["A", "B"],
50
                ["C_ref"],
51
            )
52
        )
53

54
        shape_hints = {"A": A.shape, "B": B.shape}
55
        pred_net_onnxified = onnxifi_caffe2_net(pred_net,
56
                                                shape_hints,
57
                                                debug=True,
58
                                                adjust_batch=True,
59
                                                use_onnx=False)
60
        print(pred_net_onnxified)
61
        num_onnxified_ops = sum(
62
            1 if o.type == "Onnxifi" else 0 for o in pred_net_onnxified.op)
63
        np.testing.assert_equal(num_onnxified_ops, 1)
64
        workspace.SwitchWorkspace("glow_test_ws", True)
65
        workspace.FeedBlob("A", A)
66
        workspace.FeedBlob("B", B)
67

68
        workspace.CreateNet(pred_net_ref)
69
        workspace.CreateNet(pred_net_onnxified)
70
        num_iterations = 10
71
        for _ in range(num_iterations):
72
            A = np.random.uniform(low=-100.0, high=100.0, size=dims).astype(np.float32)
73
            B = np.random.uniform(low=-100.0, high=100.0, size=dims).astype(np.float32)
74
            # Avoid dividing by 0
75
            B[np.abs(B) < 1e-3] = 1e-3
76

77
            workspace.FeedBlob("A", A)
78
            workspace.FeedBlob("B", B)
79
            # Run caffe2 net
80
            workspace.RunNet(pred_net_ref.name)
81
            Y_c2 = workspace.FetchBlob("C_ref")
82

83
            # Run Glow net
84
            workspace.RunNet(pred_net_onnxified.name)
85
            Y_glow = workspace.FetchBlob("C")
86

87
            Y_glow[Y_glow == np.Inf] = np.finfo(np.float16).max
88
            Y_glow[Y_glow == np.NINF] = np.finfo(np.float16).min
89

90
            # Ignore mismatches solely due to difference in precision
91
            fp16_finite = np.isfinite(A.astype(np.float16) / B.astype(np.float16))
92

93
            # Results should be identical since we are comparing with the C2 emulation
94
            if not np.allclose(Y_c2[fp16_finite], Y_glow[fp16_finite]):
95
                diff = np.abs((Y_glow - Y_c2) / (Y_c2 + kEpsilon))
96
                print_test_debug_info(name, {
97
                    "dims": dims, "iter": _, "seed": seed, "A": A, "B": B,
98
                    "Y_glow": Y_glow, "Y_c2": Y_c2, "diff": diff})
99
                assert(0)
100

101
    @given(seed=st.integers(0, 65534))
102
    @settings(deadline=datetime.timedelta(seconds=10))
103
    def test_add_graph(self, seed):
104
        self._test_binary_op_graph("Add", seed)
105

106
    @given(seed=st.integers(0, 65534))
107
    @settings(deadline=datetime.timedelta(seconds=10))
108
    def test_sub_graph(self, seed):
109
        self._test_binary_op_graph("Sub", seed)
110

111
    @given(seed=st.integers(0, 65534))
112
    @settings(deadline=datetime.timedelta(seconds=10))
113
    def test_mul_graph(self, seed):
114
        self._test_binary_op_graph("Mul", seed)
115

116
    @given(seed=st.integers(0, 65534))
117
    @settings(deadline=datetime.timedelta(seconds=10))
118
    def test_div_graph(self, seed):
119
        self._test_binary_op_graph("Div", seed)
120

121

122
class UnaryOpTest(serial.SerializedTestCase):
123
    def _test_unary_op(self, opname, X, rtol=1e-5, atol=1e-8):
124
        workspace.ResetWorkspace()
125

126
        pred_net = caffe2_pb2.NetDef()
127
        pred_net.name = "pred"
128
        pred_net.external_input.append("X")
129
        pred_net.external_output.append("Y")
130
        pred_net.op.add().CopyFrom(
131
            core.CreateOperator(
132
                opname,
133
                ['X'],
134
                ['Y'])
135
        )
136
        ref_net = caffe2_pb2.NetDef()
137
        ref_net.name = "ref"
138
        ref_net.external_input.append("X")
139
        ref_net.external_output.append("Y")
140
        ref_net.op.add().CopyFrom(
141
            core.CreateOperator(
142
                opname + 'FakeFp16NNPI',
143
                ['X'],
144
                ['Y'])
145
        )
146
        print("REF NET = {}".format(ref_net))
147

148
        shape_hints = {"X": X.shape}
149
        pred_net_onnxified = onnxifi_caffe2_net(pred_net,
150
                                                shape_hints,
151
                                                debug=True,
152
                                                adjust_batch=False,
153
                                                use_onnx=False)
154
        num_onnxified_ops = sum(
155
            1 if o.type == "Onnxifi" else 0 for o in pred_net_onnxified.op)
156
        np.testing.assert_equal(num_onnxified_ops, 1)
157
        workspace.SwitchWorkspace("glow_test_ws", True)
158
        workspace.FeedBlob("X", X)
159
        workspace.CreateNet(ref_net)
160
        workspace.CreateNet(pred_net_onnxified)
161
        # Run Glow net
162
        workspace.RunNet(pred_net_onnxified.name)
163
        Y_glow = workspace.FetchBlob('Y')
164
        # Run caffe2 reference net
165
        workspace.RunNet(ref_net.name)
166
        Y_c2 = workspace.FetchBlob('Y')
167

168
        if not np.allclose(Y_c2, Y_glow, rtol=atol, atol=atol):
169
            diff = np.abs(Y_c2 - Y_glow)
170
            np.save('/tmp/' + opname + 'diff', diff)
171
            np.save('/tmp/' + opname + 'result', Y_c2)
172
            print_test_debug_info(opname, {
173
                "X": X,
174
                "Y_c2": Y_c2,
175
                "Y_glow": Y_glow,
176
                "diff": diff
177
            })
178
            assert(0)
179

180
        return Y_glow
181

182
    def _test_op_w_ulp_error(self, seed, opname, regions, atol=0, err_threshold=2):
183
        ulp_err = 0
184
        for x0, x1 in regions:
185
            X = np.linspace(x0, x1, num=1025, dtype=np.float16).astype(np.float32)
186
            Y_glow = self._test_unary_op(opname, X, atol=atol)
187
            region_err = compute_ulp_error(opname, X, Y_glow)
188
            ulp_err = max(np.max(np.abs(region_err)), ulp_err)
189
        if (ulp_err > err_threshold):
190
            print(r'{} Op detected ulp_err={}'.format(opname, ulp_err))
191
            assert(0)
192

193
    # These tests doesn't need to run multiple times given that it is a
194
    # linear sweep and it is deterministic.
195
    # Once hypothesis.testing version is updated, we can re-enable
196
    # testing with different hypothesis examples.
197
    @given(seed=st.integers(0, 65534))
198
    @settings(deadline=datetime.timedelta(seconds=20))
199
    def test_sigmoid(self, seed):
200
        np.random.seed(seed)
201
        opname = "Sigmoid"
202
        regions = [[-8., -4.], [-4., -2.], [-2., -1.], [-1., -.5], [-.5, -.25],
203
                   [-.25, .25], [.25, .5], [.5, 1.], [1., 2.], [2., 4.],
204
                   [4., 8.]]
205
        self._test_op_w_ulp_error(seed, opname, regions, atol=0, err_threshold=2.5)
206

207
    # These tests doesn't need to run multiple times given that it is a
208
    # linear sweep and it is deterministic.
209
    # Once hypothesis.testing version is updated, we can re-enable
210
    # testing with different hypothesis examples.
211
    @given(seed=st.integers(0, 65534))
212
    @settings(deadline=datetime.timedelta(seconds=20))
213
    def test_tanh(self, seed):
214
        np.random.seed(seed)
215
        opname = "Tanh"
216
        regions = [[2.**(-9), 2.**(-8)], [2.**(-8), 2.**(-7)],
217
                   [2.**(-7), 2.**(-6)], [2.**(-6), 2.**(-5)],
218
                   [2.**(-5), 2.**(-4)], [2.**(-4), 2.**(-3)],
219
                   [2.**(-3), 2.**(-2)], [2.**(-2), 2.**(-1)],
220
                   [2.**(-1), 1.], [1., 2.], [2., 4.], [4., 8.]]
221
        self._test_op_w_ulp_error(seed, opname, regions, atol=0, err_threshold=2)
222

223
    # These tests doesn't need to run multiple times given that it is a
224
    # linear sweep and it is deterministic.
225
    # Once hypothesis.testing version is updated, we can re-enable
226
    # testing with different hypothesis examples.
227
    # TODO: move atol to 1e-8 once we get a non-lowered swish implementation
228
    @given(seed=st.integers(0, 65534))
229
    @settings(deadline=datetime.timedelta(seconds=10))
230
    def test_swish(self, seed):
231
        np.random.seed(seed)
232
        opname = "Swish"
233
        regions = [[-20.5, -11.], [-11., -8.], [-8., -1.], [-1., -0.1],
234
                   [-1. / 8., 1. / 8.], [1. / 8, 5.], [5., 8.]]
235
        self._test_op_w_ulp_error(seed, opname, regions, atol=0.008, err_threshold=384)
236

237
    # These tests doesn't need to run multiple times given that it is a
238
    # linear sweep and it is deterministic.
239
    # Once hypothesis.testing version is updated, we can re-enable
240
    # testing with different hypothesis examples.
241
    @given(seed=st.integers(0, 65534))
242
    @settings(deadline=datetime.timedelta(seconds=10))
243
    def test_logit(self, seed):
244
        np.random.seed(seed)
245
        workspace.ResetWorkspace()
246
        n = 1
247
        m = 15361
248
        X = np.linspace(0, 1, num=m, dtype=np.float32)
249

250
        pred_net = caffe2_pb2.NetDef()
251
        pred_net.name = "pred"
252
        pred_net.external_input.append("X")
253
        pred_net.external_output.append("Y")
254
        pred_net.op.add().CopyFrom(
255
            core.CreateOperator(
256
                'Logit',
257
                ['X'],
258
                ['Y'],
259
                eps=1e-6)
260
        )
261
        ref_net = caffe2_pb2.NetDef()
262
        ref_net.name = "ref"
263
        ref_net.external_input.append("X")
264
        ref_net.external_output.append("Y")
265
        ref_net.op.add().CopyFrom(
266
            core.CreateOperator(
267
                'LogitFakeFp16NNPI',
268
                ['X'],
269
                ['Y'],
270
                eps=1e-6)
271
        )
272
        print("REF NET = {}".format(ref_net))
273

274
        shape_hints = {"X": (n, m)}
275
        pred_net_onnxified = onnxifi_caffe2_net(pred_net,
276
                                                shape_hints,
277
                                                debug=True,
278
                                                adjust_batch=False,
279
                                                use_onnx=False)
280
        num_onnxified_ops = sum(
281
            1 if o.type == "Onnxifi" else 0 for o in pred_net_onnxified.op)
282
        np.testing.assert_equal(num_onnxified_ops, 1)
283
        workspace.SwitchWorkspace("glow_test_ws", True)
284
        workspace.FeedBlob("X", X)
285
        workspace.CreateNet(ref_net)
286
        workspace.CreateNet(pred_net_onnxified)
287
        # Run Glow net
288
        workspace.RunNet(pred_net_onnxified.name)
289
        Y_glow = workspace.FetchBlob('Y')
290
        # Run caffe2 reference net
291
        workspace.RunNet(ref_net.name)
292
        Y_c2 = workspace.FetchBlob('Y')
293

294
        diff = np.abs(Y_c2 - Y_glow)
295
        if np.nanmax(diff) > 9e-3:
296
            np.save('/tmp/logit_diff', diff)
297
            np.save('/tmp/logit_result', Y_c2)
298
            print_test_debug_info('Logit', {
299
                "X": X,
300
                "Y_c2": Y_c2,
301
                "Y_glow": Y_glow,
302
                "diff": diff
303
            })
304
            assert(0)
305

306
class ReluTest(serial.SerializedTestCase):
307
    @given(seed=st.integers(0, 65534))
308
    @settings(deadline=datetime.timedelta(seconds=10))
309
    def relu_test(self, inputs, gc, dc, seed):
310
        np.random.seed(seed)
311
        inputs = np.random.rand(1).astype(np.float32)
312
        X = inputs[0]
313
        # First dimension is the batch size
314
        print(X.shape)
315
        pred_net = caffe2_pb2.NetDef()
316
        pred_net.name = "pred"
317
        pred_net.external_input.extend(["X"])
318
        pred_net.external_output.append("Y")
319
        pred_net.op.add().CopyFrom(
320
            core.CreateOperator(
321
                "Relu",
322
                ["X"],
323
                ["Y"]
324
            )
325
        )
326
        pred_net_ref = caffe2_pb2.NetDef()
327
        pred_net_ref.name = "ref"
328
        pred_net_ref.external_input.extend(["X"])
329
        pred_net_ref.external_output.append("Y_ref")
330
        pred_net_ref.op.add().CopyFrom(
331
            core.CreateOperator(
332
                "ReluFakeFp16",
333
                ["X"],
334
                ["Y_ref"],
335
            )
336
        )
337

338
        shape_hints = {"X": X.shape}
339
        pred_net_onnxified = onnxifi_caffe2_net(pred_net,
340
                                                shape_hints,
341
                                                debug=True,
342
                                                adjust_batch=True,
343
                                                use_onnx=False)
344
        print(pred_net_onnxified)
345
        num_onnxified_ops = sum(
346
            1 if o.type == "Onnxifi" else 0 for o in pred_net_onnxified.op)
347
        np.testing.assert_equal(num_onnxified_ops, 1)
348
        workspace.SwitchWorkspace("glow_test_ws", True)
349
        workspace.FeedBlob("X", X)
350

351
        workspace.CreateNet(pred_net_ref)
352
        workspace.CreateNet(pred_net_onnxified)
353
        workspace.FeedBlob("X", X)
354
        # Run caffe2 net
355
        workspace.RunNet(pred_net_ref.name)
356
        Y_c2 = workspace.FetchBlob("Y_ref")
357

358
        # Run Glow net
359
        workspace.RunNet(pred_net_onnxified.name)
360
        Y_glow = workspace.FetchBlob("Y")
361

362
        # Results should be identical since we are comparing with the C2 emulation
363
        if not np.allclose(Y_c2, Y_glow):
364
            diff = np.abs((Y_glow - Y_c2) / (Y_c2 + kEpsilon))
365
            print_test_debug_info("Relu", {
366
                "seed": seed, "X": X,
367
                "Y_glow": Y_glow, "Y_c2": Y_c2, "diff": diff})
368
            assert(0)
369

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.