Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/tensorflow/python/debug/cli/evaluator.py: 24%

49 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2024-01-03 07:57 +0000

1# Copyright 2017 The TensorFlow Authors. All Rights Reserved. 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14# ============================================================================== 

15"""Library for arbitrary expression evaluation based on a debugger data dump.""" 

16import re 

17 

18import numpy as np # pylint: disable=unused-import 

19 

20from tensorflow.python.debug.lib import debug_data 

21 

22_DUMP_TENSOR_PATTERN = re.compile(r"`.*?`") 

23_DEVICE_NAME_PREFIX_PATTERN = re.compile( 

24 r"/job:(\w)+/replica:(\d)+/task:(\d)+/(\w)+:(\d)+:") 

25_EXEC_INDEX_SUFFIX_PATTERN = re.compile(r"\[(\d)*\]$") 

26 

27_DEFAULT_DEBUG_OP = "DebugIdentity" 

28 

29 

30def _parse_debug_tensor_name(debug_tensor_name): 

31 # pylint: disable=line-too-long 

32 """Parse a debug tensor name in a to-be-evaluated expression. 

33 

34 Args: 

35 debug_tensor_name: name of the debug tensor, with or without 

36 device name as a prefix, with or without debug op, with or 

37 without '[<exec_index>]' as a suffix. 

38 E.g., without device name prefix, without debug op suffix: 

39 "hidden_0/MatMul:0" 

40 E.g., with device name prefix: 

41 "/job:worker/replica:0/task:1/gpu:0:hidden_0/MatMul:0" 

42 E.g., with debug op suffix: 

43 "hidden_0/MatMul:0:DebugNumericSummary" 

44 E.g., with device name prefix and debug op suffix: 

45 "/job:worker/replica:0/task:1/gpu:0:hidden_0/MatMul:0:DebugNumericSummary" 

46 E.g., with device name prefix, debug op and an exec index: 

47 "/job:worker/replica:0/task:1/gpu:0:hidden_0/MatMul:0:DebugNumericSummary[1]" 

48 

49 Returns: 

50 device_name: If device name prefix exists, the device name; otherwise, 

51 `None`. 

52 node_name: Name of the node. 

53 output_slot: Output slot index as an `int`. 

54 debug_op: If the debug op suffix exists, the debug op name; otherwise, 

55 `None`. 

56 exec_index: Execution index (applicable to cases in which a debug tensor 

57 is computed multiple times in a `tf.Session.run` call, e.g., due to 

58 `tf.while_loop`). If the exec_index suffix does not exist, this value 

59 defaults to `0`. 

60 

61 Raises: 

62 ValueError: If the input `debug_tensor_name` is malformed. 

63 """ 

64 # pylint: enable=line-too-long 

65 device_prefix_match = re.match(_DEVICE_NAME_PREFIX_PATTERN, debug_tensor_name) 

66 if device_prefix_match: 

67 device_name = debug_tensor_name[ 

68 device_prefix_match.start() : device_prefix_match.end() - 1] 

69 debug_tensor_name = debug_tensor_name[device_prefix_match.end():] 

70 else: 

71 device_name = None 

72 

73 split_items = debug_tensor_name.split(":") 

74 if len(split_items) not in (2, 3): 

75 raise ValueError( 

76 "The debug tensor name in the to-be-evaluated expression is malformed: " 

77 "'%s'" % debug_tensor_name) 

78 # TODO(cais): Provide examples of good debug tensor names in the error 

79 # message. 

80 

81 exec_index_match = re.search(_EXEC_INDEX_SUFFIX_PATTERN, split_items[-1]) 

82 if exec_index_match: 

83 exec_index = int(split_items[-1][ 

84 exec_index_match.start() + 1 : exec_index_match.end() - 1]) 

85 split_items[-1] = split_items[-1][:exec_index_match.start()] 

86 else: 

87 exec_index = 0 

88 

89 if len(split_items) == 2: 

90 node_name = split_items[0] 

91 output_slot = int(split_items[1]) 

92 debug_op = _DEFAULT_DEBUG_OP 

93 else: 

94 split_items = debug_tensor_name.split(":") 

95 node_name = split_items[0] 

96 output_slot = int(split_items[1]) 

97 debug_op = split_items[2] 

98 

99 return device_name, node_name, output_slot, debug_op, exec_index 

100 

101 

102class ExpressionEvaluator(object): 

103 """Evaluates Python expressions using debug tensor values from a dump.""" 

104 

105 def __init__(self, dump): 

106 """Constructor of ExpressionEvaluator. 

107 

108 Args: 

109 dump: an instance of `DebugDumpDir`. 

110 """ 

111 self._dump = dump 

112 self._cached_tensor_values = {} 

113 

114 def evaluate(self, expression): 

115 """Parse an expression. 

116 

117 Args: 

118 expression: the expression to be parsed. 

119 

120 Returns: 

121 The result of the evaluation. 

122 

123 Raises: 

124 ValueError: If the value of one or more of the debug tensors in the 

125 expression are not available. 

126 """ 

127 dump_tensors_iter = re.finditer(_DUMP_TENSOR_PATTERN, expression) 

128 rewritten_expression = expression 

129 for match in reversed(list(dump_tensors_iter)): 

130 tensor_name = match.group(0)[1:-1].strip() 

131 device_name, node_name, output_slot, debug_op, exec_index = ( 

132 _parse_debug_tensor_name(tensor_name)) 

133 if tensor_name not in self._cached_tensor_values: 

134 try: 

135 value = self._dump.get_tensors( 

136 node_name, output_slot, debug_op, 

137 device_name=device_name)[exec_index] 

138 except debug_data.WatchKeyDoesNotExistInDebugDumpDirError: 

139 raise ValueError( 

140 "Eval failed due to the value of %s:%d:DebugIdentity being " 

141 "unavailable" % (node_name, output_slot)) 

142 self._cached_tensor_values[tensor_name] = value 

143 rewritten_expression = ( 

144 rewritten_expression[:match.start(0)] + 

145 "self._cached_tensor_values['" + tensor_name + "']" + 

146 rewritten_expression[match.end(0):]) 

147 

148 return eval(rewritten_expression) # pylint: disable=eval-used