[tfdbg2] Fix num_outputs properties when execution or graph op has no output
The previous assumption that `self._output_tensor_ids` is always a tuple is incorrect. It can be `None` for ops without output tensors. Also in this CL: Clarify when properties are `None` and when they are `tuple`s in doc strings of the data objects. PiperOrigin-RevId: 315261796 Change-Id: I398192ba4451e9d8087a2b9e934dff3f561b651a
This commit is contained in:
parent
251a474096
commit
94ce307aa0
@ -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):
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user