From 6150f26c91a5d2511481fbf5d8fcceaf5bd14364 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Thu, 16 Apr 2020 16:35:41 -0400 Subject: [PATCH 01/29] [DebuggerV2] Flesh out graph execution data display --- .../debugger_v2/debug_data_multiplexer.py | 12 +-- .../actions/debugger_actions.ts | 19 +++++ .../effects/debugger_effects.ts | 76 ++++++++++++++++++- .../store/debugger_reducers.ts | 70 +++++++++++++++++ .../store/debugger_selectors.ts | 36 +++++++++ .../store/debugger_types.ts | 8 +- .../views/graph_executions/BUILD | 1 + .../graph_executions_component.css | 52 +++++++++++++ .../graph_executions_component.ng.html | 34 ++++++++- .../graph_executions_component.ts | 20 ++++- .../graph_executions_container.ts | 28 ++++++- .../graph_executions_module.ts | 3 +- 12 files changed, 347 insertions(+), 12 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/debug_data_multiplexer.py b/tensorboard/plugins/debugger_v2/debug_data_multiplexer.py index 87bc0fb3e41..775d42f7db7 100644 --- a/tensorboard/plugins/debugger_v2/debug_data_multiplexer.py +++ b/tensorboard/plugins/debugger_v2/debug_data_multiplexer.py @@ -366,15 +366,17 @@ def GraphExecutionData(self, run, begin, end, trace_id=None): "trace_id support for GraphExecutionTraceData is " "not implemented yet." ) - graph_executions = self._reader.graph_execution_traces(digest=False) - end = self._checkBeginEndIndices(begin, end, len(graph_executions)) + digests = self._reader.graph_execution_traces(digest=True) + end = self._checkBeginEndIndices(begin, end, len(digests)) + digests = digests[begin:end] + graph_executions = [ + self._reader.read_graph_execution_trace(digest) for digest in digests + ] return { "begin": begin, "end": end, - "num_digests": len(graph_executions), "graph_executions": [ - graph_exec.to_json() - for graph_exec in graph_executions[begin:end] + graph_exec.to_json() for graph_exec in graph_executions ], } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions/debugger_actions.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions/debugger_actions.ts index 0e04b595cce..4b417771214 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions/debugger_actions.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions/debugger_actions.ts @@ -27,6 +27,7 @@ import { import { ExecutionDigestsResponse, ExecutionDataResponse, + GraphExecutionDataResponse, SourceFileResponse, } from '../data_source/tfdbg2_data_source'; @@ -144,6 +145,24 @@ export const numGraphExecutionsLoaded = createAction( props<{numGraphExecutions: number}>() ); +export const graphExecutionDataRequested = createAction( + '[Debugger] Intra-Graph Execution Data Requested', + props<{pageIndex: number}>() +); + +export const graphExecutionDataLoaded = createAction( + '[Debugger] Intra-Graph Execution Data Loaded', + props() +); + +export const graphExecutionScrollToIndex = createAction( + '[Debugger] Scroll the Graph Execution List to Given Index', + props<{index: number}>() +); + +/** + * Actions related to source files and stack traces. + */ export const sourceFileListRequested = createAction( '[Debugger] Source File List Requested.' ); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts index d6447a575d7..9aea3709bfb 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts @@ -17,6 +17,7 @@ import {Store} from '@ngrx/store'; import {Actions, createEffect, ofType} from '@ngrx/effects'; import {merge, Observable} from 'rxjs'; import { + debounceTime, filter, map, mergeMap, @@ -37,6 +38,8 @@ import { executionScrollLeft, executionScrollRight, executionScrollToIndex, + graphExecutionDataLoaded, + graphExecutionScrollToIndex, numAlertsAndBreakdownLoaded, numAlertsAndBreakdownRequested, numExecutionsLoaded, @@ -61,6 +64,9 @@ import { getExecutionPageSize, getExecutionScrollBeginIndex, getFocusedSourceFileContent, + getGraphExecutionData, + getGraphExecutionPageSize, + getGraphExecutionScrollBeginIndex, getNumExecutions, getNumExecutionsLoaded, getLoadedAlertsOfFocusedType, @@ -541,6 +547,70 @@ export class DebuggerEffects { ); } + /** + * Emits when scrolling event leads to need to load new intra-graph execution + * digests. + */ + private onGraphExecutionScroll(): Observable { + return this.actions$.pipe( + ofType(graphExecutionScrollToIndex), + debounceTime(100), // TODO(cais): Remove magic number. + withLatestFrom( + this.store.select(getActiveRunId), + this.store.select(getNumGraphExecutions), + this.store.select(getGraphExecutionScrollBeginIndex), + this.store.select(getGraphExecutionPageSize), + this.store.select(getGraphExecutionData) + ), + filter( + ([, runId, numGraphExecutions]) => + runId !== null && numGraphExecutions > 0 + ), + map( + ([ + , + runId, + numGraphExecutions, + scrollBeginIndex, + pageSize, + graphExecutionData, + ]) => { + const pageIndex = Math.floor(scrollBeginIndex / pageSize); + const begin = pageSize * pageIndex; + const end = Math.min(begin + 2 * pageSize, numGraphExecutions); + let dataMissing = false; + for (let i = begin; i < end; ++i) { + if (graphExecutionData[i] === undefined) { + dataMissing = true; + break; + } + } + return { + runId, + dataMissing, + begin, + end, + }; + } + ), + filter(({dataMissing}) => dataMissing), + mergeMap(({runId, begin, end}) => { + console.log( + `mergeMap() 200: runId=${runId}, begin=${begin}, end=${end}` + ); // DEBUG + return this.dataSource.fetchGraphExecutionData(runId!, begin, end).pipe( + tap((graphExecutionDataResponse) => { + this.store.dispatch( + graphExecutionDataLoaded(graphExecutionDataResponse) + ); + }), + map(() => void null) + ); + // TODO(cais): Add catchError() to pipe. + }) + ); + } + /** * Emits when user focuses on an alert type. * @@ -825,6 +895,9 @@ export class DebuggerEffects { onLoad$ ); + // TODO(cais): Hook it up. + const onGraphExecutionScroll$ = this.onGraphExecutionScroll(); + const onSourceFileFocused$ = this.onSourceFileFocused(); // ExecutionDigest and ExecutionData can be loaded in parallel. @@ -834,7 +907,8 @@ export class DebuggerEffects { onExecutionDataLoaded$, onNumGraphExecutionLoaded$, loadSourceFileList$, - onSourceFileFocused$ + onSourceFileFocused$, + onGraphExecutionScroll$ ).pipe( // createEffect expects an Observable that emits {}. map(() => ({})) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts index 913c9eabe43..b3380362d1c 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts @@ -18,6 +18,7 @@ import * as actions from '../actions'; import { ExecutionDataResponse, ExecutionDigestsResponse, + GraphExecutionDataResponse, GraphExecutionDigestsResponse, SourceFileResponse, } from '../data_source/tfdbg2_data_source'; @@ -83,6 +84,7 @@ export function createInitialGraphExecutionsState(): GraphExecutions { scrollBeginIndex: 0, focusIndex: null, graphExecutionDigests: {}, + loadingGraphExecutionDataPages: [], graphExecutionData: {}, }; } @@ -564,6 +566,74 @@ const reducer = createReducer( return newState; } ), + on( + actions.graphExecutionDataRequested, + (state: DebuggerState, {pageIndex}): DebuggerState => { + if (state.activeRunId === null) { + return state; + } + const loadingGraphExecutionDataPages = state.graphExecutions.loadingGraphExecutionDataPages.slice(); + if (loadingGraphExecutionDataPages.indexOf(pageIndex) === -1) { + loadingGraphExecutionDataPages.push(pageIndex); + } + return { + ...state, + graphExecutions: { + ...state.graphExecutions, + loadingGraphExecutionDataPages, + }, + }; + } + ), // TODO(cais): Add unit test. + on( + actions.graphExecutionDataLoaded, + (state: DebuggerState, data: GraphExecutionDataResponse): DebuggerState => { + console.log('graphExecutionDataLoaded reducer: data=', data); // DEBUG + if (state.activeRunId === null) { + return state; + } + const pageIndex = Math.floor(data.begin / state.graphExecutions.pageSize); + console.log('pageIndex reducer: pageIndex=', pageIndex); // DEBUG + // TODO(cais): Throw error if division is not integer? + const loadingGraphExecutionDataPages = state.graphExecutions.loadingGraphExecutionDataPages.slice(); + if (loadingGraphExecutionDataPages.indexOf(pageIndex) !== -1) { + loadingGraphExecutionDataPages.splice( + loadingGraphExecutionDataPages.indexOf(pageIndex), + 1 + ); + } + const graphExecutionData = {...state.graphExecutions.graphExecutionData}; + for (let i = data.begin; i < data.end; ++i) { + graphExecutionData[i] = data.graph_executions[i - data.begin]; + } + return { + ...state, + graphExecutions: { + ...state.graphExecutions, + graphExecutionData, + loadingGraphExecutionDataPages, + }, + }; + } + ), // TODO(cais): Add unit test. + on( + actions.graphExecutionScrollToIndex, + (state: DebuggerState, action: {index: number}): DebuggerState => { + if (action.index < 0 || !Number.isInteger(action.index)) { + throw new Error( + `Attempt to scroll to negative or non-integer graph-execution ` + + `index (${action.index})` + ); + } + return { + ...state, + graphExecutions: { + ...state.graphExecutions, + scrollBeginIndex: action.index, + }, + }; + } + ), // TODO(cais): Add unit test. //////////////////////////////////////////////////////// // Reducers related to source files and stack traces. // //////////////////////////////////////////////////////// diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts index 669f59656bb..5e9599b999c 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts @@ -25,6 +25,7 @@ import { Execution, ExecutionDigest, ExecutionDigestLoadState, + GraphExecution, LoadState, SourceFileContent, SourceFileSpec, @@ -208,6 +209,41 @@ export const getNumGraphExecutions = createSelector( } ); +export const getGraphExecutionScrollBeginIndex = createSelector( + selectDebuggerState, + (state: DebuggerState): number => { + return state.graphExecutions.scrollBeginIndex; + } +); // TODO(cais): Add unit tests. + +export const getGraphExecutionPageSize = createSelector( + selectDebuggerState, + (state: DebuggerState): number => { + return state.graphExecutions.pageSize; + } +); // TODO(cais): Add unit tests. + +export const getLoadingGraphExecutionPages = createSelector( + selectDebuggerState, + (state: DebuggerState): number[] => { + return state.graphExecutions.loadingGraphExecutionDataPages; + } +); // TODO(cais): Add unit tests. + +// export const getLoadedGraphExecutionPages = createSelector( +// selectDebuggerState, +// (state: DebuggerState): number[] => { +// return state.graphExecutions.loadedGraphExecutionDataPages; +// } +// ); // TODO(cais): Add unit tests. + +export const getGraphExecutionData = createSelector( + selectDebuggerState, + (state: DebuggerState): {[index: number]: GraphExecution} => { + return state.graphExecutions.graphExecutionData; + } +); // TODO(cais): Add unit tests. + /** * Get the focused alert types (if any) of the execution digests current being * displayed. For each displayed execution digest, there are two possibilities: diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts index 5e80e34702f..1aff36b9e2e 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts @@ -256,8 +256,14 @@ export interface GraphExecutions extends PagedExecutions { // Intra-graph execution digests the frontend has loaded so far. graphExecutionDigests: {[index: number]: GraphExecutionDigest}; + // Indices to GraphExecution pages currently being loaded. + loadingGraphExecutionDataPages: number[]; + + // // Indices to GraphExecution pages that have been loaded successfully. + // loadedGraphExecutionDataPages: number[]; + // Detailed data objects about intra-graph execution. - graphExecutionData: {[index: number]: Execution}; + graphExecutionData: {[index: number]: GraphExecution}; } // The state of a loaded DebuggerV2 run. diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/BUILD index ae9a3e0b2bf..a1882c35b0e 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/BUILD @@ -21,6 +21,7 @@ ng_module( "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", + "//tensorboard/webapp/angular:expect_angular_cdk_overlay", "@npm//@angular/common", "@npm//@angular/core", "@npm//@ngrx/store", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css index a3d0e697c85..10b10f7c645 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css @@ -21,3 +21,55 @@ limitations under the License. margin-left: 8px; padding-left: 10px; } + +.graph-executions-viewport { + flex-grow: 1; + font-size: 12px; + width: 100%; + overflow-x: hidden; +} + +.op-type { + display: inline-block; + overflow: hidden; + text-align: left; + text-overflow: ellipsis; + width: 80px; +} + +.graph-execution-index { + display: inline-block; + text-align: right; + width: 40px; + padding-right: 4px; +} + +.loading-spinner { + display: inline-block; +} + +.tensor-container { + width: 100%; +} + +.tensor-item { + display: flex; + flex-wrap: nowrap; + height: 24px; + line-height: 24px; + text-align: left; + vertical-align: top; + white-space: nowrap; + width: 100%; +} + +.tensor-name { + direction: rtl; + display: inline-block; + overflow: hidden; + padding-right: 8px; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + width: 240px; +} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html index 6b78f3fe71c..82d9bb9bec8 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html @@ -20,5 +20,37 @@ Graph Executions ({{ numGraphExecutions }}) - + +
+
+
+ {{ i }} +
+
+ {{ graphExecutionData[i].op_name }}:{{ + graphExecutionData[i].output_slot }} +
+
+ {{ graphExecutionData[i].op_type }} +
+
+ + +
+ {{ i }} +
+
+ Loading... +
+
+
+
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts index 7cd3f43230a..c801e9b789e 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts @@ -13,14 +13,32 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -import {Component, Input} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + Output, +} from '@angular/core'; + +import {GraphExecution} from '../../store/debugger_types'; @Component({ selector: 'graph-executions-component', templateUrl: './graph_executions_component.ng.html', styleUrls: ['./graph_executions_component.css'], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class GraphExecutionsComponent { @Input() numGraphExecutions: number | null = null; + + @Input() + graphExecutionData: {[index: number]: GraphExecution} = {}; + + @Input() + graphExecutionIndices: number[] | null = null; + + @Output() + onScrolledIndexChange = new EventEmitter(); } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container.ts index 9af09cf15c8..cc609ee27c4 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container.ts @@ -13,9 +13,10 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ import {Component} from '@angular/core'; -import {select, Store} from '@ngrx/store'; +import {createSelector, select, Store} from '@ngrx/store'; -import {getNumGraphExecutions} from '../../store'; +import {graphExecutionScrollToIndex} from '../../actions'; +import {getGraphExecutionData, getNumGraphExecutions} from '../../store'; import {State} from '../../store/debugger_types'; /** @typehack */ import * as _typeHackRxjs from 'rxjs'; @@ -25,11 +26,34 @@ import {State} from '../../store/debugger_types'; template: ` `, }) export class GraphExecutionsContainer { readonly numGraphExecutions$ = this.store.pipe(select(getNumGraphExecutions)); + readonly graphExecutionData$ = this.store.pipe(select(getGraphExecutionData)); + + readonly graphExecutionIndices$ = this.store.pipe( + select( + createSelector( + getNumGraphExecutions, + (numGraphExecution: number): number[] | null => { + if (numGraphExecution === 0) { + return null; + } + return Array.from({length: numGraphExecution}).map((_, i) => i); + } + ) + ) + ); + + onScrolledIndexChange(scrolledIndex: number) { + this.store.dispatch(graphExecutionScrollToIndex({index: scrolledIndex})); + } + constructor(private readonly store: Store) {} } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts index 864a258ae44..5e43f6e91cb 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts @@ -13,6 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +import {ScrollingModule} from '@angular/cdk/scrolling'; import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; @@ -21,7 +22,7 @@ import {GraphExecutionsContainer} from './graph_executions_container'; @NgModule({ declarations: [GraphExecutionsComponent, GraphExecutionsContainer], - imports: [CommonModule], + imports: [CommonModule, ScrollingModule], exports: [GraphExecutionsContainer], }) export class GraphExecutionsModule {} From d7dd9c5cbdc4ee57b86a6e39ad084e4da3b8a9ce Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Fri, 17 Apr 2020 09:10:32 -0400 Subject: [PATCH 02/29] Flesh out scrolling effect; Improve CSS --- .../effects/debugger_effects.ts | 76 +++++++++++++------ .../store/debugger_reducers.ts | 39 ++++++---- .../store/debugger_selectors.ts | 19 +++-- .../store/debugger_types.ts | 4 +- .../graph_executions_component.css | 30 ++++++-- .../graph_executions_component.ng.html | 19 +++-- 6 files changed, 125 insertions(+), 62 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts index 9aea3709bfb..87800cd8e39 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts @@ -64,7 +64,7 @@ import { getExecutionPageSize, getExecutionScrollBeginIndex, getFocusedSourceFileContent, - getGraphExecutionData, + getGraphExecutionDisplayCount, getGraphExecutionPageSize, getGraphExecutionScrollBeginIndex, getNumExecutions, @@ -77,6 +77,8 @@ import { getNumGraphExecutionsLoaded, getSourceFileListLoaded, getFocusedSourceFileIndex, + getGraphExecutionDataPageLoadedSizes, + getLoadingGraphExecutionPages, } from '../store/debugger_selectors'; import { DataLoadState, @@ -554,18 +556,17 @@ export class DebuggerEffects { private onGraphExecutionScroll(): Observable { return this.actions$.pipe( ofType(graphExecutionScrollToIndex), - debounceTime(100), // TODO(cais): Remove magic number. + debounceTime(100), // TODO(cais): Remove magic number. Look at race condition. withLatestFrom( this.store.select(getActiveRunId), this.store.select(getNumGraphExecutions), this.store.select(getGraphExecutionScrollBeginIndex), this.store.select(getGraphExecutionPageSize), - this.store.select(getGraphExecutionData) - ), - filter( - ([, runId, numGraphExecutions]) => - runId !== null && numGraphExecutions > 0 + this.store.select(getGraphExecutionDisplayCount) ), + filter(([, runId, numGraphExecutions]) => { + return runId !== null && numGraphExecutions > 0; + }), map( ([ , @@ -573,31 +574,56 @@ export class DebuggerEffects { numGraphExecutions, scrollBeginIndex, pageSize, - graphExecutionData, + displayCount, + ]) => ({ + runId, + numGraphExecutions, + scrollBeginIndex, + pageSize, + displayCount, + }) + ), + withLatestFrom( + this.store.select(getLoadingGraphExecutionPages), + this.store.select(getGraphExecutionDataPageLoadedSizes) + ), + map( + ([ + {runId, numGraphExecutions, scrollBeginIndex, pageSize, displayCount}, + loadingPages, + pageLoadedSizes, ]) => { - const pageIndex = Math.floor(scrollBeginIndex / pageSize); - const begin = pageSize * pageIndex; - const end = Math.min(begin + 2 * pageSize, numGraphExecutions); - let dataMissing = false; - for (let i = begin; i < end; ++i) { - if (graphExecutionData[i] === undefined) { - dataMissing = true; - break; + const missingPages = getMissingPages( + scrollBeginIndex, + Math.min(scrollBeginIndex + displayCount, numGraphExecutions), + pageSize, + numGraphExecutions, + pageLoadedSizes + ); + // Omit pages that are already loading. + for (let i = missingPages.length - 1; i >= 0; --i) { + if (loadingPages.indexOf(missingPages[i]) !== -1) { + missingPages.splice(i, 1); // TODO(cais): Add unit test. } } return { runId, - dataMissing, - begin, - end, + missingPages, + pageSize, + numGraphExecutions, }; } ), - filter(({dataMissing}) => dataMissing), - mergeMap(({runId, begin, end}) => { - console.log( - `mergeMap() 200: runId=${runId}, begin=${begin}, end=${end}` - ); // DEBUG + filter(({missingPages}) => missingPages.length > 0), + mergeMap(({runId, missingPages, pageSize, numGraphExecutions}) => { + const begin = missingPages[0] * pageSize; + const end = Math.min( + (missingPages[missingPages.length - 1] + 1) * pageSize, + numGraphExecutions + ); + // console.log( + // `mergeMap() 200: runId=${runId}, begin=${begin}, end=${end}` + // ); // DEBUG return this.dataSource.fetchGraphExecutionData(runId!, begin, end).pipe( tap((graphExecutionDataResponse) => { this.store.dispatch( @@ -609,7 +635,7 @@ export class DebuggerEffects { // TODO(cais): Add catchError() to pipe. }) ); - } + } // TODO(cais): Add unit test. /** * Emits when user focuses on an alert type. diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts index b3380362d1c..6ddddb65d51 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts @@ -40,7 +40,7 @@ import { /** @typehack */ import * as _typeHackStore from '@ngrx/store/store'; const DEFAULT_EXECUTION_PAGE_SIZE = 100; -const DEFAULT_GRAPH_EXECUTION_PAGE_SIZE = 100; +const DEFAULT_GRAPH_EXECUTION_PAGE_SIZE = 200; export function createInitialExecutionsState(): Executions { return { @@ -79,12 +79,13 @@ export function createInitialGraphExecutionsState(): GraphExecutions { }, // TODO(cais) Remove the hardcoding of this, which is coupled with css width // properties. - displayCount: 50, + displayCount: 100, pageSize: DEFAULT_GRAPH_EXECUTION_PAGE_SIZE, scrollBeginIndex: 0, focusIndex: null, graphExecutionDigests: {}, loadingGraphExecutionDataPages: [], + graphExecutionDataPageLoadedSizes: {}, graphExecutionData: {}, }; } @@ -588,30 +589,40 @@ const reducer = createReducer( on( actions.graphExecutionDataLoaded, (state: DebuggerState, data: GraphExecutionDataResponse): DebuggerState => { - console.log('graphExecutionDataLoaded reducer: data=', data); // DEBUG if (state.activeRunId === null) { return state; } - const pageIndex = Math.floor(data.begin / state.graphExecutions.pageSize); - console.log('pageIndex reducer: pageIndex=', pageIndex); // DEBUG - // TODO(cais): Throw error if division is not integer? + const {pageSize} = state.graphExecutions; const loadingGraphExecutionDataPages = state.graphExecutions.loadingGraphExecutionDataPages.slice(); - if (loadingGraphExecutionDataPages.indexOf(pageIndex) !== -1) { - loadingGraphExecutionDataPages.splice( - loadingGraphExecutionDataPages.indexOf(pageIndex), - 1 - ); - } + const graphExecutionDataPageLoadedSizes = { + ...state.graphExecutions.graphExecutionDataPageLoadedSizes, + }; const graphExecutionData = {...state.graphExecutions.graphExecutionData}; + // Update loadingGraphExecutionDataPages, graphExecutionDataPageLoadedSizes, + // and graphExecutionData. for (let i = data.begin; i < data.end; ++i) { - graphExecutionData[i] = data.graph_executions[i - data.begin]; + const pageIndex = Math.floor(i / pageSize); + if (loadingGraphExecutionDataPages.indexOf(pageIndex) !== -1) { + loadingGraphExecutionDataPages.splice( + loadingGraphExecutionDataPages.indexOf(pageIndex), + 1 + ); + } + if (graphExecutionData[i] === undefined) { + graphExecutionData[i] = data.graph_executions[i - data.begin]; + if (graphExecutionDataPageLoadedSizes[pageIndex] === undefined) { + graphExecutionDataPageLoadedSizes[pageIndex] = 0; + } + graphExecutionDataPageLoadedSizes[pageIndex]++; + } } return { ...state, graphExecutions: { ...state.graphExecutions, - graphExecutionData, loadingGraphExecutionDataPages, + graphExecutionDataPageLoadedSizes, + graphExecutionData, }, }; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts index 5e9599b999c..080ef1a349d 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts @@ -216,6 +216,13 @@ export const getGraphExecutionScrollBeginIndex = createSelector( } ); // TODO(cais): Add unit tests. +export const getGraphExecutionDisplayCount = createSelector( + selectDebuggerState, + (state: DebuggerState): number => { + return state.graphExecutions.displayCount; + } +); // TODO(cais): Add unit tests. + export const getGraphExecutionPageSize = createSelector( selectDebuggerState, (state: DebuggerState): number => { @@ -230,12 +237,12 @@ export const getLoadingGraphExecutionPages = createSelector( } ); // TODO(cais): Add unit tests. -// export const getLoadedGraphExecutionPages = createSelector( -// selectDebuggerState, -// (state: DebuggerState): number[] => { -// return state.graphExecutions.loadedGraphExecutionDataPages; -// } -// ); // TODO(cais): Add unit tests. +export const getGraphExecutionDataPageLoadedSizes = createSelector( + selectDebuggerState, + (state: DebuggerState): {[page: number]: number} => { + return state.graphExecutions.graphExecutionDataPageLoadedSizes; + } +); // TODO(cais): Add unit tests. export const getGraphExecutionData = createSelector( selectDebuggerState, diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts index 1aff36b9e2e..0e4f641ec76 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts @@ -259,8 +259,8 @@ export interface GraphExecutions extends PagedExecutions { // Indices to GraphExecution pages currently being loaded. loadingGraphExecutionDataPages: number[]; - // // Indices to GraphExecution pages that have been loaded successfully. - // loadedGraphExecutionDataPages: number[]; + // Number of items in each `GraphExecution` page that have been loaded. + graphExecutionDataPageLoadedSizes: {[page: number]: number}; // Detailed data objects about intra-graph execution. graphExecutionData: {[index: number]: GraphExecution}; diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css index 10b10f7c645..4a28ec4c3ed 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css @@ -30,11 +30,17 @@ limitations under the License. } .op-type { - display: inline-block; - overflow: hidden; - text-align: left; - text-overflow: ellipsis; - width: 80px; + background-color: #e3e5e8; + border: 1px solid #c0c0c0; + border-radius: 4px; + direction: rtl; + font-family: 'Roboto Mono', monospace; + font-size: 10px; + display: block; + height: 14px; + line-height: 14px; + padding: 1px 3px; + width: max-content; } .graph-execution-index { @@ -53,10 +59,11 @@ limitations under the License. } .tensor-item { + border-bottom: 1px solid rgba(0, 0, 0, 0.12); display: flex; flex-wrap: nowrap; - height: 24px; - line-height: 24px; + height: 36px; + line-height: 36px; text-align: left; vertical-align: top; white-space: nowrap; @@ -64,6 +71,15 @@ limitations under the License. } .tensor-name { + direction: rtl; + display: block; + height: 16px; + line-height: 16px; + padding: 0 2px; + width: 100%; +} + +.tensor-name-and-op-type { direction: rtl; display: inline-block; overflow: hidden; diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html index 82d9bb9bec8..378e8823f84 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html @@ -22,7 +22,8 @@ @@ -32,14 +33,16 @@ >
- {{ i }} -
-
- {{ graphExecutionData[i].op_name }}:{{ - graphExecutionData[i].output_slot }} + {{ i }}:
-
- {{ graphExecutionData[i].op_type }} +
+
+ {{ graphExecutionData[i].op_name }}:{{ + graphExecutionData[i].output_slot }} +
+
+ {{ graphExecutionData[i].op_type }} +
From 4b31ddb49f63c25d6239512b98c7f1d2f2e220af Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Fri, 17 Apr 2020 09:44:31 -0400 Subject: [PATCH 03/29] Add unit tests for selectors --- .../actions/debugger_actions.ts | 2 +- .../effects/debugger_effects.ts | 6 +- .../store/debugger_reducers.ts | 22 +-- .../store/debugger_selectors.ts | 16 +- .../store/debugger_selectors_test.ts | 145 ++++++++++++++++++ .../store/debugger_types.ts | 2 +- 6 files changed, 169 insertions(+), 24 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions/debugger_actions.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions/debugger_actions.ts index 4b417771214..aa1082f4b7f 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions/debugger_actions.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions/debugger_actions.ts @@ -156,7 +156,7 @@ export const graphExecutionDataLoaded = createAction( ); export const graphExecutionScrollToIndex = createAction( - '[Debugger] Scroll the Graph Execution List to Given Index', + '[Debugger] Scroll Intra-Graph Execution List to Given Index', props<{index: number}>() ); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts index 87800cd8e39..d65f93cb2db 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts @@ -64,9 +64,11 @@ import { getExecutionPageSize, getExecutionScrollBeginIndex, getFocusedSourceFileContent, + getGraphExecutionDataPageLoadedSizes, getGraphExecutionDisplayCount, getGraphExecutionPageSize, getGraphExecutionScrollBeginIndex, + getGraphExecutionDataLoadingPages, getNumExecutions, getNumExecutionsLoaded, getLoadedAlertsOfFocusedType, @@ -77,8 +79,6 @@ import { getNumGraphExecutionsLoaded, getSourceFileListLoaded, getFocusedSourceFileIndex, - getGraphExecutionDataPageLoadedSizes, - getLoadingGraphExecutionPages, } from '../store/debugger_selectors'; import { DataLoadState, @@ -584,7 +584,7 @@ export class DebuggerEffects { }) ), withLatestFrom( - this.store.select(getLoadingGraphExecutionPages), + this.store.select(getGraphExecutionDataLoadingPages), this.store.select(getGraphExecutionDataPageLoadedSizes) ), map( diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts index 6ddddb65d51..2b27c187ac2 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts @@ -84,7 +84,7 @@ export function createInitialGraphExecutionsState(): GraphExecutions { scrollBeginIndex: 0, focusIndex: null, graphExecutionDigests: {}, - loadingGraphExecutionDataPages: [], + graphExecutionDataLoadingPages: [], graphExecutionDataPageLoadedSizes: {}, graphExecutionData: {}, }; @@ -573,15 +573,15 @@ const reducer = createReducer( if (state.activeRunId === null) { return state; } - const loadingGraphExecutionDataPages = state.graphExecutions.loadingGraphExecutionDataPages.slice(); - if (loadingGraphExecutionDataPages.indexOf(pageIndex) === -1) { - loadingGraphExecutionDataPages.push(pageIndex); + const graphExecutionDataLoadingPages = state.graphExecutions.graphExecutionDataLoadingPages.slice(); + if (graphExecutionDataLoadingPages.indexOf(pageIndex) === -1) { + graphExecutionDataLoadingPages.push(pageIndex); } return { ...state, graphExecutions: { ...state.graphExecutions, - loadingGraphExecutionDataPages, + graphExecutionDataLoadingPages, }, }; } @@ -593,18 +593,18 @@ const reducer = createReducer( return state; } const {pageSize} = state.graphExecutions; - const loadingGraphExecutionDataPages = state.graphExecutions.loadingGraphExecutionDataPages.slice(); + const graphExecutionDataLoadingPages = state.graphExecutions.graphExecutionDataLoadingPages.slice(); const graphExecutionDataPageLoadedSizes = { ...state.graphExecutions.graphExecutionDataPageLoadedSizes, }; const graphExecutionData = {...state.graphExecutions.graphExecutionData}; - // Update loadingGraphExecutionDataPages, graphExecutionDataPageLoadedSizes, + // Update graphExecutionDataLoadingPages, graphExecutionDataPageLoadedSizes, // and graphExecutionData. for (let i = data.begin; i < data.end; ++i) { const pageIndex = Math.floor(i / pageSize); - if (loadingGraphExecutionDataPages.indexOf(pageIndex) !== -1) { - loadingGraphExecutionDataPages.splice( - loadingGraphExecutionDataPages.indexOf(pageIndex), + if (graphExecutionDataLoadingPages.indexOf(pageIndex) !== -1) { + graphExecutionDataLoadingPages.splice( + graphExecutionDataLoadingPages.indexOf(pageIndex), 1 ); } @@ -620,7 +620,7 @@ const reducer = createReducer( ...state, graphExecutions: { ...state.graphExecutions, - loadingGraphExecutionDataPages, + graphExecutionDataLoadingPages, graphExecutionDataPageLoadedSizes, graphExecutionData, }, diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts index 080ef1a349d..7ff7849cbc5 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts @@ -214,42 +214,42 @@ export const getGraphExecutionScrollBeginIndex = createSelector( (state: DebuggerState): number => { return state.graphExecutions.scrollBeginIndex; } -); // TODO(cais): Add unit tests. +); export const getGraphExecutionDisplayCount = createSelector( selectDebuggerState, (state: DebuggerState): number => { return state.graphExecutions.displayCount; } -); // TODO(cais): Add unit tests. +); export const getGraphExecutionPageSize = createSelector( selectDebuggerState, (state: DebuggerState): number => { return state.graphExecutions.pageSize; } -); // TODO(cais): Add unit tests. +); -export const getLoadingGraphExecutionPages = createSelector( +export const getGraphExecutionDataLoadingPages = createSelector( selectDebuggerState, (state: DebuggerState): number[] => { - return state.graphExecutions.loadingGraphExecutionDataPages; + return state.graphExecutions.graphExecutionDataLoadingPages; } -); // TODO(cais): Add unit tests. +); export const getGraphExecutionDataPageLoadedSizes = createSelector( selectDebuggerState, (state: DebuggerState): {[page: number]: number} => { return state.graphExecutions.graphExecutionDataPageLoadedSizes; } -); // TODO(cais): Add unit tests. +); export const getGraphExecutionData = createSelector( selectDebuggerState, (state: DebuggerState): {[index: number]: GraphExecution} => { return state.graphExecutions.graphExecutionData; } -); // TODO(cais): Add unit tests. +); /** * Get the focused alert types (if any) of the execution digests current being diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors_test.ts index 5d373bce0fb..6d5e3964b18 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors_test.ts @@ -22,6 +22,12 @@ import { getFocusedExecutionStackFrames, getFocusedSourceFileContent, getFocusedSourceFileIndex, + getGraphExecutionData, + getGraphExecutionDataLoadingPages, + getGraphExecutionDataPageLoadedSizes, + getGraphExecutionDisplayCount, + getGraphExecutionPageSize, + getGraphExecutionScrollBeginIndex, getLoadedAlertsOfFocusedType, getNumAlerts, getNumAlertsOfFocusedType, @@ -766,4 +772,143 @@ describe('debugger selectors', () => { expect(getNumGraphExecutions(state)).toBe(10); }); }); + + describe('getGraphExecutionScrollBeginIndex', () => { + it('returns correct initial zero state', () => { + const state = createState(createDebuggerState()); + expect(getGraphExecutionScrollBeginIndex(state)).toBe(0); + }); + + it('returns correct non-zero state', () => { + const state = createState( + createDebuggerState({ + graphExecutions: createDebuggerGraphExecutionsState({ + scrollBeginIndex: 1234567, + }), + }) + ); + expect(getGraphExecutionScrollBeginIndex(state)).toBe(1234567); + }); + }); + + describe('getGraphExecutionDisplayCount', () => { + it('returns correct value', () => { + const state = createState( + createDebuggerState({ + graphExecutions: createDebuggerGraphExecutionsState({ + displayCount: 240, + }), + }) + ); + expect(getGraphExecutionDisplayCount(state)).toBe(240); + }); + }); + + describe('getGraphExecutionPageSize', () => { + it('returns correct value', () => { + const state = createState( + createDebuggerState({ + graphExecutions: createDebuggerGraphExecutionsState({ + pageSize: 126, + }), + }) + ); + expect(getGraphExecutionPageSize(state)).toBe(126); + }); + }); + + describe('getGraphExecutionDataLoadingPages', () => { + it('returns correct empty value', () => { + const state = createState( + createDebuggerState({ + graphExecutions: createDebuggerGraphExecutionsState({ + graphExecutionDataLoadingPages: [], + }), + }) + ); + expect(getGraphExecutionDataLoadingPages(state)).toEqual([]); + }); + + it('returns correct non-empty value', () => { + const state = createState( + createDebuggerState({ + graphExecutions: createDebuggerGraphExecutionsState({ + graphExecutionDataLoadingPages: [1, 2, 100], + }), + }) + ); + expect(getGraphExecutionDataLoadingPages(state)).toEqual([ + 1, + 2, + 100, + ]); + }); + }); + + describe('getGraphExecutionDataLoadingPages', () => { + it('returns correct empty value', () => { + const state = createState( + createDebuggerState({ + graphExecutions: createDebuggerGraphExecutionsState({ + graphExecutionDataPageLoadedSizes: {}, + }), + }) + ); + expect(getGraphExecutionDataPageLoadedSizes(state)).toEqual({}); + }); + + it('returns correct non-empty value', () => { + const state = createState( + createDebuggerState({ + graphExecutions: createDebuggerGraphExecutionsState({ + graphExecutionDataPageLoadedSizes: {0: 10, 2: 40}, + }), + }) + ); + expect(getGraphExecutionDataPageLoadedSizes(state)).toEqual({ + 0: 10, + 2: 40, + }); + }); + }); + + describe('getGraphExecutionData', () => { + it('returns correct initial empty state', () => { + const state = createState(createDebuggerState()); + expect(getGraphExecutionData(state)).toEqual({}); + }); + + it('returns correct non-empty value', () => { + const state = createState( + createDebuggerState({ + graphExecutions: createDebuggerGraphExecutionsState({ + graphExecutionData: { + 10: { + op_name: 'Dense_1/MatMul', + op_type: 'MatMul', + output_slot: 0, + graph_id: 'g1', + graph_ids: ['g0', 'g1'], + tensor_debug_mode: 2, + debug_tensor_value: [0, 1], + device_name: '/GPU:0' + } + } + }), + }) + ); + expect(getGraphExecutionData(state)).toEqual({ + 10: { + op_name: 'Dense_1/MatMul', + op_type: 'MatMul', + output_slot: 0, + graph_id: 'g1', + graph_ids: ['g0', 'g1'], + tensor_debug_mode: 2, + debug_tensor_value: [0, 1], + device_name: '/GPU:0' + } + }); + }); + }); }); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts index 0e4f641ec76..09ca45e2f89 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts @@ -257,7 +257,7 @@ export interface GraphExecutions extends PagedExecutions { graphExecutionDigests: {[index: number]: GraphExecutionDigest}; // Indices to GraphExecution pages currently being loaded. - loadingGraphExecutionDataPages: number[]; + graphExecutionDataLoadingPages: number[]; // Number of items in each `GraphExecution` page that have been loaded. graphExecutionDataPageLoadedSizes: {[page: number]: number}; From 20daabfdc9be71e292edc4475470e07841c7dce6 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Fri, 17 Apr 2020 11:18:54 -0400 Subject: [PATCH 04/29] Add unit tests for reducers --- .../effects/debugger_effects.ts | 10 +- .../store/debugger_reducers.ts | 16 +-- .../store/debugger_reducers_test.ts | 130 ++++++++++++++++++ .../store/debugger_selectors_test.ts | 31 +---- .../tf_debugger_v2_plugin/testing/index.ts | 17 +++ .../graph_executions_component.css | 5 +- 6 files changed, 166 insertions(+), 43 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts index d65f93cb2db..9fa9db5e8f3 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts @@ -593,7 +593,7 @@ export class DebuggerEffects { loadingPages, pageLoadedSizes, ]) => { - const missingPages = getMissingPages( + let missingPages: number[] = getMissingPages( scrollBeginIndex, Math.min(scrollBeginIndex + displayCount, numGraphExecutions), pageSize, @@ -601,11 +601,9 @@ export class DebuggerEffects { pageLoadedSizes ); // Omit pages that are already loading. - for (let i = missingPages.length - 1; i >= 0; --i) { - if (loadingPages.indexOf(missingPages[i]) !== -1) { - missingPages.splice(i, 1); // TODO(cais): Add unit test. - } - } + missingPages = missingPages.filter( + (page) => loadingPages.indexOf(page) === -1 + ); return { runId, missingPages, diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts index 2b27c187ac2..4d9e68981b0 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers.ts @@ -585,7 +585,7 @@ const reducer = createReducer( }, }; } - ), // TODO(cais): Add unit test. + ), on( actions.graphExecutionDataLoaded, (state: DebuggerState, data: GraphExecutionDataResponse): DebuggerState => { @@ -598,8 +598,6 @@ const reducer = createReducer( ...state.graphExecutions.graphExecutionDataPageLoadedSizes, }; const graphExecutionData = {...state.graphExecutions.graphExecutionData}; - // Update graphExecutionDataLoadingPages, graphExecutionDataPageLoadedSizes, - // and graphExecutionData. for (let i = data.begin; i < data.end; ++i) { const pageIndex = Math.floor(i / pageSize); if (graphExecutionDataLoadingPages.indexOf(pageIndex) !== -1) { @@ -608,13 +606,13 @@ const reducer = createReducer( 1 ); } + if (graphExecutionDataPageLoadedSizes[pageIndex] === undefined) { + graphExecutionDataPageLoadedSizes[pageIndex] = 0; + } if (graphExecutionData[i] === undefined) { - graphExecutionData[i] = data.graph_executions[i - data.begin]; - if (graphExecutionDataPageLoadedSizes[pageIndex] === undefined) { - graphExecutionDataPageLoadedSizes[pageIndex] = 0; - } graphExecutionDataPageLoadedSizes[pageIndex]++; } + graphExecutionData[i] = data.graph_executions[i - data.begin]; } return { ...state, @@ -626,7 +624,7 @@ const reducer = createReducer( }, }; } - ), // TODO(cais): Add unit test. + ), on( actions.graphExecutionScrollToIndex, (state: DebuggerState, action: {index: number}): DebuggerState => { @@ -644,7 +642,7 @@ const reducer = createReducer( }, }; } - ), // TODO(cais): Add unit test. + ), //////////////////////////////////////////////////////// // Reducers related to source files and stack traces. // //////////////////////////////////////////////////////// diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers_test.ts index 476cd196ab1..6fd82e2be97 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_reducers_test.ts @@ -31,6 +31,7 @@ import { createDebuggerStateWithLoadedExecutionDigests, createDigestsStateWhileLoadingExecutionDigests, createTestExecutionData, + createTestGraphExecution, createTestStackFrame, createTestInfNanAlert, } from '../testing'; @@ -1364,4 +1365,133 @@ describe('Debugger reducers', () => { ).toEqual(12345); }); }); + + describe('graphExecutionDataRequested', () => { + it('updates loading pages by adding a new one', () => { + const state = createDebuggerState({ + activeRunId: '__default_debugger_run__', + graphExecutions: createDebuggerGraphExecutionsState({ + graphExecutionDataLoadingPages: [2222, 7777], + }), + }); + const nextState = reducers( + state, + actions.graphExecutionDataRequested({pageIndex: 4321}) + ); + expect(nextState.graphExecutions.graphExecutionDataLoadingPages).toEqual([ + 2222, + 7777, + 4321, + ]); + }); + }); + + describe('graphExecutionDataLoaded', () => { + it('with new data, updates loading pages, loaded pages and data', () => { + const state = createDebuggerState({ + activeRunId: '__default_debugger_run__', + graphExecutions: createDebuggerGraphExecutionsState({ + pageSize: 2, + graphExecutionDataLoadingPages: [1, 2], + graphExecutionDataPageLoadedSizes: {0: 2}, + graphExecutionData: { + 0: createTestGraphExecution({op_name: 'TestOp_0'}), + 1: createTestGraphExecution({op_name: 'TestOp_1'}), + }, + }), + }); + const nextState = reducers( + state, + actions.graphExecutionDataLoaded({ + begin: 2, + end: 4, + graph_executions: [ + createTestGraphExecution({op_name: 'TestOp_2'}), + createTestGraphExecution({op_name: 'TestOp_3'}), + ], + }) + ); + expect(nextState.graphExecutions.graphExecutionDataLoadingPages).toEqual([ + 2, + ]); + expect( + nextState.graphExecutions.graphExecutionDataPageLoadedSizes + ).toEqual({ + 0: 2, + 1: 2, + }); + expect(nextState.graphExecutions.graphExecutionData).toEqual({ + 0: createTestGraphExecution({op_name: 'TestOp_0'}), + 1: createTestGraphExecution({op_name: 'TestOp_1'}), + 2: createTestGraphExecution({op_name: 'TestOp_2'}), + 3: createTestGraphExecution({op_name: 'TestOp_3'}), + }); + }); + + it('with partly new data, correctly updates pages and data', () => { + const state = createDebuggerState({ + activeRunId: '__default_debugger_run__', + graphExecutions: createDebuggerGraphExecutionsState({ + pageSize: 2, + graphExecutionDataLoadingPages: [1], + graphExecutionDataPageLoadedSizes: {0: 2, 1: 1}, + graphExecutionData: { + 0: createTestGraphExecution({op_name: 'TestOp_0'}), + 1: createTestGraphExecution({op_name: 'TestOp_1'}), + 2: createTestGraphExecution({op_name: 'TestOp_2'}), + }, + }), + }); + const nextState = reducers( + state, + actions.graphExecutionDataLoaded({ + begin: 2, + end: 4, + graph_executions: [ + createTestGraphExecution({op_name: 'TestOp_2'}), + createTestGraphExecution({op_name: 'TestOp_3'}), + ], + }) + ); + expect(nextState.graphExecutions.graphExecutionDataLoadingPages).toEqual( + [] + ); + expect( + nextState.graphExecutions.graphExecutionDataPageLoadedSizes + ).toEqual({ + 0: 2, + 1: 2, + }); + expect(nextState.graphExecutions.graphExecutionData).toEqual({ + 0: createTestGraphExecution({op_name: 'TestOp_0'}), + 1: createTestGraphExecution({op_name: 'TestOp_1'}), + 2: createTestGraphExecution({op_name: 'TestOp_2'}), + 3: createTestGraphExecution({op_name: 'TestOp_3'}), + }); + }); + }); + + describe('graphExecutionScrollToIndex', () => { + it('updates graph-execution scrollBeginIndex', () => { + const state = createDebuggerState({ + graphExecutions: createDebuggerGraphExecutionsState({ + scrollBeginIndex: 0, + }), + }); + const nextState = reducers( + state, + actions.graphExecutionScrollToIndex({index: 1337}) + ); + expect(nextState.graphExecutions.scrollBeginIndex).toBe(1337); + }); + + for (const index of [-1, 8.8, Infinity, NaN]) { + it(`throws error for invalid scroll index: ${index}`, () => { + const state = createDebuggerState(); + expect(() => + reducers(state, actions.graphExecutionScrollToIndex({index})) + ).toThrowError(/.*scroll.*negative or non-integer/); + }); + } + }); }); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors_test.ts index 6d5e3964b18..5bbb24797d1 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors_test.ts @@ -51,6 +51,7 @@ import { createState, createTestExecutionData, createTestExecutionDigest, + createTestGraphExecution, createTestInfNanAlert, } from '../testing'; @@ -837,11 +838,7 @@ describe('debugger selectors', () => { }), }) ); - expect(getGraphExecutionDataLoadingPages(state)).toEqual([ - 1, - 2, - 100, - ]); + expect(getGraphExecutionDataLoadingPages(state)).toEqual([1, 2, 100]); }); }); @@ -883,31 +880,13 @@ describe('debugger selectors', () => { createDebuggerState({ graphExecutions: createDebuggerGraphExecutionsState({ graphExecutionData: { - 10: { - op_name: 'Dense_1/MatMul', - op_type: 'MatMul', - output_slot: 0, - graph_id: 'g1', - graph_ids: ['g0', 'g1'], - tensor_debug_mode: 2, - debug_tensor_value: [0, 1], - device_name: '/GPU:0' - } - } + 10: createTestGraphExecution(), + }, }), }) ); expect(getGraphExecutionData(state)).toEqual({ - 10: { - op_name: 'Dense_1/MatMul', - op_type: 'MatMul', - output_slot: 0, - graph_id: 'g1', - graph_ids: ['g0', 'g1'], - tensor_debug_mode: 2, - debug_tensor_value: [0, 1], - device_name: '/GPU:0' - } + 10: createTestGraphExecution(), }); }); }); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/testing/index.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/testing/index.ts index 4465d64b48f..f1c00a5c126 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/testing/index.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/testing/index.ts @@ -24,6 +24,7 @@ import { DebuggerState, Execution, Executions, + GraphExecution, ExecutionDigest, GraphExecutions, InfNanAlert, @@ -89,6 +90,22 @@ export function createTestExecutionDigest( }; } +export function createTestGraphExecution( + override?: Partial +): GraphExecution { + return { + op_name: 'test_namescope/TestOp', + op_type: 'TestOp', + output_slot: 0, + graph_id: 'g1', + graph_ids: ['g0', 'g1,'], + device_name: '/GPU:0', + tensor_debug_mode: 2, + debug_tensor_value: [0, 1], + ...override, + }; +} + export function createDebuggerState( override?: Partial ): DebuggerState { diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css index 4a28ec4c3ed..584dcb54fca 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css @@ -75,7 +75,10 @@ limitations under the License. display: block; height: 16px; line-height: 16px; + overflow: hidden; padding: 0 2px; + text-overflow: ellipsis; + white-space: nowrap; width: 100%; } @@ -85,7 +88,5 @@ limitations under the License. overflow: hidden; padding-right: 8px; text-align: right; - text-overflow: ellipsis; - white-space: nowrap; width: 240px; } From 5eb5e10f5ca2d084b1e716ffe0eb6b543ff0f394 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Fri, 17 Apr 2020 13:37:11 -0400 Subject: [PATCH 05/29] Adjust CSS --- .../tf_debugger_v2_plugin/debugger_component.css | 9 +++++++-- .../tf_debugger_v2_plugin/debugger_component.ng.html | 2 +- .../graph_executions/graph_executions_component.css | 2 +- .../graph_executions/graph_executions_component.ng.html | 2 +- .../views/stack_trace/stack_trace_component.css | 2 +- .../views/timeline/timeline_component.ng.html | 2 +- 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css index 294d74fa4c0..83ee7b2b904 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.css @@ -15,13 +15,18 @@ limitations under the License. .bottom-section { border-top: 1px solid rgba(0, 0, 0, 0.12); - height: 353px; + height: 34%; padding-top: 6px; width: 100%; } +.debugger-container { + background-color: #fff; + height: 100%; +} + .top-section { - height: 360px; + height: 66%; padding: 6px 0; width: 100%; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ng.html index 922caabc465..761c52137c1 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_component.ng.html @@ -15,7 +15,7 @@ limitations under the License. --> -
+
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css index 584dcb54fca..a3d0a7892ff 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css @@ -44,8 +44,8 @@ limitations under the License. } .graph-execution-index { + color: #757575; display: inline-block; - text-align: right; width: 40px; padding-right: 4px; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html index 378e8823f84..10bfcb0078d 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html @@ -33,7 +33,7 @@ >
- {{ i }}: + {{ i }}
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css index 681f9bb652a..1a4fce8e9d5 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace/stack_trace_component.css @@ -54,7 +54,7 @@ limitations under the License. border-left: 1px solid rgba(0, 0, 0, 0.12); font-size: 10px; font-family: 'Roboto Mono', monospace; - height: 360px; + height: 100%; margin-left: 8px; max-height: 360px; overflow-x: hidden; diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline/timeline_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline/timeline_component.ng.html index a836b8891bf..7e2e44c3381 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline/timeline_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline/timeline_component.ng.html @@ -16,7 +16,7 @@ -->
-
Execution Timeline
+
Eager Execution Timeline
From d1ef4ab249a0092cfcdb344a192815ca3621d92d Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Fri, 17 Apr 2020 16:15:19 -0400 Subject: [PATCH 06/29] Add unit tests for effect --- .../effects/debugger_effects.ts | 18 +-- .../effects/debugger_effects_test.ts | 107 +++++++++++++++++- 2 files changed, 114 insertions(+), 11 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts index 9fa9db5e8f3..02c46817007 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts @@ -39,6 +39,7 @@ import { executionScrollRight, executionScrollToIndex, graphExecutionDataLoaded, + graphExecutionDataRequested, graphExecutionScrollToIndex, numAlertsAndBreakdownLoaded, numAlertsAndBreakdownRequested, @@ -553,10 +554,10 @@ export class DebuggerEffects { * Emits when scrolling event leads to need to load new intra-graph execution * digests. */ - private onGraphExecutionScroll(): Observable { + private onGraphExecutionScroll(): Observable<{}> { return this.actions$.pipe( ofType(graphExecutionScrollToIndex), - debounceTime(100), // TODO(cais): Remove magic number. Look at race condition. + debounceTime(100), withLatestFrom( this.store.select(getActiveRunId), this.store.select(getNumGraphExecutions), @@ -613,27 +614,28 @@ export class DebuggerEffects { } ), filter(({missingPages}) => missingPages.length > 0), + tap(({missingPages}) => { + missingPages.forEach((pageIndex) => + this.store.dispatch(graphExecutionDataRequested({pageIndex})) + ); + }), mergeMap(({runId, missingPages, pageSize, numGraphExecutions}) => { const begin = missingPages[0] * pageSize; const end = Math.min( (missingPages[missingPages.length - 1] + 1) * pageSize, numGraphExecutions ); - // console.log( - // `mergeMap() 200: runId=${runId}, begin=${begin}, end=${end}` - // ); // DEBUG return this.dataSource.fetchGraphExecutionData(runId!, begin, end).pipe( tap((graphExecutionDataResponse) => { this.store.dispatch( graphExecutionDataLoaded(graphExecutionDataResponse) ); - }), - map(() => void null) + }) ); // TODO(cais): Add catchError() to pipe. }) ); - } // TODO(cais): Add unit test. + } /** * Emits when user focuses on an alert type. diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects_test.ts index 18c8470ea44..d03fe89d685 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects_test.ts @@ -12,7 +12,7 @@ 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. ==============================================================================*/ -import {TestBed} from '@angular/core/testing'; +import {fakeAsync, TestBed, tick} from '@angular/core/testing'; import {provideMockActions} from '@ngrx/effects/testing'; import {Action, Store} from '@ngrx/store'; import {MockStore, provideMockStore} from '@ngrx/store/testing'; @@ -30,6 +30,9 @@ import { executionScrollLeft, executionScrollRight, executionScrollToIndex, + graphExecutionDataRequested, + graphExecutionDataLoaded, + graphExecutionScrollToIndex, numAlertsAndBreakdownRequested, numAlertsAndBreakdownLoaded, numExecutionsLoaded, @@ -47,6 +50,7 @@ import { AlertsResponse, ExecutionDataResponse, ExecutionDigestsResponse, + GraphExecutionDataResponse, GraphExecutionDigestsResponse, SourceFileListResponse, SourceFileResponse, @@ -62,10 +66,16 @@ import { getNumAlertsOfFocusedType, getNumExecutionsLoaded, getNumExecutions, + getNumGraphExecutions, getDisplayCount, getExecutionDigestsLoaded, getExecutionPageSize, getExecutionScrollBeginIndex, + getGraphExecutionDisplayCount, + getGraphExecutionDataLoadingPages, + getGraphExecutionDataPageLoadedSizes, + getGraphExecutionPageSize, + getGraphExecutionScrollBeginIndex, getLoadedAlertsOfFocusedType, getLoadedExecutionData, getLoadedStackFrames, @@ -78,6 +88,7 @@ import { DebuggerRunListing, Execution, ExecutionDigest, + GraphExecution, State, SourceFileSpec, SourceFileContent, @@ -86,9 +97,10 @@ import { createDebuggerState, createState, createTestExecutionData, - createTestStackFrame, - createTestInfNanAlert, createTestExecutionDigest, + createTestGraphExecution, + createTestInfNanAlert, + createTestStackFrame, } from '../testing'; import {TBHttpClientTestingModule} from '../../../../webapp/webapp_data_source/tb_http_client_testing'; @@ -322,6 +334,20 @@ describe('Debugger effects', () => { .and.returnValue(of(graphExcutionDigestsResponse)); } + function createFetchGraphExecutionDataSpy( + runId: string, + begin: number, + end: number, + graphExcutionDataResponse: GraphExecutionDataResponse + ) { + return spyOn( + TestBed.get(Tfdbg2HttpServerDataSource), + 'fetchGraphExecutionData' + ) + .withArgs(runId, begin, end) + .and.returnValue(of(graphExcutionDataResponse)); + } + describe('loadData', () => { const runListingForTest: DebuggerRunListing = { __default_debugger_run__: { @@ -881,6 +907,81 @@ describe('Debugger effects', () => { } }); + describe('graphExecutionScrollToIndex', () => { + beforeEach(() => { + debuggerEffects.loadData$.subscribe(); + }); + + for (const {dataExists, page3Size, loadingPages} of [ + {dataExists: false, page3Size: 0, loadingPages: [3]}, + {dataExists: false, page3Size: 0, loadingPages: []}, + {dataExists: true, page3Size: 2, loadingPages: []}, + ]) { + it('triggers GraphExecution loading', fakeAsync(() => { + const runId = '__default_debugger_run__'; + const originalScrollBeginIndex = 50; + const newScrollBeginIndex = originalScrollBeginIndex + 2; + const numGraphExecutions = 100; + const pageSize = 20; + const displayCount = 10; + store.overrideSelector(getActiveRunId, runId); + store.overrideSelector(getNumGraphExecutions, numGraphExecutions); + store.overrideSelector( + getGraphExecutionScrollBeginIndex, + newScrollBeginIndex + ); + store.overrideSelector(getGraphExecutionPageSize, pageSize); + store.overrideSelector(getGraphExecutionDisplayCount, displayCount); + store.overrideSelector(getExecutionPageSize, pageSize); + store.overrideSelector(getGraphExecutionDataLoadingPages, loadingPages); + const pageLoadedSizes: {[pageIndex: number]: number} = { + 0: 20, + 1: 20, + 2: 20, + }; + pageLoadedSizes[3] = page3Size; + store.overrideSelector( + getGraphExecutionDataPageLoadedSizes, + pageLoadedSizes + ); + store.refreshState(); + + const graphExecutions = new Array(pageSize).fill( + createTestGraphExecution() + ); + const graphExecutionDataResponse: GraphExecutionDataResponse = { + begin: 60, + end: 60 + pageSize, + graph_executions: graphExecutions, + }; + const fetchExecutionData = createFetchGraphExecutionDataSpy( + runId, + 60, + 60 + pageSize, + graphExecutionDataResponse + ); + + action.next(graphExecutionScrollToIndex({index: newScrollBeginIndex})); + tick(100); + + if (dataExists || loadingPages.length > 0) { + expect(fetchExecutionData).not.toHaveBeenCalled(); + expect(dispatchedActions).toEqual([]); + } else { + expect(fetchExecutionData).toHaveBeenCalledTimes(1); + expect(dispatchedActions).toEqual([ + graphExecutionDataRequested({pageIndex: 3}), + graphExecutionDataLoaded({ + begin: 60, + end: 60 + pageSize, + graph_executions: graphExecutions, + }), + ]); + } + })); + } + }); + describe('load alerts of given type', () => { const runId = '__default_debugger_run__'; const alert0 = createTestInfNanAlert({ From 4df718ffc942cd3f3bab97faaf5e5f32af6694f4 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Fri, 17 Apr 2020 16:52:00 -0400 Subject: [PATCH 07/29] Add container tests --- .../graph_executions_container_test.ts | 67 ++++++++++++++++--- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts index b01ff8e7fdf..afc7b26aa42 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts @@ -16,16 +16,25 @@ limitations under the License. * Unit tests for the the intra-graph execution component and container. */ import {CommonModule} from '@angular/common'; -import {TestBed} from '@angular/core/testing'; +import {fakeAsync, TestBed, tick} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; import {Store} from '@ngrx/store'; -import {provideMockStore, MockStore} from '@ngrx/store/testing'; +import {MockStore, provideMockStore} from '@ngrx/store/testing'; import {DebuggerComponent} from '../../debugger_component'; import {DebuggerContainer} from '../../debugger_container'; -import {State} from '../../store/debugger_types'; -import {createDebuggerState, createState} from '../../testing'; +import {State, GraphExecution} from '../../store/debugger_types'; +import { + getNumGraphExecutions, + getGraphExecutionData, + getGraphExecutionDisplayCount, +} from '../../store'; +import { + createDebuggerState, + createState, + createTestGraphExecution, +} from '../../testing'; import {AlertsModule} from '../alerts/alerts_module'; import {ExecutionDataModule} from '../execution_data/execution_data_module'; import {InactiveModule} from '../inactive/inactive_module'; @@ -36,9 +45,8 @@ import {GraphExecutionsContainer} from './graph_executions_container'; import {GraphExecutionsModule} from './graph_executions_module'; /** @typehack */ import * as _typeHackStore from '@ngrx/store'; -import {getNumGraphExecutions} from '../../store'; -describe('Graph Executions Container', () => { +fdescribe('Graph Executions Container', () => { let store: MockStore; beforeEach(async () => { @@ -64,14 +72,55 @@ describe('Graph Executions Container', () => { store = TestBed.get(Store); }); - it('renders number of graph executions', () => { + it('does not render execs viewport if # execs = 0', fakeAsync(() => { + const fixture = TestBed.createComponent(GraphExecutionsContainer); + store.overrideSelector(getNumGraphExecutions, 0); + fixture.autoDetectChanges(); + tick(500); + + const titleElement = fixture.debugElement.query( + By.css('.graph-executions-title') + ); + expect(titleElement.nativeElement.innerText).toBe('Graph Executions (0)'); + const viewPort = fixture.debugElement.query( + By.css('.graph-executions-viewport') + ); + expect(viewPort).toBeNull(); + })); + + it('renders # execs and execs viewport if # execs > 0; fully loaded', fakeAsync(() => { const fixture = TestBed.createComponent(GraphExecutionsContainer); store.overrideSelector(getNumGraphExecutions, 120); - fixture.detectChanges(); + const graphExecutionData: {[index: number]: GraphExecution} = {}; + for (let i = 0; i < 120; ++i) { + graphExecutionData[i] = createTestGraphExecution({ + op_name: `TestOp_${i}`, + op_type: `OpType_${i}`, + }); + } + store.overrideSelector(getGraphExecutionData, graphExecutionData); + fixture.autoDetectChanges(); + tick(500); const titleElement = fixture.debugElement.query( By.css('.graph-executions-title') ); expect(titleElement.nativeElement.innerText).toBe('Graph Executions (120)'); - }); + const viewPort = fixture.debugElement.query( + By.css('.graph-executions-viewport') + ); + expect(viewPort).not.toBeNull(); + const tensorContainers = fixture.debugElement.queryAll( + By.css('.tensor-container') + ); + expect(tensorContainers.length).toBeGreaterThan(0); + const tensorNames = fixture.debugElement.queryAll(By.css('.tensor-name')); + const opTypes = fixture.debugElement.queryAll(By.css('.op-type')); + expect(tensorNames.length).toBe(tensorContainers.length); + expect(opTypes.length).toBe(tensorContainers.length); + for (let i = 0; i < tensorNames.length; ++i) { + expect(tensorNames[i].nativeElement.innerText).toBe(`TestOp_${i}:0`); + expect(opTypes[i].nativeElement.innerText).toBe(`OpType_${i}`); + } + })); }); From 964c20ccdd2fc92056e6fe00f76b0ac2a687d1df Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Fri, 17 Apr 2020 17:02:18 -0400 Subject: [PATCH 08/29] Fix loading spinner css --- .../graph_executions_component.ng.html | 34 +++++++------- .../graph_executions_container_test.ts | 46 ++++++++++++++++--- 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html index 10bfcb0078d..10f26ac3b2b 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html @@ -31,29 +31,29 @@ *cdkVirtualFor="let i of graphExecutionIndices" class="tensor-container" > -
+
{{ i }}
-
-
- {{ graphExecutionData[i].op_name }}:{{ - graphExecutionData[i].output_slot }} -
-
- {{ graphExecutionData[i].op_type }} +
+
+
+ {{ graphExecutionData[i].op_name }}:{{ + graphExecutionData[i].output_slot }} +
+
+ {{ graphExecutionData[i].op_type }} +
-
- -
- {{ i }} -
-
- Loading... -
-
+ +
+ Loading... + +
+
+
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts index afc7b26aa42..e7fced92c71 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts @@ -25,11 +25,7 @@ import {MockStore, provideMockStore} from '@ngrx/store/testing'; import {DebuggerComponent} from '../../debugger_component'; import {DebuggerContainer} from '../../debugger_container'; import {State, GraphExecution} from '../../store/debugger_types'; -import { - getNumGraphExecutions, - getGraphExecutionData, - getGraphExecutionDisplayCount, -} from '../../store'; +import {getNumGraphExecutions, getGraphExecutionData} from '../../store'; import { createDebuggerState, createState, @@ -46,7 +42,7 @@ import {GraphExecutionsModule} from './graph_executions_module'; /** @typehack */ import * as _typeHackStore from '@ngrx/store'; -fdescribe('Graph Executions Container', () => { +describe('Graph Executions Container', () => { let store: MockStore; beforeEach(async () => { @@ -114,13 +110,51 @@ fdescribe('Graph Executions Container', () => { By.css('.tensor-container') ); expect(tensorContainers.length).toBeGreaterThan(0); + const graphExecutionIndices = fixture.debugElement.queryAll( + By.css('.graph-execution-index') + ); const tensorNames = fixture.debugElement.queryAll(By.css('.tensor-name')); const opTypes = fixture.debugElement.queryAll(By.css('.op-type')); + expect(graphExecutionIndices.length).toBe(tensorContainers.length); expect(tensorNames.length).toBe(tensorContainers.length); expect(opTypes.length).toBe(tensorContainers.length); for (let i = 0; i < tensorNames.length; ++i) { + expect(graphExecutionIndices[i].nativeElement.innerText).toBe(`${i}`); expect(tensorNames[i].nativeElement.innerText).toBe(`TestOp_${i}:0`); expect(opTypes[i].nativeElement.innerText).toBe(`OpType_${i}`); } })); + + it('renders # execs and execs viewport if # execs > 0; not loaded', fakeAsync(() => { + const fixture = TestBed.createComponent(GraphExecutionsContainer); + store.overrideSelector(getNumGraphExecutions, 120); + store.overrideSelector(getGraphExecutionData, {}); + fixture.autoDetectChanges(); + tick(500); + + const titleElement = fixture.debugElement.query( + By.css('.graph-executions-title') + ); + expect(titleElement.nativeElement.innerText).toBe('Graph Executions (120)'); + const viewPort = fixture.debugElement.query( + By.css('.graph-executions-viewport') + ); + expect(viewPort).not.toBeNull(); + const tensorContainers = fixture.debugElement.queryAll( + By.css('.tensor-container') + ); + expect(tensorContainers.length).toBeGreaterThan(0); + const graphExecutionIndices = fixture.debugElement.queryAll( + By.css('.graph-execution-index') + ); + const loadingElements = fixture.debugElement.queryAll( + By.css('.loading-spinner') + ); + const tensorNames = fixture.debugElement.queryAll(By.css('.tensor-name')); + const opTypes = fixture.debugElement.queryAll(By.css('.op-type')); + expect(graphExecutionIndices.length).toBe(tensorContainers.length); + expect(loadingElements.length).toBe(tensorContainers.length); + expect(tensorNames.length).toBe(0); + expect(opTypes.length).toBe(0); + })); }); From 9e37e35eff99810ea61e4cd2cb4b00c667c6a434 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Fri, 17 Apr 2020 17:02:47 -0400 Subject: [PATCH 09/29] Revert extraneous change --- .../plugins/debugger_v2/debug_data_multiplexer.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/debug_data_multiplexer.py b/tensorboard/plugins/debugger_v2/debug_data_multiplexer.py index 775d42f7db7..87bc0fb3e41 100644 --- a/tensorboard/plugins/debugger_v2/debug_data_multiplexer.py +++ b/tensorboard/plugins/debugger_v2/debug_data_multiplexer.py @@ -366,17 +366,15 @@ def GraphExecutionData(self, run, begin, end, trace_id=None): "trace_id support for GraphExecutionTraceData is " "not implemented yet." ) - digests = self._reader.graph_execution_traces(digest=True) - end = self._checkBeginEndIndices(begin, end, len(digests)) - digests = digests[begin:end] - graph_executions = [ - self._reader.read_graph_execution_trace(digest) for digest in digests - ] + graph_executions = self._reader.graph_execution_traces(digest=False) + end = self._checkBeginEndIndices(begin, end, len(graph_executions)) return { "begin": begin, "end": end, + "num_digests": len(graph_executions), "graph_executions": [ - graph_exec.to_json() for graph_exec in graph_executions + graph_exec.to_json() + for graph_exec in graph_executions[begin:end] ], } From ab58b6501eb4055334e04eb942797a8a1d4a4653 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Fri, 17 Apr 2020 17:13:55 -0400 Subject: [PATCH 10/29] Tweak some comments --- .../effects/debugger_effects.ts | 9 ++++---- .../graph_executions_component.css | 22 +++++++++---------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts index 02c46817007..a5c5ff4f236 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects/debugger_effects.ts @@ -860,7 +860,9 @@ export class DebuggerEffects { * | * on alert type focus --------> fetch alerts of a type -----------+ * - * on source file requested ---> fetch source file + * on source file requested ---> fetch source + * + * on graph-execution scroll --> fetch graph-execution data * **/ this.loadData$ = createEffect( @@ -921,11 +923,10 @@ export class DebuggerEffects { onLoad$ ); - // TODO(cais): Hook it up. - const onGraphExecutionScroll$ = this.onGraphExecutionScroll(); - const onSourceFileFocused$ = this.onSourceFileFocused(); + const onGraphExecutionScroll$ = this.onGraphExecutionScroll(); + // ExecutionDigest and ExecutionData can be loaded in parallel. return merge( onNumAlertsLoaded$, diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css index a3d0a7892ff..b297ad3e6d3 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css @@ -22,6 +22,13 @@ limitations under the License. padding-left: 10px; } +.graph-execution-index { + color: #757575; + display: inline-block; + width: 40px; + padding-right: 4px; +} + .graph-executions-viewport { flex-grow: 1; font-size: 12px; @@ -29,6 +36,10 @@ limitations under the License. overflow-x: hidden; } +.loading-spinner { + display: inline-block; +} + .op-type { background-color: #e3e5e8; border: 1px solid #c0c0c0; @@ -43,17 +54,6 @@ limitations under the License. width: max-content; } -.graph-execution-index { - color: #757575; - display: inline-block; - width: 40px; - padding-right: 4px; -} - -.loading-spinner { - display: inline-block; -} - .tensor-container { width: 100%; } From 8893db23032c1bf5cf00a1b103f2c747a4ba0bf2 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Mon, 20 Apr 2020 11:49:54 -0400 Subject: [PATCH 11/29] [DebuggerV2] Add tensor-debug info to GraphExecutionComponent --- .../graph_executions_component.css | 13 +++ .../graph_executions_component.ng.html | 19 ++++ .../graph_executions_component.ts | 91 +++++++++++++++++++ .../graph_executions_module.ts | 15 ++- 4 files changed, 136 insertions(+), 2 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css index b297ad3e6d3..ee228915da4 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css @@ -58,6 +58,19 @@ limitations under the License. width: 100%; } +.tensor-debug-info { + display: inline-block; + overflow: hidden; + width: 240px; +} + +.tensor-debug-info-flexbox { + align-items: flex-start; + display: flex; + flex-wrap: nowrap; + vertical-align: top; +} + .tensor-item { border-bottom: 1px solid rgba(0, 0, 0, 0.12); display: flex; diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html index 10f26ac3b2b..7b4acae8106 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html @@ -45,6 +45,25 @@ {{ graphExecutionData[i].op_type }}
+ +
+
+ + + + + + +
+
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts index c801e9b789e..160481a3795 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts @@ -22,6 +22,95 @@ import { } from '@angular/core'; import {GraphExecution} from '../../store/debugger_types'; +import {DTYPE_ENUM_TO_NAME} from '../../tf_dtypes'; + +@Component({ + selector: 'debug-tensor-dtype', + template: ` +
+ + dtype: + + + {{ dtype }} + +
+ `, + styles: [` + :host { + background-color: #e3e5e8; + border: 1px solid #c0c0c0; + border-radius: 4px; + height: 14px; + line-height: 14px; + margin: 0 2px; + padding: 1px 3px; + width: max-content; + } + .dtype-name { + font-weight: 600 + } + `] +}) +export class DebugTensorDTypeComponent { + @Input() + dtype!: string; +} + +@Component({ + selector: 'debug-tensor-rank', + template: ` +
+ {{ rank }}D +
+ `, + styles: [` + :host { + background-color: #e3e5e8; + border: 1px solid #c0c0c0; + border-radius: 4px; + height: 14px; + line-height: 14px; + margin: 0 2px; + padding: 1px 3px; + width: max-content; + } + `] +}) +export class DebugTensorRankComponent { + @Input() + rank!: number; +} + +@Component({ + selector: 'debug-tensor-size', + template: ` +
+ + size: + + + {{ size }} + +
+ `, + styles: [` + :host { + background-color: #e3e5e8; + border: 1px solid #c0c0c0; + border-radius: 4px; + height: 14px; + line-height: 14px; + margin: 0 2px; + padding: 1px 3px; + width: max-content; + } + `] +}) +export class DebugTensorSizeComponent { + @Input() + size!: number; +} @Component({ selector: 'graph-executions-component', @@ -41,4 +130,6 @@ export class GraphExecutionsComponent { @Output() onScrolledIndexChange = new EventEmitter(); + + DTYPE_ENUM_TO_NAME = DTYPE_ENUM_TO_NAME; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts index 5e43f6e91cb..e0ff98f8832 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts @@ -17,11 +17,22 @@ import {ScrollingModule} from '@angular/cdk/scrolling'; import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; -import {GraphExecutionsComponent} from './graph_executions_component'; +import { + DebugTensorDTypeComponent, + DebugTensorRankComponent, + DebugTensorSizeComponent, + GraphExecutionsComponent +} from './graph_executions_component'; import {GraphExecutionsContainer} from './graph_executions_container'; @NgModule({ - declarations: [GraphExecutionsComponent, GraphExecutionsContainer], + declarations: [ + DebugTensorDTypeComponent, + DebugTensorRankComponent, + DebugTensorSizeComponent, + GraphExecutionsComponent, + GraphExecutionsContainer + ], imports: [CommonModule, ScrollingModule], exports: [GraphExecutionsContainer], }) From a6d5e5615372e99f74d57ca186ffce0f08e60254 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Tue, 21 Apr 2020 23:19:05 -0400 Subject: [PATCH 12/29] WIP: Add debug_tensor_value.ts --- .../tf_debugger_v2_plugin/store/BUILD | 13 + .../store/debug_tensor_value.ts | 60 +++++ .../store/debug_tensor_value_test.ts | 179 ++++++++++++++ .../store/debugger_types.ts | 38 +++ .../graph_executions_component.css | 1 - .../graph_executions_component.ng.html | 17 +- .../graph_executions_component.ts | 230 ++++++++++++++---- .../graph_executions_container_test.ts | 2 +- .../graph_executions_module.ts | 10 +- 9 files changed, 491 insertions(+), 59 deletions(-) create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/BUILD index 123282e662e..864934b7d40 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/BUILD @@ -31,15 +31,28 @@ ng_module( ], ) +ng_module( + name = "debug_tensor_value", + srcs = [ + "debug_tensor_value.ts", + ], + deps = [ + ":types", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin:tf_types", + ], +) + tf_ts_library( name = "debugger_store_test_lib", testonly = True, srcs = [ + "debug_tensor_value_test.ts", "debugger_reducers_test.ts", "debugger_selectors_test.ts", ], tsconfig = "//:tsconfig-test", deps = [ + ":debug_tensor_value", ":store", ":types", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts new file mode 100644 index 00000000000..3688c533789 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts @@ -0,0 +1,60 @@ +/* Copyright 2020 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. +==============================================================================*/ + +import {DTYPE_ENUM_TO_NAME} from '../tf_dtypes'; +import {DebugTensorValue, TensorDebugMode} from './debugger_types'; + +export function parseDebugTensorValue( + tensorDebugMode: TensorDebugMode, + vector: number[] +): DebugTensorValue { + switch (tensorDebugMode) { + case TensorDebugMode.NO_TENSOR: { + return {}; + } + case TensorDebugMode.CURT_HEALTH: { + return { + hasInfOrNaN: Boolean(vector[1]), + }; + } + case TensorDebugMode.CONCISE_HEALTH: { + const value: DebugTensorValue = { + size: vector[1], + }; + if (vector[2] > 0) { + value.numNaNs = vector[2]; + } + if (vector[3] > 0) { + value.numNegativeInfs = vector[3]; + } + if (vector[4] > 0) { + value.numPositiveInfs = vector[4]; + } + return value; + } + case TensorDebugMode.SHAPE: { + const rank = vector[2]; + return { + dtype: DTYPE_ENUM_TO_NAME[vector[1]], + rank, + size: vector[3], + shape: vector.slice(4, 4 + rank), + }; + } + default: { + throw new Error(`Unrecognized tensorDebugMode: ${tensorDebugMode}`); + } + } +} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts new file mode 100644 index 00000000000..bb7d0789e77 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts @@ -0,0 +1,179 @@ +/* Copyright 2020 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. +==============================================================================*/ + +import {TensorDebugMode} from './debugger_types'; +import {parseDebugTensorValue} from './debug_tensor_value'; + +describe('parseDebugTensorValue', () => { + describe('CURT_HEALTH', () => { + it('has no inf or nan', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.CURT_HEALTH, [ + 123, + 0, + ]); + expect(debugValue).toEqual({ + hasInfOrNaN: false, + }); + }); + + it('has inf or nan', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.CURT_HEALTH, [ + 123, + 1, + ]); + expect(debugValue).toEqual({ + hasInfOrNaN: true, + }); + }); + }); + + describe('CONCISE_HEALTH', () => { + it('all healthy', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ + 123, + 1000, + 0, + 0, + 0, + ]); + expect(debugValue).toEqual({ + size: 1000, + }); + }); + + it('has nan', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ + 123, + 1000, + 1, + 0, + 0, + ]); + expect(debugValue).toEqual({ + size: 1000, + numNaNs: 1, + }); + }); + + it('has neg inf', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ + 123, + 1000, + 0, + 2, + 0, + ]); + expect(debugValue).toEqual({ + size: 1000, + numNegativeInfs: 2, + }); + }); + + it('has pos inf', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ + 123, + 1000, + 0, + 0, + 22, + ]); + expect(debugValue).toEqual({ + size: 1000, + numPositiveInfs: 22, + }); + }); + + it('full house', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ + 123, + 1000, + 10, + 20, + 30, + ]); + expect(debugValue).toEqual({ + size: 1000, + numNaNs: 10, + numNegativeInfs: 20, + numPositiveInfs: 30, + }); + }); + }); + + describe('SHAPE', () => { + it('0D bool', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ + 123, + 10, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + ]); + expect(debugValue).toEqual({ + dtype: 'bool', + rank: 0, + size: 1, + shape: [], + }); + }); + + it('1D int32', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ + 123, + 3, + 1, + 46, + 46, + 0, + 0, + 0, + 0, + 0, + ]); + expect(debugValue).toEqual({ + dtype: 'int32', + rank: 1, + size: 46, + shape: [46], + }); + }); + + it('2D float32', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ + 123, + 1, + 2, + 1200, + 30, + 40, + 0, + 0, + 0, + 0, + ]); + expect(debugValue).toEqual({ + dtype: 'float32', + rank: 2, + size: 1200, + shape: [30, 40], + }); + }); + }); +}); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts index 09ca45e2f89..53995d80576 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts @@ -155,6 +155,44 @@ export interface InfNanAlert extends Alert { graph_execution_trace_index: number | null; } +/** + * The values summarizing a tensor value watched by the debugger. + */ +export interface DebugTensorValue { + // Data type of the tensor. + dtype?: string; + + // Rank of the tensor (e.g., 0 for scalar, 1 for 1D tensor, etc.) + rank?: number; + + // Shape of the tensor. + shape?: number[]; + + // Size (total element count) of the tensor. + size?: number; + + // Number of NaNa elements. + numNaNs?: number; + + // Number of -Infinity elements. + numNegativeInfs?: number; + + // Number of +Infinity elements. + numPositiveInfs?: number; + + // Number of finite negative elements. + numNegativeFinites?: number; + + // Numbe of zeros elements. + numZeros?: number; + + // Number of finite positive elements. + numPositiveFinites?: number; + + // Whether the tensor contains any NaN or Infinity elements. + hasInfOrNaN?: boolean; +} + export interface ExecutionDigestLoadState extends LoadState { // A map from page number to whether the page has been loaded // - in full, in which case the value is pageSize. diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css index ee228915da4..e039d0f3eb7 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css @@ -61,7 +61,6 @@ limitations under the License. .tensor-debug-info { display: inline-block; overflow: hidden; - width: 240px; } .tensor-debug-info-flexbox { diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html index afbf74cc66f..63b9e7b9444 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html @@ -47,7 +47,8 @@
+ class="tensor-debug-info" + >
- --> + + - +
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts index 7f681f37e49..fcbe8b9e457 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts @@ -27,27 +27,26 @@ import {DTYPE_ENUM_TO_NAME} from '../../tf_dtypes'; @Component({ selector: 'debug-tensor-dtype', template: ` -
- dtype: - {{ dtype }} -
+ {{ dtype }} `, - styles: [` - :host { - background-color: #e3e5e8; - border: 1px solid #c0c0c0; - border-radius: 4px; - font-family: 'Roboto Mono', monospace; - height: 14px; - line-height: 14px; - margin: 0 2px; - padding: 1px 3px; - width: max-content; - } - .dtype-name { - font-weight: 600 - } - `] + styles: [ + ` + :host { + background-color: #e3e5e8; + border: 1px solid #c0c0c0; + border-radius: 4px; + font-family: 'Roboto Mono', monospace; + height: 14px; + line-height: 14px; + margin: 0 2px; + padding: 1px 3px; + width: max-content; + } + .dtype-name { + font-weight: 600; + } + `, + ], }) export class DebugTensorDTypeComponent { @Input() @@ -57,54 +56,185 @@ export class DebugTensorDTypeComponent { @Component({ selector: 'debug-tensor-rank', template: ` -
{{ rank }}D
+ {{ rank }}D `, - styles: [` - :host { - background-color: #e3e5e8; - border: 1px solid #c0c0c0; - border-radius: 4px; - font-family: 'Roboto Mono', monospace; - height: 14px; - line-height: 14px; - margin: 0 2px; - padding: 1px 3px; - width: max-content; - } - `] + styles: [ + ` + :host { + background-color: #e3e5e8; + border: 1px solid #c0c0c0; + border-radius: 4px; + font-family: 'Roboto Mono', monospace; + height: 14px; + line-height: 14px; + margin: 0 2px; + padding: 1px 3px; + width: max-content; + } + `, + ], }) export class DebugTensorRankComponent { @Input() rank!: number; } +// @Component({ +// selector: 'debug-tensor-size', +// template: ` + +// `, +// styles: [` +// :host { +// background-color: #e3e5e8; +// border: 1px solid #c0c0c0; +// border-radius: 4px; +// font-family: 'Roboto Mono', monospace; +// height: 14px; +// line-height: 14px; +// margin: 0 2px; +// padding: 1px 3px; +// width: max-content; +// } +// `] +// }) +// export class DebugTensorSizeComponent { +// @Input() +// } + @Component({ - selector: 'debug-tensor-size', + selector: 'debug-tensor-numeric-breakdown', template: ` -
+
size: {{ size }}
+
+
+
+ NaN + ×{{ numNaNs }} +
+
+ -∞ + ×{{ numNegativeInfs }} +
+
+ +∞ + ×{{ numPositiveInfs }} +
+
+ - + ×{{ numNegativeFinites }} +
+
+ 0 + ×{{ numZeros }} +
+
+ + + ×{{ numPositiveFinites }} +
+
`, - styles: [` - :host { - background-color: #e3e5e8; - border: 1px solid #c0c0c0; - border-radius: 4px; - font-family: 'Roboto Mono', monospace; - height: 14px; - line-height: 14px; - margin: 0 2px; - padding: 1px 3px; - width: max-content; - } - `] + styles: [ + ` + :host { + background-color: #e3e5e8; + border: 1px solid #c0c0c0; + border-radius: 4px; + font-family: 'Roboto Mono', monospace; + font-size: 10px; + height: 28px; + line-height: 28px; + padding: 0 2px; + width: max-content; + } + .break { + flex-basis: 100%; + width: 0; + } + .size { + border-bottom: 1px solid rgba(0, 0, 0, 0.12); + display: block; + height: 12px; + line-height: 12px; + margin: 0 3px; + vertical-align: middle; + } + .breakdown { + display: flex; + height: 12px; + line-height: 12px; + padding: 0 2px; + vertical-align: middle; + } + .category { + margin-bottom: 2px; + margin-left: 4px; + margin-top: 2px; + heigth: 100%; + width: max-content; + } + .category-tag { + border-radius: 2px; + padding: 0 2px; + } + .finite { + background-color: #aaa; + color: #fefefe; + } + .infinite { + background-color: #e52592; + color: #fff; + } + `, + ], }) -export class DebugTensorSizeComponent { +export class DebugTensorNumericBreakdownComponent { @Input() size!: number; + + @Input() + numNaNs: number | undefined; + // TODO(cais): Colorize. + + @Input() + numNegativeInfs: number | undefined; + + @Input() + numPositiveInfs: number | undefined; + + @Input() + numNegativeFinites: number | undefined; + + @Input() + numZeros: number | undefined; + + @Input() + numPositiveFinites: number | undefined; } +// export class DebugValueComponent { +// @Input() +// tensor_debug_mode: number; + +// @Input() +// debug_tensor_value: number[]; +// } + @Component({ selector: 'graph-executions-component', templateUrl: './graph_executions_component.ng.html', diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts index 6a1091fac6b..6e6749f057d 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts @@ -43,7 +43,7 @@ import {GraphExecutionsModule} from './graph_executions_module'; /** @typehack */ import * as _typeHackStore from '@ngrx/store'; describe('Graph Executions Container', () => { -let store: MockStore; + let store: MockStore; beforeEach(async () => { await TestBed.configureTestingModule({ diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts index e0ff98f8832..6a365de9151 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts @@ -19,19 +19,21 @@ import {NgModule} from '@angular/core'; import { DebugTensorDTypeComponent, + DebugTensorNumericBreakdownComponent, DebugTensorRankComponent, - DebugTensorSizeComponent, - GraphExecutionsComponent + // DebugTensorSizeComponent, + GraphExecutionsComponent, } from './graph_executions_component'; import {GraphExecutionsContainer} from './graph_executions_container'; @NgModule({ declarations: [ DebugTensorDTypeComponent, + DebugTensorNumericBreakdownComponent, DebugTensorRankComponent, - DebugTensorSizeComponent, + // DebugTensorSizeComponent, GraphExecutionsComponent, - GraphExecutionsContainer + GraphExecutionsContainer, ], imports: [CommonModule, ScrollingModule], exports: [GraphExecutionsContainer], From 14613dad9971f80c8215c77d4feb40c083b752a9 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 22 Apr 2020 09:48:33 -0400 Subject: [PATCH 13/29] Add logic and tests for FULL_TENSOR and FULL_HEALTH; doc string --- .../store/debug_tensor_value.ts | 72 ++++++++-- .../store/debug_tensor_value_test.ts | 130 ++++++++++++++++-- 2 files changed, 175 insertions(+), 27 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts index 3688c533789..938cf1ce993 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts @@ -16,9 +16,23 @@ limitations under the License. import {DTYPE_ENUM_TO_NAME} from '../tf_dtypes'; import {DebugTensorValue, TensorDebugMode} from './debugger_types'; +/** + * Parse a number array that represents debugging summary of an instrumented + * tensor value. + * + * @param tensorDebugMode Tensor-debug mode. + * @param array The array of number that represents various aspect of the + * instrumented tensor. The semantics of the numbers are determined by + * `tensorDebugModel`. + * @returns A DebugTensorValue object with the same information as + * carried by `array`, but represented in a more explicit fashion. + * For numbers that represent breakdown of numeric values by type + * (e.g., counts of -inf, +inf and nan), the corresponding fields + * in the returned object will be defined only of the count is non-zero. + */ export function parseDebugTensorValue( tensorDebugMode: TensorDebugMode, - vector: number[] + array: number[] | null ): DebugTensorValue { switch (tensorDebugMode) { case TensorDebugMode.NO_TENSOR: { @@ -26,33 +40,65 @@ export function parseDebugTensorValue( } case TensorDebugMode.CURT_HEALTH: { return { - hasInfOrNaN: Boolean(vector[1]), + hasInfOrNaN: Boolean(array![1]), }; } case TensorDebugMode.CONCISE_HEALTH: { const value: DebugTensorValue = { - size: vector[1], + size: array![1], }; - if (vector[2] > 0) { - value.numNaNs = vector[2]; + if (array![2] > 0) { + value.numNaNs = array![2]; } - if (vector[3] > 0) { - value.numNegativeInfs = vector[3]; + if (array![3] > 0) { + value.numNegativeInfs = array![3]; } - if (vector[4] > 0) { - value.numPositiveInfs = vector[4]; + if (array![4] > 0) { + value.numPositiveInfs = array![4]; } return value; } case TensorDebugMode.SHAPE: { - const rank = vector[2]; + const rank = array![2]; return { - dtype: DTYPE_ENUM_TO_NAME[vector[1]], + dtype: DTYPE_ENUM_TO_NAME[array![1]], rank, - size: vector[3], - shape: vector.slice(4, 4 + rank), + size: array![3], + shape: array!.slice(4, 4 + rank), }; } + case TensorDebugMode.FULL_HEALTH: { + const rank = array![3]; + const value: DebugTensorValue = { + dtype: DTYPE_ENUM_TO_NAME[array![2]], + rank, + size: array![4], + }; + if (array![5] > 0) { + value.numNegativeInfs = array![5]; + } + if (array![6] > 0) { + value.numPositiveInfs = array![6]; + } + if (array![7] > 0) { + value.numNaNs = array![7]; + } + if (array![8] > 0) { + value.numNegativeFinites = array![8]; + } + if (array![9] > 0) { + value.numZeros = array![9]; + } + if (array![10] > 0) { + value.numPositiveFinites = array![10]; + } + return value; + } + case TensorDebugMode.FULL_TENSOR: { + // Under FULL_TENSOR mode, the full tensor value is supplied via + // separate means. No summary values are provided for the tensor value. + return {}; + } default: { throw new Error(`Unrecognized tensorDebugMode: ${tensorDebugMode}`); } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts index bb7d0789e77..916b281f2df 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts @@ -20,8 +20,8 @@ describe('parseDebugTensorValue', () => { describe('CURT_HEALTH', () => { it('has no inf or nan', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.CURT_HEALTH, [ - 123, - 0, + 123, // tensor ID + 0, // has inf or nan? ]); expect(debugValue).toEqual({ hasInfOrNaN: false, @@ -30,8 +30,8 @@ describe('parseDebugTensorValue', () => { it('has inf or nan', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.CURT_HEALTH, [ - 123, - 1, + 123, // tensor ID + 1, // has inf or nan? ]); expect(debugValue).toEqual({ hasInfOrNaN: true, @@ -43,7 +43,7 @@ describe('parseDebugTensorValue', () => { it('all healthy', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ 123, - 1000, + 1000, // size 0, 0, 0, @@ -56,7 +56,7 @@ describe('parseDebugTensorValue', () => { it('has nan', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ 123, - 1000, + 1000, // size 1, 0, 0, @@ -84,7 +84,7 @@ describe('parseDebugTensorValue', () => { it('has pos inf', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ 123, - 1000, + 1000, // size 0, 0, 22, @@ -98,7 +98,7 @@ describe('parseDebugTensorValue', () => { it('full house', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ 123, - 1000, + 1000, // size 10, 20, 30, @@ -116,9 +116,9 @@ describe('parseDebugTensorValue', () => { it('0D bool', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ 123, - 10, - 0, - 1, + 10, // bool + 0, // rank + 1, // size 0, 0, 0, @@ -137,9 +137,9 @@ describe('parseDebugTensorValue', () => { it('1D int32', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ 123, - 3, - 1, - 46, + 3, // int32 + 1, // rank + 46, // size 46, 0, 0, @@ -176,4 +176,106 @@ describe('parseDebugTensorValue', () => { }); }); }); + + describe('FULL_HEALTH', () => { + it('float32 2D with no inf or nan', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.FULL_HEALTH, [ + 123, + 0, + 1, // float32 + 2, // rank + 600, // size + 0, + 0, + 0, + 100, + 200, + 300, + ]); + expect(debugValue).toEqual({ + dtype: 'float32', + rank: 2, + size: 600, + numNegativeFinites: 100, + numZeros: 200, + numPositiveFinites: 300, + }); + }); + + it('float64 scalar nan', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.FULL_HEALTH, [ + 123, + 0, + 2, // float64 + 0, // rank + 1, // size + 0, + 0, + 1, + 0, + 0, + 0, + ]); + expect(debugValue).toEqual({ + dtype: 'float64', + rank: 0, + size: 1, + numNaNs: 1, + }); + }); + + it('bfloat16 1D with -inf and +inf', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.FULL_HEALTH, [ + 123, + 0, + 14, // bfloat64. + 1, // rank + 10, // size + 3, + 7, + 0, + 0, + 0, + 0, + ]); + expect(debugValue).toEqual({ + dtype: 'bfloat16', + rank: 1, + size: 10, + numNegativeInfs: 3, + numPositiveInfs: 7, + }); + }); + }); + + describe('NO_TENSOR', () => { + it('returns empty object', () => { + expect(parseDebugTensorValue(TensorDebugMode.NO_TENSOR, null)).toEqual( + {} + ); + }); + }); + + describe('FULL_TENSOR', () => { + it('returns empty object', () => { + expect(parseDebugTensorValue(TensorDebugMode.FULL_TENSOR, null)).toEqual( + {} + ); + }); + }); + + describe('Invalid TensorDebugMode', () => { + for (const debugMode of [ + null, + undefined, + NaN, + TensorDebugMode.UNSPECIFIED, + ]) { + it('throws error', () => { + expect(() => + parseDebugTensorValue(debugMode as TensorDebugMode, null) + ).toThrowError(); + }); + } + }); }); From 64282ad8e1f0913b8635c343480ed0a2a29cdfc4 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 22 Apr 2020 10:11:00 -0400 Subject: [PATCH 14/29] Add undefined filling for shape --- .../store/debug_tensor_value.ts | 7 +- .../store/debug_tensor_value_test.ts | 69 ++++++++++++++++++- .../store/debugger_types.ts | 16 ++++- 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts index 938cf1ce993..d596f43ac31 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts @@ -60,11 +60,16 @@ export function parseDebugTensorValue( } case TensorDebugMode.SHAPE: { const rank = array![2]; + let shape: number[] = array!.slice(4, Math.min(4 + rank, array!.length)); + if (shape.length < rank) { + // The SHAPE mode truncates the shape at head. + shape = new Array(rank - shape.length).concat(shape); + } return { dtype: DTYPE_ENUM_TO_NAME[array![1]], rank, size: array![3], - shape: array!.slice(4, 4 + rank), + shape, }; } case TensorDebugMode.FULL_HEALTH: { diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts index 916b281f2df..d05b514fe1d 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts @@ -158,8 +158,8 @@ describe('parseDebugTensorValue', () => { it('2D float32', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ 123, - 1, - 2, + 1, // float32 + 2, // rank 1200, 30, 40, @@ -175,6 +175,71 @@ describe('parseDebugTensorValue', () => { shape: [30, 40], }); }); + + it('6D float64', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ + 123, + 2, // float64 + 6, // rank + 1200, + 1, + 2, + 3, + 4, + 5, + 10, + ]); + expect(debugValue).toEqual({ + dtype: 'float64', + rank: 6, + size: 1200, + shape: [1, 2, 3, 4, 5, 10], + }); + }); + + it('truncated shape: 7D', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ + 123, + 5, // int16 + 7, // rankk 8 + 1200, + 3, + 4, + 1, + 2, + 1, + 5, + ]); + expect(debugValue).toEqual({ + dtype: 'int16', + rank: 7, + size: 1200, + // Truncated dimensions are filled with `undefined`s. + shape: [undefined, 3, 4, 1, 2, 1, 5], + }); + }); + + it('truncated shape: 8D', () => { + const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ + 123, + 1, // float32 + 8, // rankk 8 + 1200, + 3, + 4, + 1, + 2, + 1, + 5, + ]); + expect(debugValue).toEqual({ + dtype: 'float32', + rank: 8, + size: 1200, + // Truncated dimensions are filled with `undefined`s. + shape: [undefined, undefined, 3, 4, 1, 2, 1, 5], + }); + }); }); describe('FULL_HEALTH', () => { diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts index 53995d80576..9df4eb3a211 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts @@ -166,7 +166,10 @@ export interface DebugTensorValue { rank?: number; // Shape of the tensor. - shape?: number[]; + // In the case where the shape is truncated beyond the highest + // rank a debug mode can represent, the truncated part is filled with + // `undefined`s. + shape?: Array; // Size (total element count) of the tensor. size?: number; @@ -191,6 +194,17 @@ export interface DebugTensorValue { // Whether the tensor contains any NaN or Infinity elements. hasInfOrNaN?: boolean; + + // Minimum value. + min?: number; + + // Maximum value. + max?: number; + + // Arithemtic mean. + mean?: number; + + variance?: number; } export interface ExecutionDigestLoadState extends LoadState { From 02c8e3210fc0126dbd318d3d82c8edaed388ed91 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 22 Apr 2020 11:27:44 -0400 Subject: [PATCH 15/29] Refactoring into DebugTensorValueComponent --- .../store/debug_tensor_value.ts | 2 +- .../views/graph_executions/BUILD | 2 +- .../graph_executions_component.ng.html | 37 +++----- .../graph_executions_component.ts | 86 +++++++++++-------- .../graph_executions_module.ts | 4 +- 5 files changed, 66 insertions(+), 65 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts index d596f43ac31..495ee0eb56d 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts @@ -34,7 +34,7 @@ export function parseDebugTensorValue( tensorDebugMode: TensorDebugMode, array: number[] | null ): DebugTensorValue { - switch (tensorDebugMode) { + switch (+tensorDebugMode) { case TensorDebugMode.NO_TENSOR: { return {}; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/BUILD index aa77f493bc8..334bcd6cefa 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/BUILD @@ -17,9 +17,9 @@ ng_module( "graph_executions_component.ng.html", ], deps = [ - "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin:tf_types", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:debug_tensor_value", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", "//tensorboard/webapp/angular:expect_angular_cdk_scrolling", "@npm//@angular/common", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html index 63b9e7b9444..cd2b461ad94 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html @@ -45,35 +45,18 @@
-
--> + -
- - - - - - - - -
-
+ +
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts index fcbe8b9e457..15c7ce78fa7 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts @@ -21,8 +21,12 @@ import { Output, } from '@angular/core'; -import {GraphExecution} from '../../store/debugger_types'; -import {DTYPE_ENUM_TO_NAME} from '../../tf_dtypes'; +import {parseDebugTensorValue} from '../../store/debug_tensor_value'; +import { + DebugTensorValue, + GraphExecution, + TensorDebugMode, +} from '../../store/debugger_types'; @Component({ selector: 'debug-tensor-dtype', @@ -79,29 +83,6 @@ export class DebugTensorRankComponent { rank!: number; } -// @Component({ -// selector: 'debug-tensor-size', -// template: ` - -// `, -// styles: [` -// :host { -// background-color: #e3e5e8; -// border: 1px solid #c0c0c0; -// border-radius: 4px; -// font-family: 'Roboto Mono', monospace; -// height: 14px; -// line-height: 14px; -// margin: 0 2px; -// padding: 1px 3px; -// width: max-content; -// } -// `] -// }) -// export class DebugTensorSizeComponent { -// @Input() -// } - @Component({ selector: 'debug-tensor-numeric-breakdown', template: ` @@ -209,7 +190,6 @@ export class DebugTensorNumericBreakdownComponent { @Input() numNaNs: number | undefined; - // TODO(cais): Colorize. @Input() numNegativeInfs: number | undefined; @@ -227,13 +207,51 @@ export class DebugTensorNumericBreakdownComponent { numPositiveFinites: number | undefined; } -// export class DebugValueComponent { -// @Input() -// tensor_debug_mode: number; - -// @Input() -// debug_tensor_value: number[]; -// } +@Component({ + selector: 'debug-tensor-value', + template: ` +
+ + + + + + +
+ `, + styles: [ + ` + :host { + display: inline-block; + overflow: hidden; + } + .flexbox { + align-items: flex-start; + display: flex; + flex-wrap: nowrap; + vertical-align: top; + } + `, + ], +}) +export class DebugTensorValueComponent { + @Input() + debugTensorValue!: DebugTensorValue; +} @Component({ selector: 'graph-executions-component', @@ -254,5 +272,5 @@ export class GraphExecutionsComponent { @Output() onScrolledIndexChange = new EventEmitter(); - DTYPE_ENUM_TO_NAME = DTYPE_ENUM_TO_NAME; + parseDebugTensorValue = parseDebugTensorValue; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts index 6a365de9151..82b6f814473 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts @@ -21,7 +21,7 @@ import { DebugTensorDTypeComponent, DebugTensorNumericBreakdownComponent, DebugTensorRankComponent, - // DebugTensorSizeComponent, + DebugTensorValueComponent, GraphExecutionsComponent, } from './graph_executions_component'; import {GraphExecutionsContainer} from './graph_executions_container'; @@ -31,7 +31,7 @@ import {GraphExecutionsContainer} from './graph_executions_container'; DebugTensorDTypeComponent, DebugTensorNumericBreakdownComponent, DebugTensorRankComponent, - // DebugTensorSizeComponent, + DebugTensorValueComponent, GraphExecutionsComponent, GraphExecutionsContainer, ], From df83903491f6e50489f2016c4fd2cd3b89f34db6 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 22 Apr 2020 11:45:30 -0400 Subject: [PATCH 16/29] Refactor DebugTensorValueComponent into separate folder --- .../views/debug_tensor_value/BUILD | 50 ++++ .../debug_tensor_value_component.ts | 242 ++++++++++++++++++ .../debug_tensor_value_module.ts | 36 +++ .../views/graph_executions/BUILD | 2 + .../graph_executions_component.ts | 231 +---------------- .../graph_executions_module.ts | 20 +- 6 files changed, 335 insertions(+), 246 deletions(-) create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_module.ts diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD new file mode 100644 index 00000000000..a88d58171d3 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD @@ -0,0 +1,50 @@ +package(default_visibility = ["//tensorboard:internal"]) + +load("@npm_angular_bazel//:index.bzl", "ng_module") +load("//tensorboard/defs:defs.bzl", "tf_ts_library") + +licenses(["notice"]) # Apache 2.0 + +ng_module( + name = "debug_tensor_value", + srcs = [ + "debug_tensor_value_component.ts", + "debug_tensor_value_module.ts", + ], + deps = [ + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:debug_tensor_value", + "@npm//@angular/common", + "@npm//@angular/core", + ], +) + +# tf_ts_library( +# name = "alerts_container_test_lib", +# testonly = True, +# srcs = [ +# "alerts_container_test.ts", +# ], +# tsconfig = "//:tsconfig-test", +# deps = [ +# ":alerts", +# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin:debugger_v2", +# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions", +# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store", +# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", +# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/testing", +# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data", +# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions", +# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/inactive", +# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files", +# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace", +# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline", +# "//tensorboard/webapp/angular:expect_angular_core_testing", +# "//tensorboard/webapp/angular:expect_ngrx_store_testing", +# "@npm//@angular/common", +# "@npm//@angular/compiler", +# "@npm//@angular/core", +# "@npm//@angular/platform-browser", +# "@npm//@ngrx/store", +# "@npm//@types/jasmine", +# ], +# ) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts new file mode 100644 index 00000000000..37aa18b3aa0 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts @@ -0,0 +1,242 @@ +/* Copyright 2020 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. +==============================================================================*/ +import {Component, Input} from '@angular/core'; + +import {DebugTensorValue} from '../../store/debugger_types'; + +@Component({ + selector: 'debug-tensor-dtype', + template: ` + {{ dtype }} + `, + styles: [ + ` + :host { + background-color: #e3e5e8; + border: 1px solid #c0c0c0; + border-radius: 4px; + font-family: 'Roboto Mono', monospace; + height: 14px; + line-height: 14px; + margin: 0 2px; + padding: 1px 3px; + width: max-content; + } + .dtype-name { + font-weight: 600; + } + `, + ], +}) +export class DebugTensorDTypeComponent { + @Input() + dtype!: string; +} + +@Component({ + selector: 'debug-tensor-rank', + template: ` + {{ rank }}D + `, + styles: [ + ` + :host { + background-color: #e3e5e8; + border: 1px solid #c0c0c0; + border-radius: 4px; + font-family: 'Roboto Mono', monospace; + height: 14px; + line-height: 14px; + margin: 0 2px; + padding: 1px 3px; + width: max-content; + } + `, + ], +}) +export class DebugTensorRankComponent { + @Input() + rank!: number; +} + +@Component({ + selector: 'debug-tensor-numeric-breakdown', + template: ` +
+ size: + {{ size }} +
+
+
+
+ NaN + ×{{ numNaNs }} +
+
+ -∞ + ×{{ numNegativeInfs }} +
+
+ +∞ + ×{{ numPositiveInfs }} +
+
+ - + ×{{ numNegativeFinites }} +
+
+ 0 + ×{{ numZeros }} +
+
+ + + ×{{ numPositiveFinites }} +
+
+ `, + styles: [ + ` + :host { + background-color: #e3e5e8; + border: 1px solid #c0c0c0; + border-radius: 4px; + font-family: 'Roboto Mono', monospace; + font-size: 10px; + height: 28px; + line-height: 28px; + padding: 0 2px; + width: max-content; + } + .break { + flex-basis: 100%; + width: 0; + } + .size { + border-bottom: 1px solid rgba(0, 0, 0, 0.12); + display: block; + height: 12px; + line-height: 12px; + margin: 0 3px; + vertical-align: middle; + } + .breakdown { + display: flex; + height: 12px; + line-height: 12px; + padding: 0 2px; + vertical-align: middle; + } + .category { + margin-bottom: 2px; + margin-left: 4px; + margin-top: 2px; + heigth: 100%; + width: max-content; + } + .category-tag { + border-radius: 2px; + padding: 0 2px; + } + .finite { + background-color: #aaa; + color: #fefefe; + } + .infinite { + background-color: #e52592; + color: #fff; + } + `, + ], +}) +export class DebugTensorNumericBreakdownComponent { + @Input() + size!: number; + + @Input() + numNaNs: number | undefined; + + @Input() + numNegativeInfs: number | undefined; + + @Input() + numPositiveInfs: number | undefined; + + @Input() + numNegativeFinites: number | undefined; + + @Input() + numZeros: number | undefined; + + @Input() + numPositiveFinites: number | undefined; +} + +@Component({ + selector: 'debug-tensor-value', + template: ` +
+ + + + + + +
+ `, + styles: [ + ` + :host { + display: inline-block; + overflow: hidden; + } + .flexbox { + align-items: flex-start; + display: flex; + flex-wrap: nowrap; + vertical-align: top; + } + `, + ], +}) +export class DebugTensorValueComponent { + @Input() + debugTensorValue!: DebugTensorValue; +} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_module.ts new file mode 100644 index 00000000000..6f1dbb21d01 --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_module.ts @@ -0,0 +1,36 @@ +/* Copyright 2020 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. +==============================================================================*/ + +import {CommonModule} from '@angular/common'; +import {NgModule} from '@angular/core'; + +import { + DebugTensorDTypeComponent, + DebugTensorNumericBreakdownComponent, + DebugTensorRankComponent, + DebugTensorValueComponent, +} from './debug_tensor_value_component'; + +@NgModule({ + declarations: [ + DebugTensorDTypeComponent, + DebugTensorNumericBreakdownComponent, + DebugTensorRankComponent, + DebugTensorValueComponent, + ], + imports: [CommonModule], + exports: [DebugTensorValueComponent], +}) +export class DebugTensorValueModule {} diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/BUILD index 334bcd6cefa..618ef9b5991 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/BUILD @@ -21,6 +21,7 @@ ng_module( "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:debug_tensor_value", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value", "//tensorboard/webapp/angular:expect_angular_cdk_scrolling", "@npm//@angular/common", "@npm//@angular/core", @@ -44,6 +45,7 @@ tf_ts_library( "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/testing", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/inactive", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts index 15c7ce78fa7..8237aacb6b1 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ts @@ -22,236 +22,7 @@ import { } from '@angular/core'; import {parseDebugTensorValue} from '../../store/debug_tensor_value'; -import { - DebugTensorValue, - GraphExecution, - TensorDebugMode, -} from '../../store/debugger_types'; - -@Component({ - selector: 'debug-tensor-dtype', - template: ` - {{ dtype }} - `, - styles: [ - ` - :host { - background-color: #e3e5e8; - border: 1px solid #c0c0c0; - border-radius: 4px; - font-family: 'Roboto Mono', monospace; - height: 14px; - line-height: 14px; - margin: 0 2px; - padding: 1px 3px; - width: max-content; - } - .dtype-name { - font-weight: 600; - } - `, - ], -}) -export class DebugTensorDTypeComponent { - @Input() - dtype!: string; -} - -@Component({ - selector: 'debug-tensor-rank', - template: ` - {{ rank }}D - `, - styles: [ - ` - :host { - background-color: #e3e5e8; - border: 1px solid #c0c0c0; - border-radius: 4px; - font-family: 'Roboto Mono', monospace; - height: 14px; - line-height: 14px; - margin: 0 2px; - padding: 1px 3px; - width: max-content; - } - `, - ], -}) -export class DebugTensorRankComponent { - @Input() - rank!: number; -} - -@Component({ - selector: 'debug-tensor-numeric-breakdown', - template: ` -
- size: - {{ size }} -
-
-
-
- NaN - ×{{ numNaNs }} -
-
- -∞ - ×{{ numNegativeInfs }} -
-
- +∞ - ×{{ numPositiveInfs }} -
-
- - - ×{{ numNegativeFinites }} -
-
- 0 - ×{{ numZeros }} -
-
- + - ×{{ numPositiveFinites }} -
-
- `, - styles: [ - ` - :host { - background-color: #e3e5e8; - border: 1px solid #c0c0c0; - border-radius: 4px; - font-family: 'Roboto Mono', monospace; - font-size: 10px; - height: 28px; - line-height: 28px; - padding: 0 2px; - width: max-content; - } - .break { - flex-basis: 100%; - width: 0; - } - .size { - border-bottom: 1px solid rgba(0, 0, 0, 0.12); - display: block; - height: 12px; - line-height: 12px; - margin: 0 3px; - vertical-align: middle; - } - .breakdown { - display: flex; - height: 12px; - line-height: 12px; - padding: 0 2px; - vertical-align: middle; - } - .category { - margin-bottom: 2px; - margin-left: 4px; - margin-top: 2px; - heigth: 100%; - width: max-content; - } - .category-tag { - border-radius: 2px; - padding: 0 2px; - } - .finite { - background-color: #aaa; - color: #fefefe; - } - .infinite { - background-color: #e52592; - color: #fff; - } - `, - ], -}) -export class DebugTensorNumericBreakdownComponent { - @Input() - size!: number; - - @Input() - numNaNs: number | undefined; - - @Input() - numNegativeInfs: number | undefined; - - @Input() - numPositiveInfs: number | undefined; - - @Input() - numNegativeFinites: number | undefined; - - @Input() - numZeros: number | undefined; - - @Input() - numPositiveFinites: number | undefined; -} - -@Component({ - selector: 'debug-tensor-value', - template: ` -
- - - - - - -
- `, - styles: [ - ` - :host { - display: inline-block; - overflow: hidden; - } - .flexbox { - align-items: flex-start; - display: flex; - flex-wrap: nowrap; - vertical-align: top; - } - `, - ], -}) -export class DebugTensorValueComponent { - @Input() - debugTensorValue!: DebugTensorValue; -} +import {GraphExecution} from '../../store/debugger_types'; @Component({ selector: 'graph-executions-component', diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts index 82b6f814473..f90afb617f1 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_module.ts @@ -17,25 +17,13 @@ import {ScrollingModule} from '@angular/cdk/scrolling'; import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; -import { - DebugTensorDTypeComponent, - DebugTensorNumericBreakdownComponent, - DebugTensorRankComponent, - DebugTensorValueComponent, - GraphExecutionsComponent, -} from './graph_executions_component'; +import {DebugTensorValueModule} from '../debug_tensor_value/debug_tensor_value_module'; +import {GraphExecutionsComponent} from './graph_executions_component'; import {GraphExecutionsContainer} from './graph_executions_container'; @NgModule({ - declarations: [ - DebugTensorDTypeComponent, - DebugTensorNumericBreakdownComponent, - DebugTensorRankComponent, - DebugTensorValueComponent, - GraphExecutionsComponent, - GraphExecutionsContainer, - ], - imports: [CommonModule, ScrollingModule], + declarations: [GraphExecutionsComponent, GraphExecutionsContainer], + imports: [CommonModule, DebugTensorValueModule, ScrollingModule], exports: [GraphExecutionsContainer], }) export class GraphExecutionsModule {} From 3820d93b83b26f12e51c5e79ec03e61ba39b48c6 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 22 Apr 2020 15:28:04 -0400 Subject: [PATCH 17/29] Adjust breakdown component CSS --- .../debug_tensor_value_component.ts | 53 ++++++++++++------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts index 37aa18b3aa0..8ab7b1cb197 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts @@ -78,8 +78,15 @@ export class DebugTensorRankComponent { size: {{ size }}
-
-
+
+
+
NaN ×{{ numNaNs }} @@ -126,28 +133,25 @@ export class DebugTensorRankComponent { border-radius: 4px; font-family: 'Roboto Mono', monospace; font-size: 10px; - height: 28px; - line-height: 28px; - padding: 0 2px; - width: max-content; + padding: 1px; } .break { flex-basis: 100%; width: 0; } .size { - border-bottom: 1px solid rgba(0, 0, 0, 0.12); display: block; - height: 12px; - line-height: 12px; - margin: 0 3px; + height: 11px; + line-height: 11px; + margin: 0 3px 1px; vertical-align: middle; } .breakdown { + border-top: 1px solid rgba(0, 0, 0, 0.12); display: flex; - height: 12px; - line-height: 12px; - padding: 0 2px; + height: 11px; + line-height: 11px; + padding: 2px; vertical-align: middle; } .category { @@ -177,7 +181,7 @@ export class DebugTensorNumericBreakdownComponent { size!: number; @Input() - numNaNs: number | undefined; + numNaNs!: number | undefined; @Input() numNegativeInfs: number | undefined; @@ -193,6 +197,15 @@ export class DebugTensorNumericBreakdownComponent { @Input() numPositiveFinites: number | undefined; + + get breakdownExists(): boolean { + return this.numNaNs !== undefined || + this.numNegativeInfs !== undefined || + this.numPositiveInfs !== undefined || + this.numNegativeFinites !== undefined || + this.numZeros !== undefined || + this.numPositiveFinites !== undefined; + } } @Component({ @@ -211,12 +224,12 @@ export class DebugTensorNumericBreakdownComponent {
From ccbc314292f17a018ee59a19fef4b3d8ac024141 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 22 Apr 2020 15:52:47 -0400 Subject: [PATCH 18/29] Add DebugTensorShapeComponent --- .../debug_tensor_value_component.ts | 75 ++++++++++++++----- .../debug_tensor_value_module.ts | 2 + 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts index 8ab7b1cb197..4bcbe6a0d92 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts @@ -78,15 +78,8 @@ export class DebugTensorRankComponent { size: {{ size }}
-
-
-
+
+
NaN ×{{ numNaNs }} @@ -133,6 +126,7 @@ export class DebugTensorRankComponent { border-radius: 4px; font-family: 'Roboto Mono', monospace; font-size: 10px; + margin: 0 2px; padding: 1px; } .break { @@ -143,7 +137,7 @@ export class DebugTensorRankComponent { display: block; height: 11px; line-height: 11px; - margin: 0 3px 1px; + margin: 0 3px; vertical-align: middle; } .breakdown { @@ -199,12 +193,52 @@ export class DebugTensorNumericBreakdownComponent { numPositiveFinites: number | undefined; get breakdownExists(): boolean { - return this.numNaNs !== undefined || - this.numNegativeInfs !== undefined || - this.numPositiveInfs !== undefined || - this.numNegativeFinites !== undefined || - this.numZeros !== undefined || - this.numPositiveFinites !== undefined; + return ( + this.numNaNs !== undefined || + this.numNegativeInfs !== undefined || + this.numPositiveInfs !== undefined || + this.numNegativeFinites !== undefined || + this.numZeros !== undefined || + this.numPositiveFinites !== undefined + ); + } +} + +@Component({ + selector: 'debug-tensor-shape', + template: ` + shape:{{ shapeString }} + `, + styles: [ + ` + :host { + background-color: #e3e5e8; + border: 1px solid #c0c0c0; + border-radius: 4px; + font-family: 'Roboto Mono', monospace; + height: 14px; + line-height: 14px; + margin: 0 2px; + padding: 1px 3px; + width: max-content; + } + `, + ], +}) +export class DebugTensorShapeComponent { + @Input() + shape!: Array; + + get shapeString(): string { + return ( + '[' + + this.shape + .map((dim) => { + return dim === undefined ? '?' : String(dim); + }) + .join(',') + + ']' + ); } } @@ -214,14 +248,19 @@ export class DebugTensorNumericBreakdownComponent {
+ + Date: Wed, 22 Apr 2020 16:15:41 -0400 Subject: [PATCH 19/29] Add DebugTensorHasInfOrNaNComponent --- .../debug_tensor_value_component.ts | 104 ++++++++++-------- .../debug_tensor_value_module.ts | 2 + 2 files changed, 60 insertions(+), 46 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts index 4bcbe6a0d92..f735bb4af59 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts @@ -16,29 +16,26 @@ import {Component, Input} from '@angular/core'; import {DebugTensorValue} from '../../store/debugger_types'; +const basicDebugInfoStyle = ` + :host { + background-color: #e3e5e8; + border: 1px solid #c0c0c0; + border-radius: 4px; + font-family: 'Roboto Mono', monospace; + height: 14px; + line-height: 14px; + margin: 0 2px; + padding: 1px 3px; + width: max-content; + } +`; + @Component({ selector: 'debug-tensor-dtype', template: ` {{ dtype }} `, - styles: [ - ` - :host { - background-color: #e3e5e8; - border: 1px solid #c0c0c0; - border-radius: 4px; - font-family: 'Roboto Mono', monospace; - height: 14px; - line-height: 14px; - margin: 0 2px; - padding: 1px 3px; - width: max-content; - } - .dtype-name { - font-weight: 600; - } - `, - ], + styles: [basicDebugInfoStyle], }) export class DebugTensorDTypeComponent { @Input() @@ -50,21 +47,7 @@ export class DebugTensorDTypeComponent { template: ` {{ rank }}D `, - styles: [ - ` - :host { - background-color: #e3e5e8; - border: 1px solid #c0c0c0; - border-radius: 4px; - font-family: 'Roboto Mono', monospace; - height: 14px; - line-height: 14px; - margin: 0 2px; - padding: 1px 3px; - width: max-content; - } - `, - ], + styles: [basicDebugInfoStyle], }) export class DebugTensorRankComponent { @Input() @@ -209,12 +192,39 @@ export class DebugTensorNumericBreakdownComponent { template: ` shape:{{ shapeString }} `, + styles: [basicDebugInfoStyle], +}) +export class DebugTensorShapeComponent { + @Input() + shape!: Array; + + get shapeString(): string { + return ( + '[' + + this.shape + .map((dim) => { + return dim === undefined ? '?' : String(dim); + }) + .join(',') + + ']' + ); + } +} + +@Component({ + selector: 'debug-tensor-has-inf-or-nan', + template: ` +
+ {{ infoString }} +
+ `, styles: [ ` - :host { + .container { background-color: #e3e5e8; border: 1px solid #c0c0c0; border-radius: 4px; + color: #666666; font-family: 'Roboto Mono', monospace; height: 14px; line-height: 14px; @@ -222,23 +232,19 @@ export class DebugTensorNumericBreakdownComponent { padding: 1px 3px; width: max-content; } + .has-inf-or-nan { + background-color: #e52592; + color: #fff; + } `, ], }) -export class DebugTensorShapeComponent { +export class DebugTensorHasInfOrNaNComponent { @Input() - shape!: Array; + hasInfOrNaN!: boolean; - get shapeString(): string { - return ( - '[' + - this.shape - .map((dim) => { - return dim === undefined ? '?' : String(dim); - }) - .join(',') + - ']' - ); + get infoString(): string { + return this.hasInfOrNaN ? 'Has ∞/NaN' : 'No ∞/NaN'; } } @@ -261,7 +267,13 @@ export class DebugTensorShapeComponent { [shape]="debugTensorValue.shape" > + + Date: Wed, 22 Apr 2020 16:56:10 -0400 Subject: [PATCH 20/29] Switch ExecutionDataComponent to using DebugTensorValueCompoennt --- .../debugger_container_test.ts | 457 ------------------ .../debug_tensor_value_component.ts | 2 +- .../views/execution_data/BUILD | 2 + .../execution_data_component.css | 29 +- .../execution_data_component.ng.html | 218 +-------- .../execution_data_component.ts | 2 + .../execution_data/execution_data_module.ts | 3 +- 7 files changed, 45 insertions(+), 668 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts index 51949f4e509..f50904ce71d 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts @@ -34,7 +34,6 @@ import {DebuggerContainer} from './debugger_container'; import { DataLoadState, State, - TensorDebugMode, AlertType, } from './store/debugger_types'; import { @@ -47,7 +46,6 @@ import { createTestStackFrame, } from './testing'; import {AlertsModule} from './views/alerts/alerts_module'; -import {ExecutionDataContainer} from './views/execution_data/execution_data_container'; import {ExecutionDataModule} from './views/execution_data/execution_data_module'; import {GraphExecutionsModule} from './views/graph_executions/graph_executions_module'; import {InactiveModule} from './views/inactive/inactive_module'; @@ -434,461 +432,6 @@ describe('Debugger Container', () => { }); } - describe('Execution Data module', () => { - it('CURT_HEALTH TensorDebugMode, One Output', () => { - const fixture = TestBed.createComponent(ExecutionDataContainer); - fixture.detectChanges(); - - store.setState( - createState( - createDebuggerState({ - executions: { - numExecutionsLoaded: { - state: DataLoadState.LOADED, - lastLoadedTimeInMs: 111, - }, - executionDigestsLoaded: { - state: DataLoadState.LOADED, - lastLoadedTimeInMs: 222, - pageLoadedSizes: {0: 100}, - numExecutions: 1000, - }, - executionDigests: {}, - pageSize: 100, - displayCount: 50, - scrollBeginIndex: 90, - focusIndex: 98, - executionData: { - 98: createTestExecutionData({ - op_type: 'Inverse', - tensor_debug_mode: TensorDebugMode.NO_TENSOR, - debug_tensor_values: null, - }), - }, - }, - }) - ) - ); - fixture.detectChanges(); - - const opTypeElement = fixture.debugElement.query(By.css('.op-type')); - expect(opTypeElement.nativeElement.innerText).toEqual('Inverse'); - const inputTensorsElement = fixture.debugElement.query( - By.css('.input-tensors') - ); - expect(inputTensorsElement.nativeElement.innerText).toEqual('1'); - const outputTensorsElement = fixture.debugElement.query( - By.css('.output-tensors') - ); - expect(outputTensorsElement.nativeElement.innerText).toEqual('1'); - const debugTensorValuesContainers = fixture.debugElement.queryAll( - By.css('.debug-tensor-values-container') - ); - expect(debugTensorValuesContainers.length).toEqual(0); - }); - - it('CURT_HEALTH TensorDebugMode, One Output', () => { - const fixture = TestBed.createComponent(ExecutionDataContainer); - fixture.detectChanges(); - - store.setState( - createState( - createDebuggerState({ - executions: { - numExecutionsLoaded: { - state: DataLoadState.LOADED, - lastLoadedTimeInMs: 111, - }, - executionDigestsLoaded: { - state: DataLoadState.LOADED, - lastLoadedTimeInMs: 222, - pageLoadedSizes: {0: 100}, - numExecutions: 1000, - }, - executionDigests: {}, - pageSize: 100, - displayCount: 50, - scrollBeginIndex: 90, - focusIndex: 98, - executionData: { - 98: createTestExecutionData({ - op_type: 'Inverse', - tensor_debug_mode: TensorDebugMode.CURT_HEALTH, - debug_tensor_values: [[-1, 1]], - }), - }, - }, - }) - ) - ); - fixture.detectChanges(); - - const opTypeElement = fixture.debugElement.query(By.css('.op-type')); - expect(opTypeElement.nativeElement.innerText).toEqual('Inverse'); - const inputTensorsElement = fixture.debugElement.query( - By.css('.input-tensors') - ); - expect(inputTensorsElement.nativeElement.innerText).toEqual('1'); - const outputTensorsElement = fixture.debugElement.query( - By.css('.output-tensors') - ); - expect(outputTensorsElement.nativeElement.innerText).toEqual('1'); - const outputSlotElements = fixture.debugElement.queryAll( - By.css('.output-slot') - ); - expect(outputSlotElements.length).toEqual(1); - expect(outputSlotElements[0].nativeElement.innerText).toEqual('0'); - const anyInfNanElements = fixture.debugElement.queryAll( - By.css('.curt-health-contains-inf-nan') - ); - expect(anyInfNanElements.length).toEqual(1); - expect(anyInfNanElements[0].nativeElement.innerText).toEqual('Yes'); - }); - - it('CONCISE_HEALTH TensorDebugMode, Two Outputs', () => { - const fixture = TestBed.createComponent(ExecutionDataContainer); - fixture.detectChanges(); - - store.setState( - createState( - createDebuggerState({ - executions: { - numExecutionsLoaded: { - state: DataLoadState.LOADED, - lastLoadedTimeInMs: 111, - }, - executionDigestsLoaded: { - state: DataLoadState.LOADED, - lastLoadedTimeInMs: 222, - pageLoadedSizes: {0: 100}, - numExecutions: 1000, - }, - executionDigests: {}, - pageSize: 100, - displayCount: 50, - scrollBeginIndex: 90, - focusIndex: 98, - executionData: { - 98: createTestExecutionData({ - op_type: 'FooOp', - output_tensor_device_ids: ['d0', 'd0'], - output_tensor_ids: [123, 124], - tensor_debug_mode: TensorDebugMode.CONCISE_HEALTH, - debug_tensor_values: [[-1, 100, 0, 0, 0], [-1, 10, 1, 2, 3]], - }), - }, - }, - }) - ) - ); - fixture.detectChanges(); - - const opTypeElement = fixture.debugElement.query(By.css('.op-type')); - expect(opTypeElement.nativeElement.innerText).toEqual('FooOp'); - const inputTensorsElement = fixture.debugElement.query( - By.css('.input-tensors') - ); - expect(inputTensorsElement.nativeElement.innerText).toEqual('1'); - const outputTensorsElement = fixture.debugElement.query( - By.css('.output-tensors') - ); - expect(outputTensorsElement.nativeElement.innerText).toEqual('2'); - const outputSlotElements = fixture.debugElement.queryAll( - By.css('.output-slot') - ); - expect(outputSlotElements.length).toEqual(2); - expect(outputSlotElements[0].nativeElement.innerText).toEqual('0'); - expect(outputSlotElements[1].nativeElement.innerText).toEqual('1'); - const sizeElements = fixture.debugElement.queryAll( - By.css('.concise-health-size') - ); - expect(sizeElements.length).toEqual(2); - expect(sizeElements[0].nativeElement.innerText).toEqual('100'); - expect(sizeElements[1].nativeElement.innerText).toEqual('10'); - const negInfsElements = fixture.debugElement.queryAll( - By.css('.concise-health-neg-infs') - ); - expect(negInfsElements.length).toEqual(2); - expect(negInfsElements[0].nativeElement.innerText).toEqual('0'); - expect(negInfsElements[1].nativeElement.innerText).toEqual('1'); - const posInfsElements = fixture.debugElement.queryAll( - By.css('.concise-health-pos-infs') - ); - expect(posInfsElements.length).toEqual(2); - expect(posInfsElements[0].nativeElement.innerText).toEqual('0'); - expect(posInfsElements[1].nativeElement.innerText).toEqual('2'); - const nanElements = fixture.debugElement.queryAll( - By.css('.concise-health-nans') - ); - expect(nanElements.length).toEqual(2); - expect(nanElements[0].nativeElement.innerText).toEqual('0'); - expect(nanElements[1].nativeElement.innerText).toEqual('3'); - }); - - it('CONCISE_HEALTH TensorDebugMode, Two Outputs, Only One With Data', () => { - const fixture = TestBed.createComponent(ExecutionDataContainer); - fixture.detectChanges(); - - store.setState( - createState( - createDebuggerState({ - executions: { - numExecutionsLoaded: { - state: DataLoadState.LOADED, - lastLoadedTimeInMs: 111, - }, - executionDigestsLoaded: { - state: DataLoadState.LOADED, - lastLoadedTimeInMs: 222, - pageLoadedSizes: {0: 100}, - numExecutions: 1000, - }, - executionDigests: {}, - pageSize: 100, - displayCount: 50, - scrollBeginIndex: 90, - focusIndex: 98, - executionData: { - 98: createTestExecutionData({ - op_type: 'BarOp', - output_tensor_device_ids: ['d0', 'd0'], - output_tensor_ids: [123, 124], - tensor_debug_mode: TensorDebugMode.CONCISE_HEALTH, - // First output slot has no data (e.g., due to non-floating - // dtype). - debug_tensor_values: [null, [-1, 10, 1, 2, 3]], - }), - }, - }, - }) - ) - ); - fixture.detectChanges(); - - const opTypeElement = fixture.debugElement.query(By.css('.op-type')); - expect(opTypeElement.nativeElement.innerText).toEqual('BarOp'); - const inputTensorsElement = fixture.debugElement.query( - By.css('.input-tensors') - ); - expect(inputTensorsElement.nativeElement.innerText).toEqual('1'); - const outputTensorsElement = fixture.debugElement.query( - By.css('.output-tensors') - ); - expect(outputTensorsElement.nativeElement.innerText).toEqual('2'); - const outputSlotElements = fixture.debugElement.queryAll( - By.css('.output-slot') - ); - expect(outputSlotElements.length).toEqual(2); - expect(outputSlotElements[0].nativeElement.innerText).toEqual('0'); - expect(outputSlotElements[1].nativeElement.innerText).toEqual('1'); - const sizeElements = fixture.debugElement.queryAll( - By.css('.concise-health-size') - ); - expect(sizeElements.length).toEqual(1); - expect(sizeElements[0].nativeElement.innerText).toEqual('10'); - const negInfsElements = fixture.debugElement.queryAll( - By.css('.concise-health-neg-infs') - ); - expect(negInfsElements.length).toEqual(1); - expect(negInfsElements[0].nativeElement.innerText).toEqual('1'); - const posInfsElements = fixture.debugElement.queryAll( - By.css('.concise-health-pos-infs') - ); - expect(posInfsElements.length).toEqual(1); - expect(posInfsElements[0].nativeElement.innerText).toEqual('2'); - const nanElements = fixture.debugElement.queryAll( - By.css('.concise-health-nans') - ); - expect(nanElements.length).toEqual(1); - expect(nanElements[0].nativeElement.innerText).toEqual('3'); - }); - - it('FULL_HEALTH TensorDebugMode, One outputs', () => { - const fixture = TestBed.createComponent(ExecutionDataContainer); - fixture.detectChanges(); - - store.setState( - createState( - createDebuggerState({ - executions: { - numExecutionsLoaded: { - state: DataLoadState.LOADED, - lastLoadedTimeInMs: 111, - }, - executionDigestsLoaded: { - state: DataLoadState.LOADED, - lastLoadedTimeInMs: 222, - pageLoadedSizes: {0: 100}, - numExecutions: 1000, - }, - executionDigests: {}, - pageSize: 100, - displayCount: 50, - scrollBeginIndex: 90, - focusIndex: 98, - executionData: { - 98: createTestExecutionData({ - op_type: 'FooOp', - output_tensor_device_ids: ['d0'], - output_tensor_ids: [123], - tensor_debug_mode: TensorDebugMode.FULL_HEALTH, - debug_tensor_values: [ - // [tensor_id, device_id, dtype, rank, element_count, - // neg_inf_count, pos_inf_count, nan_count, - // neg_finite_count, zero_count, pos_finite_count]. - [-1, -1, 1, 2, 6, 0, 0, 1, 2, 3, 0], - ], - }), - }, - }, - }) - ) - ); - fixture.detectChanges(); - - const opTypeElement = fixture.debugElement.query(By.css('.op-type')); - expect(opTypeElement.nativeElement.innerText).toEqual('FooOp'); - const inputTensorsElement = fixture.debugElement.query( - By.css('.input-tensors') - ); - expect(inputTensorsElement.nativeElement.innerText).toEqual('1'); - const outputTensorsElement = fixture.debugElement.query( - By.css('.output-tensors') - ); - expect(outputTensorsElement.nativeElement.innerText).toEqual('1'); - const outputSlotElements = fixture.debugElement.queryAll( - By.css('.output-slot') - ); - expect(outputSlotElements.length).toEqual(1); - expect(outputSlotElements[0].nativeElement.innerText).toEqual('0'); - const dtypeElements = fixture.debugElement.queryAll( - By.css('.full-health-dtype') - ); - expect(dtypeElements.length).toEqual(1); - expect(dtypeElements[0].nativeElement.innerText).toEqual('float32'); - const rankElements = fixture.debugElement.queryAll( - By.css('.full-health-rank') - ); - expect(rankElements.length).toEqual(1); - expect(rankElements[0].nativeElement.innerText).toEqual('2'); - const sizeElements = fixture.debugElement.queryAll( - By.css('.full-health-size') - ); - expect(sizeElements.length).toEqual(1); - expect(sizeElements[0].nativeElement.innerText).toEqual('6'); - const negInfElements = fixture.debugElement.queryAll( - By.css('.full-health-neg-inf') - ); - expect(negInfElements.length).toEqual(1); - expect(negInfElements[0].nativeElement.innerText).toEqual('0'); - const posInfElements = fixture.debugElement.queryAll( - By.css('.full-health-pos-inf') - ); - expect(posInfElements.length).toEqual(1); - expect(posInfElements[0].nativeElement.innerText).toEqual('0'); - const nanElements = fixture.debugElement.queryAll( - By.css('.full-health-nan') - ); - expect(nanElements.length).toEqual(1); - expect(nanElements[0].nativeElement.innerText).toEqual('1'); - const negFiniteElements = fixture.debugElement.queryAll( - By.css('.full-health-neg-finite') - ); - expect(negFiniteElements.length).toEqual(1); - expect(negFiniteElements[0].nativeElement.innerText).toEqual('2'); - const zeroElements = fixture.debugElement.queryAll( - By.css('.full-health-zero') - ); - expect(zeroElements.length).toEqual(1); - expect(zeroElements[0].nativeElement.innerText).toEqual('3'); - const posFiniteElements = fixture.debugElement.queryAll( - By.css('.full-health-pos-finite') - ); - expect(posFiniteElements.length).toEqual(1); - expect(posFiniteElements[0].nativeElement.innerText).toEqual('0'); - }); - - it('SHAPE TensorDebugMode, Two Outputs', () => { - const fixture = TestBed.createComponent(ExecutionDataContainer); - fixture.detectChanges(); - - store.setState( - createState( - createDebuggerState({ - executions: { - numExecutionsLoaded: { - state: DataLoadState.LOADED, - lastLoadedTimeInMs: 111, - }, - executionDigestsLoaded: { - state: DataLoadState.LOADED, - lastLoadedTimeInMs: 222, - pageLoadedSizes: {0: 100}, - numExecutions: 1000, - }, - executionDigests: {}, - pageSize: 100, - displayCount: 50, - scrollBeginIndex: 90, - focusIndex: 98, - executionData: { - 98: createTestExecutionData({ - op_type: 'FooOp', - output_tensor_device_ids: ['d0', 'd0'], - output_tensor_ids: [123, 124], - tensor_debug_mode: TensorDebugMode.SHAPE, - debug_tensor_values: [ - [-1, 1, 0, 1, 0, 0, 0, 0, 0, 0], - // Use -1337 dtype enum value to test the unknown-dtype logic. - [-1, -1337, 2, 20, 4, 5, 0, 0, 0, 0], - ], - }), - }, - }, - }) - ) - ); - fixture.detectChanges(); - - const opTypeElement = fixture.debugElement.query(By.css('.op-type')); - expect(opTypeElement.nativeElement.innerText).toEqual('FooOp'); - const inputTensorsElement = fixture.debugElement.query( - By.css('.input-tensors') - ); - expect(inputTensorsElement.nativeElement.innerText).toEqual('1'); - const outputTensorsElement = fixture.debugElement.query( - By.css('.output-tensors') - ); - expect(outputTensorsElement.nativeElement.innerText).toEqual('2'); - const outputSlotElements = fixture.debugElement.queryAll( - By.css('.output-slot') - ); - expect(outputSlotElements.length).toEqual(2); - expect(outputSlotElements[0].nativeElement.innerText).toEqual('0'); - expect(outputSlotElements[1].nativeElement.innerText).toEqual('1'); - const dtypeElements = fixture.debugElement.queryAll( - By.css('.shape-dtype') - ); - expect(dtypeElements.length).toEqual(2); - expect(dtypeElements[0].nativeElement.innerText).toEqual('float32'); - expect(dtypeElements[1].nativeElement.innerText).toEqual('Unknown dtype'); - const rankElements = fixture.debugElement.queryAll(By.css('.shape-rank')); - expect(rankElements.length).toEqual(2); - expect(rankElements[0].nativeElement.innerText).toEqual('0'); - expect(rankElements[1].nativeElement.innerText).toEqual('2'); - const sizeElements = fixture.debugElement.queryAll(By.css('.shape-size')); - expect(sizeElements.length).toEqual(2); - expect(sizeElements[0].nativeElement.innerText).toEqual('1'); - expect(sizeElements[1].nativeElement.innerText).toEqual('20'); - const shapeElements = fixture.debugElement.queryAll( - By.css('.shape-shape') - ); - expect(shapeElements.length).toEqual(2); - expect(shapeElements[0].nativeElement.innerText).toEqual('()'); - expect(shapeElements[1].nativeElement.innerText).toEqual('(4,5)'); - }); - }); - describe('Stack Trace module', () => { it('Shows non-empty stack frames correctly', () => { const fixture = TestBed.createComponent(StackTraceContainer); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts index f735bb4af59..405ce9afbb8 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts @@ -93,7 +93,7 @@ export class DebugTensorRankComponent { ×{{ numZeros }}
+ diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/BUILD index e65580b3c84..a15f09e2a70 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/BUILD @@ -19,7 +19,9 @@ ng_module( "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin:tf_types", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:debug_tensor_value", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value", "@npm//@angular/common", "@npm//@angular/core", "@npm//@ngrx/store", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.css index 0957ac2e5c0..1e27c0c4b98 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.css @@ -13,12 +13,6 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -.debug-tensor-values-container { - height: 60px; - overflow-x: auto; - overflow-y: auto; -} - .debug-tensor-values-table { width: 100%; } @@ -57,6 +51,29 @@ limitations under the License. width: 360px; } +.output-slots { + height: 60px; + overflow-x: auto; + overflow-y: auto; +} + +.output-slot-container { + border-top: 1px solid rgba(0, 0, 0, 0.12); + margin-top: 5px; + padding: 2px 0; + vertical-align: top; +} + +.output-slot-number { + display: block; + font-family: 'Roboto Mono', monospace; +} + +.output-slot-debug-tensor-value { + display: block; + margin: 3px 0 3px 30px; +} + .output-tensors { margin-top: 5px; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ng.html index 4cc5066cf34..e7a8d5190a4 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ng.html @@ -18,7 +18,7 @@
- Execution #{{ focusedExecutionIndex }} + Eager Execution #{{ focusedExecutionIndex }}
@@ -58,210 +58,22 @@
-
-
-
- - - - - - - - - -
SlotContains inf/nan?
- {{ i }} - - {{ singleDebugTensorValues[1] ? "Yes" : "No" }} -
+
+
+
+ Output slot {{ i }}:
- -
- - - - - - - - - - - - - - - -
SlotSize#(-inf)#(inf)#(nan)
- {{ i }} - - {{ singleDebugTensorValues[1] }} - - {{ singleDebugTensorValues[2] }} - - {{ singleDebugTensorValues[3] }} - - {{ singleDebugTensorValues[4] }} -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - -
SlotDTypeRankSize#(-inf)#(inf)#(nan)#(-)#(+)#(0)
- {{ i }} - - - {{ debugTensorDtypes[i] }} - - - {{ singleDebugTensorValues[3] }} - - {{ singleDebugTensorValues[4] }} - - {{ singleDebugTensorValues[5] }} - - {{ singleDebugTensorValues[6] }} - - {{ singleDebugTensorValues[7] }} - - {{ singleDebugTensorValues[8] }} - - {{ singleDebugTensorValues[9] }} - - {{ singleDebugTensorValues[10] }} -
+
+ +
- -
- - - - - - - - - - - - - - - -
SlotDTypeRankSizeShape
- {{ i }} - - - {{ debugTensorDtypes[i] }} - - - {{ singleDebugTensorValues[2] }} - - {{ singleDebugTensorValues[3] }} - - ({{ singleDebugTensorValues.slice(4, 4 + - singleDebugTensorValues[2]) }}) -
-
- - -
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ts index a945b7f144e..ad3ac9824bf 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ts @@ -15,6 +15,7 @@ limitations under the License. import {Component, Input} from '@angular/core'; import {Execution, TensorDebugMode} from '../../store/debugger_types'; +import {parseDebugTensorValue} from '../../store/debug_tensor_value'; @Component({ selector: 'execution-data-component', @@ -51,4 +52,5 @@ export class ExecutionDataComponent { // So that the enum can be used in the template html. public TensorDebugMode = TensorDebugMode; + parseDebugTensorValue = parseDebugTensorValue; } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_module.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_module.ts index f524e3b505e..e8d69218042 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_module.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_module.ts @@ -16,12 +16,13 @@ limitations under the License. import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; +import {DebugTensorValueModule} from '../debug_tensor_value/debug_tensor_value_module'; import {ExecutionDataComponent} from './execution_data_component'; import {ExecutionDataContainer} from './execution_data_container'; @NgModule({ declarations: [ExecutionDataComponent, ExecutionDataContainer], - imports: [CommonModule], + imports: [CommonModule, DebugTensorValueModule], exports: [ExecutionDataContainer], }) export class ExecutionDataModule {} From 7f71cbb6c642d1fd1a6c343cf580f05cc19a4a2a Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 22 Apr 2020 17:23:03 -0400 Subject: [PATCH 21/29] Adding unit tests for debug-tensor-value components --- .../debugger_v2/tf_debugger_v2_plugin/BUILD | 1 + .../debugger_container_test.ts | 6 +- .../views/debug_tensor_value/BUILD | 48 ++++++-------- .../debug_tensor_value_component.ts | 5 +- .../debug_tensor_value_component_test.ts | 64 +++++++++++++++++++ 5 files changed, 87 insertions(+), 37 deletions(-) create mode 100644 tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD index 15cb1ad18bd..0a21c073660 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/BUILD @@ -78,6 +78,7 @@ tf_ng_web_test_suite( "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/effects:debugger_effects_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:debugger_store_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/alerts:alerts_container_test_lib", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value:debug_tensor_value_component_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions:graph_executions_container_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code:source_code_container_test_lib", "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_code:source_code_test_lib", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts index f50904ce71d..335e74a3e4f 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts @@ -31,11 +31,7 @@ import { } from './actions'; import {DebuggerComponent} from './debugger_component'; import {DebuggerContainer} from './debugger_container'; -import { - DataLoadState, - State, - AlertType, -} from './store/debugger_types'; +import {DataLoadState, State, AlertType} from './store/debugger_types'; import { createAlertsState, createDebuggerState, diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD index a88d58171d3..6d93073428d 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD @@ -18,33 +18,21 @@ ng_module( ], ) -# tf_ts_library( -# name = "alerts_container_test_lib", -# testonly = True, -# srcs = [ -# "alerts_container_test.ts", -# ], -# tsconfig = "//:tsconfig-test", -# deps = [ -# ":alerts", -# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin:debugger_v2", -# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/actions", -# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store", -# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", -# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/testing", -# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data", -# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions", -# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/inactive", -# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/source_files", -# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/stack_trace", -# "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/timeline", -# "//tensorboard/webapp/angular:expect_angular_core_testing", -# "//tensorboard/webapp/angular:expect_ngrx_store_testing", -# "@npm//@angular/common", -# "@npm//@angular/compiler", -# "@npm//@angular/core", -# "@npm//@angular/platform-browser", -# "@npm//@ngrx/store", -# "@npm//@types/jasmine", -# ], -# ) +tf_ts_library( + name = "debug_tensor_value_component_test_lib", + testonly = True, + srcs = [ + "debug_tensor_value_component_test.ts", + ], + tsconfig = "//:tsconfig-test", + deps = [ + ":debug_tensor_value", + "//tensorboard/webapp/angular:expect_angular_core_testing", + "//tensorboard/webapp/angular:expect_ngrx_store_testing", + "@npm//@angular/common", + "@npm//@angular/compiler", + "@npm//@angular/core", + "@npm//@angular/platform-browser", + "@npm//@types/jasmine", + ], +) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts index 405ce9afbb8..8f15510a942 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts @@ -45,7 +45,7 @@ export class DebugTensorDTypeComponent { @Component({ selector: 'debug-tensor-rank', template: ` - {{ rank }}D + {{ rank }}D `, styles: [basicDebugInfoStyle], }) @@ -93,7 +93,8 @@ export class DebugTensorRankComponent { ×{{ numZeros }}
+ diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts new file mode 100644 index 00000000000..86e30583f6e --- /dev/null +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts @@ -0,0 +1,64 @@ +/* Copyright 2020 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. +==============================================================================*/ +/** + * Unit tests for the the DebugTensorValue Angular component. + */ + +import {TestBed} from '@angular/core/testing'; +import {By} from '@angular/platform-browser'; + +import { + DebugTensorDTypeComponent, + DebugTensorRankComponent, +} from './debug_tensor_value_component'; + +fdescribe('debug-tensor-value components', () => { + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [DebugTensorDTypeComponent, DebugTensorRankComponent], + }).compileComponents(); + }); + + describe('DebugTensorDTypeComponent', () => { + it('displays correct dtype', () => { + const fixture = TestBed.createComponent(DebugTensorDTypeComponent); + const component = fixture.componentInstance; + component.dtype = 'bfloat16'; + fixture.detectChanges(); + const dtypeNameElement = fixture.debugElement.query( + By.css('.dtype-name') + ); + expect(dtypeNameElement.nativeElement.innerText).toBe('bfloat16'); + }); + }); + + describe('DebugTensorRankComponent', () => { + for (const [rank, expectedDimText] of [ + [0, '0D'], + [1, '1D'], + [2, '2D'], + [6, '6D'], + ] as Array<[number, string]>) { + it(`displays correct rank=${rank}`, () => { + const fixture = TestBed.createComponent(DebugTensorRankComponent); + const component = fixture.componentInstance; + component.rank = rank; + fixture.detectChanges(); + const rankElement = fixture.debugElement.query(By.css('.rank-name')); + expect(rankElement.nativeElement.innerText).toBe(expectedDimText); + }); + } + }); +}); From 606f80fbdb0401f31ad5dc2dc2e6f57f1ecca5a4 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 22 Apr 2020 23:12:12 -0400 Subject: [PATCH 22/29] Add more unit tests for debug-tensor-value components --- .../views/debug_tensor_value/BUILD | 2 + .../debug_tensor_value_component.ts | 62 ++--- .../debug_tensor_value_component_test.ts | 224 +++++++++++++++++- 3 files changed, 253 insertions(+), 35 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD index 6d93073428d..741fa820f3e 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD @@ -27,6 +27,8 @@ tf_ts_library( tsconfig = "//:tsconfig-test", deps = [ ":debug_tensor_value", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:debug_tensor_value", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", "//tensorboard/webapp/angular:expect_angular_core_testing", "//tensorboard/webapp/angular:expect_ngrx_store_testing", "@npm//@angular/common", diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts index 8f15510a942..7f93c183e50 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts @@ -45,7 +45,7 @@ export class DebugTensorDTypeComponent { @Component({ selector: 'debug-tensor-rank', template: ` - {{ rank }}D + {{ rank }}D `, styles: [basicDebugInfoStyle], }) @@ -54,6 +54,30 @@ export class DebugTensorRankComponent { rank!: number; } +@Component({ + selector: 'debug-tensor-shape', + template: ` + shape:{{ shapeString }} + `, + styles: [basicDebugInfoStyle], +}) +export class DebugTensorShapeComponent { + @Input() + shape!: Array; + + get shapeString(): string { + return ( + '[' + + this.shape + .map((dim) => { + return dim === undefined ? '?' : String(dim); + }) + .join(',') + + ']' + ); + } +} + @Component({ selector: 'debug-tensor-numeric-breakdown', template: ` @@ -65,32 +89,32 @@ export class DebugTensorRankComponent {
NaN - ×{{ numNaNs }} + ×{{ numNaNs }}
-∞ - ×{{ numNegativeInfs }} + ×{{ numNegativeInfs }}
+∞ - ×{{ numPositiveInfs }} + ×{{ numPositiveInfs }}
- - ×{{ numNegativeFinites }} + ×{{ numNegativeFinites }}
0 - ×{{ numZeros }} + ×{{ numZeros }}
+ - ×{{ numPositiveFinites }} + ×{{ numPositiveFinites }}
`, @@ -188,30 +212,6 @@ export class DebugTensorNumericBreakdownComponent { } } -@Component({ - selector: 'debug-tensor-shape', - template: ` - shape:{{ shapeString }} - `, - styles: [basicDebugInfoStyle], -}) -export class DebugTensorShapeComponent { - @Input() - shape!: Array; - - get shapeString(): string { - return ( - '[' + - this.shape - .map((dim) => { - return dim === undefined ? '?' : String(dim); - }) - .join(',') + - ']' - ); - } -} - @Component({ selector: 'debug-tensor-has-inf-or-nan', template: ` diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts index 86e30583f6e..266da9cf653 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts @@ -19,15 +19,28 @@ limitations under the License. import {TestBed} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; +import {parseDebugTensorValue} from '../../store/debug_tensor_value'; +import {TensorDebugMode} from '../../store/debugger_types'; import { DebugTensorDTypeComponent, + DebugTensorHasInfOrNaNComponent, + DebugTensorNumericBreakdownComponent, DebugTensorRankComponent, + DebugTensorShapeComponent, + DebugTensorValueComponent, } from './debug_tensor_value_component'; -fdescribe('debug-tensor-value components', () => { +describe('debug-tensor-value components', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [DebugTensorDTypeComponent, DebugTensorRankComponent], + declarations: [ + DebugTensorDTypeComponent, + DebugTensorHasInfOrNaNComponent, + DebugTensorNumericBreakdownComponent, + DebugTensorRankComponent, + DebugTensorShapeComponent, + DebugTensorValueComponent, + ], }).compileComponents(); }); @@ -56,9 +69,212 @@ fdescribe('debug-tensor-value components', () => { const component = fixture.componentInstance; component.rank = rank; fixture.detectChanges(); - const rankElement = fixture.debugElement.query(By.css('.rank-name')); - expect(rankElement.nativeElement.innerText).toBe(expectedDimText); + expect(fixture.nativeElement.innerText).toBe(expectedDimText); }); } }); + + describe('DebugTensorShapeComponent', () => { + for (const [shape, expectedShapeText] of [ + [[], 'shape:[]'], + [[30], 'shape:[30]'], + [[4, 5], 'shape:[4,5]'], + [[1, 4, 5], 'shape:[1,4,5]'], + [[1, 3, 3, 7], 'shape:[1,3,3,7]'], + [[1, 2, 3, 4, 5], 'shape:[1,2,3,4,5]'], + [[0, 1, 2, 3, 4, 5], 'shape:[0,1,2,3,4,5]'], + [[undefined, undefined, 1, 3, 3, 7, 10, 20], 'shape:[?,?,1,3,3,7,10,20]'], + ] as Array<[Array, string]>) { + it(`displays correct shape: ${JSON.stringify(expectedShapeText)}`, () => { + const fixture = TestBed.createComponent(DebugTensorShapeComponent); + const component = fixture.componentInstance; + component.shape = shape; + fixture.detectChanges(); + expect(fixture.nativeElement.innerText).toBe(expectedShapeText); + }); + } + }); + + describe('DebugTensorNumericBreakdownComponent', () => { + it('No breakdown available: displays size only', () => { + const fixture = TestBed.createComponent( + DebugTensorNumericBreakdownComponent + ); + const component = fixture.componentInstance; + component.size = 345; + fixture.detectChanges(); + const sizeElement = fixture.debugElement.query(By.css('.size-value')); + expect(sizeElement.nativeElement.innerText).toBe('345'); + const breakdownElement = fixture.debugElement.query(By.css('.breakdown')); + expect(breakdownElement).toBeNull(); + }); + + it('displays size and number of finite elements', () => { + const fixture = TestBed.createComponent( + DebugTensorNumericBreakdownComponent + ); + const component = fixture.componentInstance; + component.size = 345; + component.numNegativeFinites = 300; + component.numZeros = 40; + component.numPositiveFinites = 5; + fixture.detectChanges(); + const sizeElement = fixture.debugElement.query(By.css('.size-value')); + expect(sizeElement.nativeElement.innerText).toBe('345'); + const breakdownElement = fixture.debugElement.query(By.css('.breakdown')); + expect(breakdownElement).not.toBeNull(); + const tagElements = fixture.debugElement.queryAll( + By.css('.category-tag') + ); + const countElements = fixture.debugElement.queryAll( + By.css('.category-count') + ); + expect(tagElements.length).toEqual(3); + expect(countElements.length).toEqual(3); + expect(tagElements[0].nativeElement.innerText).toBe('-'); + expect(countElements[0].nativeElement.innerText).toBe('×300'); + expect(tagElements[1].nativeElement.innerText).toBe('0'); + expect(countElements[1].nativeElement.innerText).toBe('×40'); + expect(tagElements[2].nativeElement.innerText).toBe('+'); + expect(countElements[2].nativeElement.innerText).toBe('×5'); + }); + + it('displays size and number of infinite elements', () => { + const fixture = TestBed.createComponent( + DebugTensorNumericBreakdownComponent + ); + const component = fixture.componentInstance; + component.size = 345; + component.numNaNs = 300; + component.numNegativeInfs = 40; + component.numPositiveInfs = 5; + fixture.detectChanges(); + const sizeElement = fixture.debugElement.query(By.css('.size-value')); + expect(sizeElement.nativeElement.innerText).toBe('345'); + const breakdownElement = fixture.debugElement.query(By.css('.breakdown')); + expect(breakdownElement).not.toBeNull(); + const tagElements = fixture.debugElement.queryAll( + By.css('.category-tag') + ); + const countElements = fixture.debugElement.queryAll( + By.css('.category-count') + ); + expect(tagElements.length).toEqual(3); + expect(countElements.length).toEqual(3); + expect(tagElements[0].nativeElement.innerText).toBe('NaN'); + expect(countElements[0].nativeElement.innerText).toBe('×300'); + expect(tagElements[1].nativeElement.innerText).toBe('-∞'); + expect(countElements[1].nativeElement.innerText).toBe('×40'); + expect(tagElements[2].nativeElement.innerText).toBe('+∞'); + expect(countElements[2].nativeElement.innerText).toBe('×5'); + }); + }); + + describe('DebugTensorHasInfOrNaNComponent', () => { + it('displays no inf or nan', () => { + const fixture = TestBed.createComponent(DebugTensorHasInfOrNaNComponent); + const component = fixture.componentInstance; + component.hasInfOrNaN = false; + fixture.detectChanges(); + expect(fixture.nativeElement.innerText).toBe('No ∞/NaN'); + }); + + it('displays has inf or nan', () => { + const fixture = TestBed.createComponent(DebugTensorHasInfOrNaNComponent); + const component = fixture.componentInstance; + component.hasInfOrNaN = true; + fixture.detectChanges(); + expect(fixture.nativeElement.innerText).toBe('Has ∞/NaN'); + }); + }); + + describe('DebugTensorValueComponent', () => { + it('displays CURT_HEALTH data', () => { + const fixture = TestBed.createComponent(DebugTensorValueComponent); + const component = fixture.componentInstance; + component.debugTensorValue = parseDebugTensorValue( + TensorDebugMode.CURT_HEALTH, + [123, 0] + ); + fixture.detectChanges(); + expect( + fixture.debugElement.query(By.css('debug-tensor-has-inf-or-nan')) + ).not.toBeNull(); + expect( + fixture.debugElement.query(By.css('debug-tensor-dtype')) + ).toBeNull(); + expect( + fixture.debugElement.query(By.css('debug-tensor-shape')) + ).toBeNull(); + expect( + fixture.debugElement.query(By.css('debug-tensor-numeric-breakdown')) + ).toBeNull(); + }); + + it('displays CONCISE_HEALTH data', () => { + const fixture = TestBed.createComponent(DebugTensorValueComponent); + const component = fixture.componentInstance; + component.debugTensorValue = parseDebugTensorValue( + TensorDebugMode.CONCISE_HEALTH, + [123, 345, 300, 40, 5] + ); + fixture.detectChanges(); + expect( + fixture.debugElement.query(By.css('debug-tensor-has-inf-or-nan')) + ).toBeNull(); + expect( + fixture.debugElement.query(By.css('debug-tensor-dtype')) + ).toBeNull(); + expect( + fixture.debugElement.query(By.css('debug-tensor-shape')) + ).toBeNull(); + expect( + fixture.debugElement.query(By.css('debug-tensor-numeric-breakdown')) + ).not.toBeNull(); + }); + + it('displays SHAPE data', () => { + const fixture = TestBed.createComponent(DebugTensorValueComponent); + const component = fixture.componentInstance; + component.debugTensorValue = parseDebugTensorValue( + TensorDebugMode.SHAPE, + [123, 5, 7, 1200, 3, 4, 1, 2, 1, 5] + ); + fixture.detectChanges(); + expect( + fixture.debugElement.query(By.css('debug-tensor-has-inf-or-nan')) + ).toBeNull(); + expect( + fixture.debugElement.query(By.css('debug-tensor-dtype')) + ).not.toBeNull(); + expect( + fixture.debugElement.query(By.css('debug-tensor-shape')) + ).not.toBeNull(); + expect( + fixture.debugElement.query(By.css('debug-tensor-numeric-breakdown')) + ).not.toBeNull(); + }); + + it('displays FULL_HEALTH data', () => { + const fixture = TestBed.createComponent(DebugTensorValueComponent); + const component = fixture.componentInstance; + component.debugTensorValue = parseDebugTensorValue( + TensorDebugMode.FULL_HEALTH, + [123, 0, 1, 2, 600, 0, 0, 0, 100, 200, 300] + ); + fixture.detectChanges(); + expect( + fixture.debugElement.query(By.css('debug-tensor-has-inf-or-nan')) + ).toBeNull(); + expect( + fixture.debugElement.query(By.css('debug-tensor-dtype')) + ).not.toBeNull(); + expect( + fixture.debugElement.query(By.css('debug-tensor-shape')) + ).toBeNull(); + expect( + fixture.debugElement.query(By.css('debug-tensor-numeric-breakdown')) + ).not.toBeNull(); + }); + }); }); From c4ab22c86cb5fdd580af04d2a25caff1b3692fdd Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 22 Apr 2020 23:31:26 -0400 Subject: [PATCH 23/29] Add more unit tests --- .../debugger_container_test.ts | 132 +++++++++++++++++- .../graph_executions_component.ng.html | 5 - .../graph_executions_container_test.ts | 12 +- 3 files changed, 142 insertions(+), 7 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts index 335e74a3e4f..5ab71389d34 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/debugger_container_test.ts @@ -31,7 +31,12 @@ import { } from './actions'; import {DebuggerComponent} from './debugger_component'; import {DebuggerContainer} from './debugger_container'; -import {DataLoadState, State, AlertType} from './store/debugger_types'; +import { + DataLoadState, + State, + AlertType, + TensorDebugMode, +} from './store/debugger_types'; import { createAlertsState, createDebuggerState, @@ -42,6 +47,7 @@ import { createTestStackFrame, } from './testing'; import {AlertsModule} from './views/alerts/alerts_module'; +import {ExecutionDataContainer} from './views/execution_data/execution_data_container'; import {ExecutionDataModule} from './views/execution_data/execution_data_module'; import {GraphExecutionsModule} from './views/graph_executions/graph_executions_module'; import {InactiveModule} from './views/inactive/inactive_module'; @@ -428,6 +434,130 @@ describe('Debugger Container', () => { }); } + describe('Execution Data module', () => { + it('CURT_HEALTH TensorDebugMode, One Output', () => { + const fixture = TestBed.createComponent(ExecutionDataContainer); + fixture.detectChanges(); + + store.setState( + createState( + createDebuggerState({ + executions: { + numExecutionsLoaded: { + state: DataLoadState.LOADED, + lastLoadedTimeInMs: 111, + }, + executionDigestsLoaded: { + state: DataLoadState.LOADED, + lastLoadedTimeInMs: 222, + pageLoadedSizes: {0: 100}, + numExecutions: 1000, + }, + executionDigests: {}, + pageSize: 100, + displayCount: 50, + scrollBeginIndex: 90, + focusIndex: 98, + executionData: { + 98: createTestExecutionData({ + op_type: 'Inverse', + tensor_debug_mode: TensorDebugMode.CURT_HEALTH, + debug_tensor_values: [[0, 1]], + }), + }, + }, + }) + ) + ); + fixture.detectChanges(); + + const opTypeElement = fixture.debugElement.query(By.css('.op-type')); + expect(opTypeElement.nativeElement.innerText).toEqual('Inverse'); + const inputTensorsElement = fixture.debugElement.query( + By.css('.input-tensors') + ); + expect(inputTensorsElement.nativeElement.innerText).toEqual('1'); + const outputTensorsElement = fixture.debugElement.query( + By.css('.output-tensors') + ); + expect(outputTensorsElement.nativeElement.innerText).toEqual('1'); + const outputSlotElements = fixture.debugElement.queryAll( + By.css('.output-slot-number') + ); + expect(outputSlotElements.length).toBe(1); + expect(outputSlotElements[0].nativeElement.innerText).toBe( + 'Output slot 0:' + ); + const debugTensorValueElements = fixture.debugElement.queryAll( + By.css('debug-tensor-value') + ); + expect(debugTensorValueElements.length).toBe(1); + }); + + it('CURT_HEALTH TensorDebugMode, Two Outputs', () => { + const fixture = TestBed.createComponent(ExecutionDataContainer); + fixture.detectChanges(); + + store.setState( + createState( + createDebuggerState({ + executions: { + numExecutionsLoaded: { + state: DataLoadState.LOADED, + lastLoadedTimeInMs: 111, + }, + executionDigestsLoaded: { + state: DataLoadState.LOADED, + lastLoadedTimeInMs: 222, + pageLoadedSizes: {0: 100}, + numExecutions: 1000, + }, + executionDigests: {}, + pageSize: 100, + displayCount: 50, + scrollBeginIndex: 90, + focusIndex: 98, + executionData: { + 98: createTestExecutionData({ + op_type: 'Inverse', + output_tensor_ids: [10, 11], + tensor_debug_mode: TensorDebugMode.CURT_HEALTH, + debug_tensor_values: [[0, 0], [0, 1]], + }), + }, + }, + }) + ) + ); + fixture.detectChanges(); + + const opTypeElement = fixture.debugElement.query(By.css('.op-type')); + expect(opTypeElement.nativeElement.innerText).toEqual('Inverse'); + const inputTensorsElement = fixture.debugElement.query( + By.css('.input-tensors') + ); + expect(inputTensorsElement.nativeElement.innerText).toEqual('1'); + const outputTensorsElement = fixture.debugElement.query( + By.css('.output-tensors') + ); + expect(outputTensorsElement.nativeElement.innerText).toEqual('2'); + const outputSlotElements = fixture.debugElement.queryAll( + By.css('.output-slot-number') + ); + expect(outputSlotElements.length).toBe(2); + expect(outputSlotElements[0].nativeElement.innerText).toBe( + 'Output slot 0:' + ); + expect(outputSlotElements[1].nativeElement.innerText).toBe( + 'Output slot 1:' + ); + const debugTensorValueElements = fixture.debugElement.queryAll( + By.css('debug-tensor-value') + ); + expect(debugTensorValueElements.length).toBe(2); + }); + }); + describe('Stack Trace module', () => { it('Shows non-empty stack frames correctly', () => { const fixture = TestBed.createComponent(StackTraceContainer); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html index cd2b461ad94..51bdb18e7e1 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html @@ -45,10 +45,6 @@
- -
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts index 6e6749f057d..2eab240d676 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_container_test.ts @@ -24,7 +24,11 @@ import {MockStore, provideMockStore} from '@ngrx/store/testing'; import {DebuggerComponent} from '../../debugger_component'; import {DebuggerContainer} from '../../debugger_container'; -import {State, GraphExecution} from '../../store/debugger_types'; +import { + State, + GraphExecution, + TensorDebugMode, +} from '../../store/debugger_types'; import {getNumGraphExecutions, getGraphExecutionData} from '../../store'; import { createDebuggerState, @@ -92,6 +96,8 @@ describe('Graph Executions Container', () => { graphExecutionData[i] = createTestGraphExecution({ op_name: `TestOp_${i}`, op_type: `OpType_${i}`, + tensor_debug_mode: TensorDebugMode.CONCISE_HEALTH, + debug_tensor_value: [i, 100, 0, 0, 0], }); } store.overrideSelector(getGraphExecutionData, graphExecutionData); @@ -123,6 +129,10 @@ describe('Graph Executions Container', () => { expect(tensorNames[i].nativeElement.innerText).toBe(`TestOp_${i}:0`); expect(opTypes[i].nativeElement.innerText).toBe(`OpType_${i}`); } + const debugTensorValueElements = fixture.debugElement.queryAll( + By.css('debug-tensor-value') + ); + expect(debugTensorValueElements.length).toBe(tensorContainers.length); })); it('renders # execs and execs viewport if # execs > 0; not loaded', fakeAsync(() => { From 0dc32819b74713d62c1e89f4b86fbb8213054aba Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 22 Apr 2020 23:51:33 -0400 Subject: [PATCH 24/29] Fix typos --- .../tf_debugger_v2_plugin/store/debug_tensor_value.ts | 4 ++-- .../tf_debugger_v2_plugin/store/debug_tensor_value_test.ts | 6 +++--- .../tf_debugger_v2_plugin/store/debugger_types.ts | 2 +- .../debug_tensor_value/debug_tensor_value_component.ts | 2 +- .../debug_tensor_value/debug_tensor_value_component_test.ts | 6 ++---- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts index 495ee0eb56d..e6f57df6033 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts @@ -23,12 +23,12 @@ import {DebugTensorValue, TensorDebugMode} from './debugger_types'; * @param tensorDebugMode Tensor-debug mode. * @param array The array of number that represents various aspect of the * instrumented tensor. The semantics of the numbers are determined by - * `tensorDebugModel`. + * `tensorDebugMode`. * @returns A DebugTensorValue object with the same information as * carried by `array`, but represented in a more explicit fashion. * For numbers that represent breakdown of numeric values by type * (e.g., counts of -inf, +inf and nan), the corresponding fields - * in the returned object will be defined only of the count is non-zero. + * in the returned object will be defined only if the count is non-zero. */ export function parseDebugTensorValue( tensorDebugMode: TensorDebugMode, diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts index d05b514fe1d..310e0550d4d 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts @@ -201,7 +201,7 @@ describe('parseDebugTensorValue', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ 123, 5, // int16 - 7, // rankk 8 + 7, // rank 7 1200, 3, 4, @@ -223,7 +223,7 @@ describe('parseDebugTensorValue', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ 123, 1, // float32 - 8, // rankk 8 + 8, // rank 8 1200, 3, 4, @@ -293,7 +293,7 @@ describe('parseDebugTensorValue', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.FULL_HEALTH, [ 123, 0, - 14, // bfloat64. + 14, // bfloat16 1, // rank 10, // size 3, diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts index 9df4eb3a211..e4f81d465f8 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts @@ -156,7 +156,7 @@ export interface InfNanAlert extends Alert { } /** - * The values summarizing a tensor value watched by the debugger. + * Values that summarize a tensor watched by the debugger. */ export interface DebugTensorValue { // Data type of the tensor. diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts index 7f93c183e50..4626b0b8396 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts @@ -33,7 +33,7 @@ const basicDebugInfoStyle = ` @Component({ selector: 'debug-tensor-dtype', template: ` - {{ dtype }} + {{ dtype }} `, styles: [basicDebugInfoStyle], }) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts index 266da9cf653..98e6b296b39 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts @@ -50,10 +50,7 @@ describe('debug-tensor-value components', () => { const component = fixture.componentInstance; component.dtype = 'bfloat16'; fixture.detectChanges(); - const dtypeNameElement = fixture.debugElement.query( - By.css('.dtype-name') - ); - expect(dtypeNameElement.nativeElement.innerText).toBe('bfloat16'); + expect(fixture.nativeElement.innerText).toBe('bfloat16'); }); }); @@ -83,6 +80,7 @@ describe('debug-tensor-value components', () => { [[1, 3, 3, 7], 'shape:[1,3,3,7]'], [[1, 2, 3, 4, 5], 'shape:[1,2,3,4,5]'], [[0, 1, 2, 3, 4, 5], 'shape:[0,1,2,3,4,5]'], + [[undefined, 1, 3, 3, 7, 10, 20], 'shape:[?,1,3,3,7,10,20]'], [[undefined, undefined, 1, 3, 3, 7, 10, 20], 'shape:[?,?,1,3,3,7,10,20]'], ] as Array<[Array, string]>) { it(`displays correct shape: ${JSON.stringify(expectedShapeText)}`, () => { From 86348080a28ebab66981c7d15138138abd568073 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Wed, 22 Apr 2020 23:54:08 -0400 Subject: [PATCH 25/29] Fix more typos --- .../debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts index e4f81d465f8..f654b793a1d 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts @@ -201,9 +201,10 @@ export interface DebugTensorValue { // Maximum value. max?: number; - // Arithemtic mean. + // Arithmetic mean. mean?: number; + // Variance. variance?: number; } From 0873c95e16763804c4839dc5cc178b394724f1a7 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Fri, 24 Apr 2020 18:58:47 -0400 Subject: [PATCH 26/29] Address Stephan's comments --- .../store/debug_tensor_value.ts | 96 ++++++++++----- .../store/debug_tensor_value_test.ts | 112 ++++++++++++++---- .../store/debugger_types.ts | 2 +- .../debug_tensor_value_component.ts | 72 ++++++----- .../debug_tensor_value_component_test.ts | 8 +- .../execution_data_component.ng.html | 2 + .../graph_executions_component.css | 19 +-- 7 files changed, 206 insertions(+), 105 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts index e6f57df6033..4502c10919b 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts @@ -29,79 +29,119 @@ import {DebugTensorValue, TensorDebugMode} from './debugger_types'; * For numbers that represent breakdown of numeric values by type * (e.g., counts of -inf, +inf and nan), the corresponding fields * in the returned object will be defined only if the count is non-zero. + * This is because the return value of this function is meant for + * consumption by UI elements, which have the need to be concise. + * They will omit 0 counts because those are implied and would be + * space-consuming and distracting to show. */ export function parseDebugTensorValue( tensorDebugMode: TensorDebugMode, array: number[] | null ): DebugTensorValue { - switch (+tensorDebugMode) { + switch (tensorDebugMode) { case TensorDebugMode.NO_TENSOR: { + if (array !== null) { + throw new Error( + 'Unexpectedly received non-null debug-tensor-value array ' + + 'under NO_TENSOR mode' + ); + } return {}; } case TensorDebugMode.CURT_HEALTH: { + if (array === null || array.length !== 2) { + throw new Error( + `Under CURT_HEALTH mode, expected debug-tensor-value array ` + + `to have length 2, but got ${JSON.stringify(array)}` + ); + } return { - hasInfOrNaN: Boolean(array![1]), + hasInfOrNaN: Boolean(array[1]), }; } case TensorDebugMode.CONCISE_HEALTH: { + if (array === null || array.length !== 5) { + throw new Error( + `Under CONCISE_HEALTH mode, expected debug-tensor-value array ` + + `to have length 5, but got ${JSON.stringify(array)}` + ); + } const value: DebugTensorValue = { - size: array![1], + size: array[1], }; - if (array![2] > 0) { - value.numNaNs = array![2]; + if (array[2] > 0) { + value.numNegativeInfs = array[2]; } - if (array![3] > 0) { - value.numNegativeInfs = array![3]; + if (array[3] > 0) { + value.numPositiveInfs = array[3]; } - if (array![4] > 0) { - value.numPositiveInfs = array![4]; + if (array[4] > 0) { + value.numNaNs = array[4]; } return value; } case TensorDebugMode.SHAPE: { - const rank = array![2]; - let shape: number[] = array!.slice(4, Math.min(4 + rank, array!.length)); + if (array === null || array.length !== 10) { + throw new Error( + `Under SHAPE mode, expected debug-tensor-value array ` + + `to have length 10, but got ${JSON.stringify(array)}` + ); + } + const rank = array[2]; + let shape: number[] = array.slice(4, Math.min(4 + rank, array.length)); if (shape.length < rank) { // The SHAPE mode truncates the shape at head. shape = new Array(rank - shape.length).concat(shape); } return { - dtype: DTYPE_ENUM_TO_NAME[array![1]], + dtype: DTYPE_ENUM_TO_NAME[array[1]], rank, - size: array![3], + size: array[3], shape, }; } case TensorDebugMode.FULL_HEALTH: { - const rank = array![3]; + if (array === null || array.length !== 11) { + throw new Error( + `Under FULL_HEALTH mode, expected debug-tensor-value array ` + + `to have length 11, but got ${JSON.stringify(array)}` + ); + } + const rank = array[3]; const value: DebugTensorValue = { - dtype: DTYPE_ENUM_TO_NAME[array![2]], + dtype: DTYPE_ENUM_TO_NAME[array[2]], rank, - size: array![4], + size: array[4], }; - if (array![5] > 0) { - value.numNegativeInfs = array![5]; + if (array[5] > 0) { + value.numNegativeInfs = array[5]; } - if (array![6] > 0) { - value.numPositiveInfs = array![6]; + if (array[6] > 0) { + value.numPositiveInfs = array[6]; } - if (array![7] > 0) { - value.numNaNs = array![7]; + if (array[7] > 0) { + value.numNaNs = array[7]; } - if (array![8] > 0) { - value.numNegativeFinites = array![8]; + if (array[8] > 0) { + value.numNegativeFinites = array[8]; } - if (array![9] > 0) { - value.numZeros = array![9]; + if (array[9] > 0) { + value.numZeros = array[9]; } - if (array![10] > 0) { - value.numPositiveFinites = array![10]; + if (array[10] > 0) { + value.numPositiveFinites = array[10]; } return value; } case TensorDebugMode.FULL_TENSOR: { // Under FULL_TENSOR mode, the full tensor value is supplied via // separate means. No summary values are provided for the tensor value. + if (array !== null) { + throw new Error( + 'Unexpectedly received non-null debug-tensor-value array ' + + 'under FULL_TENSOR mode' + ); + } return {}; } default: { diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts index 310e0550d4d..f0cdfba984b 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts @@ -18,7 +18,7 @@ import {parseDebugTensorValue} from './debug_tensor_value'; describe('parseDebugTensorValue', () => { describe('CURT_HEALTH', () => { - it('has no inf or nan', () => { + it('returns correct value if tensor has no inf or nan', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.CURT_HEALTH, [ 123, // tensor ID 0, // has inf or nan? @@ -28,7 +28,7 @@ describe('parseDebugTensorValue', () => { }); }); - it('has inf or nan', () => { + it('returns correct value if tensor has inf or nan', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.CURT_HEALTH, [ 123, // tensor ID 1, // has inf or nan? @@ -37,10 +37,20 @@ describe('parseDebugTensorValue', () => { hasInfOrNaN: true, }); }); + + for (const array of [null, [0], [0, 1, 1]]) { + it(`throws error for null or wrong array arg: ${JSON.stringify( + array + )}`, () => { + expect(() => + parseDebugTensorValue(TensorDebugMode.CURT_HEALTH, array) + ).toThrowError(/CURT_HEALTH.*expect.*length 2/); + }); + } }); describe('CONCISE_HEALTH', () => { - it('all healthy', () => { + it('returns correct value if tensor is all healthy', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ 123, 1000, // size @@ -53,13 +63,13 @@ describe('parseDebugTensorValue', () => { }); }); - it('has nan', () => { + it('returns correct value if tensor has nan', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ 123, 1000, // size - 1, 0, 0, + 1, ]); expect(debugValue).toEqual({ size: 1000, @@ -67,13 +77,13 @@ describe('parseDebugTensorValue', () => { }); }); - it('has neg inf', () => { + it('returns correct value if tensor has neg inf', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ 123, 1000, - 0, 2, 0, + 0, ]); expect(debugValue).toEqual({ size: 1000, @@ -81,13 +91,13 @@ describe('parseDebugTensorValue', () => { }); }); - it('has pos inf', () => { + it('returns correct value if tensor has pos inf', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ 123, 1000, // size 0, - 0, 22, + 0, ]); expect(debugValue).toEqual({ size: 1000, @@ -95,7 +105,7 @@ describe('parseDebugTensorValue', () => { }); }); - it('full house', () => { + it('returns correct value if tensor has nan, -inf and inf', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ 123, 1000, // size @@ -105,15 +115,25 @@ describe('parseDebugTensorValue', () => { ]); expect(debugValue).toEqual({ size: 1000, - numNaNs: 10, - numNegativeInfs: 20, - numPositiveInfs: 30, + numNegativeInfs: 10, + numPositiveInfs: 20, + numNaNs: 30, }); }); + + for (const array of [null, [0, 10, 0, 0], [0, 10, 0, 0, 0, 0]]) { + it(`throws error for null or wrong array arg: ${JSON.stringify( + array + )}`, () => { + expect(() => + parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, array) + ).toThrowError(/CONCISE_HEALTH.*expect.*length 5/); + }); + } }); describe('SHAPE', () => { - it('0D bool', () => { + it('returns correct value for 0D bool', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ 123, 10, // bool @@ -134,7 +154,7 @@ describe('parseDebugTensorValue', () => { }); }); - it('1D int32', () => { + it('returns correct value for 1D int32', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ 123, 3, // int32 @@ -155,7 +175,7 @@ describe('parseDebugTensorValue', () => { }); }); - it('2D float32', () => { + it('returns correct value for 2D float32', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ 123, 1, // float32 @@ -176,7 +196,7 @@ describe('parseDebugTensorValue', () => { }); }); - it('6D float64', () => { + it('returns correct value for 6D float64', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ 123, 2, // float64 @@ -197,7 +217,7 @@ describe('parseDebugTensorValue', () => { }); }); - it('truncated shape: 7D', () => { + it('returns correct value for truncated shape: 7D', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ 123, 5, // int16 @@ -219,7 +239,7 @@ describe('parseDebugTensorValue', () => { }); }); - it('truncated shape: 8D', () => { + it('returns correct value for truncated shape: 8D', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ 123, 1, // float32 @@ -240,10 +260,24 @@ describe('parseDebugTensorValue', () => { shape: [undefined, undefined, 3, 4, 1, 2, 1, 5], }); }); + + for (const array of [ + null, + [123, 1, 8, 1200, 3, 4, 1, 2, 1], + [123, 1, 8, 1200, 3, 4, 1, 2, 1, 5, 6], + ]) { + it(`throws error for null or wrong array arg: ${JSON.stringify( + array + )}`, () => { + expect(() => + parseDebugTensorValue(TensorDebugMode.SHAPE, array) + ).toThrowError(/SHAPE.*expect.*length 10/); + }); + } }); describe('FULL_HEALTH', () => { - it('float32 2D with no inf or nan', () => { + it('returns correct value for float32 2D with no inf or nan', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.FULL_HEALTH, [ 123, 0, @@ -267,7 +301,7 @@ describe('parseDebugTensorValue', () => { }); }); - it('float64 scalar nan', () => { + it('returns correct value for float64 scalar nan', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.FULL_HEALTH, [ 123, 0, @@ -289,7 +323,7 @@ describe('parseDebugTensorValue', () => { }); }); - it('bfloat16 1D with -inf and +inf', () => { + it('returns correct value for bfloat16 1D with -inf and +inf', () => { const debugValue = parseDebugTensorValue(TensorDebugMode.FULL_HEALTH, [ 123, 0, @@ -311,6 +345,20 @@ describe('parseDebugTensorValue', () => { numPositiveInfs: 7, }); }); + + for (const array of [ + null, + [123, 0, 14, 1, 10, 3, 7, 0, 0, 0], + [123, 0, 14, 1, 10, 3, 7, 0, 0, 0, 0, 0], + ]) { + it(`throws error for null or wrong array arg: ${JSON.stringify( + array + )}`, () => { + expect(() => + parseDebugTensorValue(TensorDebugMode.FULL_HEALTH, array) + ).toThrowError(/FULL_HEALTH.*expect.*length 11/); + }); + } }); describe('NO_TENSOR', () => { @@ -319,6 +367,16 @@ describe('parseDebugTensorValue', () => { {} ); }); + + for (const array of [[], [0]]) { + it(`throws error for non-null array arg: ${JSON.stringify( + array + )}`, () => { + expect(() => + parseDebugTensorValue(TensorDebugMode.NO_TENSOR, array) + ).toThrowError(/non-null.*NO_TENSOR/); + }); + } }); describe('FULL_TENSOR', () => { @@ -327,6 +385,16 @@ describe('parseDebugTensorValue', () => { {} ); }); + + for (const array of [[], [0]]) { + it(`throws error for non-null array arg: ${JSON.stringify( + array + )}`, () => { + expect(() => + parseDebugTensorValue(TensorDebugMode.FULL_TENSOR, array) + ).toThrowError(/non-null.*FULL_TENSOR/); + }); + } }); describe('Invalid TensorDebugMode', () => { diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts index f654b793a1d..dac2076c4fa 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_types.ts @@ -174,7 +174,7 @@ export interface DebugTensorValue { // Size (total element count) of the tensor. size?: number; - // Number of NaNa elements. + // Number of NaN elements. numNaNs?: number; // Number of -Infinity elements. diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts index 4626b0b8396..53c2febb61c 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts @@ -252,52 +252,50 @@ export class DebugTensorHasInfOrNaNComponent { @Component({ selector: 'debug-tensor-value', template: ` -
- - - - - - - - - - -
+ + + + + + + + + + `, styles: [ ` :host { - display: inline-block; - overflow: hidden; - } - .flexbox { align-items: flex-start; display: flex; flex-wrap: nowrap; + overflow: hidden; vertical-align: top; } + debug-tensor-numeric-breakdown { + display: inline-block; + } `, ], }) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts index 98e6b296b39..4d214cd488c 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts @@ -127,8 +127,8 @@ describe('debug-tensor-value components', () => { const countElements = fixture.debugElement.queryAll( By.css('.category-count') ); - expect(tagElements.length).toEqual(3); - expect(countElements.length).toEqual(3); + expect(tagElements.length).toBe(3); + expect(countElements.length).toBe(3); expect(tagElements[0].nativeElement.innerText).toBe('-'); expect(countElements[0].nativeElement.innerText).toBe('×300'); expect(tagElements[1].nativeElement.innerText).toBe('0'); @@ -157,8 +157,8 @@ describe('debug-tensor-value components', () => { const countElements = fixture.debugElement.queryAll( By.css('.category-count') ); - expect(tagElements.length).toEqual(3); - expect(countElements.length).toEqual(3); + expect(tagElements.length).toBe(3); + expect(countElements.length).toBe(3); expect(tagElements[0].nativeElement.innerText).toBe('NaN'); expect(countElements[0].nativeElement.innerText).toBe('×300'); expect(tagElements[1].nativeElement.innerText).toBe('-∞'); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ng.html index e7a8d5190a4..9a23ab1844b 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ng.html @@ -63,6 +63,8 @@ *ngFor="let singleDebugTensorValues of debugTensorValues; index as i;" class="output-slot-container" > + +
Output slot {{ i }}:
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css index e039d0f3eb7..fa1f54c6793 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.css @@ -58,18 +58,6 @@ limitations under the License. width: 100%; } -.tensor-debug-info { - display: inline-block; - overflow: hidden; -} - -.tensor-debug-info-flexbox { - align-items: flex-start; - display: flex; - flex-wrap: nowrap; - vertical-align: top; -} - .tensor-item { border-bottom: 1px solid rgba(0, 0, 0, 0.12); display: flex; @@ -77,7 +65,7 @@ limitations under the License. height: 36px; line-height: 36px; text-align: left; - vertical-align: top; + vertical-align: middle; white-space: nowrap; width: 100%; } @@ -102,3 +90,8 @@ limitations under the License. text-align: right; width: 240px; } + +debug-tensor-value { + display: inline-block; + margin: 2px 0; +} From a67a8f520026262a4666be14289aac270b61c47a Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Mon, 27 Apr 2020 10:14:16 -0400 Subject: [PATCH 27/29] Address 2nd round of comments --- .../store/debug_tensor_value.ts | 82 +++- .../store/debug_tensor_value_test.ts | 400 ++++++++++-------- .../debug_tensor_value_component_test.ts | 32 +- .../execution_data_component.ng.html | 7 +- .../graph_executions_component.ng.html | 7 +- 5 files changed, 329 insertions(+), 199 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts index 4502c10919b..b21bda64290 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value.ts @@ -16,28 +16,90 @@ limitations under the License. import {DTYPE_ENUM_TO_NAME} from '../tf_dtypes'; import {DebugTensorValue, TensorDebugMode} from './debugger_types'; +export interface RawDebugTensorValue { + tensorDebugMode: TensorDebugMode; + array: null | number[]; +} + +export interface RawDebugTensorValueNoTensor extends RawDebugTensorValue { + tensorDebugMode: TensorDebugMode.NO_TENSOR; + array: null; +} + +export interface RawDebugTensorValueCurtHealth extends RawDebugTensorValue { + tensorDebugMode: TensorDebugMode.CURT_HEALTH; + array: [ + number, // Tensor ID. + number // 0-1 indicator for the presence of inf/nan. + ]; +} + +export interface RawDebugTensorValueConciseHealth extends RawDebugTensorValue { + tensorDebugMode: TensorDebugMode.CURT_HEALTH; + array: [ + number, // Tensor ID. + number, // Element count (size). + number, // -inf count. + number, // +inf count. + number // nan count. + ]; +} + +export interface RawDebugTensorValueShape extends RawDebugTensorValue { + tensorDebugMode: TensorDebugMode.SHAPE; + array: [ + number, // Tensor ID. + number, // DType enum value. + number, // Rank. + number, // Size. + number, // Shape truncated at head to a maximum length of 6. + number, + number, + number, + number, + number + ]; +} + +export interface RawDebugTensorValueFullHealth extends RawDebugTensorValue { + tensorDebugMode: TensorDebugMode.FULL_HEALTH; + array: [ + number, // Tensor ID. + number, // Device ID. + number, // DType enum value. + number, // Rank. + number, // Size. + number, // -inf count. + number, // +inf count. + number, // nan count. + number, // -finite count. + number, // zero count. + number // +finite count. + ]; +} + +export interface RawDebugTensorValueFullTensor extends RawDebugTensorValue { + tensorDebugMode: TensorDebugMode.FULL_HEALTH; + array: null; +} + /** * Parse a number array that represents debugging summary of an instrumented * tensor value. * - * @param tensorDebugMode Tensor-debug mode. - * @param array The array of number that represents various aspect of the - * instrumented tensor. The semantics of the numbers are determined by - * `tensorDebugMode`. + * @param tensorDebugMode and the array of number that represents various + * aspect of the instrumented tensor. The semantics of the numbers are + * determined by `tensorDebugMode`. * @returns A DebugTensorValue object with the same information as * carried by `array`, but represented in a more explicit fashion. * For numbers that represent breakdown of numeric values by type * (e.g., counts of -inf, +inf and nan), the corresponding fields * in the returned object will be defined only if the count is non-zero. - * This is because the return value of this function is meant for - * consumption by UI elements, which have the need to be concise. - * They will omit 0 counts because those are implied and would be - * space-consuming and distracting to show. */ export function parseDebugTensorValue( - tensorDebugMode: TensorDebugMode, - array: number[] | null + raw: RawDebugTensorValue ): DebugTensorValue { + const {tensorDebugMode, array} = raw; switch (tensorDebugMode) { case TensorDebugMode.NO_TENSOR: { if (array !== null) { diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts index f0cdfba984b..830fc7cb6a4 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debug_tensor_value_test.ts @@ -19,20 +19,26 @@ import {parseDebugTensorValue} from './debug_tensor_value'; describe('parseDebugTensorValue', () => { describe('CURT_HEALTH', () => { it('returns correct value if tensor has no inf or nan', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.CURT_HEALTH, [ - 123, // tensor ID - 0, // has inf or nan? - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.CURT_HEALTH, + array: [ + 123, // tensor ID + 0, // has inf or nan? + ], + }); expect(debugValue).toEqual({ hasInfOrNaN: false, }); }); it('returns correct value if tensor has inf or nan', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.CURT_HEALTH, [ - 123, // tensor ID - 1, // has inf or nan? - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.CURT_HEALTH, + array: [ + 123, // tensor ID + 1, // has inf or nan? + ], + }); expect(debugValue).toEqual({ hasInfOrNaN: true, }); @@ -43,7 +49,10 @@ describe('parseDebugTensorValue', () => { array )}`, () => { expect(() => - parseDebugTensorValue(TensorDebugMode.CURT_HEALTH, array) + parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.CURT_HEALTH, + array, + }) ).toThrowError(/CURT_HEALTH.*expect.*length 2/); }); } @@ -51,26 +60,32 @@ describe('parseDebugTensorValue', () => { describe('CONCISE_HEALTH', () => { it('returns correct value if tensor is all healthy', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ - 123, - 1000, // size - 0, - 0, - 0, - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.CONCISE_HEALTH, + array: [ + 123, + 1000, // size + 0, + 0, + 0, + ], + }); expect(debugValue).toEqual({ size: 1000, }); }); it('returns correct value if tensor has nan', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ - 123, - 1000, // size - 0, - 0, - 1, - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.CONCISE_HEALTH, + array: [ + 123, + 1000, // size + 0, + 0, + 1, + ], + }); expect(debugValue).toEqual({ size: 1000, numNaNs: 1, @@ -78,13 +93,10 @@ describe('parseDebugTensorValue', () => { }); it('returns correct value if tensor has neg inf', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ - 123, - 1000, - 2, - 0, - 0, - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.CONCISE_HEALTH, + array: [123, 1000, 2, 0, 0], + }); expect(debugValue).toEqual({ size: 1000, numNegativeInfs: 2, @@ -92,13 +104,16 @@ describe('parseDebugTensorValue', () => { }); it('returns correct value if tensor has pos inf', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ - 123, - 1000, // size - 0, - 22, - 0, - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.CONCISE_HEALTH, + array: [ + 123, + 1000, // size + 0, + 22, + 0, + ], + }); expect(debugValue).toEqual({ size: 1000, numPositiveInfs: 22, @@ -106,13 +121,16 @@ describe('parseDebugTensorValue', () => { }); it('returns correct value if tensor has nan, -inf and inf', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, [ - 123, - 1000, // size - 10, - 20, - 30, - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.CONCISE_HEALTH, + array: [ + 123, + 1000, // size + 10, + 20, + 30, + ], + }); expect(debugValue).toEqual({ size: 1000, numNegativeInfs: 10, @@ -126,7 +144,10 @@ describe('parseDebugTensorValue', () => { array )}`, () => { expect(() => - parseDebugTensorValue(TensorDebugMode.CONCISE_HEALTH, array) + parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.CONCISE_HEALTH, + array, + }) ).toThrowError(/CONCISE_HEALTH.*expect.*length 5/); }); } @@ -134,18 +155,21 @@ describe('parseDebugTensorValue', () => { describe('SHAPE', () => { it('returns correct value for 0D bool', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ - 123, - 10, // bool - 0, // rank - 1, // size - 0, - 0, - 0, - 0, - 0, - 0, - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.SHAPE, + array: [ + 123, + 10, // bool + 0, // rank + 1, // size + 0, + 0, + 0, + 0, + 0, + 0, + ], + }); expect(debugValue).toEqual({ dtype: 'bool', rank: 0, @@ -155,18 +179,21 @@ describe('parseDebugTensorValue', () => { }); it('returns correct value for 1D int32', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ - 123, - 3, // int32 - 1, // rank - 46, // size - 46, - 0, - 0, - 0, - 0, - 0, - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.SHAPE, + array: [ + 123, + 3, // int32 + 1, // rank + 46, // size + 46, + 0, + 0, + 0, + 0, + 0, + ], + }); expect(debugValue).toEqual({ dtype: 'int32', rank: 1, @@ -176,18 +203,21 @@ describe('parseDebugTensorValue', () => { }); it('returns correct value for 2D float32', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ - 123, - 1, // float32 - 2, // rank - 1200, - 30, - 40, - 0, - 0, - 0, - 0, - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.SHAPE, + array: [ + 123, + 1, // float32 + 2, // rank + 1200, + 30, + 40, + 0, + 0, + 0, + 0, + ], + }); expect(debugValue).toEqual({ dtype: 'float32', rank: 2, @@ -197,18 +227,21 @@ describe('parseDebugTensorValue', () => { }); it('returns correct value for 6D float64', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ - 123, - 2, // float64 - 6, // rank - 1200, - 1, - 2, - 3, - 4, - 5, - 10, - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.SHAPE, + array: [ + 123, + 2, // float64 + 6, // rank + 1200, + 1, + 2, + 3, + 4, + 5, + 10, + ], + }); expect(debugValue).toEqual({ dtype: 'float64', rank: 6, @@ -218,18 +251,21 @@ describe('parseDebugTensorValue', () => { }); it('returns correct value for truncated shape: 7D', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ - 123, - 5, // int16 - 7, // rank 7 - 1200, - 3, - 4, - 1, - 2, - 1, - 5, - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.SHAPE, + array: [ + 123, + 5, // int16 + 7, // rank 7 + 1200, + 3, + 4, + 1, + 2, + 1, + 5, + ], + }); expect(debugValue).toEqual({ dtype: 'int16', rank: 7, @@ -240,18 +276,21 @@ describe('parseDebugTensorValue', () => { }); it('returns correct value for truncated shape: 8D', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.SHAPE, [ - 123, - 1, // float32 - 8, // rank 8 - 1200, - 3, - 4, - 1, - 2, - 1, - 5, - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.SHAPE, + array: [ + 123, + 1, // float32 + 8, // rank 8 + 1200, + 3, + 4, + 1, + 2, + 1, + 5, + ], + }); expect(debugValue).toEqual({ dtype: 'float32', rank: 8, @@ -270,7 +309,7 @@ describe('parseDebugTensorValue', () => { array )}`, () => { expect(() => - parseDebugTensorValue(TensorDebugMode.SHAPE, array) + parseDebugTensorValue({tensorDebugMode: TensorDebugMode.SHAPE, array}) ).toThrowError(/SHAPE.*expect.*length 10/); }); } @@ -278,19 +317,22 @@ describe('parseDebugTensorValue', () => { describe('FULL_HEALTH', () => { it('returns correct value for float32 2D with no inf or nan', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.FULL_HEALTH, [ - 123, - 0, - 1, // float32 - 2, // rank - 600, // size - 0, - 0, - 0, - 100, - 200, - 300, - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.FULL_HEALTH, + array: [ + 123, + 0, + 1, // float32 + 2, // rank + 600, // size + 0, + 0, + 0, + 100, + 200, + 300, + ], + }); expect(debugValue).toEqual({ dtype: 'float32', rank: 2, @@ -302,19 +344,22 @@ describe('parseDebugTensorValue', () => { }); it('returns correct value for float64 scalar nan', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.FULL_HEALTH, [ - 123, - 0, - 2, // float64 - 0, // rank - 1, // size - 0, - 0, - 1, - 0, - 0, - 0, - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.FULL_HEALTH, + array: [ + 123, + 0, + 2, // float64 + 0, // rank + 1, // size + 0, + 0, + 1, + 0, + 0, + 0, + ], + }); expect(debugValue).toEqual({ dtype: 'float64', rank: 0, @@ -324,19 +369,22 @@ describe('parseDebugTensorValue', () => { }); it('returns correct value for bfloat16 1D with -inf and +inf', () => { - const debugValue = parseDebugTensorValue(TensorDebugMode.FULL_HEALTH, [ - 123, - 0, - 14, // bfloat16 - 1, // rank - 10, // size - 3, - 7, - 0, - 0, - 0, - 0, - ]); + const debugValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.FULL_HEALTH, + array: [ + 123, + 0, + 14, // bfloat16 + 1, // rank + 10, // size + 3, + 7, + 0, + 0, + 0, + 0, + ], + }); expect(debugValue).toEqual({ dtype: 'bfloat16', rank: 1, @@ -355,7 +403,10 @@ describe('parseDebugTensorValue', () => { array )}`, () => { expect(() => - parseDebugTensorValue(TensorDebugMode.FULL_HEALTH, array) + parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.FULL_HEALTH, + array, + }) ).toThrowError(/FULL_HEALTH.*expect.*length 11/); }); } @@ -363,9 +414,12 @@ describe('parseDebugTensorValue', () => { describe('NO_TENSOR', () => { it('returns empty object', () => { - expect(parseDebugTensorValue(TensorDebugMode.NO_TENSOR, null)).toEqual( - {} - ); + expect( + parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.NO_TENSOR, + array: null, + }) + ).toEqual({}); }); for (const array of [[], [0]]) { @@ -373,7 +427,10 @@ describe('parseDebugTensorValue', () => { array )}`, () => { expect(() => - parseDebugTensorValue(TensorDebugMode.NO_TENSOR, array) + parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.NO_TENSOR, + array, + }) ).toThrowError(/non-null.*NO_TENSOR/); }); } @@ -381,9 +438,12 @@ describe('parseDebugTensorValue', () => { describe('FULL_TENSOR', () => { it('returns empty object', () => { - expect(parseDebugTensorValue(TensorDebugMode.FULL_TENSOR, null)).toEqual( - {} - ); + expect( + parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.FULL_TENSOR, + array: null, + }) + ).toEqual({}); }); for (const array of [[], [0]]) { @@ -391,7 +451,10 @@ describe('parseDebugTensorValue', () => { array )}`, () => { expect(() => - parseDebugTensorValue(TensorDebugMode.FULL_TENSOR, array) + parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.FULL_TENSOR, + array, + }) ).toThrowError(/non-null.*FULL_TENSOR/); }); } @@ -406,7 +469,10 @@ describe('parseDebugTensorValue', () => { ]) { it('throws error', () => { expect(() => - parseDebugTensorValue(debugMode as TensorDebugMode, null) + parseDebugTensorValue({ + tensorDebugMode: debugMode as TensorDebugMode, + array: null, + }) ).toThrowError(); }); } diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts index 4d214cd488c..1ad97f8f934 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component_test.ts @@ -190,10 +190,10 @@ describe('debug-tensor-value components', () => { it('displays CURT_HEALTH data', () => { const fixture = TestBed.createComponent(DebugTensorValueComponent); const component = fixture.componentInstance; - component.debugTensorValue = parseDebugTensorValue( - TensorDebugMode.CURT_HEALTH, - [123, 0] - ); + component.debugTensorValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.CURT_HEALTH, + array: [123, 0], + }); fixture.detectChanges(); expect( fixture.debugElement.query(By.css('debug-tensor-has-inf-or-nan')) @@ -212,10 +212,10 @@ describe('debug-tensor-value components', () => { it('displays CONCISE_HEALTH data', () => { const fixture = TestBed.createComponent(DebugTensorValueComponent); const component = fixture.componentInstance; - component.debugTensorValue = parseDebugTensorValue( - TensorDebugMode.CONCISE_HEALTH, - [123, 345, 300, 40, 5] - ); + component.debugTensorValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.CONCISE_HEALTH, + array: [123, 345, 300, 40, 5], + }); fixture.detectChanges(); expect( fixture.debugElement.query(By.css('debug-tensor-has-inf-or-nan')) @@ -234,10 +234,10 @@ describe('debug-tensor-value components', () => { it('displays SHAPE data', () => { const fixture = TestBed.createComponent(DebugTensorValueComponent); const component = fixture.componentInstance; - component.debugTensorValue = parseDebugTensorValue( - TensorDebugMode.SHAPE, - [123, 5, 7, 1200, 3, 4, 1, 2, 1, 5] - ); + component.debugTensorValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.SHAPE, + array: [123, 5, 7, 1200, 3, 4, 1, 2, 1, 5], + }); fixture.detectChanges(); expect( fixture.debugElement.query(By.css('debug-tensor-has-inf-or-nan')) @@ -256,10 +256,10 @@ describe('debug-tensor-value components', () => { it('displays FULL_HEALTH data', () => { const fixture = TestBed.createComponent(DebugTensorValueComponent); const component = fixture.componentInstance; - component.debugTensorValue = parseDebugTensorValue( - TensorDebugMode.FULL_HEALTH, - [123, 0, 1, 2, 600, 0, 0, 0, 100, 200, 300] - ); + component.debugTensorValue = parseDebugTensorValue({ + tensorDebugMode: TensorDebugMode.FULL_HEALTH, + array: [123, 0, 1, 2, 600, 0, 0, 0, 100, 200, 300], + }); fixture.detectChanges(); expect( fixture.debugElement.query(By.css('debug-tensor-has-inf-or-nan')) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ng.html index 9a23ab1844b..06f69702b2f 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/execution_data/execution_data_component.ng.html @@ -70,9 +70,10 @@
diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html index 51bdb18e7e1..827041487e4 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph_executions/graph_executions_component.ng.html @@ -47,9 +47,10 @@
From b33d934ab37b2b3315e3d99ac97a18be2c7c5b22 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Mon, 27 Apr 2020 10:23:40 -0400 Subject: [PATCH 28/29] Remove cruft --- .../views/debug_tensor_value/debug_tensor_value_component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts index 53c2febb61c..a55fe017e38 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/debug_tensor_value_component.ts @@ -118,7 +118,6 @@ export class DebugTensorShapeComponent {
+ From b6ce53322bfa235bacfd7fbe269733a9bb3028a2 Mon Sep 17 00:00:00 2001 From: Shanqing Cai Date: Mon, 27 Apr 2020 10:46:55 -0400 Subject: [PATCH 29/29] Add missing BUILD dependency --- .../tf_debugger_v2_plugin/views/debug_tensor_value/BUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD index 741fa820f3e..f8df14e00f8 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/debug_tensor_value/BUILD @@ -13,6 +13,7 @@ ng_module( ], deps = [ "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:debug_tensor_value", + "//tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store:types", "@npm//@angular/common", "@npm//@angular/core", ],