Skip to content

Commit 7eeb09b

Browse files
qiuminxunfelt
authored andcommitted
Add multiple program support to tf_op_profile. (#1470)
1. Add a by_program toggle button to switch and see per program hlo_op_profile or overall by category hlo_op_profile. 2. Add an idle node under the root profile to show the portion of the total execution time on device that is idle. 3. Display the number of ops being left out.
1 parent dfe8119 commit 7eeb09b

File tree

5 files changed

+135
-68
lines changed

5 files changed

+135
-68
lines changed

tensorboard/plugins/profile/tf_op_profile/BUILD

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ tf_web_library(
1313
":tf_op_details",
1414
":tf_op_table",
1515
":utils",
16+
"@org_polymer_paper_slider",
17+
"@org_polymer_paper_toggle_button",
1618
],
1719
)
1820

@@ -32,8 +34,6 @@ tf_web_library(
3234
path = "/tf-op-profile",
3335
deps = [
3436
":utils",
35-
"@org_polymer_paper_slider",
36-
"@org_polymer_paper_toggle_button",
3737
],
3838
)
3939

tensorboard/plugins/profile/tf_op_profile/tf-op-details.html

+4-5
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,11 @@
112112
<paper-card id="card" heading="[[node.name]]" elevation="2">
113113
<div id="subheader">[[_subheader(node)]]</div>
114114
<div class="card-content">
115-
<div hidden="[[!node.metrics]]">
115+
<div hidden="[[!_hasFlops(node)]]">
116116
<b>FLOPS utilization: </b>
117117
<tf-op-bar value="[[_utilization(node)]]"></tf-op-bar>
118118
</div>
119-
<div hidden="[[_hasMemoryUtilization(node)]]">
119+
<div hidden="[[!_hasMemoryUtilization(node)]]">
120120
<b>Memory utilization: </b>
121121
<tf-op-bar value="[[_memoryUtilization(node)]]"></tf-op-bar>
122122
</div>
@@ -159,9 +159,8 @@
159159
},
160160
_utilization: tf_op_profile.utilization,
161161
_memoryUtilization: tf_op_profile.memoryUtilization,
162-
_hasMemoryUtilization: function(node) {
163-
return !node || !node.metrics || !node.metrics.memoryBandwidth;
164-
},
162+
_hasFlops: tf_op_profile.hasFlops,
163+
_hasMemoryUtilization: tf_op_profile.hasMemoryUtilization,
165164
_updateCard: function(node) {
166165
if (!node) return;
167166
var color = tf_op_profile.flameColor(tf_op_profile.utilization(node), 0.7);

tensorboard/plugins/profile/tf_op_profile/tf-op-profile.html

+101-7
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
limitations under the License.
1616
-->
1717

18+
<link rel="import" href="../paper-slider/paper-slider.html">
19+
<link rel="import" href="../paper-toggle-button/paper-toggle-button.html">
1820
<link rel="import" href="tf-op-table.html">
1921
<link rel="import" href="tf-op-details.html">
2022
<link rel="import" href="utils.html">
@@ -33,6 +35,36 @@
3335
display: block;
3436
margin-right: 1.5em;
3537
}
38+
#control {
39+
display: flex;
40+
flex-flow: row nowrap;
41+
justify-content: space-between;
42+
overflow:auto;
43+
text-transform:uppercase;
44+
padding: 0.5em;
45+
vertical-align: bottom;
46+
text-align: bottom;
47+
}
48+
.controlRowLeft {
49+
display: flex;
50+
flex-flow: row nowrap;
51+
align-items: center;
52+
line-height: 50px;
53+
text-align: bottom;
54+
justify-content: flex-start;
55+
}
56+
.controlRowRight{
57+
display: flex;
58+
flex-flow: row nowrap;
59+
align-items: center;
60+
line-height: 50px;
61+
text-align: bottom;
62+
justify-content: flex-end;
63+
}
64+
paper-slider {
65+
--paper-slider-input: {width: 100px}
66+
--paper-slider-height: 3px;
67+
}
3668
#description {
3769
margin-bottom: 2em;
3870
width: 600px;
@@ -45,9 +77,32 @@ <h4>Overall TPU FLOPS utilization is
4577
</h4>
4678
<div id="description">
4779
<p>Modifying your model's architecture, data dimensions, and improving
48-
the efficiency of CPU operations may help reach the TPU's FLOPS potential.
49-
</p></div>
50-
<tf-op-table root-node="[[_root]]" active={{active}}></tf-op-table>
80+
the efficiency of CPU operations may help reach the TPU's FLOPS
81+
potential.
82+
</p>
83+
<p>"Idle" represents the portion of the total execution time on device
84+
that is idle.</p>
85+
</div>
86+
<div id="control">
87+
<span class="controlRowLeft" hidden="[[!_hasTwoProfiles]]">By Program
88+
<paper-toggle-button checked={{isByCategory}}>
89+
</paper-toggle-button>By Category</span>
90+
<!--
91+
paper-slider sets how many child nodes to show for each category.
92+
If paper-toggle-button is checked, then only children in top 90th
93+
percentile of time spent are listed.
94+
-->
95+
<span class="controlRowLeft">Show top
96+
<paper-slider min="10" max="100" snaps step="10"
97+
value="{{childrenCount}}" editable>
98+
</paper-slider>ops</span>
99+
<span class="controlRowRight">off&nbsp;
100+
<paper-toggle-button checked={{showP90}}>
101+
</paper-toggle-button>Top 90%</span>
102+
</div>
103+
<tf-op-table root-node="[[_root]]" active={{active}}
104+
show-p90="{{showP90}}" children-count="{{childrenCount}}">
105+
</tf-op-table>
51106
</div>
52107
</template>
53108

@@ -61,19 +116,58 @@ <h4>Overall TPU FLOPS utilization is
61116
},
62117
_root: {
63118
type: Object,
64-
computed: '_getRoot(_data, "byCategory")',
65119
notify: true,
66120
},
67121
active: {
68122
type: Object,
69123
notify: true,
70124
value: null,
71125
},
126+
_hasTwoProfiles: {
127+
type: Boolean,
128+
computed: '_checkProfiles(_data)',
129+
notify: true,
130+
},
131+
isByCategory: {
132+
type: Boolean,
133+
value: false,
134+
notify: true,
135+
},
136+
showP90: {
137+
type: Boolean,
138+
value: false,
139+
notify: true,
140+
},
141+
childrenCount: {
142+
type: Number,
143+
value: 10,
144+
notify: true,
145+
},
146+
},
147+
observers: [
148+
'_getRoot(_data, isByCategory)',
149+
],
150+
_load: function(run) {
151+
this._data = run;
152+
},
153+
_getRoot: function(data, isByCategory) {
154+
if (!this._hasTwoProfiles) {
155+
this._root = data['byCategory'] || data['byProgram'];
156+
} else if (isByCategory) {
157+
this._root = data['byCategory'];
158+
} else {
159+
this._root = data['byProgram'];
160+
}
161+
},
162+
// Returns true if we have both byProgram and byCategory.
163+
_checkProfiles: function(data) {
164+
return data['byProgram'] != null && data['byCategory'] != null;
72165
},
73-
_getRoot: function(data, breakdown) { return data[breakdown]; },
74-
_utilizationPercent: function(node) { return tf_op_profile.percent(tf_op_profile.utilization(node)); },
166+
_utilizationPercent: function(node) {
167+
return tf_op_profile.percent(tf_op_profile.utilization(node)); },
75168
_hasFlops: function(node) { return node.metrics.flops > 0; },
76-
_textColor: function(node) { return tf_op_profile.flameColor(tf_op_profile.utilization(node), 0.7); },
169+
_textColor: function(node) {
170+
return tf_op_profile.flameColor(tf_op_profile.utilization(node), 0.7); },
77171
});
78172
</script>
79173
</dom-module>

tensorboard/plugins/profile/tf_op_profile/tf-op-table.html

+19-53
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
limitations under the License.
1616
-->
1717

18-
<link rel="import" href="../paper-slider/paper-slider.html">
19-
<link rel="import" href="../paper-toggle-button/paper-toggle-button.html">
2018
<link rel="import" href="utils.html">
2119

2220
<!-- tf-op-table-styles contains shared styles used in this file -->
@@ -64,41 +62,6 @@
6462
display: block;
6563
background-color: white;
6664
}
67-
#control {
68-
display: flex;
69-
flex-flow: row nowrap;
70-
justify-content: space-between;
71-
72-
overflow:auto;
73-
text-transform:uppercase;
74-
padding: 0.5em;
75-
vertical-align: bottom;
76-
text-align: bottom;
77-
}
78-
79-
.controlRowLeft {
80-
display: flex;
81-
flex-flow: row nowrap;
82-
align-items: center;
83-
line-height: 50px;
84-
text-align: bottom;
85-
justify-content: flex-start;
86-
}
87-
88-
.controlRowRight{
89-
display: flex;
90-
flex-flow: row nowrap;
91-
align-items: center;
92-
line-height: 50px;
93-
text-align: bottom;
94-
justify-content: flex-end;
95-
}
96-
97-
paper-slider {
98-
--paper-slider-input: {width: 100px}
99-
--paper-slider-height: 3px;
100-
}
101-
10265
#header {
10366
font-size: smaller;
10467
font-weight: bold;
@@ -111,20 +74,6 @@
11174
/* Match indented names */
11275
#header > #name { padding-left: 2em; }
11376
</style>
114-
<div id="control">
115-
<!--
116-
paper-slider sets how many child nodes to show for each category.
117-
If paper-toggle-button is checked, then only children in top 90th
118-
percentile of time spent are listed.
119-
-->
120-
<span class="controlRowLeft">Show top
121-
<paper-slider min="10" max="100" snaps step="10"
122-
value="{{childrenCount}}" editable>
123-
</paper-slider>ops</span>
124-
<span class="controlRowRight">off&nbsp;
125-
<paper-toggle-button checked={{showP90}}>
126-
</paper-toggle-button>Top 90%</span>
127-
</div>
12877
<div id="header">
12978
<span id="time">Time</span>
13079
<span id="name">Name</span>
@@ -271,7 +220,7 @@
271220
</span>{{node.name}}
272221
</span>
273222
<span id="provenance">{{_provenance(node)}}&nbsp;</span>
274-
<span id="utilization" hidden="[[!node.metrics]]"
223+
<span id="utilization" hidden="[[!_hasFlops(node)]]"
275224
style$="background-color:{{_flameColor(node)}}">
276225
{{_utilization(node)}}</span>
277226
</div>
@@ -287,6 +236,12 @@
287236
header-click="{{headerClick}}">
288237
</tf-op-table-entry>
289238
</template>
239+
<template is="dom-if" if="[[_hasLeftout(node, childrenCount, level)]]">
240+
<span id="name" style$="padding-left:[[_getPaddingLeft(level)]]em;">
241+
[[_numLeftout(node, childrenCount)]] categories or ops
242+
have been left out.
243+
</span>
244+
</template>
290245
</template>
291246
</template>
292247

@@ -345,6 +300,7 @@
345300
_utilization: function(node) {
346301
return tf_op_profile.percent(tf_op_profile.utilization(node));
347302
},
303+
_hasFlops: tf_op_profile.hasFlops,
348304
_flameColor: function(node) {
349305
return tf_op_profile.flameColor(tf_op_profile.utilization(node), 1, 0.2);
350306
},
@@ -355,7 +311,7 @@
355311
_selectedChanged: function(v) { this.classList.toggle('selected', v); },
356312
/*
357313
Returns top K children for the node. If p90 is true, then only children
358-
fallen in the top 90th percentile in time are returned.
314+
fallen in the top 90th percentile in time are returned.
359315
*/
360316
_getKChildren: function(node, k, p90, level) {
361317
if (p90 && node.children.length > 0 && node.children[0].metrics) {
@@ -368,6 +324,16 @@
368324
}
369325
return level ? node.children.slice(0, k) : node.children;
370326
},
327+
_hasLeftout: function(node, k, level) {
328+
if (!level) return false;
329+
return node.numChildren > Math.min(k, node.children.length);
330+
},
331+
_numLeftout: function(node, k) {
332+
return node.numChildren - Math.min(k, node.children.length);
333+
},
334+
_getPaddingLeft: function(level) {
335+
return level + 5;
336+
},
371337
});
372338
</script>
373339
</dom-module>

tensorboard/plugins/profile/tf_op_profile/utils.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export function utilization(node: any) {
4040
// NaN indicates undefined utilization for fused operations (we can't measure
4141
// performance inside a fusion). It could also indicate operations with zero
4242
// time, but they currently don't appear in the profile.
43-
if (!node || !node.metrics) return 0/0;
43+
if (!node || !node.metrics || !node.metrics.time) return 0/0;
4444
return node.metrics.flops / node.metrics.time;
4545
}
4646

@@ -51,6 +51,14 @@ export function memoryUtilization(node: any) {
5151
return node.metrics.memoryBandwidth;
5252
}
5353

54+
export function hasMemoryUtilization(node: any) {
55+
return node && node.metrics && node.metrics.memoryBandwidth;
56+
}
57+
58+
export function hasFlops(node: any) {
59+
return node && node.metrics && node.metrics.time;
60+
}
61+
5462
export function percent(fraction: number) {
5563
if (isNaN(fraction)) return "-";
5664
return fraction >= 0.995 ? "100%" : fraction < 0.00001 ? "0.00%" :

0 commit comments

Comments
 (0)