diff --git a/tensorflow/python/debug/lib/debug_events_reader.py b/tensorflow/python/debug/lib/debug_events_reader.py index af4d4d0974d..4adb97de25b 100644 --- a/tensorflow/python/debug/lib/debug_events_reader.py +++ b/tensorflow/python/debug/lib/debug_events_reader.py @@ -308,14 +308,17 @@ class Execution(ExecutionDigest): graph_id: ID of the executed FuncGraph (applicable only the execution of a tf.function). `None` for the eager execution of an individual op. input_tensor_ids: IDs of the input (eager) tensor(s) for this execution, if - any. + any. If the eager execution has no input tensor, this is `None`. Else, + this is a `tuple` of `int`s. output_tensor_ids: IDs of the output (eager) tensor(s) from this execution, - if any. + if any. If the eager execution produces no output tensor, this is `None`. + Else, this is a `tuple` of `int`s. debug_tensor_values: Values of the debug tensor(s), applicable only to non-FULL_TENSOR tensor debug mode. A tuple of list of numbers. Each element of the tuple corresponds to an output tensor of the execution. See documentation of the various TensorDebugModes for the semantics of the - numbers. + numbers. If the eager execution produces no output tensor, this is + `None`. Else, this is a `tuple` of `list`s. """ def __init__(self, @@ -362,7 +365,7 @@ class Execution(ExecutionDigest): @property def num_outputs(self): - return len(self._output_tensor_ids) + return len(self._output_tensor_ids) if self._output_tensor_ids else 0 @property def output_tensor_ids(self): @@ -542,6 +545,8 @@ class GraphOpCreationDigest(BaseDigest): op_type: Type name of the op (e.g., "MatMul"). op_name: Name of the op (e.g., "dense_1/MatMul"). output_tensor_ids: Debugger-generated IDs for the output(s) of the op. + If the op produces no output tensor, this is `None`. Else, this is a + `tuple` of `int`s. input_names: Names of the input tensors to the op. device_name: The name of the device that the op is placed on (if available). host_name: Name of the host on which the op is created. @@ -588,7 +593,7 @@ class GraphOpCreationDigest(BaseDigest): @property def num_outputs(self): - return len(self._output_tensor_ids) + return len(self._output_tensor_ids) if self.output_tensor_ids else 0 @property def input_names(self): diff --git a/tensorflow/python/debug/lib/debug_events_writer_test.py b/tensorflow/python/debug/lib/debug_events_writer_test.py index 8002671450b..57721c1450f 100644 --- a/tensorflow/python/debug/lib/debug_events_writer_test.py +++ b/tensorflow/python/debug/lib/debug_events_writer_test.py @@ -583,7 +583,7 @@ class DebugEventsWriterTest(dumping_callback_test_lib.DumpingCallbackTestBase, self.assertEqual(traces[-1].op_name, "Op_%d" % (expected_end - 1)) -class DataObjectsTest(test_util.TensorFlowTestCase): +class DataObjectsTest(test_util.TensorFlowTestCase, parameterized.TestCase): def jsonRoundTripCheck(self, obj): self.assertEqual( @@ -660,6 +660,22 @@ class DataObjectsTest(test_util.TensorFlowTestCase): self.assertIsNone(json["output_tensor_ids"]) self.assertIsNone(json["debug_tensor_values"]) + @parameterized.named_parameters( + ("EmptyList", []), + ("None", None), + ) + def testExecutionWithNoOutputTensorsReturnsZeroForNumOutputs( + self, output_tensor_ids): + execution = debug_events_reader.Execution( + debug_events_reader.ExecutionDigest(1234, 5678, "FooOp"), + "localhost", ("a1", "b2"), + debug_event_pb2.TensorDebugMode.FULL_HEALTH, + graph_id="abcd", + input_tensor_ids=[13, 37], + output_tensor_ids=output_tensor_ids, + debug_tensor_values=None) + self.assertEqual(execution.num_outputs, 0) + def testDebuggedDeviceToJons(self): debugged_device = debug_events_reader.DebuggedDevice("/TPU:3", 4) self.assertEqual(debugged_device.to_json(), { @@ -697,6 +713,24 @@ class DataObjectsTest(test_util.TensorFlowTestCase): "inner_graph_ids": ["c2d3", "c2d3e4"], }) + @parameterized.named_parameters( + ("EmptyList", []), + ("None", None), + ) + def testGraphOpDigestWithNoOutpusReturnsNumOutputsZero( + self, output_tensor_ids): + op_creation_digest = debug_events_reader.GraphOpCreationDigest( + 1234, + 5678, + "deadbeef", + "FooOp", + "Model_1/Foo_2", + output_tensor_ids, + "machine.cluster", ("a1", "a2"), + input_names=None, + device_name=None) + self.assertEqual(op_creation_digest.num_outputs, 0) + def testGraphOpCreationDigestNoInputNoDeviceNameToJson(self): op_creation_digest = debug_events_reader.GraphOpCreationDigest( 1234,