def testDebugNumericSummaryV2OpLargeTensorIDError(self): modes = [ debug_event_pb2.TensorDebugMode.CURT_HEALTH, debug_event_pb2.TensorDebugMode.CONCISE_HEALTH, debug_event_pb2.TensorDebugMode.SHAPE, ] # Maximum allowed tensor_id tensor_id = np.power(2, 53) for mode in modes: self.evaluate( gen_debug_ops.debug_numeric_summary_v2( constant_op.constant(42.0), tensor_debug_mode=mode, tensor_id=tensor_id, output_dtype=dtypes.float64)) # Incrementing by one should error tensor_id += 1 for mode in modes: with self.assertRaises(errors.InvalidArgumentError): self.evaluate( gen_debug_ops.debug_numeric_summary_v2( constant_op.constant(42.0), tensor_debug_mode=mode, tensor_id=tensor_id, output_dtype=dtypes.float64))
def debug_summary(x): return self.evaluate( gen_debug_ops.debug_numeric_summary_v2( x, tensor_debug_mode=(debug_event_pb2.TensorDebugMode.SHAPE), tensor_id=x._id, output_dtype=dtypes.float64)), x._id
def testDebugNumericSummaryV2OpDeterminism(self): x = np.zeros([100, 100, 50], dtype=np.float64) x = constant_op.constant(x) modes = ( debug_event_pb2.TensorDebugMode.CONCISE_HEALTH, debug_event_pb2.TensorDebugMode.FULL_HEALTH, ) for mode in modes: debug_mode = debug_event_pb2.TensorDebugMode.Name(mode) with test_util.deterministic_ops(): if test_util.is_gpu_available(cuda_only=True): with self.assertRaisesRegex( errors_impl.UnimplementedError, "Determinism is not yet " "supported for DebugNumericSummaryV2 when tensor_debug_mode is " + debug_mode + "."): self.evaluate( gen_debug_ops.debug_numeric_summary_v2( x, tensor_debug_mode=mode, tensor_id=x._id, output_dtype=dtypes.float64))
def _dump_eager_tensors(self, tensors, op_type, input_tensor_ids, graph_id=None): """Dump the value of eager tensors. The destination of the dumping is determined by the dump_root of the currently enabled dumping callback. The tensors may be transformed prior to dumping (e.g., reduced as summary statistics such as minimum, maximum and arithmetic mean). The details of this transformation (if any) depends on the tensor_debug_mode of the currently enabled dumping callback. Args: tensors: The EagerTensors whose values are to be dumped, with or without value transform. op_type: Type of the op that generates the tensors, as a string. input_tensor_ids: IDs of the input EagerTensors to the op. graph_id: ID of the executed graph, applicable only to eager execution of a FuncGraph. Returns: A tfdbg Execution protocol buffer. """ tensor_debug_mode = self._tensor_debug_mode output_tensor_ids = [t._id for t in tensors] # pylint:disable=protected-access if tensor_debug_mode == debug_event_pb2.TensorDebugMode.NO_TENSOR: return debug_event_pb2.Execution( op_type=op_type, graph_id=graph_id, num_outputs=len(tensors), input_tensor_ids=input_tensor_ids, output_tensor_ids=output_tensor_ids, tensor_debug_mode=tensor_debug_mode, code_location=self._process_stack_frames()) elif tensor_debug_mode in ( debug_event_pb2.TensorDebugMode.CURT_HEALTH, debug_event_pb2.TensorDebugMode.CONCISE_HEALTH, debug_event_pb2.TensorDebugMode.SHAPE, debug_event_pb2.TensorDebugMode.FULL_TENSOR): execution_proto = debug_event_pb2.Execution( op_type=op_type, num_outputs=len(tensors), graph_id=graph_id, input_tensor_ids=input_tensor_ids, output_tensor_ids=output_tensor_ids, tensor_debug_mode=tensor_debug_mode, code_location=self._process_stack_frames()) for tensor in tensors: if (self._should_dump_tensor(op_type, tensor.dtype) and tensor.dtype.is_numpy_compatible): if tensor_debug_mode in ( debug_event_pb2.TensorDebugMode.CURT_HEALTH, debug_event_pb2.TensorDebugMode.CONCISE_HEALTH): if tensor.dtype.is_floating: tensor_proto = _concrete_tensor_to_proto( gen_debug_ops.debug_numeric_summary_v2( tensor, tensor_debug_mode=tensor_debug_mode, output_dtype=dtypes.float64)) else: # A placeholder for non-floating-type output tensors. tensor_proto = tensor_pb2.TensorProto() elif tensor_debug_mode == debug_event_pb2.TensorDebugMode.SHAPE: if (tensor.dtype.is_floating or tensor.dtype.is_integer or tensor.dtype.is_bool): tensor_proto = _concrete_tensor_to_proto( gen_debug_ops.debug_numeric_summary_v2( tensor, tensor_debug_mode=tensor_debug_mode, output_dtype=dtypes.float64)) else: # A placeholder for non-floating-type output tensors. tensor_proto = tensor_pb2.TensorProto() elif tensor_debug_mode == debug_event_pb2.TensorDebugMode.FULL_TENSOR: tensor_proto = _concrete_tensor_to_proto(tensor) if tensor_proto: execution_proto.tensor_protos.append(tensor_proto) return execution_proto else: raise NotImplementedError( "Tensor instrumentation is not implemented for debug mode %s yet " % self._tensor_debug_mode)
def _instrument_symbolic_tensors(self, tensors, op_type, op_name, tfdbg_context_id, tensor_ids): """Add debugging instrumentation for symbolic (i.e., non-eager) tensors. The detailed fashion in which the tensors are instrumented is determined by the tensor_debug_mode configured for the currently enabled dumping callback. Args: tensors: A tuple of Tensors to instrument. It is assumed that their ordering corresponds to the ordering of output tensors of an original op. Output slot indices (0-based) will be generated based on the ordering. op_type: Type name of the op that emits the Tensors (e.g., "MatMul"). op_name: Name of the op that emits the Tensors (e.g., "dense_1/MatMul"). tfdbg_context_id: A unique ID for the context that the op belongs to (e.g., a graph). tensor_ids: A list of unique ID numbers for the tensors, for tfdbg's internal use. Returns: Non-eager Tensors that override the `tensors` as the output of the op that originally generated `tensors`. In some cases (e.g., non-V1 graph mode), this may be `None`, as the instrumentation can simply rely on automatic control dependencies (see `auto_control_deps.py`) instead of tensor overriding. """ # TODO(b/144441464, b/144440920, b/144440922): Make use of it. tensor_debug_mode = self._tensor_debug_mode debug_urls = ["file://%s" % self._dump_root] is_v1_graph_mode = not ops.executing_eagerly_outside_functions() instrumented_tensors = [] if is_v1_graph_mode else None if tensor_debug_mode == debug_event_pb2.TensorDebugMode.NO_TENSOR: for output_slot, tensor in enumerate(tensors): if (not self._should_dump_tensor(op_type, tensor.dtype) or not tensor.dtype.is_numpy_compatible): # Instrumenting DT_VARIANT and DT_RESOURCE type tensors under # V1 graph mode is known to have issues. TODO(cais): Investigate. if is_v1_graph_mode: instrumented_tensors.append(tensor) continue if is_v1_graph_mode and not tensor.dtype.is_numpy_compatible: instrumented_tensors.append(tensor) continue # Except in V1 graph mode + control flow, debug_identity_v2 trigger auto # control dependency because it's a stateful op. debug_tensor = gen_debug_ops.debug_identity_v2( # Use an empty (shape=[0]) float32 tensor for the NO_TENSOR mode # as a low-overhead placeholder, since no actual tensor value is # traced. constant_op.constant([], dtype=dtypes.float32), tfdbg_context_id=tfdbg_context_id, op_name=op_name, output_slot=output_slot, tensor_debug_mode=self._tensor_debug_mode, debug_urls=debug_urls) if is_v1_graph_mode: # TODO(cais): Evaluate performance optimization options. For the # `NO_TENSOR` debug mode, an alternative is to add `debug_tensor` as a # control dependency of `tensor.op` without an additional identity op. identity = array_ops.identity(tensor) identity.op._add_control_input( # pylint: disable=protected-access debug_tensor.op) instrumented_tensors.append(identity) return instrumented_tensors elif tensor_debug_mode in ( debug_event_pb2.TensorDebugMode.CURT_HEALTH, debug_event_pb2.TensorDebugMode.CONCISE_HEALTH, debug_event_pb2.TensorDebugMode.SHAPE): for output_slot, tensor in enumerate(tensors): dtype = tensor.dtype dtype_is_dumpable = ( tensor_debug_mode in (debug_event_pb2.TensorDebugMode.CURT_HEALTH, debug_event_pb2.TensorDebugMode.CONCISE_HEALTH) and dtype.is_floating or tensor_debug_mode == debug_event_pb2.TensorDebugMode.SHAPE and (dtype.is_floating or dtype.is_integer or dtype.is_bool)) if (not self._should_dump_tensor(op_type, tensor.dtype) or not dtype_is_dumpable): if is_v1_graph_mode: instrumented_tensors.append(tensor) continue debug_tensor = gen_debug_ops.debug_identity_v2( gen_debug_ops.debug_numeric_summary_v2( tensor, tensor_id=tensor_ids[output_slot], tensor_debug_mode=self._tensor_debug_mode, output_dtype=dtypes.float64), tfdbg_context_id=tfdbg_context_id, op_name=op_name, output_slot=output_slot, tensor_debug_mode=self._tensor_debug_mode, debug_urls=debug_urls) if is_v1_graph_mode: identity = array_ops.identity(tensor) identity.op._add_control_input( # pylint: disable=protected-access debug_tensor.op) instrumented_tensors.append(identity) return instrumented_tensors elif tensor_debug_mode == debug_event_pb2.TensorDebugMode.FULL_TENSOR: for output_slot, tensor in enumerate(tensors): if (not self._should_dump_tensor(op_type, tensor.dtype) or not tensor.dtype.is_numpy_compatible): # Instrumenting DT_VARIANT and DT_RESOURCE type tensors under # V1 graph mode is known to have issues. TODO(cais): Investigate. if is_v1_graph_mode: instrumented_tensors.append(tensor) continue debug_tensor = gen_debug_ops.debug_identity_v2( tensor, tfdbg_context_id=tfdbg_context_id, op_name=op_name, output_slot=output_slot, tensor_debug_mode=self._tensor_debug_mode, debug_urls=debug_urls) if is_v1_graph_mode: instrumented_tensors.append(debug_tensor) return instrumented_tensors else: raise NotImplementedError( "Symbolic tensor instrumentation is not implemented for debug mode " "%s" % self._tensor_debug_mode)
def _debug_summary(x): return gen_debug_ops.debug_numeric_summary_v2( x, tensor_debug_mode=( debug_event_pb2.TensorDebugMode.REDUCE_INF_NAN_THREE_SLOTS))
def _instrument_symbolic_tensors(self, tensors, op_type, op_name, tfdbg_context_id, tensor_ids): """Add debugging instrumentation for symbolic (i.e., non-eager) tensors. The detailed fashion in which the tensors are instrumented is determined by the tensor_debug_mode configured for the currently enabled dumping callback. Args: tensors: A tuple of Tensors to instrument. It is assumed that their ordering corresponds to the ordering of output tensors of an original op. Output slot indices (0-based) will be generated based on the ordering. op_type: Type name of the op that emits the Tensors (e.g., "MatMul"). op_name: Name of the op that emits the Tensors (e.g., "dense_1/MatMul"). tfdbg_context_id: A unique ID for the context that the op belongs to (e.g., a graph). tensor_ids: A list of unique ID numbers for the tensors, for tfdbg's internal use. Returns: Non-eager Tensors that override the `tensors` as the output of the op that originally generated `tensors`. In some cases (e.g., non-V1 graph mode), this may be `None`, as the instrumentation can simply rely on automatic control dependencies (see `auto_control_deps.py`) instead of tensor overriding. """ tensor_debug_mode = self._tensor_debug_mode debug_urls = ["file://%s" % self._dump_root] is_v1_graph_mode = not ops.executing_eagerly_outside_functions() instrumented_tensors = [] if is_v1_graph_mode else None for output_slot, tensor in enumerate(tensors): with self._symbolic_tensor_counter_lock: debug_identity_name = ("DebugIdentityV2_%d" % self._symbolic_tensor_counter) debug_identity_op_kwargs = { "tfdbg_context_id": tfdbg_context_id, "op_name": op_name, "output_slot": output_slot, "tensor_debug_mode": self._tensor_debug_mode, "debug_urls": debug_urls, "name": debug_identity_name, } if tf_compat.forward_compatible(2020, 6, 24): debug_identity_op_kwargs[ "circular_buffer_size"] = self._circular_buffer_size if tf_compat.forward_compatible(2020, 7, 1): debug_identity_op_kwargs["tfdbg_run_id"] = self._tfdbg_run_id if tensor_debug_mode == debug_event_pb2.TensorDebugMode.NO_TENSOR: if (not self._should_dump_tensor(op_type, tensor.dtype) or not tensor.dtype.is_numpy_compatible): if is_v1_graph_mode: instrumented_tensors.append(tensor) continue if is_v1_graph_mode and not tensor.dtype.is_numpy_compatible: # Avoid instrumenting Placeholder under is_v1_graph_mode. Doing that # would cause runtime complaint about Placeholders not being fed. instrumented_tensors.append(tensor) continue # Except in V1 graph mode + control flow, debug_identity_v2 triggers # auto control dependency because it's a stateful op. debug_tensor = gen_debug_ops.debug_identity_v2( # Use an empty (shape=[0]) float32 tensor for the NO_TENSOR mode # as a low-overhead placeholder, since no actual tensor value is # traced. constant_op.constant([], dtype=dtypes.float32), **debug_identity_op_kwargs) if is_v1_graph_mode: instrumented_tensors.append( self._process_v1_graph_mode_tensor( op_type, tensor, debug_tensor, tensor_debug_mode)) elif tensor_debug_mode in ( debug_event_pb2.TensorDebugMode.CURT_HEALTH, debug_event_pb2.TensorDebugMode.CONCISE_HEALTH, debug_event_pb2.TensorDebugMode.FULL_HEALTH, debug_event_pb2.TensorDebugMode.SHAPE): dtype = tensor.dtype dtype_is_dumpable = ( tensor_debug_mode in (debug_event_pb2.TensorDebugMode.CURT_HEALTH, debug_event_pb2.TensorDebugMode.CONCISE_HEALTH, debug_event_pb2.TensorDebugMode.FULL_HEALTH) and dtype.is_floating or tensor_debug_mode == debug_event_pb2.TensorDebugMode.SHAPE and (dtype.is_floating or dtype.is_integer or dtype.is_bool)) if (not self._should_dump_tensor(op_type, tensor.dtype) or not dtype_is_dumpable): if is_v1_graph_mode: instrumented_tensors.append(tensor) continue debug_tensor = gen_debug_ops.debug_identity_v2( gen_debug_ops.debug_numeric_summary_v2( tensor, tensor_id=tensor_ids[output_slot], tensor_debug_mode=self._tensor_debug_mode, output_dtype=dtypes.float64), **debug_identity_op_kwargs) if is_v1_graph_mode: instrumented_tensors.append( self._process_v1_graph_mode_tensor( op_type, tensor, debug_tensor, tensor_debug_mode)) elif tensor_debug_mode == debug_event_pb2.TensorDebugMode.FULL_TENSOR: if (not self._should_dump_tensor(op_type, tensor.dtype) or not tensor.dtype.is_numpy_compatible): # Instrumenting DT_VARIANT and DT_RESOURCE type tensors under # V1 graph mode is known to have issues. TODO(cais): Investigate. if is_v1_graph_mode: instrumented_tensors.append(tensor) continue debug_tensor = gen_debug_ops.debug_identity_v2( tensor, **debug_identity_op_kwargs) if is_v1_graph_mode: instrumented_tensors.append( self._process_v1_graph_mode_tensor( op_type, tensor, debug_tensor, tensor_debug_mode)) else: raise NotImplementedError( "Symbolic tensor instrumentation is not implemented for debug mode " "%s" % self._tensor_debug_mode) return instrumented_tensors