Skip to content

Commit 37d758b

Browse files
No public description
PiperOrigin-RevId: 779797363
1 parent faa8c91 commit 37d758b

3 files changed

Lines changed: 169 additions & 70 deletions

File tree

tensorflow/python/debug/lib/BUILD

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ py_strict_library(
125125
deps = [
126126
":debug_graphs",
127127
"//tensorflow/core:protos_all_py",
128+
"//tensorflow/core/framework:graph_proto_py_proto",
129+
"//tensorflow/core/util:event_proto_py_proto",
128130
"//tensorflow/python/framework:tensor_util",
129131
"//tensorflow/python/platform:gfile",
130132
"//tensorflow/python/platform:tf_logging",
@@ -280,6 +282,7 @@ py_strict_test(
280282
deps = [
281283
":debug_data",
282284
"//tensorflow/core:protos_all_py",
285+
"//tensorflow/core/framework:graph_proto_py_proto",
283286
"//tensorflow/python/framework:test_lib",
284287
"//tensorflow/python/lib/io:file_io",
285288
"//tensorflow/python/platform:client_testlib",

tensorflow/python/debug/lib/debug_data.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,12 @@ def _load_partition_graphs(self, client_partition_graphs, validate):
785785
device_name))
786786

787787
for partition_graph, maybe_device_name in partition_graphs_and_device_names:
788+
# Normalize all node names and their input references directly in the
789+
# GraphDef protobuf before any other processing. b/429335661
790+
for node in partition_graph.node:
791+
node.name = re.sub(r"/+", "/", node.name)
792+
for i, inp in enumerate(node.input):
793+
node.input[i] = re.sub(r"/+", "/", inp)
788794
debug_graph = debug_graphs.DebugGraph(partition_graph,
789795
device_name=maybe_device_name)
790796
self._debug_graphs[debug_graph.device_name] = debug_graph

tensorflow/python/debug/lib/debug_data_test.py

Lines changed: 160 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,29 @@ class DeviceNamePathConversionTest(test_util.TensorFlowTestCase):
3333

3434
def testDeviceNameToDevicePath(self):
3535
self.assertEqual(
36-
debug_data.METADATA_FILE_PREFIX + debug_data.DEVICE_TAG +
37-
",job_ps,replica_1,task_2,cpu_0",
38-
debug_data.device_name_to_device_path("/job:ps/replica:1/task:2/cpu:0"))
36+
debug_data.METADATA_FILE_PREFIX
37+
+ debug_data.DEVICE_TAG
38+
+ ",job_ps,replica_1,task_2,cpu_0",
39+
debug_data.device_name_to_device_path("/job:ps/replica:1/task:2/cpu:0"),
40+
)
3941

4042
def testDevicePathToDeviceName(self):
4143
self.assertEqual(
4244
"/job:ps/replica:1/task:2/cpu:0",
4345
debug_data.device_path_to_device_name(
44-
debug_data.METADATA_FILE_PREFIX + debug_data.DEVICE_TAG +
45-
",job_ps,replica_1,task_2,cpu_0"))
46+
debug_data.METADATA_FILE_PREFIX
47+
+ debug_data.DEVICE_TAG
48+
+ ",job_ps,replica_1,task_2,cpu_0"
49+
),
50+
)
4651

4752

4853
class HasNanOrInfTest(test_util.TensorFlowTestCase):
4954

5055
def setUp(self):
5156
self._dummy_datum = dummy_datum = debug_data.DebugTensorDatum(
52-
"/foo", "bar_0_DebugIdentity_42")
57+
"/foo", "bar_0_DebugIdentity_42"
58+
)
5359

5460
def testNaN(self):
5561
a = np.array([np.nan, np.nan, 7.0])
@@ -72,14 +78,22 @@ def testEmpty(self):
7278
self.assertFalse(debug_data.has_inf_or_nan(self._dummy_datum, a))
7379

7480
def testInconvertibleTensorProto(self):
75-
self.assertFalse(debug_data.has_inf_or_nan(
76-
self._dummy_datum,
77-
debug_data.InconvertibleTensorProto(tensor_pb2.TensorProto(),
78-
initialized=False)))
79-
self.assertFalse(debug_data.has_inf_or_nan(
80-
self._dummy_datum,
81-
debug_data.InconvertibleTensorProto(tensor_pb2.TensorProto(),
82-
initialized=True)))
81+
self.assertFalse(
82+
debug_data.has_inf_or_nan(
83+
self._dummy_datum,
84+
debug_data.InconvertibleTensorProto(
85+
tensor_pb2.TensorProto(), initialized=False
86+
),
87+
)
88+
)
89+
self.assertFalse(
90+
debug_data.has_inf_or_nan(
91+
self._dummy_datum,
92+
debug_data.InconvertibleTensorProto(
93+
tensor_pb2.TensorProto(), initialized=True
94+
),
95+
)
96+
)
8397

8498
def testDTypeComplexWorks(self):
8599
a = np.array([1j, 3j, 3j, 7j], dtype=np.complex128)
@@ -109,9 +123,11 @@ class DebugTensorDatumTest(test_util.TensorFlowTestCase):
109123
def testDebugDatum(self):
110124
dump_root = "/tmp/tfdbg_1"
111125
debug_dump_rel_path = (
112-
debug_data.METADATA_FILE_PREFIX + debug_data.DEVICE_TAG +
113-
",job_localhost,replica_0,task_0,cpu_0" +
114-
"/ns1/ns2/node_a_1_2_DebugIdentity_1472563253536385")
126+
debug_data.METADATA_FILE_PREFIX
127+
+ debug_data.DEVICE_TAG
128+
+ ",job_localhost,replica_0,task_0,cpu_0"
129+
+ "/ns1/ns2/node_a_1_2_DebugIdentity_1472563253536385"
130+
)
115131

116132
datum = debug_data.DebugTensorDatum(dump_root, debug_dump_rel_path)
117133

@@ -122,19 +138,20 @@ def testDebugDatum(self):
122138
self.assertEqual(1472563253536385, datum.timestamp)
123139
self.assertEqual("ns1/ns2/node_a_1:2:DebugIdentity", datum.watch_key)
124140
self.assertEqual(
125-
os.path.join(dump_root, debug_dump_rel_path), datum.file_path)
141+
os.path.join(dump_root, debug_dump_rel_path), datum.file_path
142+
)
126143
self.assertEqual(
127144
"{DebugTensorDatum (/job:localhost/replica:0/task:0/cpu:0) "
128-
"%s:%d @ %s @ %d}" % (datum.node_name,
129-
datum.output_slot,
130-
datum.debug_op,
131-
datum.timestamp), str(datum))
145+
"%s:%d @ %s @ %d}"
146+
% (datum.node_name, datum.output_slot, datum.debug_op, datum.timestamp),
147+
str(datum),
148+
)
132149
self.assertEqual(
133150
"{DebugTensorDatum (/job:localhost/replica:0/task:0/cpu:0) "
134-
"%s:%d @ %s @ %d}" % (datum.node_name,
135-
datum.output_slot,
136-
datum.debug_op,
137-
datum.timestamp), repr(datum))
151+
"%s:%d @ %s @ %d}"
152+
% (datum.node_name, datum.output_slot, datum.debug_op, datum.timestamp),
153+
repr(datum),
154+
)
138155

139156
def testDumpSizeBytesIsNoneForNonexistentFilePath(self):
140157
dump_root = "/tmp/tfdbg_1"
@@ -156,25 +173,37 @@ def tearDown(self):
156173
def _makeDataDirWithMultipleDevicesAndDuplicateNodeNames(self):
157174
cpu_0_dir = os.path.join(
158175
self._dump_root,
159-
debug_data.METADATA_FILE_PREFIX + debug_data.DEVICE_TAG +
160-
",job_localhost,replica_0,task_0,cpu_0")
176+
debug_data.METADATA_FILE_PREFIX
177+
+ debug_data.DEVICE_TAG
178+
+ ",job_localhost,replica_0,task_0,cpu_0",
179+
)
161180
gpu_0_dir = os.path.join(
162181
self._dump_root,
163-
debug_data.METADATA_FILE_PREFIX + debug_data.DEVICE_TAG +
164-
",job_localhost,replica_0,task_0,device_GPU_0")
182+
debug_data.METADATA_FILE_PREFIX
183+
+ debug_data.DEVICE_TAG
184+
+ ",job_localhost,replica_0,task_0,device_GPU_0",
185+
)
165186
gpu_1_dir = os.path.join(
166187
self._dump_root,
167-
debug_data.METADATA_FILE_PREFIX + debug_data.DEVICE_TAG +
168-
",job_localhost,replica_0,task_0,device_GPU_1")
188+
debug_data.METADATA_FILE_PREFIX
189+
+ debug_data.DEVICE_TAG
190+
+ ",job_localhost,replica_0,task_0,device_GPU_1",
191+
)
169192
os.makedirs(cpu_0_dir)
170193
os.makedirs(gpu_0_dir)
171194
os.makedirs(gpu_1_dir)
172-
open(os.path.join(
173-
cpu_0_dir, "node_foo_1_2_DebugIdentity_1472563253536386"), "wb")
174-
open(os.path.join(
175-
gpu_0_dir, "node_foo_1_2_DebugIdentity_1472563253536385"), "wb")
176-
open(os.path.join(
177-
gpu_1_dir, "node_foo_1_2_DebugIdentity_1472563253536387"), "wb")
195+
open(
196+
os.path.join(cpu_0_dir, "node_foo_1_2_DebugIdentity_1472563253536386"),
197+
"wb",
198+
)
199+
open(
200+
os.path.join(gpu_0_dir, "node_foo_1_2_DebugIdentity_1472563253536385"),
201+
"wb",
202+
)
203+
open(
204+
os.path.join(gpu_1_dir, "node_foo_1_2_DebugIdentity_1472563253536387"),
205+
"wb",
206+
)
178207

179208
def testDebugDumpDir_nonexistentDumpRoot(self):
180209
with self.assertRaisesRegex(IOError, "does not exist"):
@@ -184,13 +213,16 @@ def testDebugDumpDir_invalidFileNamingPattern(self):
184213
# File name with too few underscores should lead to an exception.
185214
device_dir = os.path.join(
186215
self._dump_root,
187-
debug_data.METADATA_FILE_PREFIX + debug_data.DEVICE_TAG +
188-
",job_localhost,replica_0,task_0,cpu_0")
216+
debug_data.METADATA_FILE_PREFIX
217+
+ debug_data.DEVICE_TAG
218+
+ ",job_localhost,replica_0,task_0,cpu_0",
219+
)
189220
os.makedirs(device_dir)
190221
open(os.path.join(device_dir, "node1_DebugIdentity_1234"), "wb")
191222

192-
with self.assertRaisesRegex(ValueError,
193-
"does not conform to the naming pattern"):
223+
with self.assertRaisesRegex(
224+
ValueError, "does not conform to the naming pattern"
225+
):
194226
debug_data.DebugDumpDir(self._dump_root)
195227

196228
def testDebugDumpDir_validDuplicateNodeNamesWithMultipleDevices(self):
@@ -214,22 +246,29 @@ def testDebugDumpDir_validDuplicateNodeNamesWithMultipleDevices(self):
214246

215247
dump_dir = debug_data.DebugDumpDir(
216248
self._dump_root,
217-
partition_graphs=[graph_cpu_0, graph_gpu_0, graph_gpu_1])
218-
219-
self.assertItemsEqual(
220-
["/job:localhost/replica:0/task:0/cpu:0",
221-
"/job:localhost/replica:0/task:0/device:GPU:0",
222-
"/job:localhost/replica:0/task:0/device:GPU:1"], dump_dir.devices())
249+
partition_graphs=[graph_cpu_0, graph_gpu_0, graph_gpu_1],
250+
)
251+
252+
self.assertCountEqual(
253+
[
254+
"/job:localhost/replica:0/task:0/cpu:0",
255+
"/job:localhost/replica:0/task:0/device:GPU:0",
256+
"/job:localhost/replica:0/task:0/device:GPU:1",
257+
],
258+
dump_dir.devices(),
259+
)
223260
self.assertEqual(1472563253536385, dump_dir.t0)
224261
self.assertEqual(3, dump_dir.size)
225262

226263
with self.assertRaisesRegex(ValueError, r"Invalid device name: "):
227264
dump_dir.nodes("/job:localhost/replica:0/task:0/device:GPU:2")
228-
self.assertItemsEqual(["node_foo_1", "node_foo_1", "node_foo_1"],
229-
dump_dir.nodes())
230-
self.assertItemsEqual(
265+
self.assertCountEqual(
266+
["node_foo_1", "node_foo_1", "node_foo_1"], dump_dir.nodes()
267+
)
268+
self.assertCountEqual(
231269
["node_foo_1"],
232-
dump_dir.nodes(device_name="/job:localhost/replica:0/task:0/cpu:0"))
270+
dump_dir.nodes(device_name="/job:localhost/replica:0/task:0/cpu:0"),
271+
)
233272

234273
def testDuplicateNodeNamesInGraphDefOfSingleDeviceRaisesException(self):
235274
self._makeDataDirWithMultipleDevicesAndDuplicateNodeNames()
@@ -256,7 +295,8 @@ def testDuplicateNodeNamesInGraphDefOfSingleDeviceRaisesException(self):
256295
with self.assertRaisesRegex(ValueError, r"Duplicate node name on device "):
257296
debug_data.DebugDumpDir(
258297
self._dump_root,
259-
partition_graphs=[graph_cpu_0, graph_gpu_0, graph_gpu_1])
298+
partition_graphs=[graph_cpu_0, graph_gpu_0, graph_gpu_1],
299+
)
260300

261301
def testDebugDumpDir_emptyDumpDir(self):
262302
dump_dir = debug_data.DebugDumpDir(self._dump_root)
@@ -275,27 +315,77 @@ def fake_gfile_glob(glob_pattern):
275315
return []
276316

277317
with test.mock.patch.object(
278-
gfile, "Glob", side_effect=fake_gfile_glob, autospec=True) as fake:
318+
gfile, "Glob", side_effect=fake_gfile_glob, autospec=True
319+
) as fake:
279320
debug_data.DebugDumpDir(self._dump_root)
280321
expected_calls = [
281-
test.mock.call(os.path.join(
282-
self._dump_root,
283-
(debug_data.METADATA_FILE_PREFIX +
284-
debug_data.CORE_METADATA_TAG + "*"))),
285-
test.mock.call(os.path.join(
286-
self._dump_root,
287-
(debug_data.METADATA_FILE_PREFIX +
288-
debug_data.FETCHES_INFO_FILE_TAG + "*"))),
289-
test.mock.call(os.path.join(
290-
self._dump_root,
291-
(debug_data.METADATA_FILE_PREFIX +
292-
debug_data.FEED_KEYS_INFO_FILE_TAG + "*"))),
293-
test.mock.call(os.path.join(
294-
self._dump_root,
295-
(debug_data.METADATA_FILE_PREFIX +
296-
debug_data.DEVICE_TAG + "*")))]
322+
test.mock.call(
323+
os.path.join(
324+
self._dump_root,
325+
(
326+
debug_data.METADATA_FILE_PREFIX
327+
+ debug_data.CORE_METADATA_TAG
328+
+ "*"
329+
),
330+
)
331+
),
332+
test.mock.call(
333+
os.path.join(
334+
self._dump_root,
335+
(
336+
debug_data.METADATA_FILE_PREFIX
337+
+ debug_data.FETCHES_INFO_FILE_TAG
338+
+ "*"
339+
),
340+
)
341+
),
342+
test.mock.call(
343+
os.path.join(
344+
self._dump_root,
345+
(
346+
debug_data.METADATA_FILE_PREFIX
347+
+ debug_data.FEED_KEYS_INFO_FILE_TAG
348+
+ "*"
349+
),
350+
)
351+
),
352+
test.mock.call(
353+
os.path.join(
354+
self._dump_root,
355+
(
356+
debug_data.METADATA_FILE_PREFIX
357+
+ debug_data.DEVICE_TAG
358+
+ "*"
359+
),
360+
)
361+
),
362+
]
297363
fake.assert_has_calls(expected_calls, any_order=True)
298364

365+
def testValidationSucceedsOnDoubleSlashNodeName(self):
366+
device_dir = os.path.join(
367+
self._dump_root,
368+
debug_data.device_name_to_device_path(
369+
"/job:localhost/replica:0/task:0/cpu:0"
370+
),
371+
)
372+
node_scope_dir = os.path.join(device_dir, "scope_A")
373+
os.makedirs(node_scope_dir)
374+
file_io.write_string_to_file(
375+
os.path.join(node_scope_dir, "op_B_0_DebugIdentity_12345"), "dummy"
376+
)
377+
graph_def = graph_pb2.GraphDef()
378+
node = graph_def.node.add()
379+
# Previously double slash would have caused validation to fail. b/429335661
380+
node.name = "scope_A//op_B"
381+
node.op = "NoOp"
382+
node.device = "/job:localhost/replica:0/task:0/cpu:0"
383+
dump_dir = debug_data.DebugDumpDir(
384+
self._dump_root, partition_graphs=[graph_def]
385+
)
386+
self.assertEqual(1, dump_dir.size)
387+
self.assertIn("scope_A/op_B", dump_dir.nodes()[0])
388+
299389

300390
if __name__ == "__main__":
301391
googletest.main()

0 commit comments

Comments
 (0)