| # Copyright 2019 The TensorFlow Authors. All Rights Reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # ============================================================================== |
| """Tests for debugger functionalities in tf.Session.""" |
| from __future__ import absolute_import |
| from __future__ import division |
| from __future__ import print_function |
| |
| import os |
| import shutil |
| import tempfile |
| |
| from tensorflow.core.protobuf import config_pb2 |
| from tensorflow.core.protobuf import rewriter_config_pb2 |
| from tensorflow.python.client import session |
| from tensorflow.python.debug.lib import debug_data |
| from tensorflow.python.debug.lib import debug_utils |
| from tensorflow.python.framework import dtypes |
| from tensorflow.python.framework import ops |
| from tensorflow.python.framework import test_util |
| from tensorflow.python.ops import math_ops |
| from tensorflow.python.ops import variables |
| from tensorflow.python.platform import googletest |
| |
| |
| def _grappler_enabled_session_config(): |
| """Constructs a Session config proto that explicitly enables Grappler. |
| |
| Returns: |
| A config proto that obtains extra safety for the unit tests in this |
| file by ensuring that the relevant Grappler rewrites are always enabled. |
| """ |
| rewriter_config = rewriter_config_pb2.RewriterConfig( |
| disable_model_pruning=False, |
| arithmetic_optimization=rewriter_config_pb2.RewriterConfig.ON) |
| graph_options = config_pb2.GraphOptions(rewrite_options=rewriter_config) |
| return config_pb2.ConfigProto(graph_options=graph_options) |
| |
| |
| class SessionDebugGrapplerInteractionTest(test_util.TensorFlowTestCase): |
| |
| def setUp(self): |
| super(SessionDebugGrapplerInteractionTest, self).setUp() |
| self._dump_root = tempfile.mkdtemp() |
| self._debug_url = "file://%s" % self._dump_root |
| |
| def tearDown(self): |
| ops.reset_default_graph() |
| if os.path.isdir(self._dump_root): |
| shutil.rmtree(self._dump_root) |
| super(SessionDebugGrapplerInteractionTest, self).tearDown() |
| |
| def testArithmeticOptimizationActive(self): |
| """Tests that tfdbg can dump the tensor from nodes created by Grappler.""" |
| with session.Session(config=_grappler_enabled_session_config()) as sess: |
| u = variables.VariableV1([[1, 2], [3, 4]], name="u", dtype=dtypes.float32) |
| # The next two ops should be optimized by Grappler into a single op: |
| # either an AddN op or a Mul op. |
| x = math_ops.add(u, u) |
| x = math_ops.add(x, u) |
| y = math_ops.multiply(x, u) |
| |
| sess.run(variables.global_variables_initializer()) |
| |
| run_options = config_pb2.RunOptions(output_partition_graphs=True) |
| debug_utils.watch_graph( |
| run_options, |
| sess.graph, |
| debug_ops=["DebugIdentity"], |
| debug_urls=[self._debug_url]) |
| |
| run_metadata = config_pb2.RunMetadata() |
| run_result = sess.run(y, options=run_options, run_metadata=run_metadata) |
| self.assertAllClose(run_result, [[3, 12], [27, 48]]) |
| |
| dump_data = debug_data.DebugDumpDir( |
| self._dump_root, partition_graphs=run_metadata.partition_graphs, |
| validate=True) |
| |
| original_node_names = set([op.name for op in sess.graph.get_operations()]) |
| dumped_node_names = set(dump_data.nodes()) |
| grappler_created_node_names = dumped_node_names - original_node_names |
| grappler_removed_node_names = original_node_names - dumped_node_names |
| |
| # Assert that Grappler should have replaced some of the nodes from the |
| # original graph with new nodes. |
| self.assertTrue(grappler_created_node_names) |
| self.assertTrue(grappler_removed_node_names) |
| |
| # Iterate through the nodes created by Grappler. One of them should be |
| # be the result of replacing the original add ops with an AddN op or a |
| # Mul op. |
| found_optimized_node = False |
| for grappler_node_name in grappler_created_node_names: |
| node_op_type = dump_data.node_op_type(grappler_node_name) |
| # Look for the node created by Grappler's arithmetic optimization. |
| if node_op_type in ("AddN", "Mul"): |
| datum = dump_data.get_tensors(grappler_node_name, 0, "DebugIdentity") |
| self.assertEqual(1, len(datum)) |
| self.assertAllClose(datum[0], [[3, 6], [9, 12]]) |
| found_optimized_node = True |
| break |
| self.assertTrue( |
| found_optimized_node, |
| "Failed to find optimized node created by Grappler's arithmetic " |
| "optimization.") |
| |
| |
| if __name__ == "__main__": |
| googletest.main() |