diff --git a/mindinsight/ui/src/locales/zh-cn.json b/mindinsight/ui/src/locales/zh-cn.json index 831951f0b85a9bb7f199ed09344ab4dc3eed312d..1ff574c971430e3c083e2b77419a675fd9e1c309 100644 --- a/mindinsight/ui/src/locales/zh-cn.json +++ b/mindinsight/ui/src/locales/zh-cn.json @@ -248,9 +248,7 @@ "suggestions": "优化建议", "common-profiler_tutorial": { "desc": "如何使用Profiler进行性能分析", - "anchor": [ - "desc" - ], + "anchor": ["desc"], "url": [ "https://www.mindspore.cn/tutorial/zh-CN/master/advanced_use/performance_profiling.html" ] @@ -361,7 +359,21 @@ "approximateTime": "总时长 ≈ ", "stepInputTip": "请输入step值(1~{max}的正整数)", "inputError": "输入参数异常,请输入一个1~{max}的正整数", - "defaultTip": "默认展示平均值" + "defaultTip": "默认展示平均值", + "downloadTimeline": "下载", + "timelineTips": { + "title1": "时间线功能可以帮您对训练过程进行分析,它可以展示:", + "content11": "- 算子分配到哪个设备 (AICPU/AI Core) 执行;", + "content12": "- MindSpore对该网络的流切分策略;", + "content13": "- 算子在Device上的执行序列和执行时长。", + "title2": "如何查看时间线:", + "content21": "要查看时间线的详细信息,您可以点击 \"下载\" 按钮将带有时间线信息的文件保存到本地,再通过工具查看。", + "content22": "我们推荐您使用谷歌插件:chrome://tracing,或 Perfetto工具:https://ui.perfetto.dev/#!/viewer", + "content23": "选择一个工具,在浏览器地址栏输入地址并回车,进入页面点击按钮加载文件查看时间线(tracing工具点击左上角 \"load\",Perfetto工具点击左侧栏 \"Open trace file\")。", + "title3": "如何使用时间线:", + "content31": "您可以通过时间线信息分析流切分方法是否合理、迭代间隙和拖尾时间是否过长等;", + "content32": "也可以具体定位到某个算子,查看分析它的执行时间。" + } }, "components": { "summaryTitle": "训练选择", diff --git a/mindinsight/ui/src/views/train-manage/data-process.vue b/mindinsight/ui/src/views/train-manage/data-process.vue index a568bc784aafcdcc1f47cb177f0e575034c3063e..0414e689a0b9ca6110181d76b7945d75cf452169 100644 --- a/mindinsight/ui/src/views/train-manage/data-process.vue +++ b/mindinsight/ui/src/views/train-manage/data-process.vue @@ -1350,6 +1350,7 @@ export default { .chart { height: calc(100% - 70px); min-height: 150px; + overflow: hidden; } } .chart-wrap.highlight { diff --git a/mindinsight/ui/src/views/train-manage/operator.vue b/mindinsight/ui/src/views/train-manage/operator.vue index a25a57219075bdb92dd179759b81df02ec902263..c48a3de176a7c8c52aa1ee5c32a7b95bd37b07d2 100644 --- a/mindinsight/ui/src/views/train-manage/operator.vue +++ b/mindinsight/ui/src/views/train-manage/operator.vue @@ -85,7 +85,7 @@ :property="ele" :key="key" :sortable="ele === 'op_info' ? false : 'custom'" - :width="(ele==='execution_time'|| ele==='subgraph' || + :width="(ele==='avg_execution_time (ms)'|| ele==='subgraph' || ele==='op_name'|| ele==='op_type')?'220':''" show-overflow-tooltip :label="ele"> @@ -122,7 +122,7 @@ :key="$index" :label="item" :sortable="item === 'op_info' ? false : 'custom'" - :width="(item==='execution_time'|| item==='subgraph' || + :width="(item==='avg_execution_time (ms)'|| item==='subgraph' || item==='op_name'|| item==='op_type')?'220':''" show-overflow-tooltip> @@ -147,10 +147,9 @@ + name="cpu">
+ v-if="false">
{{ $t('operator.operatorStatistics') }} @@ -268,7 +267,7 @@ export default { pageTotal: 0, opDetailPage: { offset: 0, - limit: 8, + limit: 15, }, op_filter_condition: {}, op_sort_condition: { @@ -365,7 +364,7 @@ export default { pageTotal: 0, opDetailPage: { offset: 0, - limit: 20, + limit: 15, }, op_filter_condition: {}, op_sort_condition: { @@ -572,10 +571,6 @@ export default { }); this.setOption(this.cpuCharts); } - if (res.data.object.length > 8) { - this.opCpuList.opDetailPage.limit = 8; - res.data.object.splice(8); - } this.formatterDetailData(this.opCpuList, res.data); if (isSort) { this.$nextTick(() => { @@ -733,7 +728,10 @@ export default { row.opDetailCol = []; row.opDetailPage.offset = 0; row.pageTotal = 0; - row.op_sort_condition = {name: 'execution_time', type: 'descending'}; + row.op_sort_condition = { + name: 'avg_execution_time', + type: 'descending', + }; this.getCoreDetailList(row, true); } else { this.curActiveRow = { @@ -772,7 +770,7 @@ export default { coreTableChange() { if (this.statisticType && !this.opAllTypeList.opDetailCol.length) { this.opAllTypeList.op_sort_condition = { - name: 'execution_time', + name: 'avg_execution_time', type: 'descending', }; this.getCoreDetailList(this.opAllTypeList, true); @@ -811,7 +809,7 @@ export default { : chart.data[i].name; legendStr = `{a|${i + 1}}{b|${name} ${chart.data[ i - ].value.toFixed(3)}}\n{c|${chart.data[i].percent.toFixed(2)}%}`; + ].value.toFixed(6)}}\n{c|${chart.data[i].percent.toFixed(2)}%}`; } } return legendStr; @@ -877,9 +875,7 @@ export default { option.tooltip = { trigger: 'axis', formatter: (params) => { - return `${params[0].axisValue}
${ - params[0].marker - }${params[0].value.toFixed(4)}`; + return `${params[0].axisValue}
${params[0].marker}${params[0].value}`; }, confine: true, }; @@ -1108,7 +1104,7 @@ export default { height: calc(36% + 32px); } .cl-profiler-bottom { - height: calc(64% - 32px); + height: 100%; } } .profiler-title { @@ -1128,7 +1124,7 @@ export default { width: 100%; height: 100%; min-width: 1300px; - min-height: 232px; + min-height: 306px; overflow: hidden; } } diff --git a/mindinsight/ui/src/views/train-manage/profiling-dashboard.vue b/mindinsight/ui/src/views/train-manage/profiling-dashboard.vue index bc14d64884c0fa8be27d80d601d278fd6371e503..4f0c23938dff8189e7ba2da860d0df1844558221 100644 --- a/mindinsight/ui/src/views/train-manage/profiling-dashboard.vue +++ b/mindinsight/ui/src/views/train-manage/profiling-dashboard.vue @@ -292,10 +292,33 @@ limitations under the License.
{{ $t('profiling.timeLine') }}
- + +
+
+ +
+
{{$t("profiling.features")}}
+
{{$t("profiling.timelineTips.title1")}}
+
{{$t("profiling.timelineTips.content11")}}
+
{{$t("profiling.timelineTips.content12")}}
+
{{$t("profiling.timelineTips.content13")}}
+
+
{{$t("profiling.timelineTips.title2")}}
+
{{$t("profiling.timelineTips.content21")}}
+
{{$t("profiling.timelineTips.content22")}}
+
{{$t("profiling.timelineTips.content23")}}
+
+
{{$t("profiling.timelineTips.title3")}}
+
{{$t("profiling.timelineTips.content31")}}
+
{{$t("profiling.timelineTips.content32")}}
+
+ +
{ return { name: i.name, - time: i.value.toFixed(4), + time: i.value, frequency: i.frequency, }; }); @@ -728,7 +749,7 @@ export default { name = this.$t('profiling.lterationGap'); break; case 'fp_and_bp': - name = this.$t('profiling.deviceQueueOp'); + name = this.$t('profiling.deviceQueueOpTip'); break; case 'tail': name = this.$t('profiling.lterationTail'); @@ -879,24 +900,6 @@ export default { } return new Uint8Array(arr); }, - toPerfetto() { - if (this.perfetto.data) { - const popupwin = window.open(this.perfetto.url); - setTimeout(() => { - const params = { - perfetto: { - title: '', - buffer: this.perfetto.data, - }, - }; - if (popupwin) { - popupwin.postMessage(params, this.perfetto.url); - } - }, this.perfetto.delay); - } else { - this.perfetto.waiting = true; - } - }, queryTimeline() { const params = { dir: this.relativePath, @@ -917,18 +920,28 @@ export default { .catch(() => { this.timelineInfo.noData = true; }); - this.perfetto.waiting = true; + this.timeLine.waiting = true; RequestService.queryTimeline(params) .then((res) => { if (res && res.data) { - this.perfetto.data = this.stringToUint8Array( + this.timeLine.data = this.stringToUint8Array( JSON.stringify(res.data), ); - this.perfetto.waiting = false; + this.timeLine.waiting = false; } }) .catch(() => {}); }, + downloadPerfetto() { + const downloadLink = document.createElement('a'); + downloadLink.download = this.getDocName(); + downloadLink.style.display = 'none'; + const blob = new Blob([this.timeLine.data]); + downloadLink.href = URL.createObjectURL(blob); + document.body.appendChild(downloadLink); + downloadLink.click(); + document.body.removeChild(downloadLink); + }, dealProcess(data) { this.processSummary.device = { empty: 0, @@ -960,6 +973,22 @@ export default { this.processSummary.noData = false; } }, + getDocName() { + const dealNumber = (value) => { + const prefix = value < 10 ? '0' : ''; + return prefix + value; + }; + const date = new Date(); + const year = date.getFullYear(); + const mouth = dealNumber(date.getMonth() + 1); + const day = dealNumber(date.getDate()); + const hour = dealNumber(date.getHours()); + const minute = dealNumber(date.getMinutes()); + const second = dealNumber(date.getSeconds()); + const millisecond = date.getMilliseconds(); + const timestamp = `${year}${mouth}${day}${hour}${minute}${second}${millisecond}`; + return `timeline_${this.trainingJobId}_${this.currentCard}_${timestamp}.json`; + }, }, destroyed() { window.removeEventListener('resize', this.resizeTrace, false); diff --git a/mindinsight/ui/src/views/train-manage/step-trace.vue b/mindinsight/ui/src/views/train-manage/step-trace.vue index 3bd0c06a79844c0ae319341e389cee82209fc7d4..b3f80f7757a3d9910377106fbdce306d6050eaf0 100644 --- a/mindinsight/ui/src/views/train-manage/step-trace.vue +++ b/mindinsight/ui/src/views/train-manage/step-trace.vue @@ -29,6 +29,7 @@ limitations under the License. { + this.steps.step = this.steps.trueStep; + }, 200); + }, getTimeInfo(id, type) { const params = { dir: this.relativePath, @@ -535,7 +544,7 @@ export default { name = this.$t('profiling.lterationGap'); break; case 'fp_and_bp': - name = this.$t('profiling.deviceQueueOp'); + name = this.$t('profiling.deviceQueueOpTip'); break; case 'tail': name = this.$t('profiling.lterationTail');