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