From 51351d088d19bbbb7a483322aa75f55f021f3959 Mon Sep 17 00:00:00 2001 From: Clive Verghese Date: Tue, 19 Sep 2023 10:38:58 -0700 Subject: [PATCH] Update pod_viewer display. PiperOrigin-RevId: 566676394 --- frontend/app/common/interfaces/data_table.ts | 13 ++ .../topology_graph/topology_graph.ng.html | 18 +- .../topology_graph/topology_graph.scss | 2 +- .../topology_graph/topology_graph.ts | 161 ++++++++++++++---- 4 files changed, 154 insertions(+), 40 deletions(-) diff --git a/frontend/app/common/interfaces/data_table.ts b/frontend/app/common/interfaces/data_table.ts index 44a4dd51..598d8f62 100644 --- a/frontend/app/common/interfaces/data_table.ts +++ b/frontend/app/common/interfaces/data_table.ts @@ -378,6 +378,18 @@ declare interface PodStatsSequence { podStatsMap?: PodStatsMap[]; } +/** Chip details. */ +export declare interface Chip { + globalId?: number; + hostX?: number; + hostY?: number; + hostZ?: number; + indexOnHost?: number; + x?: number; + y?: number; + z?: number; +} + /** The base interface for information to draw topology graph. */ export declare interface PodViewerTopology { xDimension?: number; @@ -387,6 +399,7 @@ export declare interface PodViewerTopology { hostYStride?: number; hostZStride?: number; numCoresPerChip?: number; + cores?: Chip[]; } /** The base interface for a pod viewer summary. */ diff --git a/frontend/app/components/pod_viewer/topology_graph/topology_graph.ng.html b/frontend/app/components/pod_viewer/topology_graph/topology_graph.ng.html index 389e530f..185aa5f4 100644 --- a/frontend/app/components/pod_viewer/topology_graph/topology_graph.ng.html +++ b/frontend/app/components/pod_viewer/topology_graph/topology_graph.ng.html @@ -41,9 +41,11 @@
+

Z = {{z_axis}}

-
+
+
{{tooltipText}}
-
diff --git a/frontend/app/components/pod_viewer/topology_graph/topology_graph.scss b/frontend/app/components/pod_viewer/topology_graph/topology_graph.scss index 2b6a8c73..f0a23070 100644 --- a/frontend/app/components/pod_viewer/topology_graph/topology_graph.scss +++ b/frontend/app/components/pod_viewer/topology_graph/topology_graph.scss @@ -109,7 +109,7 @@ } .node-tooltip { - position: absolute; + position: fixed; background-color: white; padding: 10px; border-radius: 8px; diff --git a/frontend/app/components/pod_viewer/topology_graph/topology_graph.ts b/frontend/app/components/pod_viewer/topology_graph/topology_graph.ts index bca5f783..71587c5a 100644 --- a/frontend/app/components/pod_viewer/topology_graph/topology_graph.ts +++ b/frontend/app/components/pod_viewer/topology_graph/topology_graph.ts @@ -19,6 +19,10 @@ interface ElementInfo { y: number; } +interface Nodes { + nodes: ElementInfo[]; +} + interface ArrowElementInfo extends ElementInfo { rotate?: number; scale?: number; @@ -34,8 +38,6 @@ const LABEL_PADDING = 5; const LABEL_WIDTH = 20; const NODE_HEIGHT = 30; const NODE_WIDTH = 15; -const TOOLTIP_OFFSET_X = 20; -const TOOLTIP_OFFSET_Y = 35; const NODE_COLORS = [ '#ffffd9', '#edf8b1', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#253494', '#081d58' @@ -75,7 +77,9 @@ export class TopologyGraph implements OnChanges, OnDestroy { hosts: ElementInfo[] = []; labels: ElementInfo[] = []; - nodes: ElementInfo[] = []; + // Since we currently do not support 3d visualizations, We will unwrap the z + // axis and create a 2d plane for each z axis. + nodes: Nodes[] = []; colorInfos: ColorInfo[] = []; channels: number[] = []; arrows: ArrowElementInfo[] = []; @@ -128,6 +132,37 @@ export class TopologyGraph implements OnChanges, OnDestroy { return NODE_COLORS[colorIndex]; } + /** + * Get the node coordinates to relatively position the node within the + * container. We create a new container for each z axis. + */ + private getNodePositionFromCoordinates( + xCoordinate: number, yCoordinate: number, nodeId: number): ElementInfo { + const hostWidthWithPadding = HOST_PADDING + BORDER_WIDTH + this.hostWidth + + BORDER_WIDTH + HOST_PADDING; + const hostHeightWithPadding = HOST_PADDING + BORDER_WIDTH + + this.hostHeight + BORDER_WIDTH + HOST_PADDING; + const chipWidthWithPadding = CHIP_PADDING + + (BORDER_WIDTH + NODE_WIDTH) * this.nodesPerChip + BORDER_WIDTH + + CHIP_PADDING; + const chipHeightWithPadding = + CHIP_PADDING + BORDER_WIDTH + NODE_HEIGHT + BORDER_WIDTH + CHIP_PADDING; + let x = CONTAINER_MARGIN + LABEL_PADDING + LABEL_WIDTH + LABEL_PADDING; + let y = CONTAINER_MARGIN + LABEL_PADDING + LABEL_HEIGHT + LABEL_PADDING; + + x += hostWidthWithPadding * Math.floor(xCoordinate / this.hostXStride); + x += HOST_PADDING + BORDER_WIDTH + HOST_MARGIN; + x += chipWidthWithPadding * (xCoordinate % this.hostXStride); + x += CHIP_PADDING + (BORDER_WIDTH + NODE_WIDTH) * nodeId; + + y += hostHeightWithPadding * Math.floor(yCoordinate / this.hostYStride); + y += HOST_PADDING + BORDER_WIDTH + HOST_MARGIN; + y += chipHeightWithPadding * (yCoordinate % this.hostYStride); + y += CHIP_PADDING; + + return {x, y}; + } + private getNodePosition(chipId: number, nodeId: number): ElementInfo { const hostWidthWithPadding = HOST_PADDING + BORDER_WIDTH + this.hostWidth + BORDER_WIDTH + HOST_PADDING; @@ -296,6 +331,18 @@ export class TopologyGraph implements OnChanges, OnDestroy { } } + private createElementId(chipId: number, node: number): string { + return 'node-' + chipId.toString() + '-' + node.toString(); + } + + private getChipId(id: string): number { + return Number(id.split('-')[1]); + } + + private getNodeId(id: string): number { + return Number(id.split('-')[2]); + } + private updateNodes() { this.nodes = []; @@ -303,18 +350,41 @@ export class TopologyGraph implements OnChanges, OnDestroy { return; } - Object.keys(this.podStatsPerCore).forEach(coreId => { - const podStatsRecord = this.podStatsPerCore![coreId]; - const chipId = podStatsRecord.chipId || 0; - const nodeId = podStatsRecord.nodeId || 0; - const nodeInfo = this.getNodePosition(chipId, nodeId); - nodeInfo.id = 'node-' + chipId.toString() + '-' + nodeId.toString(); - if (this.coreIdToReplicaIdMap && - this.coreIdToReplicaIdMap[coreId] !== undefined) { - nodeInfo.rid = this.coreIdToReplicaIdMap[coreId]; - } - this.nodes.push(nodeInfo); - }); + if (this.topology.cores && this.topology.cores.length > 0) { + const numCoresPerChip = this.topology.numCoresPerChip || 1; + this.topology.cores.forEach(chip => { + for (let i = 0; i < numCoresPerChip; i++) { + const chipId = chip.globalId || 0; + const chipx = chip.x || 0; + const chipy = chip.y || 0; + const chipz = chip.z || 0; + const nodeInfo = this.getNodePositionFromCoordinates(chipx, chipy, i); + nodeInfo.id = this.createElementId(chipId, i); + if (this.coreIdToReplicaIdMap && + this.coreIdToReplicaIdMap[chipId] !== undefined) { + nodeInfo.rid = this.coreIdToReplicaIdMap[chipId]; + } + if (this.nodes[chipz] === undefined) { + this.nodes[chipz] = {nodes: []}; + } + this.nodes[chipz].nodes.push(nodeInfo); + } + }); + } else { + this.nodes[0] = {nodes: []}; + Object.keys(this.podStatsPerCore).forEach(coreId => { + const podStatsRecord = this.podStatsPerCore![coreId]; + const chipId = podStatsRecord.chipId || 0; + const nodeId = podStatsRecord.nodeId || 0; + const nodeInfo = this.getNodePosition(chipId, nodeId); + nodeInfo.id = this.createElementId(chipId, nodeId); + if (this.coreIdToReplicaIdMap && + this.coreIdToReplicaIdMap[coreId] !== undefined) { + nodeInfo.rid = this.coreIdToReplicaIdMap[coreId]; + } + this.nodes[0].nodes.push(nodeInfo); + }); + } } private updateSystemInfo() { @@ -386,7 +456,7 @@ export class TopologyGraph implements OnChanges, OnDestroy { Object.values(this.podStatsPerCore).forEach(podStatsRecord => { const chipId = podStatsRecord.chipId || 0; const nodeId = podStatsRecord.nodeId || 0; - const id = 'node-' + chipId.toString() + '-' + nodeId.toString(); + const id = this.createElementId(chipId, nodeId); const nodeEl = this.elRef.nativeElement.querySelector('#' + id); if (nodeEl) { let value = utils.getPodStatsRecordBreakdownProperty( @@ -399,16 +469,45 @@ export class TopologyGraph implements OnChanges, OnDestroy { }); } - showTooltip(id: string) { + showTooltip(id: string, event: MouseEvent) { this.tooltipText = ''; + this.tooltipX = event.x; + this.tooltipY = event.y; let podStatsRecord: PodStatsRecord|null = null; let coreId = ''; + const globalId = this.getChipId(id); + + const foundCore = + this.topology?.cores?.find(chip => globalId === chip.globalId); + + if (foundCore) { + const nodeId = this.getNodeId(id); + this.tooltipText += 'pos: ('; + this.tooltipText += foundCore.x; + this.tooltipText += ','; + this.tooltipText += foundCore.y; + this.tooltipText += ','; + this.tooltipText += foundCore.z; + this.tooltipText += ')\n'; + this.tooltipText += 'chip id: '; + this.tooltipText += foundCore.globalId; + this.tooltipText += '\n'; + this.tooltipText += 'node id: ' + nodeId.toString() + '\n'; + this.tooltipText += 'host: ('; + this.tooltipText += foundCore.hostX; + this.tooltipText += ','; + this.tooltipText += foundCore.hostY; + this.tooltipText += ','; + this.tooltipText += foundCore.hostZ; + this.tooltipText += ')\n'; + } + const found = Object.entries(this.podStatsPerCore || {}).find(([, value]) => { const chipId = value.chipId || 0; const nodeId = value.nodeId || 0; - return id === 'node-' + chipId.toString() + '-' + nodeId.toString(); + return id === this.createElementId(chipId, nodeId); }); if (!found || found.length !== 2) { @@ -421,18 +520,22 @@ export class TopologyGraph implements OnChanges, OnDestroy { return; } + const chipId = podStatsRecord.chipId || 0; const nodeId = podStatsRecord.nodeId || 0; - this.tooltipText += 'pos: ('; - this.tooltipText += - (chipId % (this.hostColumns * this.hostXStride)).toString(); - this.tooltipText += ','; - this.tooltipText += - Math.floor(chipId / (this.hostColumns * this.hostXStride)).toString(); - this.tooltipText += ')\n'; + if (!foundCore) { + this.tooltipText += 'pos: ('; + this.tooltipText += + (chipId % (this.hostColumns * this.hostXStride)).toString(); + this.tooltipText += ','; + this.tooltipText += + Math.floor(chipId / (this.hostColumns * this.hostXStride)).toString(); + this.tooltipText += ')\n'; + this.tooltipText += 'chip id: ' + chipId.toString() + '\n'; + this.tooltipText += 'node id: ' + nodeId.toString() + '\n'; + } this.tooltipText += 'host: ' + (podStatsRecord.hostName || '') + '\n'; - this.tooltipText += 'chip id: ' + chipId.toString() + '\n'; - this.tooltipText += 'node id: ' + nodeId.toString() + '\n'; + if (this.coreIdToReplicaIdMap && this.coreIdToReplicaIdMap[coreId] !== undefined) { this.tooltipText += @@ -451,10 +554,6 @@ export class TopologyGraph implements OnChanges, OnDestroy { '0.00'; this.tooltipText += '% of a step.'; } - - const nodeInfo = this.getNodePosition(chipId, nodeId); - this.tooltipX = nodeInfo.x + TOOLTIP_OFFSET_X; - this.tooltipY = nodeInfo.y + TOOLTIP_OFFSET_Y; } updateChannelId(id: number) {