xref: /aosp_15_r20/external/tensorflow/tensorflow/python/debug/lib/debug_v2_ops_test.py (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1# Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
15"""Test for the internal ops used by tfdbg v2."""
16
17import os
18
19import numpy as np
20
21from tensorflow.core.protobuf import debug_event_pb2
22from tensorflow.python.debug.lib import debug_events_reader
23from tensorflow.python.debug.lib import debug_events_writer
24from tensorflow.python.debug.lib import dumping_callback_test_lib
25from tensorflow.python.eager import def_function
26from tensorflow.python.framework import constant_op
27from tensorflow.python.framework import dtypes
28from tensorflow.python.framework import errors
29from tensorflow.python.framework import errors_impl
30from tensorflow.python.framework import ops
31from tensorflow.python.framework import tensor_util
32from tensorflow.python.framework import test_util
33from tensorflow.python.ops import array_ops
34from tensorflow.python.ops import gen_debug_ops
35from tensorflow.python.ops import math_ops
36from tensorflow.python.platform import googletest
37
38
39class DebugIdentityV2OpTest(dumping_callback_test_lib.DumpingCallbackTestBase):
40  """Tests for DebugIdentityV2Op: when DebugEventsWriter is initialized.
41
42  DebugEventsWriter being initialized prior to DebugIdentityV2 ops being invoked
43  for the first time is the typical case (e.g., tfdbg2 running on a local
44  machine with only local devices.)
45  """
46
47  def setUp(self):
48    super(DebugIdentityV2OpTest, self).setUp()
49    # Testing using a small circular-buffer size.
50    self.circular_buffer_size = 4
51    self.tfdbg_run_id = "test_tfdbg_run"
52    self.writer = debug_events_writer.DebugEventsWriter(
53        self.dump_root, self.tfdbg_run_id, self.circular_buffer_size)
54
55  def tearDown(self):
56    self.writer.Close()
57    super(DebugIdentityV2OpTest, self).tearDown()
58
59  @test_util.run_in_graph_and_eager_modes
60  def testSingleTensorFullTensorDebugModeWithCircularBufferBehavior(self):
61
62    @def_function.function
63    def write_debug_trace(x):
64      square = math_ops.square(x)
65      gen_debug_ops.debug_identity_v2(
66          square,
67          tfdbg_context_id="deadbeaf",
68          op_name="Square",
69          output_slot=0,
70          tensor_debug_mode=debug_event_pb2.TensorDebugMode.FULL_TENSOR,
71          debug_urls=["file://%s" % self.dump_root])
72
73      sqrt = math_ops.sqrt(x)
74      gen_debug_ops.debug_identity_v2(
75          sqrt,
76          tfdbg_context_id="beafdead",
77          op_name="Sqrt",
78          output_slot=0,
79          tensor_debug_mode=debug_event_pb2.TensorDebugMode.FULL_TENSOR,
80          debug_urls=["file://%s" % self.dump_root])
81      return square + sqrt
82
83    x = np.array([3.0, 4.0])
84    # Only the graph-execution trace of the last iteration should be written
85    # to self.dump_root.
86    for _ in range(self.circular_buffer_size // 2 + 1):
87      self.assertAllClose(
88          write_debug_trace(x), [9.0 + np.sqrt(3.0), 16.0 + 2.0])
89
90    with debug_events_reader.DebugEventsReader(self.dump_root) as reader:
91      # Check that the .metadata DebugEvents data file has been created, even
92      # before FlushExecutionFiles() is called.
93      self.assertGreater(reader.starting_wall_time(), 0)
94      self.assertTrue(reader.tensorflow_version())
95      self.assertTrue(reader.tfdbg_file_version().startswith("debug.Event"))
96
97      graph_trace_iter = reader.graph_execution_traces_iterators()[0]
98      # Before FlushExecutionFiles() is called, the .graph_execution_traces file
99      # ought to be empty.
100      with self.assertRaises(StopIteration):
101        next(graph_trace_iter)
102
103      # Flush the circular buffer.
104      self.writer.FlushExecutionFiles()
105      graph_trace_iter = reader.graph_execution_traces_iterators()[0]
106
107      # The circular buffer has a size of 4. So only the data from the
108      # last two iterations should have been written to self.dump_root.
109      for _ in range(2):
110        debug_event = next(graph_trace_iter).debug_event
111        self.assertGreater(debug_event.wall_time, 0)
112        trace = debug_event.graph_execution_trace
113        self.assertEqual(trace.tfdbg_context_id, "deadbeaf")
114        self.assertEqual(trace.op_name, "Square")
115        self.assertEqual(trace.output_slot, 0)
116        self.assertEqual(trace.tensor_debug_mode,
117                         debug_event_pb2.TensorDebugMode.FULL_TENSOR)
118        tensor_value = tensor_util.MakeNdarray(trace.tensor_proto)
119        self.assertAllClose(tensor_value, [9.0, 16.0])
120
121        debug_event = next(graph_trace_iter).debug_event
122        self.assertGreater(debug_event.wall_time, 0)
123        trace = debug_event.graph_execution_trace
124        self.assertEqual(trace.tfdbg_context_id, "beafdead")
125        self.assertEqual(trace.op_name, "Sqrt")
126        self.assertEqual(trace.output_slot, 0)
127        self.assertEqual(trace.tensor_debug_mode,
128                         debug_event_pb2.TensorDebugMode.FULL_TENSOR)
129        tensor_value = tensor_util.MakeNdarray(trace.tensor_proto)
130        self.assertAllClose(tensor_value, [np.sqrt(3.0), 2.0])
131
132      # Only the graph-execution trace of the last iteration should be written
133      # to self.dump_root.
134      with self.assertRaises(StopIteration):
135        next(graph_trace_iter)
136
137  @test_util.run_in_graph_and_eager_modes
138  def testControlFlow(self):
139
140    @def_function.function
141    def collatz(x):
142      counter = constant_op.constant(0, dtype=dtypes.int32)
143      while math_ops.greater(x, 1):
144        counter = counter + 1
145        gen_debug_ops.debug_identity_v2(
146            x,
147            tfdbg_context_id="deadbeaf",
148            op_name="x",
149            output_slot=0,
150            tensor_debug_mode=debug_event_pb2.TensorDebugMode.FULL_TENSOR,
151            debug_urls=["file://%s" % self.dump_root])
152        if math_ops.equal(x % 2, 0):
153          x = math_ops.div(x, 2)
154        else:
155          x = x * 3 + 1
156      return counter
157
158    x = constant_op.constant(10, dtype=dtypes.int32)
159    self.evaluate(collatz(x))
160
161    self.writer.FlushExecutionFiles()
162    with debug_events_reader.DebugEventsReader(self.dump_root) as reader:
163      graph_trace_iter = reader.graph_execution_traces_iterators()[0]
164      try:
165        x_values = []
166        timestamp = 0
167        while True:
168          debug_event = next(graph_trace_iter).debug_event
169          self.assertGreater(debug_event.wall_time, timestamp)
170          timestamp = debug_event.wall_time
171          trace = debug_event.graph_execution_trace
172          self.assertEqual(trace.tfdbg_context_id, "deadbeaf")
173          self.assertEqual(trace.op_name, "x")
174          self.assertEqual(trace.output_slot, 0)
175          self.assertEqual(trace.tensor_debug_mode,
176                           debug_event_pb2.TensorDebugMode.FULL_TENSOR)
177          x_values.append(int(tensor_util.MakeNdarray(trace.tensor_proto)))
178      except StopIteration:
179        pass
180
181      # Due to the circular buffer, only the last 4 iterations of
182      # [10, 5, 16, 8, 4, 2] should have been written.
183      self.assertAllEqual(x_values, [16, 8, 4, 2])
184
185  @test_util.run_in_graph_and_eager_modes
186  def testTwoDumpRoots(self):
187    another_dump_root = os.path.join(self.dump_root, "another")
188    another_debug_url = "file://%s" % another_dump_root
189    another_writer = debug_events_writer.DebugEventsWriter(
190        another_dump_root, "test_tfdbg_run")
191
192    @def_function.function
193    def write_debug_trace(x):
194      # DebugIdentityV2 is a stateful op. It ought to be included by auto
195      # control dependency.
196      square = math_ops.square(x)
197      gen_debug_ops.debug_identity_v2(
198          square,
199          tfdbg_context_id="deadbeaf",
200          tensor_debug_mode=debug_event_pb2.TensorDebugMode.FULL_TENSOR,
201          debug_urls=["file://%s" % self.dump_root, another_debug_url])
202      return square + 1.0
203
204    x = np.array([3.0, 4.0])
205    self.assertAllClose(write_debug_trace(x), np.array([10.0, 17.0]))
206    self.writer.FlushExecutionFiles()
207    another_writer.FlushExecutionFiles()
208    another_writer.Close()
209
210    for debug_root in (self.dump_root, another_dump_root):
211      with debug_events_reader.DebugEventsReader(debug_root) as reader:
212        graph_trace_iter = reader.graph_execution_traces_iterators()[0]
213
214        debug_event = next(graph_trace_iter).debug_event
215        trace = debug_event.graph_execution_trace
216        self.assertEqual(trace.tfdbg_context_id, "deadbeaf")
217        self.assertEqual(trace.op_name, "")
218        self.assertEqual(trace.tensor_debug_mode,
219                         debug_event_pb2.TensorDebugMode.FULL_TENSOR)
220        tensor_value = tensor_util.MakeNdarray(trace.tensor_proto)
221        self.assertAllClose(tensor_value, [9.0, 16.0])
222
223        with self.assertRaises(StopIteration):
224          next(graph_trace_iter)
225
226
227class DebugIdentityV2OpUninitializedWriterTest(
228    dumping_callback_test_lib.DumpingCallbackTestBase):
229  """Tests for DebugIdentityV2Op: when DebugEventsWriter is not initialized.
230
231  This case can occur when DebugIdentityV2Ops are running on a remote
232  TensorFlow server (e.g., a TPU worker).
233  """
234
235  @test_util.run_in_graph_and_eager_modes
236  def testInvokingDebugIdentityV2OpBeforeCreatingDebugEventsWriterWorks(self):
237    circular_buffer_size = 3
238
239    @def_function.function
240    def write_debug_trace(x):
241      # DebugIdentityV2 is a stateful op. It ought to be included by auto
242      # control dependency.
243      square = math_ops.square(x)
244      gen_debug_ops.debug_identity_v2(
245          square,
246          tfdbg_context_id="deadbeaf",
247          op_name="Square",
248          output_slot=0,
249          tensor_debug_mode=debug_event_pb2.TensorDebugMode.FULL_TENSOR,
250          debug_urls=["file://%s" % self.dump_root],
251          circular_buffer_size=circular_buffer_size)
252      return square
253
254    # The DebugIdentityV2 ops are invokes *before* a DebugEventsWriter at the
255    # same dump root is created.
256    for i in range(circular_buffer_size * 2):
257      self.assertAllClose(
258          write_debug_trace(np.array([i]).astype(np.float32)), [i**2.0])
259    writer = debug_events_writer.DebugEventsWriter(self.dump_root,
260                                                   "test_tfdbg_run",
261                                                   circular_buffer_size)
262    writer.FlushNonExecutionFiles()
263    writer.FlushExecutionFiles()
264
265    with debug_events_reader.DebugEventsReader(self.dump_root) as reader:
266      graph_trace_iter = reader.graph_execution_traces_iterators()[0]
267      graph_execution_traces = []
268      while True:
269        try:
270          graph_execution_traces.append(
271              next(graph_trace_iter).debug_event.graph_execution_trace)
272        except StopIteration:
273          break
274      self.assertLen(graph_execution_traces, circular_buffer_size)
275      for i in range(circular_buffer_size):
276        self.assertAllClose(
277            tensor_util.MakeNdarray(graph_execution_traces[i].tensor_proto),
278            [(i + circular_buffer_size)**2.0])
279
280
281class DebugNumericSummaryV2Test(test_util.TensorFlowTestCase):
282
283  @test_util.run_in_graph_and_eager_modes
284  def testDebugNumericSummaryV2OpReduceInfNanThreeSlots(self):
285
286    def debug_summary(x):
287      return self.evaluate(
288          gen_debug_ops.debug_numeric_summary_v2(
289              x,
290              tensor_debug_mode=(
291                  debug_event_pb2.TensorDebugMode.REDUCE_INF_NAN_THREE_SLOTS)))
292
293    self.assertAllEqual(
294        debug_summary(constant_op.constant([])), [0.0, 0.0, 0.0])
295    self.assertAllEqual(
296        debug_summary(constant_op.constant(42.0)), [0.0, 0.0, 0.0])
297    self.assertAllEqual(
298        debug_summary(constant_op.constant([3.0, 4.0])), [0.0, 0.0, 0.0])
299    self.assertAllEqual(
300        debug_summary(constant_op.constant(np.array([3.0, -np.inf]))),
301        [-np.inf, 0.0, 0.0])
302    self.assertAllEqual(
303        debug_summary(constant_op.constant(np.array([[0, 0], [np.nan, 0]]))),
304        [0.0, 0.0, np.nan])
305    self.assertAllEqual(
306        debug_summary(
307            constant_op.constant(np.array([[0, 0], [np.nan, np.inf]]))),
308        [0.0, np.inf, np.nan])
309    self.assertAllEqual(
310        debug_summary(
311            constant_op.constant(np.array([[0, np.inf], [np.nan, -np.inf]]))),
312        [-np.inf, np.inf, np.nan])
313
314    x = np.zeros([100, 100], dtype=np.float16)
315    x[32, 47] = np.nan
316    self.assertAllEqual(
317        debug_summary(constant_op.constant(x)), [0.0, 0.0, np.nan])
318    x = np.zeros([97, 97], dtype=np.float32)
319    x[50, 83] = -np.inf
320    self.assertAllEqual(
321        debug_summary(constant_op.constant(x)), [-np.inf, 0.0, 0.0])
322    x[1, 41] = np.nan
323    self.assertAllEqual(
324        debug_summary(constant_op.constant(x)), [-np.inf, 0.0, np.nan])
325    x = np.zeros([9701], dtype=np.float64)
326    x[9700] = np.nan
327    self.assertAllEqual(
328        debug_summary(constant_op.constant(x)), [0.0, 0.0, np.nan])
329
330  @test_util.run_in_graph_and_eager_modes
331  def testDebugNumericSummaryV2OpLargeTensorIDError(self):
332    modes = [
333        debug_event_pb2.TensorDebugMode.CURT_HEALTH,
334        debug_event_pb2.TensorDebugMode.CONCISE_HEALTH,
335        debug_event_pb2.TensorDebugMode.SHAPE,
336    ]
337    # Maximum allowed tensor_id
338    tensor_id = np.power(2, 53, dtype=np.int64)
339    for mode in modes:
340      self.evaluate(
341          gen_debug_ops.debug_numeric_summary_v2(
342              constant_op.constant(42.0),
343              tensor_debug_mode=mode,
344              tensor_id=tensor_id,
345              output_dtype=dtypes.float64))
346    # Incrementing by one should error
347    tensor_id += 1
348    for mode in modes:
349      with self.assertRaises(errors.InvalidArgumentError):
350        self.evaluate(
351            gen_debug_ops.debug_numeric_summary_v2(
352                constant_op.constant(42.0),
353                tensor_debug_mode=mode,
354                tensor_id=tensor_id,
355                output_dtype=dtypes.float64))
356
357  @test_util.run_in_graph_and_eager_modes
358  def testDebugNumericSummaryV2OpCurtHealthValuesSmall(self):
359
360    def debug_summary(x):
361      return self.evaluate(
362          gen_debug_ops.debug_numeric_summary_v2(
363              x,
364              tensor_debug_mode=(debug_event_pb2.TensorDebugMode.CURT_HEALTH),
365              tensor_id=x._id,
366              output_dtype=dtypes.float64)), x._id
367
368    tensor, tensor_id = debug_summary(constant_op.constant([]))
369    self.assertAllEqual(tensor, [tensor_id, 0.0])
370
371    tensor, tensor_id = debug_summary(constant_op.constant(42.0))
372    self.assertAllEqual(tensor, [tensor_id, 0.0])
373
374    tensor, tensor_id = debug_summary(constant_op.constant([3.0, 4.0]))
375    self.assertAllEqual(tensor, [tensor_id, 0.0])
376
377    tensor, tensor_id = debug_summary(
378        constant_op.constant(np.array([3.0, -np.inf])))
379    self.assertAllEqual(tensor, [tensor_id, 1.0])
380
381    tensor, tensor_id = debug_summary(
382        constant_op.constant(np.array([[0, 0], [np.nan, 0]])))
383    self.assertAllEqual(tensor, [tensor_id, 1.0])
384
385    tensor, tensor_id = debug_summary(
386        constant_op.constant(np.array([[0, 0], [np.nan, np.inf]])))
387    self.assertAllEqual(tensor, [tensor_id, 1.0])
388
389    tensor, tensor_id = debug_summary(
390        constant_op.constant(np.array([[0, np.inf], [np.nan, -np.inf]])))
391    self.assertAllEqual(tensor, [tensor_id, 1.0])
392
393  @test_util.run_in_graph_and_eager_modes
394  def testDebugNumericSummaryV2OpCurtHealthValuesLarge(self):
395
396    def debug_summary(x):
397      return self.evaluate(
398          gen_debug_ops.debug_numeric_summary_v2(
399              x,
400              tensor_debug_mode=(debug_event_pb2.TensorDebugMode.CURT_HEALTH),
401              tensor_id=x._id,
402              output_dtype=dtypes.float64)), x._id
403
404    x = np.zeros([100, 100], dtype=np.float16)
405    x[32, 47] = np.nan
406    tensor, tensor_id = debug_summary(constant_op.constant(x))
407    self.assertAllEqual(tensor, [tensor_id, 1.0])
408    x = np.zeros([97, 97], dtype=np.float32)
409    x[50, 83] = -np.inf
410    tensor, tensor_id = debug_summary(constant_op.constant(x))
411    self.assertAllEqual(tensor, [tensor_id, 1.0])
412    x[1, 41] = np.nan
413    tensor, tensor_id = debug_summary(constant_op.constant(x))
414    self.assertAllEqual(tensor, [tensor_id, 1.0])
415    x = np.zeros([9701], dtype=np.float64)
416    x[9700] = np.nan
417    tensor, tensor_id = debug_summary(constant_op.constant(x))
418    self.assertAllEqual(tensor, [tensor_id, 1.0])
419
420  @test_util.run_in_graph_and_eager_modes
421  def testDebugNumericSummaryV2OpCurtHealthConsistency(self):
422
423    def debug_summary(x):
424      return self.evaluate(
425          gen_debug_ops.debug_numeric_summary_v2(
426              x,
427              tensor_debug_mode=(debug_event_pb2.TensorDebugMode.CURT_HEALTH),
428              tensor_id=x._id,
429              output_dtype=dtypes.float64)), x._id
430
431    x = np.zeros([100, 100], dtype=np.float16)
432    x[43, 99] = np.nan
433    c = constant_op.constant(x)
434    tensor_1, tensor_id_1 = debug_summary(c)
435    tensor_2, tensor_id_2 = debug_summary(c)
436    self.assertAllEqual(tensor_1, tensor_2)
437    self.assertEqual(tensor_id_1, tensor_id_2)
438
439    x = np.zeros([100, 100, 50], dtype=np.float64)
440    x[0, 0, 1] = np.inf
441    c = constant_op.constant(x)
442    tensor_1, tensor_id_1 = debug_summary(c)
443    tensor_2, tensor_id_2 = debug_summary(c)
444    self.assertAllEqual(tensor_1, tensor_2)
445    self.assertEqual(tensor_id_1, tensor_id_2)
446
447    c = constant_op.constant(np.ones((100, 200), np.double))
448    tensor_1, tensor_id_1 = debug_summary(c)
449    tensor_2, tensor_id_2 = debug_summary(c)
450    self.assertAllEqual(tensor_1, tensor_2)
451    self.assertEqual(tensor_id_1, tensor_id_2)
452
453  @test_util.run_in_graph_and_eager_modes
454  def testDebugNumericSummaryV2OpDeterminism(self):
455    x = np.zeros([100, 100, 50], dtype=np.float64)
456    x = constant_op.constant(x)
457    modes = (
458        debug_event_pb2.TensorDebugMode.CONCISE_HEALTH,
459        debug_event_pb2.TensorDebugMode.FULL_HEALTH,
460        )
461    for mode in modes:
462      debug_mode = debug_event_pb2.TensorDebugMode.Name(mode)
463      with test_util.deterministic_ops():
464        if test_util.is_gpu_available(cuda_only=True):
465          with self.assertRaisesRegex(
466              errors_impl.UnimplementedError, "Determinism is not yet "
467              "supported for DebugNumericSummaryV2 when tensor_debug_mode is "
468              + debug_mode + "."):
469            self.evaluate(
470                gen_debug_ops.debug_numeric_summary_v2(
471                    x,
472                    tensor_debug_mode=mode,
473                    tensor_id=x._id,
474                    output_dtype=dtypes.float64))
475
476  @test_util.run_in_graph_and_eager_modes
477  def testDebugNumericSummaryV2OpConciseHealthSmall(self):
478
479    def debug_summary(x):
480      return self.evaluate(
481          gen_debug_ops.debug_numeric_summary_v2(
482              x,
483              tensor_debug_mode=(
484                  debug_event_pb2.TensorDebugMode.CONCISE_HEALTH),
485              tensor_id=x._id,
486              output_dtype=dtypes.float64)), x._id
487
488    tensor, tensor_id = debug_summary(constant_op.constant([]))
489    self.assertAllEqual(tensor, [tensor_id, 0.0, 0.0, 0.0, 0.0])
490
491    tensor, tensor_id = debug_summary(constant_op.constant(42.0))
492    self.assertAllEqual(tensor, [tensor_id, 1.0, 0.0, 0.0, 0.0])
493
494    tensor, tensor_id = debug_summary(constant_op.constant([3.0, 4.0]))
495    self.assertAllEqual(tensor, [tensor_id, 2.0, 0.0, 0.0, 0.0])
496
497    tensor, tensor_id = debug_summary(
498        constant_op.constant(np.array([3.0, -np.inf])))
499    self.assertAllEqual(tensor, [tensor_id, 2.0, 1.0, 0.0, 0.0])
500
501    tensor, tensor_id = debug_summary(
502        constant_op.constant(np.array([[0, 0], [np.nan, 0]])))
503    self.assertAllEqual(tensor, [tensor_id, 4.0, 0.0, 0.0, 1.0])
504
505    tensor, tensor_id = debug_summary(
506        constant_op.constant(np.array([[0, 0], [np.nan, np.inf]])))
507    self.assertAllEqual(tensor, [tensor_id, 4.0, 0.0, 1.0, 1.0])
508
509    tensor, tensor_id = debug_summary(
510        constant_op.constant(np.array([[0, np.inf], [np.nan, -np.inf]])))
511    self.assertAllEqual(tensor, [tensor_id, 4.0, 1.0, 1.0, 1.0])
512
513  @test_util.run_in_graph_and_eager_modes
514  def testDebugNumericSummaryV2OpConciseHealthLarge(self):
515
516    def debug_summary(x):
517      return self.evaluate(
518          gen_debug_ops.debug_numeric_summary_v2(
519              x,
520              tensor_debug_mode=(
521                  debug_event_pb2.TensorDebugMode.CONCISE_HEALTH),
522              tensor_id=x._id,
523              output_dtype=dtypes.float64)), x._id
524
525    x = np.zeros([100, 100], dtype=np.float16)
526    x[32, :] = np.nan
527    tensor, tensor_id = debug_summary(constant_op.constant(x))
528    self.assertAllEqual(tensor, [tensor_id, 10000.0, 0.0, 0.0, 100.0])
529    x = np.zeros([97, 97], dtype=np.float32)
530    x[50, 83:85] = -np.inf
531    tensor, tensor_id = debug_summary(constant_op.constant(x))
532    self.assertAllEqual(tensor, [tensor_id, 97 * 97, 2.0, 0.0, 0.0])
533    x[1:9, 41] = np.nan
534    tensor, tensor_id = debug_summary(constant_op.constant(x))
535    self.assertAllEqual(tensor, [tensor_id, 97 * 97, 2.0, 0.0, 8.0])
536    x = np.zeros([9701], dtype=np.float64)
537    x[9700] = np.nan
538    tensor, tensor_id = debug_summary(constant_op.constant(x))
539    self.assertAllEqual(tensor, [tensor_id, 9701, 0.0, 0.0, 1.0])
540
541  @test_util.run_in_graph_and_eager_modes
542  def testDebugNumericSummaryV2OpConciseHealthConsistency(self):
543
544    def debug_summary(x):
545      return self.evaluate(
546          gen_debug_ops.debug_numeric_summary_v2(
547              x,
548              tensor_debug_mode=(
549                  debug_event_pb2.TensorDebugMode.CONCISE_HEALTH),
550              tensor_id=x._id,
551              output_dtype=dtypes.float64)), x._id
552
553    # Assert the same op is returns a consistent value
554    x = np.zeros([100, 100], dtype=np.float16)
555    x[3, 4] = -np.inf
556    c = constant_op.constant(x)
557    tensor_1, tensor_id_1 = debug_summary(c)
558    tensor_2, tensor_id_2 = debug_summary(c)
559    self.assertAllEqual(tensor_1, tensor_2)
560    self.assertEqual(tensor_id_1, tensor_id_2)
561
562    c = constant_op.constant(np.ones((100, 200), np.double))
563    tensor_1, tensor_id_1 = debug_summary(c)
564    tensor_2, tensor_id_2 = debug_summary(c)
565    self.assertAllEqual(tensor_1, tensor_2)
566    self.assertEqual(tensor_id_1, tensor_id_2)
567
568  @test_util.run_in_graph_and_eager_modes
569  def testDebugNumericSummaryV2OpShapeEmpty(self):
570
571    def debug_summary(x):
572      return self.evaluate(
573          gen_debug_ops.debug_numeric_summary_v2(
574              x,
575              tensor_debug_mode=(debug_event_pb2.TensorDebugMode.SHAPE),
576              tensor_id=x._id,
577              output_dtype=dtypes.float64)), x._id
578
579    tensor, tensor_id = debug_summary(constant_op.constant(0.0))
580    self.assertAllEqual(
581        tensor, [tensor_id, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
582
583  @test_util.run_in_graph_and_eager_modes
584  def testDebugNumericSummaryV2OpShapeSmall(self):
585
586    def debug_summary(x):
587      return self.evaluate(
588          gen_debug_ops.debug_numeric_summary_v2(
589              x,
590              tensor_debug_mode=(debug_event_pb2.TensorDebugMode.SHAPE),
591              tensor_id=x._id,
592              output_dtype=dtypes.float64)), x._id
593
594    x = np.zeros([3, 4], dtype=np.float32)
595    tensor, tensor_id = debug_summary(constant_op.constant(x))
596    self.assertAllEqual(
597        tensor, [tensor_id, 1.0, 2.0, 12.0, 3.0, 4.0, 0.0, 0.0, 0.0, 0.0])
598
599    x = np.ones([1, 2, 3, 4, 5, 6], dtype=np.float16)
600    x[0, 1, 2, 2, 2, 2] = np.nan
601    tensor, tensor_id = debug_summary(constant_op.constant(x))
602    self.assertAllEqual(
603        tensor,
604        [tensor_id, 19, 6.0, 2 * 3 * 4 * 5 * 6, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
605
606    x = np.zeros([2], dtype=np.float32)
607    tensor, tensor_id = debug_summary(constant_op.constant(x))
608    self.assertAllEqual(
609        tensor, [tensor_id, 1.0, 1.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0])
610
611    tensor, tensor_id = debug_summary(constant_op.constant([]))
612    self.assertAllEqual(
613        tensor, [tensor_id, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
614
615  @test_util.run_in_graph_and_eager_modes
616  def testDebugNumericSummaryV2OpShapeLarge(self):
617
618    def debug_summary(x):
619      return self.evaluate(
620          gen_debug_ops.debug_numeric_summary_v2(
621              x,
622              tensor_debug_mode=(debug_event_pb2.TensorDebugMode.SHAPE),
623              tensor_id=x._id,
624              output_dtype=dtypes.float64)), x._id
625
626    x = np.ones([1, 2, 3, 4, 5, 6, 7], dtype=np.double)
627    tensor, tensor_id = debug_summary(constant_op.constant(x))
628    self.assertAllEqual(tensor, [
629        tensor_id, 2.0, 7.0, 2 * 3 * 4 * 5 * 6 * 7, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0
630    ])
631
632  @test_util.run_in_graph_and_eager_modes
633  def testDebugNumericSummaryV2OpFullHealthSmall(self):
634
635    def debug_summary(x):
636      return self.evaluate(
637          gen_debug_ops.debug_numeric_summary_v2(
638              x,
639              tensor_debug_mode=(debug_event_pb2.TensorDebugMode.FULL_HEALTH),
640              tensor_id=x._id,
641              output_dtype=dtypes.float64)), x._id
642
643    tensor, tensor_id = debug_summary(constant_op.constant([]))
644    expected = [tensor_id, -1, 1, 1, 0, 0, 0, 0, 0, 0, 0]
645    self.assertAllEqual(tensor, expected)
646
647    tensor, tensor_id = debug_summary(constant_op.constant(42.0))
648    expected = [tensor_id, -1, 1, 0, 1, 0, 0, 0, 0, 0, 1]
649    self.assertAllEqual(tensor, expected)
650
651    tensor, tensor_id = debug_summary(constant_op.constant([3.0, 4.0]))
652    expected = [tensor_id, -1, 1, 1, 2, 0, 0, 0, 0, 0, 2]
653    self.assertAllEqual(tensor, expected)
654
655    tensor, tensor_id = debug_summary(
656        constant_op.constant(np.array([3, -np.inf], dtype=np.float32)))
657    expected = [tensor_id, -1, 1, 1, 2, 1, 0, 0, 0, 0, 1]
658    self.assertAllEqual(tensor, expected)
659
660    tensor, tensor_id = debug_summary(
661        constant_op.constant(np.array([[0, 0], [np.nan, 0]], dtype=np.float64)))
662    expected = [tensor_id, -1, 2, 2, 4, 0, 0, 1, 0, 3, 0]
663    self.assertAllEqual(tensor, expected)
664
665    tensor, tensor_id = debug_summary(
666        constant_op.constant(
667            np.array([[0, 0], [np.nan, np.inf]], dtype=np.float16)))
668    expected = [tensor_id, -1, 19, 2, 4, 0, 1, 1, 0, 2, 0]
669    self.assertAllEqual(tensor, expected)
670
671    tensor, tensor_id = debug_summary(
672        constant_op.constant(
673            np.array([[0, np.inf], [np.nan, -np.inf]], dtype=np.float32)))
674    expected = [tensor_id, -1, 1, 2, 4, 1, 1, 1, 0, 1, 0]
675    self.assertAllEqual(tensor, expected)
676
677  @test_util.run_in_graph_and_eager_modes
678  def testDebugNumericSummaryV2OpFullHealthLarge(self):
679
680    def debug_summary(x):
681      return self.evaluate(
682          gen_debug_ops.debug_numeric_summary_v2(
683              x,
684              tensor_debug_mode=(debug_event_pb2.TensorDebugMode.FULL_HEALTH),
685              tensor_id=x._id,
686              output_dtype=dtypes.float64)), x._id
687
688    def tensor_counts(arr):
689      counts = [len(np.shape(arr)), np.size(arr), 0, 0, 0, 0, 0, 0]
690      for n in np.ravel(arr):
691        if np.isneginf(n):
692          counts[2] += 1
693        elif np.isposinf(n):
694          counts[3] += 1
695        elif np.isnan(n):
696          counts[4] += 1
697        elif n < 0.:
698          counts[5] += 1
699        elif n == 0.:
700          counts[6] += 1
701        else:
702          counts[7] += 1
703      return counts
704
705    x = np.zeros([50, 50], dtype=np.float16)
706    x[32, 47] = np.nan
707    x[0:4, 3] = np.inf
708    x[40:50, 40:50] = 10
709    x[3, 20] = -10
710    tensor, tensor_id = debug_summary(constant_op.constant(x))
711    expected = [tensor_id, -1, 19] + tensor_counts(x)
712    self.assertAllEqual(tensor, expected)
713
714    x = np.ones([25, 25, 50], dtype=np.float32) * np.inf
715    x[:, :, 1] = np.nan
716    x[:, :, 2] = -np.inf
717    x[:, :, 3] = -1
718    x[:, :, 4] = 0
719    x[:, :, 5] = 1
720    tensor, tensor_id = debug_summary(constant_op.constant(x))
721    expected = [tensor_id, -1, 1] + tensor_counts(x)
722    self.assertAllEqual(tensor, expected)
723    x[0, 0, 0] = np.nan
724    tensor, tensor_id = debug_summary(constant_op.constant(x))
725    expected = [
726        tensor_id,
727        -1,
728        1,
729    ] + tensor_counts(x)
730    self.assertAllEqual(tensor, expected)
731    x = np.zeros([9701], dtype=np.float64)
732    x[9700] = np.nan
733    tensor, tensor_id = debug_summary(constant_op.constant(x))
734    expected = [tensor_id, -1, 2] + tensor_counts(x)
735    self.assertAllEqual(tensor, expected)
736
737  @test_util.run_in_graph_and_eager_modes
738  def testDebugNumericSummaryV2OpFullHealthConsistency(self):
739
740    def debug_summary(x):
741      return self.evaluate(
742          gen_debug_ops.debug_numeric_summary_v2(
743              x,
744              tensor_debug_mode=(debug_event_pb2.TensorDebugMode.FULL_HEALTH),
745              tensor_id=x._id,
746              output_dtype=dtypes.float64)), x._id
747
748    # Assert the same op is returns a consistent value
749    x = np.zeros([100, 100], dtype=np.float16)
750    x[32, 47] = np.nan
751    x[0:4, 3] = np.inf
752    x[90:100, 90:100] = 10
753    x[3, 20] = -10
754    c = constant_op.constant(x)
755    tensor_1, tensor_id_1 = debug_summary(c)
756    tensor_2, tensor_id_2 = debug_summary(c)
757    self.assertAllEqual(tensor_1, tensor_2)
758    self.assertEqual(tensor_id_1, tensor_id_2)
759
760    x = np.ones((100, 200, 3, 10), np.double)
761    x[1, 30, 2] = 10
762    x[5, :, 0, 1] = np.nan
763    x[90:100, 150, :, :] = np.inf
764    c = constant_op.constant(x)
765    tensor_1, tensor_id_1 = debug_summary(c)
766    tensor_2, tensor_id_2 = debug_summary(c)
767    self.assertAllEqual(tensor_1, tensor_2)
768    self.assertEqual(tensor_id_1, tensor_id_2)
769
770  def testCheckNumericsV2OpNegativeAndPositiveInf(self):
771    """Test that CheckNumericsV2 op distinguishes negative and positive infs."""
772    with self.session(graph=ops.Graph()):
773      t1 = constant_op.constant([-1.0, 1.0])
774      t2 = constant_op.constant([0.0, 0.0])
775      with self.assertRaisesRegex(
776          errors.InvalidArgumentError,
777          r"pass through test.*had -Inf and \+Inf values"):
778        self.evaluate(
779            array_ops.check_numerics_v2(t1 / t2, message="pass through test"))
780
781  def testCheckNumericsV2OpNegativeAndPositiveInfAndNaN(self):
782    """CheckNumericsV2 op distinguishes - & + infs when nan is present."""
783    with self.session(graph=ops.Graph()):
784      t1 = constant_op.constant([-1.0, 1.0, 0.0])
785      t2 = constant_op.constant([0.0, 0.0, 0.0])
786      with self.assertRaisesRegex(
787          errors.InvalidArgumentError,
788          r"pass through test.*had -Inf, \+Inf, and NaN values"):
789        self.evaluate(
790            array_ops.check_numerics_v2(t1 / t2, message="pass through test"))
791
792  def testCheckNumericsV2PositiveInfAndNaN(self):
793    """Test that CheckNumericsV2 op shows sign of inf when nan is present."""
794    with self.session(graph=ops.Graph()):
795      t1 = constant_op.constant([0.0, 1.0])
796      t2 = constant_op.constant([0.0, 0.0])
797      with self.assertRaisesRegex(
798          errors.InvalidArgumentError,
799          r"pass through test.*had \+Inf and NaN values"):
800        self.evaluate(
801            array_ops.check_numerics_v2(t1 / t2, message="pass through test"))
802
803
804if __name__ == "__main__":
805  ops.enable_eager_execution()
806  googletest.main()
807