Skip to content

Commit 61ac882

Browse files
committed
[DebuggerV2] Display detailed tensor debug-values in graph- and eager-execution components (#3541)
* Motivation for features / changes * Let the relatively new `GraphExecutionComponent` display details information about debugger-instrumented tensors, such as dtype, rank, size, shape, breakdown of numerical values by type (inf, nan, zero, etc.), and whether inf/nan exists. * In the older `ExecutionDataComponent` for eager tensors, replace the old Angular code that serves a similar purpose with the same Component as used by `GraphExecutionComponent`. This improves unity and reduces maintenance overhead going forward. * Technical description of changes * Add type `DebugTensorValue` to store/debugger_types.ts. The new interface defines the possible types of data available from various `TensorDebugMode`s (an existing enum). * Add helper function `parseDebugTensorValue()` in a new file store/debug_tensor_value.ts to parse an array representation of TensorDebugMode-specific debugger-generated tensor data into a `DebugTensorValue`. * Add `DebugTensorValueComponent` and its various subcomponents in new folder views/debug-_tensor_value/ * Use `DebugTensorValueComponent` from `GraphExecutionComponent` and `ExecutionDataComponent`. * Screenshots of UI changes * CURT_HEALTH mode: ![image](https://user-images.githubusercontent.com/16824702/80056423-31c27100-84f2-11ea-91db-b441f94d11c8.png) * CONCISE_HEALTH mode: ![image](https://user-images.githubusercontent.com/16824702/80056486-5a4a6b00-84f2-11ea-8142-6c5e282f06c5.png) * SHAPE mode: ![image](https://user-images.githubusercontent.com/16824702/80056523-72ba8580-84f2-11ea-9126-2c27c9b922b1.png) * FULL_HEALTH mode: ![image](https://user-images.githubusercontent.com/16824702/80056591-94b40800-84f2-11ea-9592-fd61c53a2316.png) * Detailed steps to verify changes work correctly (as executed by you) * Unit tests are added for the new helper method and new component and its subcomponents * Manual verification against logdirs with real tfdbg2 data.
1 parent e4ae18b commit 61ac882

21 files changed

+1528
-569
lines changed

tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ tf_ng_web_test_suite(
7878
"//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects:debugger_effects_test_lib",
7979
"//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:debugger_store_test_lib",
8080
"//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts:alerts_container_test_lib",
81+
"//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value:debug_tensor_value_component_test_lib",
8182
"//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions:graph_executions_container_test_lib",
8283
"//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code:source_code_container_test_lib",
8384
"//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code:source_code_test_lib",

tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts

Lines changed: 24 additions & 355 deletions
Large diffs are not rendered by default.

tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/BUILD

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,28 @@ ng_module(
3131
],
3232
)
3333

34+
ng_module(
35+
name = "debug_tensor_value",
36+
srcs = [
37+
"debug_tensor_value.ts",
38+
],
39+
deps = [
40+
":types",
41+
"//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin:tf_types",
42+
],
43+
)
44+
3445
tf_ts_library(
3546
name = "debugger_store_test_lib",
3647
testonly = True,
3748
srcs = [
49+
"debug_tensor_value_test.ts",
3850
"debugger_reducers_test.ts",
3951
"debugger_selectors_test.ts",
4052
],
4153
tsconfig = "//:tsconfig-test",
4254
deps = [
55+
":debug_tensor_value",
4356
":store",
4457
":types",
4558
"//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions",
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
/* Copyright 2020 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+
16+
import {DTYPE_ENUM_TO_NAME} from '../tf_dtypes';
17+
import {DebugTensorValue, TensorDebugMode} from './debugger_types';
18+
19+
export interface RawDebugTensorValue {
20+
tensorDebugMode: TensorDebugMode;
21+
array: null | number[];
22+
}
23+
24+
export interface RawDebugTensorValueNoTensor extends RawDebugTensorValue {
25+
tensorDebugMode: TensorDebugMode.NO_TENSOR;
26+
array: null;
27+
}
28+
29+
export interface RawDebugTensorValueCurtHealth extends RawDebugTensorValue {
30+
tensorDebugMode: TensorDebugMode.CURT_HEALTH;
31+
array: [
32+
number, // Tensor ID.
33+
number // 0-1 indicator for the presence of inf/nan.
34+
];
35+
}
36+
37+
export interface RawDebugTensorValueConciseHealth extends RawDebugTensorValue {
38+
tensorDebugMode: TensorDebugMode.CURT_HEALTH;
39+
array: [
40+
number, // Tensor ID.
41+
number, // Element count (size).
42+
number, // -inf count.
43+
number, // +inf count.
44+
number // nan count.
45+
];
46+
}
47+
48+
export interface RawDebugTensorValueShape extends RawDebugTensorValue {
49+
tensorDebugMode: TensorDebugMode.SHAPE;
50+
array: [
51+
number, // Tensor ID.
52+
number, // DType enum value.
53+
number, // Rank.
54+
number, // Size.
55+
number, // Shape truncated at head to a maximum length of 6.
56+
number,
57+
number,
58+
number,
59+
number,
60+
number
61+
];
62+
}
63+
64+
export interface RawDebugTensorValueFullHealth extends RawDebugTensorValue {
65+
tensorDebugMode: TensorDebugMode.FULL_HEALTH;
66+
array: [
67+
number, // Tensor ID.
68+
number, // Device ID.
69+
number, // DType enum value.
70+
number, // Rank.
71+
number, // Size.
72+
number, // -inf count.
73+
number, // +inf count.
74+
number, // nan count.
75+
number, // -finite count.
76+
number, // zero count.
77+
number // +finite count.
78+
];
79+
}
80+
81+
export interface RawDebugTensorValueFullTensor extends RawDebugTensorValue {
82+
tensorDebugMode: TensorDebugMode.FULL_HEALTH;
83+
array: null;
84+
}
85+
86+
/**
87+
* Parse a number array that represents debugging summary of an instrumented
88+
* tensor value.
89+
*
90+
* @param tensorDebugMode and the array of number that represents various
91+
* aspect of the instrumented tensor. The semantics of the numbers are
92+
* determined by `tensorDebugMode`.
93+
* @returns A DebugTensorValue object with the same information as
94+
* carried by `array`, but represented in a more explicit fashion.
95+
* For numbers that represent breakdown of numeric values by type
96+
* (e.g., counts of -inf, +inf and nan), the corresponding fields
97+
* in the returned object will be defined only if the count is non-zero.
98+
*/
99+
export function parseDebugTensorValue(
100+
raw: RawDebugTensorValue
101+
): DebugTensorValue {
102+
const {tensorDebugMode, array} = raw;
103+
switch (tensorDebugMode) {
104+
case TensorDebugMode.NO_TENSOR: {
105+
if (array !== null) {
106+
throw new Error(
107+
'Unexpectedly received non-null debug-tensor-value array ' +
108+
'under NO_TENSOR mode'
109+
);
110+
}
111+
return {};
112+
}
113+
case TensorDebugMode.CURT_HEALTH: {
114+
if (array === null || array.length !== 2) {
115+
throw new Error(
116+
`Under CURT_HEALTH mode, expected debug-tensor-value array ` +
117+
`to have length 2, but got ${JSON.stringify(array)}`
118+
);
119+
}
120+
return {
121+
hasInfOrNaN: Boolean(array[1]),
122+
};
123+
}
124+
case TensorDebugMode.CONCISE_HEALTH: {
125+
if (array === null || array.length !== 5) {
126+
throw new Error(
127+
`Under CONCISE_HEALTH mode, expected debug-tensor-value array ` +
128+
`to have length 5, but got ${JSON.stringify(array)}`
129+
);
130+
}
131+
const value: DebugTensorValue = {
132+
size: array[1],
133+
};
134+
if (array[2] > 0) {
135+
value.numNegativeInfs = array[2];
136+
}
137+
if (array[3] > 0) {
138+
value.numPositiveInfs = array[3];
139+
}
140+
if (array[4] > 0) {
141+
value.numNaNs = array[4];
142+
}
143+
return value;
144+
}
145+
case TensorDebugMode.SHAPE: {
146+
if (array === null || array.length !== 10) {
147+
throw new Error(
148+
`Under SHAPE mode, expected debug-tensor-value array ` +
149+
`to have length 10, but got ${JSON.stringify(array)}`
150+
);
151+
}
152+
const rank = array[2];
153+
let shape: number[] = array.slice(4, Math.min(4 + rank, array.length));
154+
if (shape.length < rank) {
155+
// The SHAPE mode truncates the shape at head.
156+
shape = new Array<number>(rank - shape.length).concat(shape);
157+
}
158+
return {
159+
dtype: DTYPE_ENUM_TO_NAME[array[1]],
160+
rank,
161+
size: array[3],
162+
shape,
163+
};
164+
}
165+
case TensorDebugMode.FULL_HEALTH: {
166+
if (array === null || array.length !== 11) {
167+
throw new Error(
168+
`Under FULL_HEALTH mode, expected debug-tensor-value array ` +
169+
`to have length 11, but got ${JSON.stringify(array)}`
170+
);
171+
}
172+
const rank = array[3];
173+
const value: DebugTensorValue = {
174+
dtype: DTYPE_ENUM_TO_NAME[array[2]],
175+
rank,
176+
size: array[4],
177+
};
178+
if (array[5] > 0) {
179+
value.numNegativeInfs = array[5];
180+
}
181+
if (array[6] > 0) {
182+
value.numPositiveInfs = array[6];
183+
}
184+
if (array[7] > 0) {
185+
value.numNaNs = array[7];
186+
}
187+
if (array[8] > 0) {
188+
value.numNegativeFinites = array[8];
189+
}
190+
if (array[9] > 0) {
191+
value.numZeros = array[9];
192+
}
193+
if (array[10] > 0) {
194+
value.numPositiveFinites = array[10];
195+
}
196+
return value;
197+
}
198+
case TensorDebugMode.FULL_TENSOR: {
199+
// Under FULL_TENSOR mode, the full tensor value is supplied via
200+
// separate means. No summary values are provided for the tensor value.
201+
if (array !== null) {
202+
throw new Error(
203+
'Unexpectedly received non-null debug-tensor-value array ' +
204+
'under FULL_TENSOR mode'
205+
);
206+
}
207+
return {};
208+
}
209+
default: {
210+
throw new Error(`Unrecognized tensorDebugMode: ${tensorDebugMode}`);
211+
}
212+
}
213+
}

0 commit comments

Comments
 (0)