# Copyright 2017 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 the pybind11 wrapper of Grappler items.""" from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.framework import meta_graph from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape from tensorflow.python.framework import test_util from tensorflow.python.grappler import item from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import gen_array_ops from tensorflow.python.ops import state_ops from tensorflow.python.ops import variable_v1 from tensorflow.python.platform import test class ItemTest(test.TestCase): """Unit tests for Grappler Item pybind11 wrapper functionality.""" def _create_sample_metagraph(self, include_train_op=True): with ops.Graph().as_default() as g: a = constant_op.constant(10) b = constant_op.constant(20) c = a + b z = control_flow_ops.no_op() if include_train_op: train_op = ops.get_collection_ref(ops.GraphKeys.TRAIN_OP) train_op.append(c) return meta_graph.create_meta_graph_def(graph=g), z def test_invalid_item_missing_train_op_raises(self): """Verifies that Item raises InvalidArgumentError when train_op is missing.""" mg, _ = self._create_sample_metagraph(include_train_op=False) with self.assertRaisesRegex( errors_impl.InvalidArgumentError, 'train_op not specified in the metagraph'): item.Item(mg) def test_important_ops_identification(self): """Verifies important ops are correctly identified from the metagraph.""" mg, _ = self._create_sample_metagraph(include_train_op=True) grappler_item = item.Item(mg) op_list = grappler_item.IdentifyImportantOps() self.assertCountEqual(['Const', 'Const_1', 'add'], op_list) def test_op_properties_extraction(self): """Verifies op properties are correctly extracted for graph nodes.""" mg, z = self._create_sample_metagraph(include_train_op=True) grappler_item = item.Item(mg) op_properties = grappler_item.GetOpProperties() z_prop = op_properties[z.name] self.assertEmpty(z_prop) const_prop = op_properties['Const'] self.assertLen(const_prop, 1) self.assertEqual(dtypes.int32, const_prop[0].dtype) self.assertEqual(tensor_shape.TensorShape([]), const_prop[0].shape) def test_tf_item_initial_properties_equal(self): """Verifies initial tf_item properties are consistent and equal.""" mg, _ = self._create_sample_metagraph(include_train_op=True) grappler_item = item.Item(mg) initial_tf_item = grappler_item.tf_item no_change_tf_item = grappler_item.tf_item self.assertEqual(initial_tf_item, no_change_tf_item) def test_tf_item_device_modification_updates_wrapper(self): """Verifies modifying node placement creates a new underlying tf_item.""" mg, _ = self._create_sample_metagraph(include_train_op=True) grappler_item = item.Item(mg) initial_tf_item = grappler_item.tf_item for node in grappler_item.metagraph.graph_def.node: node.device = '/cpu:0' new_tf_item = grappler_item.tf_item self.assertNotEqual(initial_tf_item, new_tf_item) def test_tf_item_identical_device_reassignment_unchanged(self): """Verifies re-assigning identical placement keeps tf_item unchanged.""" mg, _ = self._create_sample_metagraph(include_train_op=True) grappler_item = item.Item(mg) for node in grappler_item.metagraph.graph_def.node: node.device = '/cpu:0' new_tf_item = grappler_item.tf_item for node in grappler_item.metagraph.graph_def.node: node.device = '/cpu:0' newest_tf_item = grappler_item.tf_item self.assertEqual(new_tf_item, newest_tf_item) @test_util.run_v1_only('b/120545219') def test_colocation_constraints(self): """Verifies colocation constraints are correctly grouped.""" with ops.Graph().as_default() as g: c = constant_op.constant([10]) v = variable_v1.VariableV1([3], dtype=dtypes.int32) i = gen_array_ops.ref_identity(v) a = state_ops.assign(i, c) train_op = ops.get_collection_ref(ops.GraphKeys.TRAIN_OP) train_op.append(a) mg = meta_graph.create_meta_graph_def(graph=g) grappler_item = item.Item(mg) groups = grappler_item.GetColocationGroups() self.assertLen(groups, 1) self.assertCountEqual( groups[0], ['Assign', 'RefIdentity', 'Variable', 'Variable/Assign']) @test_util.run_v1_only('b/120545219') def test_colocation_constraints_missing_input(self): """Verifies standalone nodes with missing inputs are correctly grouped.""" with ops.Graph().as_default() as g: c = constant_op.constant([10]) v = variable_v1.VariableV1([3], dtype=dtypes.int32) i = gen_array_ops.ref_identity(v) a = state_ops.assign(i, c) train_op = ops.get_collection_ref(ops.GraphKeys.TRAIN_OP) train_op.append(a) mg = meta_graph.create_meta_graph_def(graph=g) for node in mg.graph_def.node: if node.op == 'Assign': del node.input[:] grappler_item = item.Item(mg) groups = grappler_item.GetColocationGroups() self.assertLen(groups, 1) self.assertCountEqual( groups[0], ['RefIdentity', 'Variable']) if __name__ == '__main__': test.main()