From 914a5790e5cf6099b7920324f28da0a0efdeb7d8 Mon Sep 17 00:00:00 2001 From: liguanchi Date: Mon, 24 Mar 2025 11:16:32 +0800 Subject: [PATCH 01/14] =?UTF-8?q?=E5=86=97=E4=BD=99=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fe/src/tf_backend/canceller.ts | 68 --- .../fe/src/tf_backend/requestManager.ts | 16 - .../tf-dashboard-layout.ts | 1 + .../src/tf_graph/components/legend/index.ts | 9 - .../fe/src/tf_graph/tf-graph-scene.html.ts | 441 +----------------- .../fe/src/tf_graph/tf-graph-scene.ts | 8 - .../fe/src/tf_graph/tf-graph.ts | 51 -- .../fe/src/tf_graph_board/tf-graph-board.ts | 4 - .../fe/src/tf_graph_common/edge.ts | 173 +------ .../components/tf_manual_match/index.ts | 6 + .../fe/src/tf_graph_dashboard/index.ts | 4 - .../app/controllers/match_nodes_controller.py | 6 +- .../tb_graph_ascend/setup.py | 2 +- 13 files changed, 17 insertions(+), 772 deletions(-) delete mode 100644 plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_backend/canceller.ts diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_backend/canceller.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_backend/canceller.ts deleted file mode 100644 index bc840bb4a41..00000000000 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_backend/canceller.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the 'License'); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an 'AS IS' BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -export interface CancelResult { - value: T; - cancelled: boolean; -} - -/** - * A class that allows marking promises as cancelled. - * - * This can be useful to, e.g., prevent old network requests from - * stomping new ones and writing bad data. - * - * Usage: - * - * const canceller = new Canceller(); - * let myPromise: Promise = getPromise(); - * myPromise.then(canceller.cancellable(({value, cancelled} => { - * if (cancelled) { - * console.warn("Don't make promises you can't keep >:-{"); - * } - * console.log("Enjoy your value:", value); - * })); - * - * // If `myPromise` is resolved now, then `cancelled` will be `false`. - * canceller.cancelAll(); - * // If `myPromise` is resolved now, then `cancelled` will be `true`. - */ -export class Canceller { - /** - * How many times has `cancelAll` been called? - */ - private cancellationCount = 0; - /** - * Create a cancellable task. This returns a new function that, when - * invoked, will pass its argument to the provided function as well as - * a `cancelled` argument. This argument will be `false` unless and - * until `cancelAll` is invoked after the creation of this task. - */ - public cancellable(f: (result: CancelResult) => U): (T) => U { - const originalCancellationCount = this.cancellationCount; - return (value) => { - const cancelled = this.cancellationCount !== originalCancellationCount; - return f({ value, cancelled }); - }; - } - - /** - * Mark all outstanding tasks as cancelled. Tasks not yet created will - * not be affected. - */ - public cancelAll(): void { - this.cancellationCount++; - } -} diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_backend/requestManager.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_backend/requestManager.ts index 9fc04e490c2..d47635c83d1 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_backend/requestManager.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_backend/requestManager.ts @@ -185,22 +185,6 @@ export class RequestManager { }); } - public clearQueue(): void { - while (this._queue.length > 0) { - this._queue.pop()?.reject(new RequestCancellationError('Request cancelled by clearQueue')); - } - } - - /* Return number of currently pending requests */ - public activeRequests(): number { - return this._nActiveRequests; - } - - /* Return total number of outstanding requests (includes queue) */ - public outstandingRequests(): number { - return this._nActiveRequests + this._queue.length; - } - /* Actually get promise from url using XMLHttpRequest */ protected _promiseFromUrl(url: string, requestOptions: RequestOptions): Promise { return new Promise((resolve, reject) => { diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_dashboard_common/tf-dashboard-layout.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_dashboard_common/tf-dashboard-layout.ts index 4ae57964ed1..264d5d2c589 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_dashboard_common/tf-dashboard-layout.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_dashboard_common/tf-dashboard-layout.ts @@ -121,6 +121,7 @@ class TfDashboardLayout extends DarkModeMixin(PolymerElement) { flex-shrink: 1; height: 100%; overflow: hidden; + background:white; } ::slotted([slot='center']) { diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/components/legend/index.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/components/legend/index.ts index c4e85d38e9e..88e97a6a9a2 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/components/legend/index.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/components/legend/index.ts @@ -38,15 +38,6 @@ class Legend extends PolymerElement { margin-left: 5px; font-size: 12px; } - .legend-clarifier { - } - .legend-item { - margin-right: 10px; - } - .legend-item-value { - margin-left: 5px; - font-size: 12px; - } .legend-clarifier { color: #266236; cursor: pointer; diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph-scene.html.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph-scene.html.ts index 769b67f5386..80cfea0b920 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph-scene.html.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph-scene.html.ts @@ -214,105 +214,6 @@ export const template = html` stroke-width: 4; } - .faded, - .faded rect, - .faded ellipse, - .faded path, - .faded use, - #rectHatch line, - #ellipseHatch line { - color: #e0d4b3 !important; - fill: white; - stroke: #e0d4b3 !important; - } - - .faded path { - stroke-width: 1px !important; - } - - .faded rect { - fill: url(#rectHatch) !important; - } - - .faded ellipse, - .faded use { - fill: url(#ellipseHatch) !important; - } - - .faded text { - opacity: 0; - } - - /* Rules used for input-tracing. */ - .input-highlight > * > rect, - .input-highlight > * > ellipse, - .input-highlight > * > use { - fill: white; - stroke: #ff9800 !important; - } - - /* - Faded non-input styling */ - .non-input > * > rect, - .non-input > * > ellipse, - .non-input > * > use, - /* For Const nodes. */ - .non-input > * > .constant:not([class*="input-highlight"]) > - .annotation-node > ellipse, - /* For styling of annotation nodes of non-input nodes. */ - .non-input > g > .annotation > .annotation-node > rect { - stroke: #e0d4b3 !important; - stroke-width: inherit; - stroke-dasharray: inherit; - } - - .non-input path { - visibility: hidden; - } - - .non-input > .nodeshape > rect, - .non-input > .annotation-node > rect, - /* For styling of annotation nodes of non-input nodes. */ - .non-input > g > .annotation > .annotation-node > rect { - fill: url(#rectHatch) !important; - } - - .non-input ellipse, - .non-input use { - fill: url(#ellipseHatch) !important; - } - - .non-input > text { - opacity: 0; - } - - .non-input .annotation > .annotation-edge { - marker-end: url(#annotation-arrowhead-faded); - } - - .non-input .annotation > .annotation-edge.refline { - marker-start: url(#ref-annotation-arrowhead-faded); - } - - /* Input edges. */ - .input-edge-highlight > text { - fill: black !important; - } - .input-highlight > .in-annotations > .annotation > .annotation-edge, - .input-highlight-selected > .in-annotations > .annotation > .annotation-edge { - stroke: #999 !important; - } - - /* Non-input edges. */ - .non-input-edge-highlight, - .non-input > g > .annotation > path, - /* Annotation styles (label and edges respectively). */ - .non-input > g > - .annotation:not(.input-highlight):not(.input-highlight-selected) > - .annotation-label - /*.annotation-edge*/ { - visibility: hidden; - } - /* --- Op Node --- */ .op > .nodeshape > .nodecolortarget, @@ -355,18 +256,10 @@ export const template = html` font-size: 9px; } - .series > text.nodelabel { - font-size: 8px; - } - .op > text.nodelabel { font-size: 6px; } - .bridge > text.nodelabel { - display: none; - } - .node.meta.expanded > text.nodelabel { cursor: normal; } @@ -396,153 +289,12 @@ export const template = html` stroke-dasharray: 1, 1; } - .annotation.summary > .annotation-node > *, - .annotation.constant > .annotation-node > * { - stroke-width: 1; - stroke-dasharray: none; - } - - .annotation > .annotation-edge { - fill: none; - stroke: #aaa; - stroke-width: 0.5; - marker-end: url(#annotation-arrowhead); - } - - .faded .annotation > .annotation-edge { - marker-end: url(#annotation-arrowhead-faded); - } - - .annotation > .annotation-edge.refline { - marker-start: url(#ref-annotation-arrowhead); - } - - .faded .annotation > .annotation-edge.refline { - marker-start: url(#ref-annotation-arrowhead-faded); - } - - .annotation > .annotation-control-edge { - stroke-dasharray: 1, 1; - } - - #annotation-arrowhead { - fill: #aaa; - } - - #annotation-arrowhead-faded { - fill: #e0d4b3; - } - - #ref-annotation-arrowhead { - fill: #aaa; - } - - #ref-annotation-arrowhead-faded { - fill: #e0d4b3; - } - - .annotation > .annotation-label { - font-size: 5px; - cursor: pointer; - } - .annotation > .annotation-label.annotation-ellipsis { - cursor: default; - } - /* Hide annotations on expanded meta nodes since they're redundant. */ .expanded > .in-annotations, .expanded > .out-annotations { display: none; } - /* --- Annotation: Constant --- */ - - .constant > .annotation-node > ellipse { - cursor: pointer; - fill: white; - stroke: #848484; - } - - .constant.selected > .annotation-node > ellipse { - fill: white; - stroke: red; - } - - .constant.highlighted > .annotation-node > ellipse { - stroke-width: 1.5; - } - - /* --- Annotation: Summary --- */ - - .summary > .annotation-node > ellipse { - cursor: pointer; - fill: #db4437; - stroke: #db4437; - } - - .summary.selected > .annotation-node > ellipse { - fill: #a52714; - stroke: #a52714; - } - - .summary.highlighted > .annotation-node > ellipse { - stroke-width: 1.5; - } - - /* --- Edge --- */ - - .edge > path.edgeline { - display: none; - fill: none; - stroke: #bbb; - stroke-linecap: round; - stroke-width: 0.75; - } - - .highlighted > path.edgeline { - cursor: pointer; - stroke: #5ae; - } - - .edge .selectableedge { - cursor: pointer; - } - - .selectededge > path.edgeline { - cursor: default; - stroke: #f00; - } - - .edge.selectededge text { - fill: #000; - } - - /* Labels showing tensor shapes on edges */ - .edge > text { - font-size: 3.5px; - fill: #666; - } - - .dataflow-arrowhead { - fill: #bbb; - } - - .reference-arrowhead { - fill: #ffb74d; - } - - .selected-arrowhead { - fill: #f00; - } - - .highlighted-arrowhead { - fill: #5ae; - } - - .edge .control-dep { - stroke-dasharray: 2, 2; - } - /* --- Group node expand/collapse button --- */ /* Hides expand/collapse buttons when a node isn't expanded or highlighted. Using @@ -554,12 +306,6 @@ export const template = html` .node.highlighted > .nodeshape > .buttoncontainer { cursor: pointer; } - .buttoncircle { - fill: #e7811d; - } - .buttoncircle:hover { - fill: #b96717; - } .expandbutton, .collapsebutton { stroke: white; @@ -578,17 +324,6 @@ export const template = html` display: none; } - .health-pill-stats { - font-size: 4px; - text-anchor: middle; - } - - .health-pill rect { - filter: url(#health-pill-shadow); - rx: 3; - ry: 3; - } - .titleContainer { position: relative; top: 20px; @@ -638,183 +373,9 @@ export const template = html`
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-`; +`; \ No newline at end of file diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph-scene.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph-scene.ts index 17d388d7145..6ef9ba1fec0 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph-scene.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph-scene.ts @@ -605,14 +605,6 @@ class TfGraphScene2 extends LegacyElementMixin(DarkModeMixin(PolymerElement)) im delete this._nodeGroupIndex[n]; } - addEdgeGroup(n, selection): void { - this._edgeGroupIndex[n] = selection; - } - - getEdgeGroup(e): any { - return this._edgeGroupIndex[e]; - } - /** * Update node and annotation node of the given name. * @param {String} n node name diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph.ts index 78c19e1f691..51f6039d47b 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph.ts @@ -563,55 +563,4 @@ class TfGraph extends LegacyElementMixin(PolymerElement) { // Rebuild the render hierarchy. this._buildRenderHierarchy(this.graphHierarchy); } - - _deselectPreviousEdge(): void { - const selectedSelector = `.${tf_graph_scene.Class.Edge.SELECTED}`; - const selectedEdge = this.$.scene.shadowRoot?.querySelector(selectedSelector); - const selectedPaths = this.$.scene.shadowRoot?.querySelectorAll('path.edgeline'); - // Visually mark the previously selected edge (if any) as deselected. - if (!!selectedEdge) { - d3.select(selectedEdge) - .classed(tf_graph_scene.Class.Edge.SELECTED, false) - .each((d: any, i) => { - // Reset its marker. - if (d.label && selectedPaths) { - const paths = d3.selectAll(selectedPaths); - if (d.label.startMarkerId) { - paths.style('marker-start', `url(#${d.label.startMarkerId})`); - } - if (d.label.endMarkerId) { - paths.style('marker-end', `url(#${d.label.endMarkerId})`); - } - } - }); - } - } - - _updateMarkerOfSelectedEdge(selectedEdge, isSelected): void { - if (selectedEdge.label) { - const statsName = isSelected ? 'selected-' : 'highlighted-'; - // The marker will vary based on the direction of the edge. - const markerId = selectedEdge.label.startMarkerId || selectedEdge.label.endMarkerId; - if (markerId) { - // Find the corresponding marker for a selected edge. - const selectedMarkerId = markerId.replace('dataflow-', statsName); - let selectedMarker = this.$.scene.shadowRoot?.querySelector(`#${selectedMarkerId}`) as HTMLElement; - if (!selectedMarker) { - // The marker for a selected edge of this size does not exist yet. Create it. - const originalMarker = this.$.scene.shadowRoot?.querySelector(`#${markerId}`); - selectedMarker = originalMarker?.cloneNode(true) as HTMLElement; - selectedMarker.setAttribute('id', selectedMarkerId); - selectedMarker.classList.add(`${statsName}arrowhead`); - originalMarker?.parentNode?.appendChild(selectedMarker); - } - // Make the path use this new marker while it is selected. - const markerAttribute = selectedEdge.label.startMarkerId ? 'marker-start' : 'marker-end'; - if (isSelected) { - this._lastSelectedEdgeGroup.selectAll('path.edgeline').style(markerAttribute, `url(#${selectedMarkerId})`); - } else { - this._lastHighlightedEdgeGroup.selectAll('path.edgeline').style(markerAttribute, `url(#${selectedMarkerId})`); - } - } - } - } } diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_board/tf-graph-board.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_board/tf-graph-board.ts index 39f7ec831fc..496506940ea 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_board/tf-graph-board.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_board/tf-graph-board.ts @@ -307,8 +307,4 @@ class TfGraphBoard extends LegacyElementMixin(PolymerElement) { } return result; } - - _onNodeInclusionToggled(event): void { - (this.$.graph as any).nodeToggleExtract(event.detail.name); - } } diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/edge.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/edge.ts index 09f3a6a93e8..a2d881ead9e 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/edge.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/edge.ts @@ -97,32 +97,6 @@ export function buildGroup(sceneGroup, graph: graphlib.Graph, sceneElement: TfGr d.label.edgeGroup = edgeGroup; // index node group for quick highlighting sceneComponent._edgeGroupIndex[getEdgeKey(d)] = edgeGroup; - - edgeGroup - .on('click', (dClick) => { - // Stop this event's propagation so that it isn't also considered - // a graph-select. - (d3.event).stopPropagation(); - sceneComponent.fire('edge-select', { - edgeData: dClick, - edgeGroup: edgeGroup, - }); - }) - .on('mouseover', (dMouseOver) => { - sceneElement.fire('edge-highlight', { - edgeData: dMouseOver, - edgeGroup: edgeGroup, - }); - }) - .on('mouseout', (dMouseOut) => { - sceneElement.fire('edge-unhighlight', { - edgeData: dMouseOut, - edgeGroup: edgeGroup, - }); - }); - // Add line during enter because we're assuming that type of line - // normally does not change. - appendEdge(edgeGroup, d, sceneComponent); }) .merge(edgeGroups) .each(function () { @@ -167,6 +141,7 @@ export function getLabelForBaseEdge(baseEdge: BaseEdge, renderInfo: render.Rende }) .join(TENSOR_SHAPE_DELIM); } + /** * Creates the label for the given metaedge. If the metaedge consists * of only 1 tensor, and it's shape is known, the label will contain that @@ -179,89 +154,7 @@ export function getLabelForEdge(metaedge: Metaedge, renderInfo: render.RenderGra ? `${metaedge.baseEdgeList.length}tensors` : getLabelForBaseEdge(metaedge.baseEdgeList[0], renderInfo); } -/** - * Computes the index into a set of points that constitute a path for which the - * distance along the path from the initial point is as large as possible - * without exceeding the length. This function was introduced after the - * native getPathSegAtLength method got deprecated by SVG 2. - * @param points Array of path control points. A point has x and y properties. - * Must be of length at least 2. - * @param length The length (float). - * @param lineFunc A function that takes points and returns the "d" attribute - * of a path made from connecting the points. - * @return The index into the points array. - */ -function getPathSegmentIndexAtLength( - points: render.Point[], - length: number, - lineFunc: (points: render.Point[]) => string, -): number { - const path = document.createElementNS(tf_graph_common.SVG_NAMESPACE, 'path'); - for (let i = 1; i < points.length; i++) { - path.setAttribute('d', lineFunc(points.slice(0, i))); - if (path.getTotalLength() > length) { - // This many points has already exceeded the length. - return i - 1; - } - } - // The entire path is shorter than the specified length. - return points.length - 1; -} -/** - * Shortens the path enought such that the tip of the start/end marker will - * point to the start/end of the path. The marker can be of arbitrary size. - * - * @param points Array of path control points. - * @param marker D3 selection of the svg element. - * @param isStart Is the marker a `start-marker`. If false, the marker is - * an `end-marker`. - * @return The new array of control points. - */ -function adjustPathPointsForMarker( - points: render.Point[], - marker: d3.Selection, - isStart: boolean, -): render.Point[] { - let lineFunc = d3 - .line() - .x((d) => d.x) - .y((d) => d.y); - let path = d3.select(document.createElementNS('http://www.w3.org/2000/svg', 'path')).attr('d', lineFunc(points)); - let markerWidth = Number(marker.attr('markerWidth')); - let viewBox = marker.attr('viewBox').split(' ').map(Number); - let viewBoxWidth = viewBox[2] - viewBox[0]; - let refX = Number(marker.attr('refX')); - let pathNode = path.node(); - if (isStart) { - // The edge flows downwards. Do not make the edge go the whole way, lest we - // clobber the arrowhead. - const fractionStickingOut = 1 - (refX / viewBoxWidth); - const length = markerWidth * fractionStickingOut; - const point = pathNode.getPointAtLength(length); - // Figure out how many segments of the path we need to remove in order - // to shorten the path. - // @ts-expect-error TS2345: Argument of type 'Line' is not assignable to parameter of type '(points: Point[]) => string'. - const segIndex = getPathSegmentIndexAtLength(points, length, lineFunc); - // Update the very first segment. - points[segIndex - 1] = { x: point.x, y: point.y }; - // Ignore every point before segIndex - 1. - return points.slice(segIndex - 1); - } else { - // The edge flows upwards. Do not make the edge go the whole way, lest we - // clobber the arrowhead. - const fractionStickingOut = 1 - refX / viewBoxWidth; - const length = pathNode.getTotalLength() - (markerWidth * fractionStickingOut); - const point = pathNode.getPointAtLength(length); - // Figure out how many segments of the path we need to remove in order - // to shorten the path. - // @ts-expect-error TS2345: Argument of type 'Line' is not assignable to parameter of type '(points: Point[]) => string'. - const segIndex = getPathSegmentIndexAtLength(points, length, lineFunc); - // Update the very last segment. - points[segIndex] = { x: point.x, y: point.y }; - // Ignore every point after segIndex. - return points.slice(0, segIndex + 1); - } -} + /** * For a given d3 selection and data object, create a path to represent the * edge described in d.label. @@ -330,8 +223,6 @@ export function appendEdge( // We have no information to show on this edge. return; } - // Put edge label in the middle of edge only if the edge is thick enough. - let baseline = strokeWidth > CENTER_EDGE_LABEL_MIN_STROKE_WIDTH ? 'central' : 'text-after-edge'; edgeGroup .append('text') .append('textPath') @@ -341,6 +232,7 @@ export function appendEdge( .attr('dominant-baseline', 'central') .text(labelForEdge); } + export const interpolate: d3.Line<{ x: number; y: number; @@ -356,68 +248,13 @@ export const interpolate: d3.Line<{ .y((d) => { return d.y; }); -/** - * Returns a tween interpolator for the endpoint of an edge path. - */ -function getEdgePathInterpolator( - component: HTMLElement, - renderPath: SVGPathElement, - d: EdgeData, - i: number, - a: SVGPathElement[], -): ((t: number) => string) | ((t: any) => string | null) { - let renderMetaedgeInfo = d.label; - let adjoiningMetaedge = renderMetaedgeInfo.adjoiningMetaedge; - let points = renderMetaedgeInfo.points; - // Adjust the path so that start/end markers point to the end - // of the path. - const { shadowRoot } = component; - if (d.label.startMarkerId) { - points = adjustPathPointsForMarker( - points, - d3.select(shadowRoot?.querySelector(`#${d.label.startMarkerId}`) as Element), - true, - ); - } - if (d.label.endMarkerId) { - points = adjustPathPointsForMarker( - points, - d3.select(shadowRoot?.querySelector(`#${d.label.endMarkerId}`) as Element), - false, - ); - } - if (!adjoiningMetaedge) { - return d3.interpolate(a, interpolate(points) ?? ''); - } - // Get the adjoining path that matches the adjoining metaedge. - let adjoiningPath = (adjoiningMetaedge.edgeGroup.node()).firstChild; - // Find the desired SVGPoint along the adjoining path, then convert those - // coordinates into the space of the renderPath using its Current - // Transformation Matrix (CTM). - let inbound = renderMetaedgeInfo.metaedge?.inbound; - return function (t): string | null { - let adjoiningPoint = adjoiningPath - .getPointAtLength(inbound ? adjoiningPath.getTotalLength() : 0) - .matrixTransform(adjoiningPath.getCTM() as DOMMatrixInit) - .matrixTransform(renderPath.getCTM()?.inverse()); - // Update the relevant point in the renderMetaedgeInfo's points list, then - // re-interpolate the path. - let index = inbound ? 0 : points.length - 1; - points[index].x = adjoiningPoint.x; - points[index].y = adjoiningPoint.y; - let dPath = interpolate(points); - return dPath; - }; -} + function position(component: HTMLElement, edgeGroup: HTMLElement): void { d3.select(edgeGroup) .select(`path.${Class.Edge.LINE}`) .transition() - // @ts-expect-error TS2769: No overload matches this call. complicated return type mismatch issue - .attrTween('d', function (d: EdgeData, i: number, a: SVGPathElement[]) { - return getEdgePathInterpolator(component, this as SVGPathElement, d, i, a); - }); } + /** * For a given d3 selection and data object, mark the edge as a control * dependency if it contains only control edges. diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_controls/components/tf_manual_match/index.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_controls/components/tf_manual_match/index.ts index f6f6ebcbc90..c5e6c0f6d49 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_controls/components/tf_manual_match/index.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_controls/components/tf_manual_match/index.ts @@ -229,6 +229,8 @@ class Legend extends PolymerElement { this.benchMatchedNodeList = bench_match_nodes; this.set('npuMatchedNodes', Object.keys(npu_match_nodes)); this.set('benchMatchedNodes', Object.keys(bench_match_nodes)); + this.set('selectedNpuMatchedNode', ''); + this.set('selectedBenchMatchedNode', ''); } else { Notification.show(`错误:${result.error}`, { position: 'middle', @@ -282,6 +284,8 @@ class Legend extends PolymerElement { const node = NPU_PREFIX + this.selectedNpuMatchedNode; this.set('selectedBenchMatchedNode', this.npuMatchedNodeList[this.selectedNpuMatchedNode]); this.set('selectedNode', node); + // 展开对应侧节点 + this.set('selectedNode', BENCH_PREFIX + this.selectedBenchMatchedNode); } else { Notification.show('提示:单图节点不支持匹配', { position: 'middle', @@ -296,6 +300,8 @@ class Legend extends PolymerElement { const node = BENCH_PREFIX + this.selectedBenchMatchedNode; this.set('selectedNpuMatchedNode', this.benchMatchedNodeList[this.selectedBenchMatchedNode]); this.set('selectedNode', node); + // 展开对应侧节点 + this.set('selectedNode', NPU_PREFIX + this.selectedNpuMatchedNode); } else { Notification.show('提示:单图节点不支持匹配', { position: 'middle', diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_dashboard/index.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_dashboard/index.ts index 2848f927a84..91b39feaac1 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_dashboard/index.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_dashboard/index.ts @@ -20,7 +20,6 @@ import { customElement, observe, property } from '@polymer/decorators'; import { html, PolymerElement } from '@polymer/polymer'; import '../polymer/irons_and_papers'; import { LegacyElementMixin } from '../polymer/legacy_element_mixin'; -import { Canceller } from '../tf_backend/canceller'; import { RequestManager } from '../tf_backend/requestManager'; import '../tf_dashboard_common/tf-dashboard-layout'; import * as tf_storage from '../tf_storage'; @@ -200,9 +199,6 @@ class TfGraphDashboard extends LegacyElementMixin(PolymerElement) { @property({ type: Object }) _requestManager: RequestManager = new RequestManager(); - @property({ type: Object }) - _canceller: Canceller = new Canceller(); - @property({ type: Boolean }) _debuggerDataEnabled: boolean; diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/server/app/controllers/match_nodes_controller.py b/plugins/tensorboard-plugins/tb_graph_ascend/server/app/controllers/match_nodes_controller.py index b2c8e64adff..a61154c3ea8 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/server/app/controllers/match_nodes_controller.py +++ b/plugins/tensorboard-plugins/tb_graph_ascend/server/app/controllers/match_nodes_controller.py @@ -220,9 +220,9 @@ class MatchNodesController: @staticmethod def calculate_md5_diff(npu_data, bench_data): # 对比每个NPU和Bench所有数据md值,如果有一个不一样则返回0,否则返回1 - for key in zip(npu_data, npu_data): - npu_md5 = npu_data[key].get('md5', '') - bench_md5 = bench_data[key].get('md5', '') + for npu_key, bench_key in zip(npu_data, npu_data): + npu_md5 = npu_data[npu_key].get('md5', '') + bench_md5 = bench_data[bench_key].get('md5', '') if npu_md5 != bench_md5: return 0 return 1 diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/setup.py b/plugins/tensorboard-plugins/tb_graph_ascend/setup.py index 4c4d59e9614..ed8a9d06da5 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/setup.py +++ b/plugins/tensorboard-plugins/tb_graph_ascend/setup.py @@ -16,7 +16,7 @@ # --------------------------------------------------------------------------------------------# import setuptools -VERSION = '1.0.0' +VERSION = '1.0.1' INSTALL_REQUIRED = ["tensorboard >= 2.11.2"] setuptools.setup( -- Gitee From c442ff63fa3468646590652964b39276d747f403 Mon Sep 17 00:00:00 2001 From: liguanchi Date: Mon, 24 Mar 2025 16:55:40 +0800 Subject: [PATCH 02/14] =?UTF-8?q?=E5=86=97=E4=BD=99=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fe/src/tf_graph/tf-graph-scene.ts | 17 +- .../fe/src/tf_graph_board/tf-graph-board.ts | 60 --- .../fe/src/tf_graph_common/graph.ts | 26 - .../fe/src/tf_graph_common/hierarchy.ts | 459 +--------------- .../fe/src/tf_graph_common/layout.ts | 127 +---- .../fe/src/tf_graph_common/node.ts | 29 - .../fe/src/tf_graph_common/parser.ts | 48 +- .../fe/src/tf_graph_common/proto.ts | 138 ----- .../fe/src/tf_graph_common/render.ts | 510 ------------------ .../fe/src/tf_graph_common/scene.ts | 2 +- .../fe/src/tf_graph_common/tf-graph-icon.ts | 6 +- .../tf-graph-dashboard-loader.ts | 14 - 12 files changed, 9 insertions(+), 1427 deletions(-) diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph-scene.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph-scene.ts index 6ef9ba1fec0..84a90dc1e58 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph-scene.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph/tf-graph-scene.ts @@ -231,19 +231,6 @@ class TfGraphScene2 extends LegacyElementMixin(DarkModeMixin(PolymerElement)) im setTimeout(this.fit.bind(this), tf_graph_layout.PARAMS.animation.duration); } - // When renderHierarchy changes, we need to first build the new SVG based - // on the new hierarchy (and it is asynchronous). We will let that observer - // update the input trace. - @observe('traceInputs', 'selectedNode') - _updateInputTrace(): void { - tf_graph_scene_node.updateInputTrace( - this.getGraphSvgRoot(), - this.renderHierarchy, - this.selectedNode, - this.traceInputs, - ); - } - getNode(nodeName): tf_graph_render.RenderNodeInfo { return this.renderHierarchy.getRenderNodeByName(nodeName); } @@ -313,7 +300,6 @@ class TfGraphScene2 extends LegacyElementMixin(DarkModeMixin(PolymerElement)) im (): void => { tf_graph_scene_node.buildGroupForScene(d3.select(this.$.root), renderHierarchy.root, this); tf_graph_scene.addGraphClickListener(this.$.svg, this); - this._updateInputTrace(); }, tb_debug.GraphDebugEventId.RENDER_SCENE_BUILD_SCENE, ); @@ -620,8 +606,7 @@ class TfGraphScene2 extends LegacyElementMixin(DarkModeMixin(PolymerElement)) im } if ( node.node.type === (tf_graph.NodeType.META || tf_graph.NodeType.API_LIST || tf_graph.NodeType.MULTI_COLLECTION) && - (node.node as any).associatedFunction && - !node.isLibraryFunction + (node.node as any).associatedFunction ) { // The node is that of a function call. Also link the node within the // function library. This clarifies to the user that the library function diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_board/tf-graph-board.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_board/tf-graph-board.ts index 496506940ea..81b79b708d7 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_board/tf-graph-board.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_board/tf-graph-board.ts @@ -203,32 +203,6 @@ class TfGraphBoard extends LegacyElementMixin(PolymerElement) { @property({ type: Object }) hierarchyParams: tf_graph_hierarchy.HierarchyParams = tf_graph_hierarchy.DefaultHierarchyParams; - /** - * A number between 0 and 100 denoting the % of progress - * for the progress bar and the displayed message. - * @type {{value: number, msg: string}} - */ - @property({ type: Object }) - progress: object; - - @property({ type: Boolean }) - traceInputs: boolean; - - @property({ type: Boolean }) - autoExtractNodes: boolean; - - @property({ type: Object, notify: true }) - renderHierarchy: tf_graph_render.MergedRenderGraphInfo; - - // Whether debugger data is enabled for this instance of Tensorboard. - @property({ type: Boolean }) - debuggerDataEnabled: boolean; - - @property({ type: Array, notify: true }) - // An array of alerts (in chronological order) provided by debugging libraries on when bad - // values (NaN, +/- Inf) appear. - debuggerNumericAlerts: unknown[]; - @property({ type: Boolean, notify: true }) allStepsModeEnabled: boolean = false; @@ -238,41 +212,7 @@ class TfGraphBoard extends LegacyElementMixin(PolymerElement) { @property({ type: Object }) colorset: any; - @property({ type: String, notify: true }) - selectedNode: string; - - @property({ type: Object, notify: true }) - selectedEdge: tf_graph_render.EdgeData; - - // A function with signature EdgeThicknessFunction that computes the - // thickness of a given edge. - @property({ type: Object }) - edgeWidthFunction: object; - - @property({ type: String }) - _highlightedNode: string; - - // An optional function that takes a node selected event (whose `detail` - // property is the selected node ... which could be null if a node is - // deselected). Called whenever a node is selected or deselected. - @property({ type: Object }) - handleNodeSelected: object; - - // An optional function that computes the label for an edge. Should - // implement the EdgeLabelFunction signature. - @property({ type: Object }) - edgeLabelFunction: object; - - // An optional callback that implements the tf.graph.edge.EdgeSelectionCallback signature. If - // provided, edges are selectable, and this callback is run when an edge is selected. - @property({ type: Object }) - handleEdgeSelected: object; - - @property({ type: Object }) - selection: object; - @property({ type: Object }) - tooltips: object; selectNodeCopy: string = ''; ready(): void { diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/graph.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/graph.ts index 7a29671a1d4..86de37513a3 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/graph.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/graph.ts @@ -724,32 +724,6 @@ class SeriesNodeImpl implements SeriesNode { nodeAttributes: { [key: string]: any; }; - - constructor( - prefix: string, - suffix: string, - parent: string, - clusterId: number, - name: string, - graphOptions: LabeledGraphOptions, - ) { - this.name = name || getSeriesNodeName(prefix, suffix, parent); - this.type = NodeType.SERIES; - this.hasLoop = false; - this.prefix = prefix; - this.suffix = suffix; - this.clusterId = clusterId; - this.ids = []; - this.parent = parent; - this.isGroupNode = true; - this.cardinality = 0; - this.metagraph = createGraph(name, GraphType.SERIES, graphOptions); - // bridgegraph must be constructed lazily-see hierarchy.getBridgegraph() - this.bridgegraph = null; - this.parentNode = null; - this.hasNonControlEdges = false; - this.include = InclusionType.UNSPECIFIED; - } } /** diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/hierarchy.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/hierarchy.ts index c8115a867fc..716c59a5b37 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/hierarchy.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/hierarchy.ts @@ -27,19 +27,15 @@ import { createGraph, createMetaedge, createMetanode, - createSeriesNode, Edges, - getSeriesNodeName, GraphType, GroupNode, Metaedge, MetaedgeImpl, Metanode, Node, - NodeType, OpNode, ROOT_NAME, - SeriesNode, SlimGraph, MetanodeImpl, } from './graph'; @@ -52,9 +48,6 @@ export enum HierarchyEvent { TEMPLATES_UPDATED = 0, } -// A map from the name of a series node to its grouping type. -type SeriesGroupMap = Map; - // Including both the NPU and the benchmark hierarchy. export interface MergedHierarchy { npu: Hierarchy; @@ -87,40 +80,17 @@ export class Hierarchy extends tf_graph_util.Dispatcher { private index: { [nodeName: string]: GroupNode | OpNode; }; - private readonly seriesGroupMap: SeriesGroupMap; constructor(params: HierarchyParams) { super(); this.graphOptions.compound = true; this.graphOptions.rankdir = params.rankDirection; this.root = createMetanode(ROOT_NAME, this.graphOptions); - this.seriesGroupMap = new Map(params.seriesMap); - /** - * @type {Object} Dictionary object that maps node name to the node - * (could be op-node, metanode, or series-node) - */ this.index = {}; this.index[ROOT_NAME] = this.root; this.orderings = {}; } - getSeriesGroupType(nodeName: string): tf_graph.SeriesGroupingType { - // If grouping was not specified, assume it should be grouped by default. - return this.seriesGroupMap.get(nodeName) ?? tf_graph.SeriesGroupingType.GROUP; - } - - setSeriesGroupType(nodeName: string, groupType: tf_graph.SeriesGroupingType): SeriesGroupMap { - return this.seriesGroupMap.set(nodeName, groupType); - } - - buildSeriesGroupMapToggled(nodeName: string): Map { - const newGroupType = - this.getSeriesGroupType(nodeName) === tf_graph.SeriesGroupingType.GROUP - ? tf_graph.SeriesGroupingType.UNGROUP - : tf_graph.SeriesGroupingType.GROUP; - return new Map([...this.seriesGroupMap, [nodeName, newGroupType]]); - } - getNodeMap(): { [nodeName: string]: GroupNode | OpNode; } { @@ -410,24 +380,12 @@ function findEdgeTargetsInGraph(graph: graphlib.Graph, node: Node, inbound: bool export interface HierarchyParams { verifyTemplate: boolean; - seriesNodeMinSize: number; - // The initial map of explicit series group types. - seriesMap: SeriesGroupMap; - // This string is supplied to dagre as the 'rankdir' property for laying out - // the graph. TB, BT, LR, or RL. The default is 'BT' (bottom to top). rankDirection: string; - // Whether to detect numeric patterns for series nodes using entire names of - // nodes. If false, only uses numeric suffixes to find patterns to collapse - // into series nodes. - useGeneralizedSeriesPatterns: boolean; } export const DefaultHierarchyParams: HierarchyParams = { verifyTemplate: true, - seriesNodeMinSize: 5, - seriesMap: new Map(), rankDirection: 'TB', - useGeneralizedSeriesPatterns: false, }; /** @@ -440,9 +398,6 @@ export function build( tracker?: ProgressTracker, ): Promise { const h = new Hierarchy(params); - const seriesNames: { - [name: string]: string; - } = {}; return tf_graph_util .runAsyncTask( 'Adding nodes', @@ -453,26 +408,6 @@ export function build( tracker, tb_debug.GraphDebugEventId.HIERARCHY_ADD_NODES, ) - .then(() => { - return tf_graph_util.runAsyncTask( - 'Detect series', - 30, - () => { - if (params.seriesNodeMinSize > 0) { - groupSeries( - h.root, - h, - seriesNames, - params.seriesNodeMinSize, - params.seriesMap, - params.useGeneralizedSeriesPatterns, - ); - } - }, - tracker, - tb_debug.GraphDebugEventId.HIERARCHY_DETECT_SERIES, - ); - }) .then(() => { return tf_graph_util.runAsyncTask( 'Adding edges', @@ -568,396 +503,4 @@ function addEdgesInVis(h: Hierarchy, graph: SlimGraph, nodeName: string): void { } metaedge.addBaseEdge(baseEdge, h, true); }); -} - -/** - * Using the hierarchy template information, detect series in the provided - * metanode. For each detected series, create a new SeriesNode - * and remove series members from the metanode's metagraph and move them to - * the new series node's metagraph. - * - * @param metanode - * @param hierarchy - * @param seriesNames Map of node names to their series they are contained in. - * This should be provided empty and is populated by this method. - * @param threshold If the series has this many nodes or more, then group them - * into a series. - * @param map Map of series names to their series grouping type, if one has - * been set. - * @param useGeneralizedSeriesPatterns Whether to use find patterns for series - * nodes using any parts of names of nodes. If false, only uses patterns - * discovered within numeric suffixes of nodes names. - * @return A dictionary from node name to series node name that contains the - * node. - */ -function groupSeries( - metanode: Metanode, - hierarchy: Hierarchy, - seriesNames: { - [name: string]: string; - }, - threshold: number, - seriesMap: SeriesGroupMap, - useGeneralizedSeriesPatterns: boolean, -): void { - let metagraph = metanode.metagraph; - _.each(metagraph.nodes(), (n) => { - let child = metagraph.node(n); - if (child.type === (tf_graph.NodeType.META || tf_graph.NodeType.MULTI_COLLECTION || tf_graph.NodeType.API_LIST)) { - groupSeries( - child as unknown as Metanode, - hierarchy, - seriesNames, - threshold, - seriesMap, - useGeneralizedSeriesPatterns, - ); - } - }); - let clusters = clusterNodes(metagraph); - const detectSeriesMethod = useGeneralizedSeriesPatterns - ? detectSeriesAnywhereInNodeName - : detectSeriesUsingNumericSuffixes; - let seriesDict = detectSeriesMethod(clusters, metagraph, hierarchy.graphOptions); - // Add each series node to the graph and add its grouped children to its own - // metagraph. - _.each(seriesDict, (seriesNode: SeriesNode, seriesName: string) => { - let nodeMemberNames = seriesNode.metagraph.nodes(); - _.each(nodeMemberNames, (n) => { - let child = metagraph.node(n) as any; - if (!child.owningSeries) { - child.owningSeries = seriesName; - } - }); - // If the series contains less than the threshold number of nodes, then set - // this series to be shown ungrouped in the map. - if ( - nodeMemberNames.length < threshold && - hierarchy.getSeriesGroupType(seriesNode.name) === tf_graph.SeriesGroupingType.GROUP - ) { - hierarchy.setSeriesGroupType(seriesNode.name, tf_graph.SeriesGroupingType.UNGROUP); - } - // If the series is in the map as ungrouped then do not group the series. - if (hierarchy.getSeriesGroupType(seriesNode.name) === tf_graph.SeriesGroupingType.UNGROUP) { - return; - } - hierarchy.setNode(seriesName, seriesNode); // add to the index - metagraph.setNode(seriesName, seriesNode); - _.each(nodeMemberNames, (n) => { - let child = metagraph.node(n) as any; - seriesNode.metagraph.setNode(n, child); - seriesNode.parentNode = child.parentNode; - seriesNode.cardinality++; - child.parentNode = seriesNode; - seriesNames[n] = seriesName; - // Remove now-grouped node from its original parent's metagraph. - metagraph.removeNode(n); - }); - }); -} - -/** - * Cluster op-nodes with similar op. This examines only the direct children of - * the metagraph, does not recursively check descendants. - * @return A map from op to a list of node names. - */ -function clusterNodes(metagraph: graphlib.Graph): { - [clusterId: string]: string[]; -} { - let result: { - [clusterId: string]: string[]; - } = {}; - return _.reduce( - metagraph.nodes(), - ( - clusters: { - [clusterId: string]: string[]; - }, - n: string, - ) => { - let child = metagraph.node(n); - if (child.type === (NodeType.META || NodeType.MULTI_COLLECTION || NodeType.API_LIST)) { - // skip metanodes - return clusters; - } - let template = (child as any).op; - if (template) { - clusters[template] = clusters[template] || []; - clusters[template].push(child.name); - } - return clusters; - }, - result, - ); -} - -/** - * For each cluster of op-nodes based op type, try to detect groupings. - * Infer series name using by trying to find pattern '' towards the end - * of node names. - * - * @param clusters Dictionary output from clusterNodes(). - * @param metagraph - * @return A dictionary from series name => seriesNode - */ -function detectSeriesUsingNumericSuffixes( - clusters: { - [clusterId: string]: string[]; - }, - metagraph: graphlib.Graph, - graphOptions: tf_graph.LabeledGraphOptions, -): { - [seriesName: string]: SeriesNode; -} { - let seriesDict: { - [seriesName: string]: SeriesNode; - } = {}; - _.each(clusters, (members, clusterId: string) => { - if (members.length <= 1) { - return; - } // isolated clusters can't make series - /** @type {Object} A dictionary mapping seriesName to seriesInfoArray, - * which is an array that contains objects with name, id, prefix, suffix, - * and parent properties. - */ - let candidatesDict: { - [seriesName: string]: SeriesNode[]; - } = {}; - // Group all nodes that have the same name, with the exception of a - // number at the end of the name after an underscore, which is allowed to - // vary. - _.each(members, (name: string) => { - const isGroup = name.charAt(name.length - 1) === '*'; - const namepath = name.split('/'); - const leaf = namepath[namepath.length - 1]; - const parent = namepath.slice(0, namepath.length - 1).join('/'); - const matches = leaf.match(/^(?\D*)(?\d+)$/); - - let prefix; - let id; - let suffix = ''; - if (matches) { - // if found '' in the name, assign id. - prefix = matches[1]; // the front non-numeric characters - id = matches[2]; // the digits - } else { - // for node without '_', make them zero-th items. - prefix = isGroup ? leaf.substr(0, leaf.length - 1) : leaf; - id = 0; - suffix = isGroup ? '*' : ''; - } - const seriesName = getSeriesNodeName(prefix, suffix, parent); - candidatesDict[seriesName] = candidatesDict[seriesName] || []; - const seriesNode = createSeriesNode(prefix, suffix, parent, Number(id), name, graphOptions); - candidatesDict[seriesName].push(seriesNode); - }); - // In each group of nodes, group nodes in bunches that have monotonically - // increasing numbers in their names. Each of these bunches is a series. - _.each(candidatesDict, (seriesInfoArray: SeriesNode[], seriesName) => { - if (seriesInfoArray.length < 2) { - return; - } - seriesInfoArray.sort((a, b) => { - return Number(a.clusterId) - Number(b.clusterId); - }); - // Loop through the nodes sorted by its detected series number, grouping - // all nodes with monotonically-increasing series numbers. - let seriesNodes = [seriesInfoArray[0]]; - for (let index = 1; index < seriesInfoArray.length; index++) { - let nextNode = seriesInfoArray[index]; - if (nextNode.clusterId === seriesNodes[seriesNodes.length - 1].clusterId + 1) { - seriesNodes.push(nextNode); - continue; - } - addSeriesToDict(seriesNodes, seriesDict, Number(clusterId), metagraph, graphOptions); - seriesNodes = [nextNode]; - } - addSeriesToDict(seriesNodes, seriesDict, Number(clusterId), metagraph, graphOptions); - }); - }); - return seriesDict; -} - -/** - * For each cluster of op-nodes based op type, try to detect groupings. - * Infer series name using by trying to find a pattern of numbers - * anywhere within node names. - * - * @param clusters Dictionary output from clusterNodes(). - * @param metagraph - * @return A dictionary from series name => seriesNode - */ -function detectSeriesAnywhereInNodeName( - clusters: { - [clusterId: string]: string[]; - }, - metagraph: graphlib.Graph, - graphOptions: tf_graph.LabeledGraphOptions, -): { - [seriesName: string]: SeriesNode; -} { - let seriesDict: { - [seriesName: string]: SeriesNode; - } = {}; - _.each(clusters, (members, clusterId: string) => { - if (members.length <= 1) { - return; - } // isolated clusters can't make series - /** - * @type {Object} A dictionary mapping a series name to a SeriesNode. - */ - let forwardDict: { - [seriesName: string]: SeriesNode; - } = {}; - /** - * @type {Object} A dictionary mapping member name to an array of series - * names this member could potentially be grouped under and the - * corresponding ids. - */ - let reverseDict: { - [seriesName: string]: any[]; - } = {}; - // Group all nodes that have the same name, with the exception of a - // number at the end of the name after an underscore, which is allowed to - // vary. - _.each(members, (name: string) => { - let isGroup = name.charAt(name.length - 1) === '*'; - let namepath = name.split('/'); - let leaf = namepath[namepath.length - 1]; - let parent = namepath.slice(0, namepath.length - 1).join('/'); - const numRegex = /(?\d+)/g; - let matches = []; - let matchResult; - let prefix; - let id; - let suffix; - let seriesName; - let matched = 0; - // Scan over the entire leaf name and match any possible numbers, - // and put the results into corresponding dictionaries. - while ((matchResult = numRegex.exec(leaf))) { - ++matched; - prefix = leaf.slice(0, matchResult.index); - id = matchResult[0]; - suffix = leaf.slice(matchResult.index + matchResult[0].length); - seriesName = getSeriesNodeName(prefix, suffix, parent); - forwardDict[seriesName] = forwardDict[seriesName]; - if (!forwardDict[seriesName]) { - forwardDict[seriesName] = createSeriesNode(prefix, suffix, parent, Number(id), name, graphOptions); - } - forwardDict[seriesName].ids.push(id); - reverseDict[name] = reverseDict[name] || []; - reverseDict[name].push([seriesName, id]); - } - if (matched < 1) { - prefix = isGroup ? leaf.substr(0, leaf.length - 1) : leaf; - id = 0; - suffix = isGroup ? '*' : ''; - seriesName = getSeriesNodeName(prefix, suffix, parent); - forwardDict[seriesName] = forwardDict[seriesName]; - if (!forwardDict[seriesName]) { - forwardDict[seriesName] = createSeriesNode(prefix, suffix, parent, Number(id), name, graphOptions); - } - forwardDict[seriesName].ids.push(id); - reverseDict[name] = reverseDict[name] || []; - reverseDict[name].push([seriesName, id]); - } - }); - /** @type {Object} A dictionary mapping seriesName to seriesInfoArray, - * which is an array that contains objects with name, id, prefix, suffix, - * and parent properties. - */ - let candidatesDict: { - [seriesName: string]: SeriesNode[]; - } = {}; - // For each of the member, put it into the maximum possible series, - // and create candidatesDict accordingly. - _.each(reverseDict, (seriesNameIdArray, name) => { - seriesNameIdArray.sort((a, b) => { - return forwardDict[b[0]].ids.length - forwardDict[a[0]].ids.length; - }); - let seriesName = seriesNameIdArray[0][0]; - let id = seriesNameIdArray[0][1]; - candidatesDict[seriesName] = candidatesDict[seriesName] || []; - const namepath = name.split('/'); - const leaf = namepath[namepath.length - 1]; - const parent = namepath.slice(0, namepath.length - 1).join('/'); - let seriesNode = createSeriesNode( - forwardDict[seriesName].prefix, - forwardDict[seriesName].suffix, - parent, - Number(id), - name, - graphOptions, - ); - candidatesDict[seriesName].push(seriesNode); - }); - // In each group of nodes, group nodes in bunches that have monotonically - // increasing numbers in their names. Each of these bunches is a series. - _.each(candidatesDict, (seriesInfoArray: SeriesNode[], seriesName) => { - if (seriesInfoArray.length < 2) { - return; - } - seriesInfoArray.sort((a, b) => { - return Number(a.clusterId) - Number(b.clusterId); - }); - // Loop through the nodes sorted by its detected series number, grouping - // all nodes with monotonically-increasing series numbers. - let seriesNodes = [seriesInfoArray[0]]; - for (let index = 1; index < seriesInfoArray.length; index++) { - let nextNode = seriesInfoArray[index]; - if (nextNode.clusterId === seriesNodes[seriesNodes.length - 1].clusterId + 1) { - seriesNodes.push(nextNode); - continue; - } - addSeriesToDict(seriesNodes, seriesDict, Number(clusterId), metagraph, graphOptions); - seriesNodes = [nextNode]; - } - addSeriesToDict(seriesNodes, seriesDict, Number(clusterId), metagraph, graphOptions); - }); - }); - return seriesDict; -} - -/** - * Add a series to the provided dictionary mapping series names to series. - * - * @param seriesNodes the nodes in the series. Contains - * name, id, prefix, suffix and parent properties of the node. - * @param seriesDict the dictionary of series - * @param clusterId ID of the template of the nodes of the series - * @param metagraph - * @param graphOptions - */ -function addSeriesToDict( - seriesNodes: SeriesNode[], - seriesDict: { - [seriesName: string]: SeriesNode; - }, - clusterId: number, - metagraph: graphlib.Graph, - graphOptions: tf_graph.LabeledGraphOptions, -): void { - if (seriesNodes.length > 1) { - let curSeriesName = getSeriesNodeName( - seriesNodes[0].prefix, - seriesNodes[0].suffix, - seriesNodes[0].parent, - seriesNodes[0].clusterId, - seriesNodes[seriesNodes.length - 1].clusterId, - ); - let curSeriesNode = createSeriesNode( - seriesNodes[0].prefix, - seriesNodes[0].suffix, - seriesNodes[0].parent, - clusterId, - curSeriesName, - graphOptions, - ); - _.each(seriesNodes, (node) => { - curSeriesNode.ids.push(node.clusterId); - curSeriesNode.metagraph.setNode(node.name, metagraph.node(node.name)); - }); - seriesDict[curSeriesName] = curSeriesNode; - } -} +} \ No newline at end of file diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/layout.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/layout.ts index 08f441b6abc..485cacc7d83 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/layout.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/layout.ts @@ -42,26 +42,6 @@ export const PARAMS = { */ edgeSep: 5, }, - /** Graph parameter for metanode. */ - series: { - /** - * Dagre's nodesep param - number of pixels that - * separate nodes horizontally in the layout. - * - */ - nodeSep: 5, - /** - * Dagre's ranksep param - number of pixels - * between each rank in the layout. - * - */ - rankSep: 25, - /** - * Dagre's edgesep param - number of pixels that separate - * edges horizontally in the layout. - */ - edgeSep: 5, - }, /** * Padding is used to correctly position the graph SVG inside of its parent * element. The padding amounts are applied using an SVG transform of X and @@ -85,13 +65,6 @@ export const PARAMS = { /** Y-space between each extracted node. */ extractYOffset: 20, }, - series: { - paddingTop: 10, - paddingBottom: 10, - paddingLeft: 10, - paddingRight: 10, - labelHeight: 10, - }, }, nodeSize: { /** Size of meta nodes. */ @@ -136,51 +109,15 @@ export const PARAMS = { labelOffset: -12, maxLabelWidth: 40, }, - /** Size of series nodes. */ - series: { - expanded: { - // For expanded series nodes, width and height will be - // computed to account for the subscene. - radius: 10, - labelOffset: 0, - }, - vertical: { - // When unexpanded, series whose underlying metagraphs contain - // one or more non-control edges will show as a vertical stack - // of ellipses. - width: 16, - height: 13, - labelOffset: -13, - }, - horizontal: { - // When unexpanded, series whose underlying metagraphs contain - // no non-control edges will show as a horizontal stack of - // ellipses. - width: 24, - height: 8, - radius: 10, - labelOffset: -10, - }, - }, - /** Size of bridge nodes. */ - bridge: { - // NOTE: bridge nodes will normally be invisible, but they must - // take up some space so that the layout step leaves room for - // their edges. - width: 20, - height: 20, - radius: 2, - labelOffset: 0, - }, }, shortcutSize: { /** Size of shortcuts for op nodes */ op: { width: 10, height: 4 }, /** Size of shortcuts for meta nodes */ meta: { width: 12, height: 4, radius: 1 }, - /** Size of shortcuts for series nodes */ - series: { width: 14, height: 4 }, + /** Size of shortcuts for multi_collection nodes */ multi_collection: { width: 12, height: 4, radius: 1 }, + /** Size of shortcuts for api_list nodes */ api_list: { width: 12, height: 4, radius: 1 }, }, annotations: { @@ -198,20 +135,6 @@ export const PARAMS = { maxLabelWidth: 40, }, constant: { size: { width: 4, height: 4 } }, - series: { - /** Maximum number of repeated item for unexpanded series node. */ - maxStackCount: 3, - /** - * Positioning offset ratio for collapsed stack - * of parallel series (series without edges between its members). - */ - parallelStackOffsetRatio: 0.2, - /** - * Positioning offset ratio for collapsed stack - * of tower series (series with edges between its members). - */ - towerStackOffsetRatio: 0.5, - }, minimap: { /** The maximum width/height the minimap can have. */ size: 150, @@ -242,8 +165,6 @@ export function layoutScene(renderNodeInfo: render.RenderGroupNodeInfo): void { // Update position of its children nodes and edges if (renderNodeInfo.node.type === NodeType.META) { layoutMetanode(renderNodeInfo, 10); - } else if (renderNodeInfo.node.type === NodeType.SERIES) { - layoutSeriesNode(renderNodeInfo); } else if (renderNodeInfo.node.type === NodeType.MULTI_COLLECTION) { layoutMetanode(renderNodeInfo, 10); } else if (renderNodeInfo.node.type === NodeType.API_LIST) { @@ -292,9 +213,6 @@ function layoutChildren(renderNodeInfo: render.RenderGroupNodeInfo): void { case NodeType.OP: _.extend(childNodeInfo, PARAMS.nodeSize.op); break; - case NodeType.BRIDGE: - _.extend(childNodeInfo, PARAMS.nodeSize.bridge); - break; case NodeType.META: case NodeType.MULTI_COLLECTION: case NodeType.API_LIST: @@ -311,19 +229,6 @@ function layoutChildren(renderNodeInfo: render.RenderGroupNodeInfo): void { layoutScene(childGroupNodeInfo); // Recursively layout its subscene. } break; - case NodeType.SERIES: - if (childNodeInfo.expanded) { - _.extend(childNodeInfo, PARAMS.nodeSize.series.expanded); - let childGroupNodeInfo = childNodeInfo; - layoutScene(childGroupNodeInfo); // Recursively layout its subscene. - } else { - let childGroupNodeInfo = childNodeInfo; - let seriesParams = childGroupNodeInfo.node.hasNonControlEdges - ? PARAMS.nodeSize.series.vertical - : PARAMS.nodeSize.series.horizontal; - _.extend(childNodeInfo, seriesParams); - } - break; default: throw Error(`Unrecognized node type: ${childNodeInfo.node.type}`); } @@ -348,17 +253,11 @@ function dagreLayout(graph: graphlib.Graph, params): { height: number; width: nu ranksep: params.rankSep, edgesep: params.edgeSep, }); - let bridgeNodeNames: any[] = []; let nonBridgeNodeNames: any[] = []; // Split out nodes into bridge and non-bridge nodes, and calculate the total // width we should use for bridge nodes. _.each(graph.nodes(), (nodeName) => { - let nodeInfo = graph.node(nodeName); - if (nodeInfo.node.type === NodeType.BRIDGE) { - bridgeNodeNames.push(nodeName); - } else { - nonBridgeNodeNames.push(nodeName); - } + nonBridgeNodeNames.push(nodeName); }); // If there are no non-bridge nodes, then the graph has zero size. if (!nonBridgeNodeNames.length) { @@ -498,23 +397,7 @@ function layoutMetanode(renderNodeInfo: render.RenderGroupNodeInfo, rankSep: num // Determine the whole metanode's height (from top to bottom). renderNodeInfo.height = renderNodeInfo.paddingTop + renderNodeInfo.coreBox.height + renderNodeInfo.paddingBottom; } -/** - * Calculate layout for series node's core graph. Only called for an expanded - * series. - */ -function layoutSeriesNode(node: render.RenderGroupNodeInfo): void { - let graph = node.coreGraph; - let params = PARAMS.subscene.series; - _.extend(node, params); - // Layout the core. - _.extend(node.coreBox, dagreLayout(node.coreGraph, PARAMS.graph.series)); - _.each(graph.nodes(), (nodeName) => { - graph.node(nodeName).excluded = false; - }); - // Series do not have in/outExtractBox so no need to include them here. - node.width = node.coreBox.width + params.paddingLeft + params.paddingRight; - node.height = node.coreBox.height + params.paddingTop + params.paddingBottom; -} + /** * Calculate layout for annotations of a given node. * This will modify positions of the given node and its annotations. @@ -641,8 +524,6 @@ function sizeAnnotation(a: render.Annotation): void { _.extend(a, PARAMS.shortcutSize.op); } else if (a.node.type === NodeType.META) { _.extend(a, PARAMS.shortcutSize.meta); - } else if (a.node.type === NodeType.SERIES) { - _.extend(a, PARAMS.shortcutSize.series); } else if (a.node.type === NodeType.MULTI_COLLECTION) { _.extend(a, PARAMS.shortcutSize.multi_collection); } else if (a.node.type === NodeType.API_LIST) { diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/node.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/node.ts index f126183b0b6..273eab274f2 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/node.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/node.ts @@ -435,30 +435,9 @@ export function buildShape(nodeGroup, d, nodeClassName: string): d3.Selectiond; - if (groupNodeInfo.coreGraph) { - stampType = groupNodeInfo.node.hasNonControlEdges ? 'vertical' : 'horizontal'; - } - let classList = [Class.Node.COLOR_TARGET]; - if (groupNodeInfo.isFadedOut) { - classList.push('faded-ellipse'); - } - tf_graph_common - .selectOrCreateChild(shapeGroup, 'use', classList) - .attr('xlink:href', `#op-series-${stampType}-stamp`); - tf_graph_common - .selectOrCreateChild(shapeGroup, 'rect', Class.Node.COLOR_TARGET) - .attr('rx', d.radius) - .attr('ry', d.radius); - break; - } case NodeType.META: case NodeType.MULTI_COLLECTION: case NodeType.API_LIST: @@ -478,12 +457,6 @@ export function nodeClass(d: render.RenderNodeInfo): string { return Class.OPNODE; case NodeType.META: return Class.METANODE; - case NodeType.SERIES: - return Class.SERIESNODE; - case NodeType.BRIDGE: - return Class.BRIDGENODE; - case NodeType.ELLIPSIS: - return Class.ELLIPSISNODE; case NodeType.MULTI_COLLECTION: return Class.MULTI_COLLECTION; case NodeType.API_LIST: @@ -694,13 +667,11 @@ export function stylize( const resolvedNodeClassName = nodeClassName || Class.Node.SHAPE || Class.Node.OUTER; const isHighlighted = sceneElement.isNodeHighlighted(renderInfo.node.name); const isSelected = sceneElement.isNodeSelected(renderInfo.node.name); - const isExtract = renderInfo.isInExtract || renderInfo.isOutExtract || renderInfo.isLibraryFunction; const isExpanded = renderInfo.expanded && resolvedNodeClassName !== Class.Annotation.NODE; const isFadedOut = renderInfo.isFadedOut; const isLinked = sceneElement.isNodeLinked(renderInfo.node.name); nodeGroup.classed('highlighted', isHighlighted); nodeGroup.classed('selected', isSelected); - nodeGroup.classed('extract', isExtract); nodeGroup.classed('expanded', isExpanded); nodeGroup.classed('faded', isFadedOut); nodeGroup.classed('linked', isLinked); diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/parser.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/parser.ts index 1d09184187c..ad3047b2572 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/parser.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/parser.ts @@ -50,38 +50,7 @@ export function fetchPbTxt(filepath: string): Promise { }); }); } -/** - * Fetches the metadata file, parses it and returns a promise of the result. - */ -export function fetchAndParseMetadata( - path: string, - tracker: ProgressTracker, -): Promise { - return tf_graph_util - .runTask( - 'Reading metadata pbtxt', - 40, - () => { - if (path == null) { - return Promise.resolve(null); - } - return fetchPbTxt(path); - }, - tracker, - tb_debug.GraphDebugEventId.FETCH_METADATA_PBTXT_BYTES, - ) - .then((arrayBuffer: ArrayBuffer | null) => { - return tf_graph_util.runAsyncPromiseTask( - 'Parsing metadata.pbtxt', - 60, - () => { - return arrayBuffer != null ? parseStatsPbTxt(arrayBuffer) : Promise.resolve(null); - }, - tracker, - tb_debug.GraphDebugEventId.PARSE_METADATA_PBTXT_INTO_OBJECT, - ); - }); -} + /** * Fetches the graph file, parses it and returns a promise of the result. The * result will be undefined if the graph is empty. @@ -215,27 +184,12 @@ const GRAPH_REPEATED_FIELDS: { 'node.attr.value.tensor.string_val': true, 'node.attr.value.tensor.tensor_shape.dim': true, }; -const METADATA_REPEATED_FIELDS: { - [attrPath: string]: boolean; -} = { - 'step_stats.dev_stats': true, - 'step_stats.dev_stats.node_stats': true, - 'step_stats.dev_stats.node_stats.output': true, - 'step_stats.dev_stats.node_stats.memory': true, - 'step_stats.dev_stats.node_stats.output.tensor_description.shape.dim': true, -}; /** * Parses an ArrayBuffer of a proto txt file into a raw Graph object. */ export function parseGraphPbTxt(input: ArrayBuffer): Promise { return parsePbtxtFile(input, GRAPH_REPEATED_FIELDS); } -/** - * Parses an ArrayBuffer of a proto txt file into a StepStats object. - */ -export function parseStatsPbTxt(input: ArrayBuffer): Promise { - return parsePbtxtFile(input, METADATA_REPEATED_FIELDS).then((obj) => obj.step_stats); -} /** * Parses a ArrayBuffer of a proto txt file into javascript object. * diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/proto.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/proto.ts index 3e34fe429be..b8209271c97 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/proto.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/proto.ts @@ -72,34 +72,6 @@ export interface EdgeInfo { value: Record; }[]; } -/** - * Specifies an argument. An argument is either an input or an output of a - * function. There are thus 2 types of arguments: input_args and output_args. - * Nodes outside a function call connect to arguments. The graph explorer - * creates nodes for all arguments within a function. - */ -export interface ArgDef { - name: string; - type: string; -} -/** - * Describes the signature of a function - its name, inputs, and outputs. - */ -export interface OpDef { - name: string; - input_arg: ArgDef[]; - output_arg: ArgDef[]; -} -/** - * Describes a single function within the library. - */ -export interface FunctionDef { - // The definition of the function's name, arguments, return values, - // attrs etc. - signature: OpDef; - // A list of nodes in the function. - node_def: NodeDef[]; -} /** * TensorFlow graph definition as defined in the graph.proto file. */ @@ -109,113 +81,3 @@ export interface GraphDef { // The information of the list of edges. edge?: EdgeInfo[]; } -/** - * Generic graph as defined in the graph_explorer.proto file. - */ -export interface GenericGraph { - /** List of nodes in the graph */ - node: GenericNode[]; - /** List of nodes in the graph */ - edge: GenericEdge[]; - /** List of attributes that describe/modify the operation. */ - attr: Array<{ - [key: string]: any; - }>; -} -/** - * GenericEdge corresponds to the Edge message in graph_explorer.proto. - */ -export interface GenericEdge { - /** Name of the source node. */ - source: string; - /** Name of the target node. */ - target: string; - /** Attributes of the edge. */ - edge_attr: Array<{ - [key: string]: any; - }>; -} -/** - * GenericNode corresponds to the Node message in graph_explorer.proto. - */ -export interface GenericNode { - /** Name of the node */ - name: string; - /** Attributes of a leaf node or leaf nodes within a metanode. */ - node_attr: Array<{ - [key: string]: any; - }>; - /** Attributes of a metanode. */ - metanode_attr: Array<{ - [key: string]: any; - }>; -} -export interface DevStat { - device: string; - node_stats: NodeExecStats[]; -} -/** - * TensorFlow stats file definition as defined in the stats proto file. - */ -export interface StepStats { - dev_stats: DevStat[]; -} -/** - * TensorFlow stats for a node as defined in the step_stats proto file. - */ -export interface NodeExecStats { - node_name: string; - // The next 4 properties are currently stored as string in json - // and must be parsed. - all_start_micros: number; - op_start_rel_micros: number; - op_end_rel_micros: number; - all_end_rel_micros: number; - memory: { - allocator_name: string; - total_bytes: number; // Stored as string in json and should be parsed. - peak_bytes: number; // Stored as string in json and should be parsed. - }[]; - /** Output sizes recorded for a single execution of a graph node */ - output: NodeOutput[]; - timeline_label: string; - scheduled_micros: string; - thread_id: string; -} -/** - * Description for the output tensor(s) of an operation in the graph as - * defined in the step_stats.proto file. - */ -export interface NodeOutput { - slot: number; // Stored as string in json and should be parsed. - tensor_description: { - /** Data type of tensor elements */ - dtype: string; - /** Shape of the tensor */ - shape: { - /** - * Dimensions of the tensor, such as [{name: 'input', size: 30}, - * {name: 'output', size: 40}] for a 30 x 40 2D tensor. The names - * are optional. The order of entries in 'dim' matters: It indicates - * the layout of the values in the tensor in-memory representation. - */ - dim: { - /** Size of the tensor in that dimension */ - size: number; // Stored as string in json and should be parsed. - /** Optional name of the tensor dimension */ - name?: string; - }[]; - }; - /** Information about the size and allocator used for the data */ - allocation_description: { - // The next 2 properties are stored as string in json and - // should be parsed. - /** Total number of bytes requested */ - requested_bytes: number; - /** Total number of bytes allocated, if known */ - allocated_bytes?: number; - /** Name of the allocator used */ - allocator_name: string; - }; - }; -} diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/render.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/render.ts index bfeecbcfe1f..9e4621ed228 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/render.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/render.ts @@ -32,7 +32,6 @@ import { GroupNode, InclusionType, Metaedge, - MetaedgeImpl, Metanode, Node, NodeType, @@ -71,50 +70,8 @@ export const MetanodeColors = { */ DEFAULT_FILL: '#d9d9d9', DEFAULT_STROKE: '#a6a6a6', - SATURATION: 0.6, - LIGHTNESS: 0.85, - /** - * Neutral color to use when the node is expanded (used when coloring by - * compute time, memory and device). - */ - EXPANDED_COLOR: '#f0f0f0', - /** - * Standard hue values for node color palette. - */ - HUES: [220, 100, 180, 40, 20, 340, 260, 300, 140, 60], - STRUCTURE_PALETTE(id: number, lightened?: boolean): string { - // The code below is a flexible way to computationally create a set - // of colors that go well together. - let hues = MetanodeColors.HUES; - let n = hues.length; - let hue = hues[id % n]; - let m = Math.sin((hue * Math.PI) / 360); - let sat = lightened ? 30 : 90 - (60 * m); - let light = lightened ? 95 : 80; - return d3.hsl(hue, 0.01 * sat, 0.01 * light).toString(); - }, - DEVICE_PALETTE(index: number): string { - return MetanodeColors.STRUCTURE_PALETTE(index); - }, - XLA_CLUSTER_PALETTE(index: number): string { - return MetanodeColors.STRUCTURE_PALETTE(index); - }, - UNKNOWN: '#eee', GRADIENT_OUTLINE: '#888', }; -/** - * Color parameters for op nodes. - */ -export const SeriesNodeColors = { - DEFAULT_FILL: 'white', - DEFAULT_STROKE: '#b2b2b2', -}; -/** - * Function that computes edge thickness in pixels. - */ -export interface EdgeThicknessFunction { - (edgeData: EdgeData, edgeClass: string): number; -} /** * Function that computes edge label strings. This function accepts a Metaedge, * which could actually encapsulate several base edges. For instance, several @@ -130,66 +87,6 @@ export interface EdgeLabelFunction { * Parameters that affect how the graph is rendered on the screen. */ const PARAMS = { - /** - * The minimum number of nodes for a graph to have in order for high in and - * out degree nodes to be extracted in auxiliary. The aim here is to prevent - * nodes from being extracted from small graphs. - */ - minNodeCountForExtraction: 15, - /** - * The minimum in or out degree a node must have in order to be possibly - * extracted. - */ - minDegreeForExtraction: 5, - /** - * Maximum number of control edges a node can have before they aren't - * displayed. - */ - maxControlDegree: 4, - /** - * Maximum in (for outbound bridge paths) or out (for inbound bridge paths) - * degree of a node allowed for a bridge path to be rendered to it from a - * subhierarchy of nodes. Having a max prevents having too many nodes emanate - * from a subhierarchy and crowding up. - */ - maxBridgePathDegree: 4, - /** - * Types patterns for predefined out-extract nodes, which are - * sink-like nodes that will be extracted from the main graph. - */ - outExtractTypes: ['NoOp'], - /** - * Types patterns for predefined in-extract nodes, which are - * source-like nodes that will be extracted from the main graph. - */ - inExtractTypes: [], - /** - * When removing edges from a high degree node, remove all of its edges if - * detachAllEdgesForHighDegree is true. Otherwise remove all in-edges if - * the node has high in-degree, or all out-edges if the node has high - * out-degree. - */ - detachAllEdgesForHighDegree: true, - /** - * After extracting high in/out degree nodes and predefined - * source-like/sink-like, extract isolated nodes to the side - * if this extractIsolatedNodesWithAnnotationsOnOneSide is true. - */ - extractIsolatedNodesWithAnnotationsOnOneSide: true, - /** - * Whether to add bridge nodes and edges to the core when building the - * subhierarchy of an expanded metanode. See buildSubhierarchy(). - */ - enableBridgegraph: true, - /** - * 2 colors, for the minimum and maximum value respectively, whenever we - * have a gradient scale. - */ - minMaxColors: ['#fff5f0', '#fb6a4a'], - /** - * Maximum number of annotations to be displayed on a node before an - * ellipsis is used. - */ maxAnnotations: 5, }; /** @@ -339,10 +236,6 @@ export class RenderGraphInfo { return nodeName; } - setDepth(depth: number): void { - setGroupNodeDepth(this.root, Number(depth)); - } - /** * Returns true if the renderNode is an isolated node within its parent node. */ @@ -360,15 +253,6 @@ export class RenderGraphInfo { return !!found; } - /** - * Returns a list of ops that have been rendered so far for this graph. More - * ops may later be rendered if the user expands nodes for instance. The list - * returned here can only stay the same size or grow on successive calls. - */ - getNamesOfRenderedOps(): string[] { - return this.renderedOpNames; - } - buildSubhierarchy(nodeName: string, subGraph: tf_graph.SlimGraph | undefined = undefined): void { // Terminate if the rendering hierarchy was already constructed // for this node. @@ -432,184 +316,12 @@ export class RenderGraphInfo { }); } }); - // Add render metaedge info for edges in the metagraph. - _.each(metagraph.edges(), (edgeObj) => { - if (edgeObj.v.includes(tf_graph.NAMESPACE_DELIM) || edgeObj.w.includes(tf_graph.NAMESPACE_DELIM)) { - let inbound = edgeObj.w.includes(tf_graph.NAMESPACE_DELIM); - if (inbound) { - let pathNames = edgeObj.w.split(tf_graph.NAMESPACE_DELIM); - this.toRenderEdgeObjs.push({ - v: edgeObj.v, - w: pathNames[pathNames.length - 1], - id: edgeObj.name, - edge: metagraph.edge(edgeObj), - }); - } else { - let pathNames = edgeObj.v.split(tf_graph.NAMESPACE_DELIM); - this.toRenderEdgeObjs.push({ - v: pathNames[pathNames.length - 1], - w: edgeObj.w, - id: edgeObj.name, - edge: metagraph.edge(edgeObj), - }); - } - return; - } - let metaedge = metagraph.edge(edgeObj); - let renderMetaedgeInfo = new RenderMetaedgeInfo(metaedge as any); - renderMetaedgeInfo.isFadedOut = this.index[edgeObj.v].isFadedOut || this.index[edgeObj.w].isFadedOut; - coreGraph.setEdge(edgeObj.v, edgeObj.w, renderMetaedgeInfo, edgeObj.name); - }); // Look up the parent node's render information and short circuit if none. let parentNode = renderGroupNodeInfo.node.parentNode; if (!parentNode) { return; } - // Utility function for computing the name of a bridge node. - let getBridgeNodeName = (inbound, ...rest): string => rest.concat([inbound ? 'IN' : 'OUT']).join('~~'); - if (subGraph) { - const subNodes = Object.keys(subGraph.metaNodes).concat(Object.keys(subGraph.nodes)); - renderNodeInfo.node.cardinality += subNodes.length; - const parentMetagraph = (parentNode as GroupNode).metagraph; - const parentBridgegraph = (parentNode as GroupNode).bridgegraph; - _.each(subNodes, (subName) => { - this.toRenderEdgeObjs - .filter((e) => e.v === subName || e.w === subName) - .forEach((item) => { - const edgeObj = item.edge; - const inbound = item.w === subName; - const edgeIO = inbound - ? [edgeObj.v?.split(tf_graph.NAMESPACE_DELIM)[0], nodeName] - : [nodeName, edgeObj.w?.split(tf_graph.NAMESPACE_DELIM)[0]]; - let bridgeMetaedge = parentMetagraph.edge(...edgeIO, item.id); - if (!bridgeMetaedge) { - bridgeMetaedge = parentBridgegraph.edge(...edgeIO, item.id); - if (!bridgeMetaedge) { - return; - } - } - _.each(edgeObj.baseEdgeList, (baseEdge) => { - let name = inbound ? baseEdge.v : baseEdge.w; - if (baseEdge.attr) { - baseEdge.attr._path = name; - } else { - baseEdge.attr = { _path: name }; - } - if (inbound) { - baseEdge.v = name?.split(tf_graph.NAMESPACE_DELIM).pop(); - baseEdge.w = subName; - } else { - baseEdge.v = subName; - baseEdge.w = name?.split(tf_graph.NAMESPACE_DELIM).pop(); - } - bridgeMetaedge.addBaseEdge(baseEdge, this.hierarchy, true); - }); - }); - }); - } - // Remove rendered edges to save memory. - this.toRenderEdgeObjs = this.toRenderEdgeObjs.filter((e) => !this.index[e.v] || !this.index[e.w]); - // Build out the bridgegraph. - let bridgegraph = this.hierarchy.getBridgegraph(nodeName); - // Look for popular nodes so we can make annotations instead of paths. - let otherCounts = { - // Counts of edges coming INTO other nodes by name (outgoing from self). - in: < - { - [nodeName: string]: number; - } - >{}, - // Counts of edges going OUT from other nodes by name (coming into self). - out: < - { - [nodeName: string]: number; - } - >{}, - // Counts of all control edges involving other nodes by name. - control: < - { - [nodeName: string]: number; - } - >{}, - }; - _.each(bridgegraph.edges(), (e) => { - // An edge is inbound if its destination node is in the metagraph. - let inbound = !!metagraph.node(e.w); - let otherName = inbound ? e.v : e.w; - let metaedge = bridgegraph.edge(e); - if (!metaedge.numRegularEdges) { - otherCounts.control[otherName] = (otherCounts.control[otherName] || 0) + 1; - } else if (inbound) { - otherCounts.out[otherName] = (otherCounts.out[otherName] || 0) + 1; - } else { - otherCounts.in[otherName] = (otherCounts.in[otherName] || 0) + 1; - } - }); - // For each bridge container (IN and/or OUT), add structural edges between - // terminal nodes and that container. A terminal node is one which has no - // non-bridge edges in the direction of the container. - // - // For example, consider a Metanode A which contains two child nodes A/B - // and A/C. Let's say it has one edge in the metagraph from A/B->A/C, and - // one edge in the bridgegraph from Z->A/C. - // - // At this point, we've added a container bridge node IN to house all - // incoming bridge nodes. We've also added a bridge node Z' (with parent IN) - // to A, and a bridge edge from Z'->C. - // - // +----------------------+ - // | A +---+ | - // | +------>| C | | - // | | +---+ | - // | | ^ | - // | | | | - // | | +----|----+ | - // | | | IN | | | - // | +---+ | +---+ | | - // | | B | | | Z'| | | - // | +---+ | +---+ | | - // | +---------+ | - // +----------------------+ - // - // With no other help, dagre would lay out B and Z' on the same level, - // because both of them have no incoming edges. In other words, B is a - // terminal node in the INCOMING direction. - // - // But we want to force dagre to lay out Z' (and everything in IN) lower - // than all non-bridge nodes, so that there's enough room for the bridge - // edges after they've been adjusted to meet up with paths coming in from - // outside. - // - // To force Z' (and all other bridge nodes) to be lowest in the graph, we - // identify terminal nodes like B and give them structural edges to - // a new structural bridge node S which we add to IN. - // - // +----------------------+ - // | A +---+ | - // | +--->| C | | - // | | +---+ | - // | +---+ ^ | - // | | B | | | - // | +---+ | | - // | ^ | | - // | | | | - // | +----|------|----+ | - // | |IN | | | | - // | | +---+ +---+ | | - // | | | S | | Z'| | | - // | | +---+ +---+ | | - // | +----------------+ | - // +----------------------+ - // - // This ensures that dagre will lay out the bridge containers strictly at - // the ends of the graph. The structural edges will never be seen in the - // visualization except as a debugging aid. _.each([true, false], (inbound) => { - let bridgeContainerName = getBridgeNodeName(inbound, nodeName); - let bridgeContainerInfo = coreGraph.node(bridgeContainerName); - if (!bridgeContainerInfo) { - return; - } _.each(coreGraph.nodes(), (childName) => { // Short-circuit if this child is a bridge node or it's not a terminal // node in the direction we're interested in. @@ -623,44 +335,6 @@ export class RenderGraphInfo { if (!isTerminal) { return; } - // Find or create a bridge node in the container for all structural - // metaedges. It would have been nice to skip this step and simply - // set a metaedge between the terminal node and the container node, but - // in that case, something about the graph upsets dagre.layout()'s - // longestPath algorithm (was getting errors due to an undefined). - let structuralNodeName = getBridgeNodeName(inbound, nodeName, 'STRUCTURAL_TARGET'); - let structuralRenderInfo = coreGraph.node(structuralNodeName); - if (!structuralRenderInfo) { - let bridgeNode: BridgeNode = { - // Important Node properties. - name: structuralNodeName, - type: NodeType.BRIDGE, - // Unimportant Node properties. - isGroupNode: false, - cardinality: 1, - parentNode: null, - include: InclusionType.UNSPECIFIED, - // BridgeNode properties. - inbound: inbound, - inputData: {}, - outputData: {}, - suggestions: {}, - nodeAttributes: {}, - }; - structuralRenderInfo = new RenderNodeInfo(bridgeNode); - structuralRenderInfo.structural = true; - this.index[structuralNodeName] = structuralRenderInfo as any; - coreGraph.setNode(structuralNodeName, structuralRenderInfo); - bridgeContainerInfo.node.cardinality++; - coreGraph.setParent(structuralNodeName, bridgeContainerName); - } - // Create the structural Metaedge and insert it. - let structuralMetaedgeInfo = new RenderMetaedgeInfo(null); - structuralMetaedgeInfo.structural = true; - structuralMetaedgeInfo.weight--; // Reduce weight for dagre layout. - inbound - ? coreGraph.setEdge(structuralNodeName, childName, structuralMetaedgeInfo) - : coreGraph.setEdge(childName, structuralNodeName, structuralMetaedgeInfo); }); }); } @@ -943,21 +617,6 @@ export class RenderNodeInfo { paddingLeft: number; paddingRight: number; paddingBottom: number; - /** - * Whether a node is extracted as source-like (having high out-degree or - * matching predefined in-extract pattern.) - */ - isInExtract: boolean; - /** - * Whether a node is extracted as sink-like (having high in-degree or matching - * predefined out-extract pattern.) - */ - isOutExtract: boolean; - /** - * Whether a node represents a function template within the library, in which - * case it should be rendered in a special scene group. - */ - isLibraryFunction: boolean; /** * Whether this node is faded out. Used when displaying stats. */ @@ -990,8 +649,6 @@ export class RenderNodeInfo { this.paddingLeft = 0; this.paddingRight = 0; this.paddingBottom = 0; - this.isInExtract = false; - this.isOutExtract = false; this.coreBox = { width: 0, height: 0 }; // By default, we don't fade nodes out. Default to false for safety. this.isFadedOut = false; @@ -1038,10 +695,6 @@ export class RenderNodeInfo { } } } - - isInCore(): boolean { - return !this.isInExtract && !this.isOutExtract && !this.isLibraryFunction; - } } /** * Contains rendering information about a Metaedge from the underlying @@ -1131,7 +784,6 @@ function setGraphDepth(graph: graphlib.Graph, depth: number): void { case NodeType.META: case NodeType.MULTI_COLLECTION: case NodeType.API_LIST: - case NodeType.SERIES: setGroupNodeDepth(child, depth - 1); break; default: @@ -1188,165 +840,3 @@ function setGroupNodeDepth(renderInfo: RenderGroupNodeInfo, depth: number): void setGraphDepth(renderInfo.coreGraph, depth); } } -/** - * Remove an edge from the graph and add annotations to both ends of the edge. - * - * @param The core graph. - * @param v Source name. - * @param w Sink name. - */ -function createShortcut(graph: graphlib.Graph, v: string, w: string): void { - let src = graph.node(v) as any; - let sink = graph.node(w) as any; - let edge = graph.edge(v, w) as any; - // If either of the nodes is explicitly included in the main graph and - // both nodes are in the main graph then do not create the shortcut - // and instead keep the real edge. - const isInclude = src.node.include === InclusionType.INCLUDE || sink.node.include === InclusionType.INCLUDE; - const isExclude = src.node.include === InclusionType.EXCLUDE || sink.node.include === InclusionType.EXCLUDE; - if (isInclude && !isExclude) { - return; - } - - // Add each annotation. - addOutAnnotation(src, sink.node, sink, edge, AnnotationType.SHORTCUT); - addInAnnotation(sink, src.node, src, edge, AnnotationType.SHORTCUT); - // Remove the edge from the core graph. - graph.removeEdge(v, w); -} -/** - * Remove edges from a node, and set its isOutExtract property to true, - * and remove the node and move it to isolatedOutExtract. - * - * If detachAllEdgesForHighDegree or forceDetach is true, extract all of its - * edges. Otherwise, only extract all in-edges. - */ -function makeOutExtract(renderNode: RenderGroupNodeInfo, n: string, forceDetach?: boolean): void { - let graph = renderNode.coreGraph; - let child = graph.node(n) as any; - child.isOutExtract = true; - _.each(graph.predecessors(n), (p, index) => { - createShortcut(graph, p, n); - }); - if (PARAMS.detachAllEdgesForHighDegree || forceDetach) { - _.each(graph.successors(n), (s, index) => { - createShortcut(graph, n, s); - }); - } - // Remove the node from the core graph if it no longer has neighbors. - if (graph.neighbors(n)?.length === 0) { - child.node.include = InclusionType.EXCLUDE; - renderNode.isolatedOutExtract.push(child); - graph.removeNode(n); - } -} -/** - * Remove edges from a node, set its isInExtract property to true, - * and remove the node and move it to isolatedInExtract. - * - * If detachAllEdgesForHighDegree or forceDetach is true, extract all of its - * edges. Otherwise, only remove all out-edges. - */ -export function makeInExtract(renderNode: RenderGroupNodeInfo, n: string, forceDetach?: boolean): void { - let graph = renderNode.coreGraph; - let child = graph.node(n) as any; - child.isInExtract = true; - _.each(graph.successors(n), (s, index) => { - createShortcut(graph, n, s); - }); - if (PARAMS.detachAllEdgesForHighDegree || forceDetach) { - _.each(graph.predecessors(n), (p, index) => { - createShortcut(graph, p, n); - }); - } - // Remove the node from the core graph if it no longer has neighbors. - if (graph.neighbors(n)?.length === 0) { - child.node.include = InclusionType.EXCLUDE; - renderNode.isolatedInExtract.push(child); - graph.removeNode(n); - } -} -/** - * Check whether the node's type is a member of the given list of types. - * - * @param node Node. - * @param types List of type to match. - */ -function hasTypeIn(node: Node, types: string[]): boolean { - if (node.type === NodeType.OP) { - for (let i = 0; i < types.length; i++) { - if ((node).op === types[i]) { - return true; - } - } - } else if (node.type === NodeType.META) { - let rootOpNode = (node).getRootOp(); - if (rootOpNode) { - for (let i = 0; i < types.length; i++) { - if (rootOpNode.op === types[i]) { - return true; - } - } - } - } - return false; -} -/** - * Given an integer, picks a hue that is far apart from other colors. - * The formula for picking color that avoid collision is: - * hue = (color range * golden ratio * index) % color range - */ -export function mapIndexToHue(id: number): number { - let GOLDEN_RATIO = 1.61803398875; - // Hue of 0 is reserved for the gray nodes. - let MIN_HUE = 1; - let MAX_HUE = 359; - let COLOR_RANGE = MAX_HUE - MIN_HUE; - return MIN_HUE + ((COLOR_RANGE * GOLDEN_RATIO * id) % COLOR_RANGE); -} -/** - * Remove edges and add to annotation instead. - * - * For root node, consider predefined types for source and sink. - * We do not extract predefined type from non-root so that Variables and the - * sgd node (op type = 'NoOp') do not get extract from inside own group. - * - * The order of extraction is important here as swapping the order can totally - * screw up the graph layout. - * - * @param {Render.Node} renderNode Node to manipulate. - * nodes from the main graph. If false, only exclude predefined nodes. - */ -/** - * Expands nodes in the graph until the desired node is visible. - * - * @param scene The scene polymer component. - * @param renderHierarchy The render hierarchy. - * @param tensorName The name of a tensor. - * @return A string that is the name of the node representing the given tensor. - * Note that the original tensor name might differ from this returned node - * name. Specifically, for instance, the tensor name usually ends with an - * output slot index (such as :0), while the node name lacks that suffix. - */ -export function expandUntilNodeIsShown(scene, renderHierarchy: RenderGraphInfo, tensorName: string): string { - const splitTensorName = tensorName.split('/'); - // Graph names do not take into account the output slot. Strip it. - const lastNodeNameMatch = splitTensorName[splitTensorName.length - 1].match(/(?.*)\w+/); - if (lastNodeNameMatch?.length === 2) { - splitTensorName[splitTensorName.length - 1] = lastNodeNameMatch?.[1]; - } - let nodeName = splitTensorName[0]; - let renderNode = renderHierarchy.getRenderNodeByName(nodeName); - for (let i = 1; i < splitTensorName.length; i++) { - // Op nodes are not expandable. - if (renderNode.node.type === tf_graph.NodeType.OP) { - break; - } - renderHierarchy.buildSubhierarchy(nodeName); - renderNode.expanded = true; - scene.setNodeExpanded(renderNode); - nodeName += `/${splitTensorName[i]}`; - renderNode = renderHierarchy.getRenderNodeByName(nodeName); - } - return renderNode.node.name; -} diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/scene.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/scene.ts index 9ed02cea768..3e13d0700d9 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/scene.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/scene.ts @@ -201,7 +201,7 @@ export function position(sceneGroup, renderNode: render.RenderGroupNodeInfo): vo // expanded metanodes, the graphs are below the labels. Do not shift them // down for series nodes as series nodes don't have labels inside of their // bounding boxes. - let yTranslate = renderNode.node.type === NodeType.SERIES ? 0 : layout.PARAMS.subscene.meta.labelHeight; + let yTranslate = layout.PARAMS.subscene.meta.labelHeight; // core translate(selectChild(sceneGroup, 'g', Class.Scene.CORE), 0, yTranslate); // in-extract diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/tf-graph-icon.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/tf-graph-icon.ts index 6d42c6acb0a..a686c9d04f3 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/tf-graph-icon.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/tf-graph-icon.ts @@ -18,7 +18,7 @@ import { html, PolymerElement } from '@polymer/polymer'; import { DarkModeMixin } from '../polymer/dark_mode_mixin'; import { LegacyElementMixin } from '../polymer/legacy_element_mixin'; import '../tf_dashboard_common/tensorboard-color'; -import { MetanodeColors, OpNodeColors, SeriesNodeColors } from './render'; +import { MetanodeColors, OpNodeColors } from './render'; export enum GraphIconType { CONST = 'CONST', @@ -230,8 +230,6 @@ class TfGraphIcon extends LegacyElementMixin(DarkModeMixin(PolymerElement)) { switch (type) { case GraphIconType.META: return MetanodeColors.DEFAULT_FILL; - case GraphIconType.SERIES: - return SeriesNodeColors.DEFAULT_FILL; default: return OpNodeColors.DEFAULT_FILL; } @@ -247,8 +245,6 @@ class TfGraphIcon extends LegacyElementMixin(DarkModeMixin(PolymerElement)) { switch (type) { case GraphIconType.META: return MetanodeColors.DEFAULT_STROKE; - case GraphIconType.SERIES: - return SeriesNodeColors.DEFAULT_STROKE; default: return OpNodeColors.DEFAULT_STROKE; } diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_loader/tf-graph-dashboard-loader.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_loader/tf-graph-dashboard-loader.ts index 58dc7350d0f..da3df789863 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_loader/tf-graph-dashboard-loader.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_loader/tf-graph-dashboard-loader.ts @@ -313,20 +313,6 @@ class TfGraphDashboardLoader extends LegacyElementMixin(PolymerElement) { } } - _readAndParseMetadata(path: string): void { - // Reset the progress bar to 0. - this.set('progress', { - value: 0, - msg: '', - }); - let tracker = tf_graph_util.getTracker(this); - tf_graph_parser.fetchAndParseMetadata(path, tracker).then( - (stats) => { - this.set('outStats', stats) - } - ); - } - _fetchAndConstructHierarchicalGraph(path: string | null, pbTxtFile?: Blob): Promise { // Reset the progress bar to 0. this.set('progress', { -- Gitee From 02694873b9bbb5ce2f6e27d2d7760102b2b7cf34 Mon Sep 17 00:00:00 2001 From: liguanchi Date: Mon, 24 Mar 2025 17:30:13 +0800 Subject: [PATCH 03/14] =?UTF-8?q?=E5=86=97=E4=BD=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fe/src/tf_graph_common/node.ts | 23 +---- .../fe/src/tf_graph_common/scene.ts | 84 +------------------ 2 files changed, 4 insertions(+), 103 deletions(-) diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/node.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/node.ts index 273eab274f2..76c4a1d0b87 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/node.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/node.ts @@ -23,7 +23,7 @@ import { Class, FontSizeInPx, selectChild, selectOrCreateChild } from './common' import * as contextmenu from './contextmenu'; import * as edge from './edge'; import * as tf_graph from './graph'; -import { MetanodeImpl, Node, NodeType, OpNode, OpNodeImpl, SeriesNode } from './graph'; +import { MetanodeImpl, Node, NodeType, OpNode, OpNodeImpl } from './graph'; import * as layout from './layout'; import * as render from './render'; import { RenderNodeInfo } from './render'; @@ -509,27 +509,6 @@ function position(nodeGroup, d: render.RenderNodeInfo): void { } break; } - case NodeType.SERIES: { - let shape = tf_graph_scene.selectChild(shapeGroup, 'use'); - if (d.expanded) { - tf_graph_scene.positionRect(shape, d.x, d.y, d.width, d.height); - subscenePosition(nodeGroup, d); - // put label on top - labelPosition(nodeGroup, cx, d.y, (-d.height / 2) + (d.labelHeight / 2)); - } else { - tf_graph_scene.positionRect(shape, cx, d.y, d.coreBox.width, d.coreBox.height); - labelPosition(nodeGroup, cx, d.y, d.labelOffset); - } - break; - } - case NodeType.BRIDGE: { - // position shape - // NOTE: In reality, these will not be visible, but it helps to put them - // in the correct position for debugging purposes. - let shape = tf_graph_scene.selectChild(shapeGroup, 'rect'); - tf_graph_scene.positionRect(shape, d.x, d.y, d.width, d.height); - break; - } case NodeType.MULTI_COLLECTION: case NodeType.API_LIST: { // position shape diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/scene.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/scene.ts index 3e13d0700d9..152c1e1b6ae 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/scene.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/scene.ts @@ -16,9 +16,8 @@ Copyright (c) 2025, Huawei Technologies. Adapt to the model hierarchical visualization data collected by the msprobe tool ==============================================================================*/ import * as d3 from 'd3'; -import * as PolymerDom from '../polymer/dom'; -import { Class as _Class, selectChild as _selectChild, SVG_NAMESPACE } from './common'; -import { NodeType, OpNode } from './graph'; +import { Class as _Class, selectChild as _selectChild } from './common'; +import { NodeType } from './graph'; import * as layout from './layout'; import * as render from './render'; @@ -30,66 +29,6 @@ export const Class = _Class; */ const MINIMAP_BOX_WIDTH = 320; const MINIMAP_BOX_HEIGHT = 150; -/** - * A health pill encapsulates an overview of tensor element values. The value - * field is a list of 12 numbers that shed light on the status of the tensor. - * Visualized in health pills are the 3rd through 8th (inclusive) numbers of - * health pill values. Those 6 numbers are counts of tensor elements that fall - * under -Inf, negative, 0, positive, +Inf, NaN (in that order). - * - * Please keep this interface consistent with HealthPillDatum within - * backend.ts. - */ -export interface HealthPill { - device_name: string; - node_name: string; - output_slot: number; - dtype: string; - shape: number[]; - value: number[]; - wall_time: number; - step: number; -} -interface HealthPillNumericStats { - min: number; - max: number; - mean: number; - stddev: number; -} -/** - * Encapsulates how to render a single entry in a health pill. Each entry - * corresponds to a category of tensor element values. - */ -export interface HealthPillEntry { - background_color: string; - label: string; -} -export const healthPillEntries: HealthPillEntry[] = [ - { - background_color: '#CC2F2C', - label: 'NaN', - }, - { - background_color: '#FF8D00', - label: '-∞', - }, - { - background_color: '#EAEAEA', - label: '-', - }, - { - background_color: '#A5A5A5', - label: '0', - }, - { - background_color: '#262626', - label: '+', - }, - { - background_color: '#003ED4', - label: '+∞', - }, -]; /** * Helper method for fitting the graph in the svg view. * @@ -274,24 +213,7 @@ export function positionRect(rect, cx: number, cy: number, width: number, height .attr('width', width) .attr('height', height); } -/** - * Positions a triangle and sizes it. - * @param polygon polygon to set position of. - * @param cx Center x. - * @param cy Center y. - * @param width Width of bounding box for triangle. - * @param height Height of bounding box for triangle. - */ -export function positionTriangle(polygon, cx, cy, width, height): void { - const halfHeight = height / 2; - const halfWidth = width / 2; - const points = [ - [cx, cy - halfHeight], - [cx + halfWidth, cy + halfHeight], - [cx - halfWidth, cy + halfHeight], - ]; - polygon.transition().attr('points', points.map((point) => point.join(',')).join(' ')); -} + /** * Helper for setting position of a svg expand/collapse button * @param button container group -- Gitee From 49fe16c41e077b25e7d8b32862a91c0dd2c5660a Mon Sep 17 00:00:00 2001 From: wangqingcai Date: Mon, 24 Mar 2025 15:29:11 +0800 Subject: [PATCH 04/14] bugfix: fix spelling errors in log message. --- debug/accuracy_tools/msprobe/pytorch/monitor/csv2tb.py | 2 +- .../msprobe/pytorch/monitor/distributed/wrap_distributed.py | 4 ++-- .../msprobe/pytorch/monitor/unittest/test_monitor.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/debug/accuracy_tools/msprobe/pytorch/monitor/csv2tb.py b/debug/accuracy_tools/msprobe/pytorch/monitor/csv2tb.py index 6ffd1ffabe7..588b1f97d14 100644 --- a/debug/accuracy_tools/msprobe/pytorch/monitor/csv2tb.py +++ b/debug/accuracy_tools/msprobe/pytorch/monitor/csv2tb.py @@ -119,7 +119,7 @@ def check_process_num(process_num): def check_data_type_list(data_type_list): if data_type_list is None: - logger.info(f"data_type_list is None, use defualt all_data_type_list: {all_data_type_list}") + logger.info(f"data_type_list is None, use default all_data_type_list: {all_data_type_list}") return if not isinstance(data_type_list, list): raise ValueError(f"data_type_list({data_type_list}) is not a list") diff --git a/debug/accuracy_tools/msprobe/pytorch/monitor/distributed/wrap_distributed.py b/debug/accuracy_tools/msprobe/pytorch/monitor/distributed/wrap_distributed.py index 20ef3757d4a..c209fdba97f 100644 --- a/debug/accuracy_tools/msprobe/pytorch/monitor/distributed/wrap_distributed.py +++ b/debug/accuracy_tools/msprobe/pytorch/monitor/distributed/wrap_distributed.py @@ -142,7 +142,7 @@ def get_process_group(process_group): def stack_filter(stack): if len(stack) > MAX_STRING_LENGTH: - logger.warning(f'The character strin contains more than {MAX_STRING_LENGTH}. re match is skipped.') + logger.warning(f'The character string contains more than {MAX_STRING_LENGTH}. re match is skipped.') for pattern in StackBlackList: if re.search(pattern, stack): return False @@ -197,7 +197,7 @@ def is_target_line(codeline): stack = get_callstack() whole_stack = ';'.join(stack) if len(whole_stack) > MAX_STRING_LENGTH: - logger.warning(f'The character strin contains more than {MAX_STRING_LENGTH}. re match is skipped.') + logger.warning(f'The character string contains more than {MAX_STRING_LENGTH}. re match is skipped.') for pattern in codeline: if re.search(pattern, whole_stack): return True diff --git a/debug/accuracy_tools/msprobe/pytorch/monitor/unittest/test_monitor.py b/debug/accuracy_tools/msprobe/pytorch/monitor/unittest/test_monitor.py index 4d5c1a717d8..acdb34ff5aa 100644 --- a/debug/accuracy_tools/msprobe/pytorch/monitor/unittest/test_monitor.py +++ b/debug/accuracy_tools/msprobe/pytorch/monitor/unittest/test_monitor.py @@ -92,7 +92,7 @@ def valid_reduce(reduced, unreduced, tp_size, dp_size, sequence_parallel): if errors: logger.info(errors) else: - logger.info(f'grad mean is in consist between unreduced grad and reduced grad monitord.') + logger.info(f'grad mean is in consist between unreduced grad and reduced grad monitored.') def assert_equal(a, b): -- Gitee From bb09a4b4678fd8d4771ecf5718a75020575161af Mon Sep 17 00:00:00 2001 From: wangqingcai Date: Mon, 24 Mar 2025 15:30:20 +0800 Subject: [PATCH 05/14] bugfix: fix log level --- debug/accuracy_tools/msprobe/pytorch/monitor/module_hook.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debug/accuracy_tools/msprobe/pytorch/monitor/module_hook.py b/debug/accuracy_tools/msprobe/pytorch/monitor/module_hook.py index 700d5673869..1a0c393cadf 100644 --- a/debug/accuracy_tools/msprobe/pytorch/monitor/module_hook.py +++ b/debug/accuracy_tools/msprobe/pytorch/monitor/module_hook.py @@ -339,11 +339,11 @@ class TrainerMon: # 初始化writer, 创建输出目录 if self.format not in FORMAT_MAPPING: - logger.error(f"Unsupported format: {self.format}, use default format: {MonitorConst.CSV}") + logger.warning(f"Unsupported format: {self.format}, use default format: {MonitorConst.CSV}") self.format = MonitorConst.CSV if self.ur_distribution and self.format != 'tensorboard': - logger.error("can only set ur_distribution when format is 'tensorboard', cancel ur_distribution") + logger.warning("can only set ur_distribution when format is 'tensorboard', cancel ur_distribution") self.ur_distribution = False writer = FORMAT_MAPPING[self.format] -- Gitee From 59da543b8015b5deabe67aa7c5b1fd34a3897f4e Mon Sep 17 00:00:00 2001 From: liguanchi Date: Tue, 25 Mar 2025 14:27:33 +0800 Subject: [PATCH 06/14] =?UTF-8?q?=E5=86=97=E4=BD=99=E6=B8=85=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fe/src/tf_graph_board/tf-graph-board.ts | 54 ++++++++++++++- .../fe/src/tf_graph_common/tf-graph-icon.ts | 66 ------------------- .../fe/src/tf_graph_common/tf-node-icon.ts | 2 - 3 files changed, 52 insertions(+), 70 deletions(-) diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_board/tf-graph-board.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_board/tf-graph-board.ts index 81b79b708d7..cdfd6667bf9 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_board/tf-graph-board.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_board/tf-graph-board.ts @@ -203,8 +203,22 @@ class TfGraphBoard extends LegacyElementMixin(PolymerElement) { @property({ type: Object }) hierarchyParams: tf_graph_hierarchy.HierarchyParams = tf_graph_hierarchy.DefaultHierarchyParams; - @property({ type: Boolean, notify: true }) - allStepsModeEnabled: boolean = false; + /** + * A number between 0 and 100 denoting the % of progress + * for the progress bar and the displayed message. + * @type {{value: number, msg: string}} + */ + @property({ type: Object }) + progress: object; + + @property({ type: Boolean }) + traceInputs: boolean; + + @property({ type: Boolean }) + autoExtractNodes: boolean; + + @property({ type: Object, notify: true }) + renderHierarchy: tf_graph_render.MergedRenderGraphInfo; @property({ type: Object }) menu: any; @@ -212,6 +226,42 @@ class TfGraphBoard extends LegacyElementMixin(PolymerElement) { @property({ type: Object }) colorset: any; + @property({ type: String, notify: true }) + selectedNode: string; + + @property({ type: Object, notify: true }) + selectedEdge: tf_graph_render.EdgeData; + + // A function with signature EdgeThicknessFunction that computes the + // thickness of a given edge. + @property({ type: Object }) + edgeWidthFunction: object; + + @property({ type: String }) + _highlightedNode: string; + + // An optional function that takes a node selected event (whose `detail` + // property is the selected node ... which could be null if a node is + // deselected). Called whenever a node is selected or deselected. + @property({ type: Object }) + handleNodeSelected: object; + + // An optional function that computes the label for an edge. Should + // implement the EdgeLabelFunction signature. + @property({ type: Object }) + edgeLabelFunction: object; + + // An optional callback that implements the tf.graph.edge.EdgeSelectionCallback signature. If + // provided, edges are selectable, and this callback is run when an edge is selected. + @property({ type: Object }) + handleEdgeSelected: object; + + @property({ type: Object }) + selection: object; + + @property({ type: Object }) + tooltips: object; + @property({ type: Object }) selectNodeCopy: string = ''; diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/tf-graph-icon.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/tf-graph-icon.ts index a686c9d04f3..6d173b8bdbf 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/tf-graph-icon.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/tf-graph-icon.ts @@ -64,47 +64,9 @@ class TfGraphIcon extends LegacyElementMixin(DarkModeMixin(PolymerElement)) { - - - - - - - - - - - - - - - - - - - - - - - - - - - `; @property({ type: String }) diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/tf-node-icon.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/tf-node-icon.ts index 6da65e0b1a7..f1c4fb5bb21 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/tf-node-icon.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_common/tf-node-icon.ts @@ -148,8 +148,6 @@ class TfNodeIcon extends LegacyElementMixin(PolymerElement) { } case tf_graph.NodeType.META: return GraphIconType.META; - case tf_graph.NodeType.SERIES: - return GraphIconType.SERIES; default: } } -- Gitee From 9513d0e030e04e0cddc6da2f09f012d1dd4a412c Mon Sep 17 00:00:00 2001 From: wangqingcai Date: Mon, 24 Mar 2025 16:02:14 +0800 Subject: [PATCH 07/14] bugfix: add upper limit of parameter --- debug/accuracy_tools/msprobe/core/common/const.py | 2 ++ .../accuracy_tools/msprobe/pytorch/monitor/csv2tb.py | 3 +++ .../accuracy_tools/msprobe/pytorch/monitor/utils.py | 12 ++++++++++++ 3 files changed, 17 insertions(+) diff --git a/debug/accuracy_tools/msprobe/core/common/const.py b/debug/accuracy_tools/msprobe/core/common/const.py index da8e190f913..00028a1866c 100644 --- a/debug/accuracy_tools/msprobe/core/common/const.py +++ b/debug/accuracy_tools/msprobe/core/common/const.py @@ -706,3 +706,5 @@ class MonitorConst: CSV = "csv" API = "api" HEADER_NAME = 'name' + + MAX_NDIGITS = 20 diff --git a/debug/accuracy_tools/msprobe/pytorch/monitor/csv2tb.py b/debug/accuracy_tools/msprobe/pytorch/monitor/csv2tb.py index 588b1f97d14..77a93eb2358 100644 --- a/debug/accuracy_tools/msprobe/pytorch/monitor/csv2tb.py +++ b/debug/accuracy_tools/msprobe/pytorch/monitor/csv2tb.py @@ -29,6 +29,7 @@ from msprobe.pytorch.monitor.utils import get_target_output_dir all_data_type_list = ["actv", "actv_grad", "exp_avg", "exp_avg_sq", "grad_unreduced", "grad_reduced", "param"] CSV_FILE_SUFFIX = r"_\d+-\d+\.csv" +MAX_PROCESS_NUM = 128 def parse_step_line(line, ops): @@ -115,6 +116,8 @@ def csv2tb_by_step_work(target_output_dirs, output_dirpath, data_type_list): def check_process_num(process_num): if not is_int(process_num) or process_num <= 0: raise ValueError(f"process_num({process_num}) is not a positive integer") + if process_num > MAX_PROCESS_NUM: + raise ValueError(f"The maximum supported process_num is {MAX_PROCESS_NUM}, current value: {process_num}.") def check_data_type_list(data_type_list): diff --git a/debug/accuracy_tools/msprobe/pytorch/monitor/utils.py b/debug/accuracy_tools/msprobe/pytorch/monitor/utils.py index 94afe56ffcf..379eaa7189c 100644 --- a/debug/accuracy_tools/msprobe/pytorch/monitor/utils.py +++ b/debug/accuracy_tools/msprobe/pytorch/monitor/utils.py @@ -105,6 +105,15 @@ def validate_ops(ops): return valid_ops +def validate_ndigits(ndigits): + if not ndigits: + return + if not is_int(ndigits) or ndigits <= 0: + raise ValueError(f"ndigits({ndigits}) is not a positive integer, current is: {ndigits}.") + if ndigits > MonitorConst.MAX_NDIGITS: + raise ValueError(f"The maximum supported ndigits is {MonitorConst.MAX_NDIGITS}, current value: {ndigits}.") + + def validate_ranks(ranks): if not isinstance(ranks, list): raise TypeError("module_ranks should be a list") @@ -209,6 +218,9 @@ def validate_step_count_per_record(step_count_per_record): def validate_config(config): config['ops'] = validate_ops(config.get('ops', [])) + ndigits = config.get('ndigits') + validate_ndigits(ndigits) + eps = config.get('eps', 1e-8) if not isinstance(eps, float): raise TypeError("eps should be a float") -- Gitee From a83b7a7dda99a51f9a96d4eb9ffc79c751984008 Mon Sep 17 00:00:00 2001 From: wangqingcai Date: Mon, 24 Mar 2025 16:47:27 +0800 Subject: [PATCH 08/14] bugfix: fix tensorboard dir and file mode --- .../msprobe/core/common/file_utils.py | 18 ++++++++++++++++++ .../msprobe/pytorch/monitor/csv2tb.py | 3 ++- .../msprobe/pytorch/monitor/module_hook.py | 5 ++++- .../msprobe/pytorch/monitor/utils.py | 12 +++++++++++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/debug/accuracy_tools/msprobe/core/common/file_utils.py b/debug/accuracy_tools/msprobe/core/common/file_utils.py index fdc626ca6a1..a4ffa3aa8b0 100644 --- a/debug/accuracy_tools/msprobe/core/common/file_utils.py +++ b/debug/accuracy_tools/msprobe/core/common/file_utils.py @@ -26,6 +26,7 @@ import yaml import numpy as np import pandas as pd +from msprobe.core.common.utils import recursion_depth_decorator from msprobe.core.common.log import logger from msprobe.core.common.exceptions import FileCheckException from msprobe.core.common.const import FileCheckConst @@ -332,6 +333,23 @@ def change_mode(path, mode): 'Failed to change {} authority. {}'.format(path, str(ex))) from ex +@recursion_depth_decorator('msprobe.core.common.file_utils.recursive_chmod') +def recursive_chmod(path): + """ + 递归地修改目录及其子目录和文件的权限,文件修改为640,路径修改为750 + + :param path: 要修改权限的目录路径 + """ + for _, dirs, files in os.walk(path): + for file_name in files: + file_path = os.path.join(path, file_name) + change_mode(file_path, FileCheckConst.DATA_FILE_AUTHORITY) + for dir_name in dirs: + dir_path = os.path.join(path, dir_name) + change_mode(dir_path, FileCheckConst.DATA_DIR_AUTHORITY) + recursive_chmod(dir_path) + + def path_len_exceeds_limit(file_path): return len(os.path.realpath(file_path)) > FileCheckConst.DIRECTORY_LENGTH or \ len(os.path.basename(file_path)) > FileCheckConst.FILE_NAME_LENGTH diff --git a/debug/accuracy_tools/msprobe/pytorch/monitor/csv2tb.py b/debug/accuracy_tools/msprobe/pytorch/monitor/csv2tb.py index 77a93eb2358..9b85070a044 100644 --- a/debug/accuracy_tools/msprobe/pytorch/monitor/csv2tb.py +++ b/debug/accuracy_tools/msprobe/pytorch/monitor/csv2tb.py @@ -22,7 +22,7 @@ from torch.utils.tensorboard import SummaryWriter from tqdm import tqdm from msprobe.core.common.const import MonitorConst -from msprobe.core.common.file_utils import read_csv, create_directory, remove_path +from msprobe.core.common.file_utils import read_csv, create_directory, remove_path, recursive_chmod from msprobe.core.common.utils import is_int from msprobe.pytorch.common.log import logger from msprobe.pytorch.monitor.utils import get_target_output_dir @@ -164,4 +164,5 @@ def csv2tensorboard_by_step( p.start() for p in processes: p.join() + recursive_chmod(output_dirpath) logger.info(f"output has been saved to: {output_dirpath}") diff --git a/debug/accuracy_tools/msprobe/pytorch/monitor/module_hook.py b/debug/accuracy_tools/msprobe/pytorch/monitor/module_hook.py index 1a0c393cadf..1b61b854056 100644 --- a/debug/accuracy_tools/msprobe/pytorch/monitor/module_hook.py +++ b/debug/accuracy_tools/msprobe/pytorch/monitor/module_hook.py @@ -40,7 +40,7 @@ from msprobe.pytorch.monitor.module_metric import get_metrics, get_summary_write from msprobe.pytorch.monitor.module_spec_verifier import validate_config_spec from msprobe.pytorch.monitor.optimizer_collect import OptimizerMonFactory from msprobe.pytorch.monitor.utils import get_param_struct, validate_config, validate_ops, \ - get_output_base_dir, get_target_output_dir + get_output_base_dir, get_target_output_dir, chmod_tensorboard_dir from msprobe.pytorch.monitor.visualizer import HeatmapVisualizer torch_version_above_or_equal_2 = torch.__version__.split('+')[0] >= '2.0' @@ -697,6 +697,9 @@ class TrainerMon: if self.anomaly_data_factory: self.anomaly_data_writer.write_detected_json(self.summary_writer.get_anomalies()) self.summary_writer.clear_anomalies() + + if self.format == MonitorConst.TENSORBOARD: + chmod_tensorboard_dir(self.tensorboard_dir) self.call_id = 0 self.param_name_call_id.clear() diff --git a/debug/accuracy_tools/msprobe/pytorch/monitor/utils.py b/debug/accuracy_tools/msprobe/pytorch/monitor/utils.py index 379eaa7189c..b6f9c8748a3 100644 --- a/debug/accuracy_tools/msprobe/pytorch/monitor/utils.py +++ b/debug/accuracy_tools/msprobe/pytorch/monitor/utils.py @@ -25,7 +25,7 @@ import torch from msprobe.core.common.const import MonitorConst, Const from msprobe.pytorch.common.log import logger from msprobe.core.common.utils import is_int -from msprobe.core.common.file_utils import check_file_or_directory_path +from msprobe.core.common.file_utils import check_file_or_directory_path, recursive_chmod device = "cpu" @@ -296,3 +296,13 @@ def get_target_output_dir(monitor_path, time_start, time_end): if start_ok and end_ok: result[rank] = os.path.join(monitor_path, dirname) return result + + +def chmod_tensorboard_dir(path): + """ + format配置为tensorboard时,需要补充文件权限设置 + """ + try: + recursive_chmod(path) + except Exception as e: + logger.warning(f"chmod tensorboard dir wrong because {e}, not updated, please check!!!") -- Gitee From b044d3a795a3eff26aee482e4e22e82693e2632a Mon Sep 17 00:00:00 2001 From: wangqingcai Date: Mon, 24 Mar 2025 20:33:41 +0800 Subject: [PATCH 09/14] bugfix: mv recursion_depth_decorator into decorator.py --- .../msprobe/core/common/decorator.py | 50 +++++++++++++++++++ .../msprobe/core/common/file_utils.py | 2 +- .../msprobe/core/common/utils.py | 32 ------------ .../data_processor/pytorch_processor.py | 3 +- .../msprobe/core/data_dump/json_writer.py | 2 +- .../generate_op_script/op_generator.py | 2 +- .../tensor_transport_layer/attl.py | 3 +- .../dump/module_dump/module_processer.py | 2 +- .../pytorch/free_benchmark/common/utils.py | 2 +- .../compare/single_benchmark.py | 2 +- .../perturbed_layers/npu/add_noise.py | 2 +- .../perturbed_layers/npu/bit_noise.py | 2 +- .../perturbed_layers/npu/change_value.py | 2 +- .../perturbed_layers/npu/improve_precision.py | 2 +- .../msprobe/pytorch/monitor/module_hook.py | 2 +- .../pytorch/online_dispatch/dump_compare.py | 2 +- .../msprobe/pytorch/online_dispatch/utils.py | 2 +- .../msprobe/test/core_ut/common/test_utils.py | 2 +- .../visualization/compare/graph_comparator.py | 2 +- 19 files changed, 68 insertions(+), 50 deletions(-) create mode 100644 debug/accuracy_tools/msprobe/core/common/decorator.py diff --git a/debug/accuracy_tools/msprobe/core/common/decorator.py b/debug/accuracy_tools/msprobe/core/common/decorator.py new file mode 100644 index 00000000000..d3710002bcc --- /dev/null +++ b/debug/accuracy_tools/msprobe/core/common/decorator.py @@ -0,0 +1,50 @@ +# Copyright (c) 2024-2025, Huawei Technologies Co., Ltd. +# 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. + +from collections import defaultdict +from functools import wraps + +from msprobe.core.common.const import Const +from msprobe.core.common.exceptions import MsprobeException +from msprobe.core.common.log import logger + +# 记录工具函数递归的深度 +recursion_depth = defaultdict(int) + + +def recursion_depth_decorator(func_info, max_depth=Const.MAX_DEPTH): + """装饰一个函数,当函数递归调用超过限制时,抛出异常并打印函数信息。""" + def decorator(func): + @wraps(func) + def wrapper(*args, **kwargs): + func_id = id(func) + recursion_depth[func_id] += 1 + if recursion_depth[func_id] > max_depth: + msg = f"call {func_info} exceeds the recursion limit." + logger.error_log_with_exp( + msg, + MsprobeException( + MsprobeException.RECURSION_LIMIT_ERROR, msg + ), + ) + try: + result = func(*args, **kwargs) + finally: + recursion_depth[func_id] -= 1 + return result + + return wrapper + + return decorator diff --git a/debug/accuracy_tools/msprobe/core/common/file_utils.py b/debug/accuracy_tools/msprobe/core/common/file_utils.py index a4ffa3aa8b0..e4d004ee5b7 100644 --- a/debug/accuracy_tools/msprobe/core/common/file_utils.py +++ b/debug/accuracy_tools/msprobe/core/common/file_utils.py @@ -26,7 +26,7 @@ import yaml import numpy as np import pandas as pd -from msprobe.core.common.utils import recursion_depth_decorator +from msprobe.core.common.decorator import recursion_depth_decorator from msprobe.core.common.log import logger from msprobe.core.common.exceptions import FileCheckException from msprobe.core.common.const import FileCheckConst diff --git a/debug/accuracy_tools/msprobe/core/common/utils.py b/debug/accuracy_tools/msprobe/core/common/utils.py index e08e40f1ee6..8d55dd4c164 100644 --- a/debug/accuracy_tools/msprobe/core/common/utils.py +++ b/debug/accuracy_tools/msprobe/core/common/utils.py @@ -18,9 +18,7 @@ import os import re import subprocess import time -from collections import defaultdict from datetime import datetime, timezone -from functools import wraps import numpy as np @@ -481,36 +479,6 @@ def safe_get_value(container, index, container_name, key=None): raise MsprobeBaseException(MsprobeBaseException.INVALID_OBJECT_TYPE_ERROR) from e -# 记录工具函数递归的深度 -recursion_depth = defaultdict(int) - - -# 装饰一个函数,当函数递归调用超过限制时,抛出异常并打印函数信息。 -def recursion_depth_decorator(func_info, max_depth=Const.MAX_DEPTH): - def decorator(func): - @wraps(func) - def wrapper(*args, **kwargs): - func_id = id(func) - recursion_depth[func_id] += 1 - if recursion_depth[func_id] > max_depth: - msg = f"call {func_info} exceeds the recursion limit." - logger.error_log_with_exp( - msg, - MsprobeException( - MsprobeException.RECURSION_LIMIT_ERROR, msg - ), - ) - try: - result = func(*args, **kwargs) - finally: - recursion_depth[func_id] -= 1 - return result - - return wrapper - - return decorator - - def check_str_param(param): if not re.match(Const.REGEX_PREFIX_PATTERN, param): logger.error('The parameter {} contains special characters.'.format(param)) diff --git a/debug/accuracy_tools/msprobe/core/data_dump/data_processor/pytorch_processor.py b/debug/accuracy_tools/msprobe/core/data_dump/data_processor/pytorch_processor.py index 04e090510f3..973bfd981ea 100644 --- a/debug/accuracy_tools/msprobe/core/data_dump/data_processor/pytorch_processor.py +++ b/debug/accuracy_tools/msprobe/core/data_dump/data_processor/pytorch_processor.py @@ -27,7 +27,8 @@ from msprobe.core.common.const import Const from msprobe.core.common.exceptions import MsprobeException from msprobe.core.common.file_utils import path_len_exceeds_limit from msprobe.core.common.log import logger -from msprobe.core.common.utils import convert_tuple, recursion_depth_decorator +from msprobe.core.common.utils import convert_tuple +from msprobe.core.common.decorator import recursion_depth_decorator from msprobe.core.data_dump.data_processor.base import BaseDataProcessor, ModuleBackwardInputsOutputs, \ ModuleForwardInputsOutputs, TensorStatInfo from msprobe.pytorch.common.utils import Const as PtConst, save_pt, is_hifloat8_tensor, is_float8_tensor diff --git a/debug/accuracy_tools/msprobe/core/data_dump/json_writer.py b/debug/accuracy_tools/msprobe/core/data_dump/json_writer.py index f1221d81227..e1f57f53b88 100644 --- a/debug/accuracy_tools/msprobe/core/data_dump/json_writer.py +++ b/debug/accuracy_tools/msprobe/core/data_dump/json_writer.py @@ -21,7 +21,7 @@ import threading from msprobe.core.common.const import Const, FileCheckConst from msprobe.core.common.file_utils import change_mode, FileOpen, save_json, load_json from msprobe.core.common.log import logger -from msprobe.core.common.utils import recursion_depth_decorator +from msprobe.core.common.decorator import recursion_depth_decorator lock = threading.Lock() diff --git a/debug/accuracy_tools/msprobe/pytorch/api_accuracy_checker/generate_op_script/op_generator.py b/debug/accuracy_tools/msprobe/pytorch/api_accuracy_checker/generate_op_script/op_generator.py index 641eada0303..e9ea4553bea 100644 --- a/debug/accuracy_tools/msprobe/pytorch/api_accuracy_checker/generate_op_script/op_generator.py +++ b/debug/accuracy_tools/msprobe/pytorch/api_accuracy_checker/generate_op_script/op_generator.py @@ -31,7 +31,7 @@ from msprobe.core.common.utils import check_file_or_directory_path, check_op_str from msprobe.core.common.const import Const, MonitorConst, MsgConst from msprobe.core.common.log import logger from msprobe.core.common.file_utils import make_dir -from msprobe.core.common.utils import recursion_depth_decorator +from msprobe.core.common.decorator import recursion_depth_decorator TENSOR_DATA_LIST = ["torch.Tensor", "torch.nn.parameter.Parameter"] TORCH_BOOL_TYPE = ["torch.bool"] diff --git a/debug/accuracy_tools/msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/attl.py b/debug/accuracy_tools/msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/attl.py index f858067b661..2cfc355ec03 100644 --- a/debug/accuracy_tools/msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/attl.py +++ b/debug/accuracy_tools/msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/attl.py @@ -27,8 +27,7 @@ from msprobe.pytorch.api_accuracy_checker.tensor_transport_layer.client import T from msprobe.pytorch.api_accuracy_checker.tensor_transport_layer.server import TCPServer from msprobe.core.common.file_utils import remove_path from msprobe.pytorch.common.utils import logger, save_api_data, load_api_data, save_pkl, load_pkl -from msprobe.core.common.utils import recursion_depth_decorator - +from msprobe.core.common.decorator import recursion_depth_decorator BufferType = Union[ApiData, Dict[str, Any], str] # Union[Tensor, Tuple[Optional[Tensor]]] diff --git a/debug/accuracy_tools/msprobe/pytorch/dump/module_dump/module_processer.py b/debug/accuracy_tools/msprobe/pytorch/dump/module_dump/module_processer.py index ae75d3c657a..d9b67c93175 100644 --- a/debug/accuracy_tools/msprobe/pytorch/dump/module_dump/module_processer.py +++ b/debug/accuracy_tools/msprobe/pytorch/dump/module_dump/module_processer.py @@ -19,7 +19,7 @@ import torch from torch.utils.hooks import BackwardHook from msprobe.core.common.const import Const -from msprobe.core.common.utils import recursion_depth_decorator +from msprobe.core.common.decorator import recursion_depth_decorator from msprobe.core.data_dump.scope import BaseScope, ModuleRangeScope, MixRangeScope from msprobe.pytorch.common.log import logger from msprobe.pytorch.common.utils import replace_last_occurrence, is_float8_tensor diff --git a/debug/accuracy_tools/msprobe/pytorch/free_benchmark/common/utils.py b/debug/accuracy_tools/msprobe/pytorch/free_benchmark/common/utils.py index e3fd2b69fef..6baa684cbff 100644 --- a/debug/accuracy_tools/msprobe/pytorch/free_benchmark/common/utils.py +++ b/debug/accuracy_tools/msprobe/pytorch/free_benchmark/common/utils.py @@ -16,7 +16,7 @@ import torch from msprobe.core.common.exceptions import FreeBenchmarkException -from msprobe.core.common.utils import recursion_depth_decorator +from msprobe.core.common.decorator import recursion_depth_decorator from msprobe.pytorch.free_benchmark.common.enums import DeviceType diff --git a/debug/accuracy_tools/msprobe/pytorch/free_benchmark/compare/single_benchmark.py b/debug/accuracy_tools/msprobe/pytorch/free_benchmark/compare/single_benchmark.py index 49e845da401..a5f18946c44 100644 --- a/debug/accuracy_tools/msprobe/pytorch/free_benchmark/compare/single_benchmark.py +++ b/debug/accuracy_tools/msprobe/pytorch/free_benchmark/compare/single_benchmark.py @@ -16,7 +16,7 @@ import math import torch -from msprobe.core.common.utils import recursion_depth_decorator +from msprobe.core.common.decorator import recursion_depth_decorator from msprobe.pytorch.free_benchmark import logger from msprobe.pytorch.free_benchmark.common.constant import ThresholdConfig from msprobe.pytorch.free_benchmark.common.utils import TorchC diff --git a/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/add_noise.py b/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/add_noise.py index 986b833ab9a..754e3b06e96 100644 --- a/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/add_noise.py +++ b/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/add_noise.py @@ -14,7 +14,7 @@ # limitations under the License. import torch -from msprobe.core.common.utils import recursion_depth_decorator +from msprobe.core.common.decorator import recursion_depth_decorator from msprobe.pytorch.free_benchmark import logger from msprobe.pytorch.free_benchmark.common.constant import ThresholdConfig from msprobe.pytorch.free_benchmark.common.enums import PerturbationMode diff --git a/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/bit_noise.py b/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/bit_noise.py index 7d5cda6be57..aec0c3ca96e 100644 --- a/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/bit_noise.py +++ b/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/bit_noise.py @@ -14,7 +14,7 @@ # limitations under the License. import torch -from msprobe.core.common.utils import recursion_depth_decorator +from msprobe.core.common.decorator import recursion_depth_decorator from msprobe.pytorch.free_benchmark import logger from msprobe.pytorch.free_benchmark.common.constant import ThresholdConfig from msprobe.pytorch.free_benchmark.common.enums import PerturbationMode diff --git a/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/change_value.py b/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/change_value.py index c4fbeaf82f8..521637a1d8b 100644 --- a/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/change_value.py +++ b/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/change_value.py @@ -14,7 +14,7 @@ # limitations under the License. import torch -from msprobe.core.common.utils import recursion_depth_decorator +from msprobe.core.common.decorator import recursion_depth_decorator from msprobe.pytorch.free_benchmark import logger from msprobe.pytorch.free_benchmark.common.enums import PerturbationMode from msprobe.pytorch.free_benchmark.common.params import DataParams diff --git a/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/improve_precision.py b/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/improve_precision.py index 095e77ffaff..daa271976f3 100644 --- a/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/improve_precision.py +++ b/debug/accuracy_tools/msprobe/pytorch/free_benchmark/perturbed_layers/npu/improve_precision.py @@ -15,7 +15,7 @@ import torch from msprobe.core.common.const import Const -from msprobe.core.common.utils import recursion_depth_decorator +from msprobe.core.common.decorator import recursion_depth_decorator from msprobe.pytorch.free_benchmark import logger from msprobe.pytorch.free_benchmark.common.constant import CommonField from msprobe.pytorch.free_benchmark.common.enums import PerturbationMode diff --git a/debug/accuracy_tools/msprobe/pytorch/monitor/module_hook.py b/debug/accuracy_tools/msprobe/pytorch/monitor/module_hook.py index 1b61b854056..2861718f044 100644 --- a/debug/accuracy_tools/msprobe/pytorch/monitor/module_hook.py +++ b/debug/accuracy_tools/msprobe/pytorch/monitor/module_hook.py @@ -26,7 +26,7 @@ from torch.utils.hooks import BackwardHook from msprobe.core.common.const import MonitorConst, Const from msprobe.core.common.file_utils import load_json, save_json -from msprobe.core.common.utils import recursion_depth_decorator +from msprobe.core.common.decorator import recursion_depth_decorator from msprobe.pytorch.common.log import logger from msprobe.pytorch.common.utils import is_recomputation, is_float8_tensor from msprobe.pytorch.monitor.anomaly_analyse import AnomalyDataWriter diff --git a/debug/accuracy_tools/msprobe/pytorch/online_dispatch/dump_compare.py b/debug/accuracy_tools/msprobe/pytorch/online_dispatch/dump_compare.py index a154064755e..915db3be704 100644 --- a/debug/accuracy_tools/msprobe/pytorch/online_dispatch/dump_compare.py +++ b/debug/accuracy_tools/msprobe/pytorch/online_dispatch/dump_compare.py @@ -20,7 +20,7 @@ from datetime import datetime, timezone import torch from msprobe.core.common.const import Const -from msprobe.core.common.utils import recursion_depth_decorator +from msprobe.core.common.decorator import recursion_depth_decorator from msprobe.core.common.file_utils import FileOpen, save_npy, save_json from msprobe.pytorch.common.log import logger diff --git a/debug/accuracy_tools/msprobe/pytorch/online_dispatch/utils.py b/debug/accuracy_tools/msprobe/pytorch/online_dispatch/utils.py index 2116186cc04..37105551a3b 100644 --- a/debug/accuracy_tools/msprobe/pytorch/online_dispatch/utils.py +++ b/debug/accuracy_tools/msprobe/pytorch/online_dispatch/utils.py @@ -27,7 +27,7 @@ else: pta_cpu_device = torch.device("cpu") from msprobe.core.common.const import CompareConst -from msprobe.core.common.utils import recursion_depth_decorator +from msprobe.core.common.decorator import recursion_depth_decorator from msprobe.pytorch.common.log import logger diff --git a/debug/accuracy_tools/msprobe/test/core_ut/common/test_utils.py b/debug/accuracy_tools/msprobe/test/core_ut/common/test_utils.py index 69abbf12b4c..df5d6c7857e 100644 --- a/debug/accuracy_tools/msprobe/test/core_ut/common/test_utils.py +++ b/debug/accuracy_tools/msprobe/test/core_ut/common/test_utils.py @@ -52,11 +52,11 @@ from msprobe.core.common.utils import (CompareException, get_stack_construct_by_dump_json_path, check_seed_all, safe_get_value, - recursion_depth_decorator, MsprobeBaseException, check_str_param, is_json_file, detect_framework_by_dump_json) +from msprobe.core.common.decorator import recursion_depth_decorator class TestUtils(TestCase): diff --git a/debug/accuracy_tools/msprobe/visualization/compare/graph_comparator.py b/debug/accuracy_tools/msprobe/visualization/compare/graph_comparator.py index 3f695d23483..f2ba394bcd3 100644 --- a/debug/accuracy_tools/msprobe/visualization/compare/graph_comparator.py +++ b/debug/accuracy_tools/msprobe/visualization/compare/graph_comparator.py @@ -19,7 +19,7 @@ from msprobe.visualization.utils import GraphConst, load_json_file, load_data_js from msprobe.visualization.graph.graph import Graph, NodeOp from msprobe.visualization.compare.mode_adapter import ModeAdapter from msprobe.core.common.const import Const -from msprobe.core.common.utils import recursion_depth_decorator +from msprobe.core.common.decorator import recursion_depth_decorator class GraphComparator: -- Gitee From fcf586ff37b4157b65d75da2e54c032611372285 Mon Sep 17 00:00:00 2001 From: sunchao <1299792067@qq.com> Date: Tue, 25 Mar 2025 15:54:09 +0800 Subject: [PATCH 10/14] =?UTF-8?q?=F0=9F=90=9E=20fix:=20=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E6=96=87=E5=AD=97=E9=87=8D=E5=8F=A0=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/tf_resize_height/index.ts | 12 ++++++------ .../fe/src/tf_graph_node_info/index.ts | 8 +++++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_node_info/components/tf_resize_height/index.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_node_info/components/tf_resize_height/index.ts index 6c8dddba910..2e7f8e5e652 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_node_info/components/tf_resize_height/index.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_node_info/components/tf_resize_height/index.ts @@ -35,18 +35,18 @@ class ResizableTabsheet extends PolymerElement { } .resize-handle { - height: 6px; + height: 2px; width: 100%; - background-color: #ddd; cursor: ns-resize; + bottom: 2px; z-index: 999; position: relative; - bottom: 10px; - background-color: transparent; + background-color:rgb(141, 141, 141); } .resize-handle:hover { background-color: hsl(214, 100%, 43%); + height: 4px; } @@ -63,8 +63,8 @@ class ResizableTabsheet extends PolymerElement { }) height: number = 300; - _resize: (event: MouseEvent) => void = () => {}; - _stopResize: (this: Document, ev: MouseEvent) => any = () => {}; + _resize: (event: MouseEvent) => void = () => { }; + _stopResize: (this: Document, ev: MouseEvent) => any = () => { }; @observe('height') _updateHeight(newHeight): void { diff --git a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_node_info/index.ts b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_node_info/index.ts index d3b38e9da92..cb394caf5f7 100644 --- a/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_node_info/index.ts +++ b/plugins/tensorboard-plugins/tb_graph_ascend/fe/src/tf_graph_node_info/index.ts @@ -46,6 +46,12 @@ class TfGraphNodeInfo extends PolymerElement { width: 100%; height: 100%; } + vaadin-tabsheet::part(content){ + background-color: white; + } + .vaadin-tabs{ + background-color:white; + } .vaadin-tab{ font-size: 14px; } @@ -113,7 +119,7 @@ class TfGraphNodeInfo extends PolymerElement { } - +