提交 32100432 编写于 作者: M mindspore-ci-bot 提交者: Gitee

!387 UI timeline dowload and operator show AI CPU

Merge pull request !387 from 潘慧/r0.5
......@@ -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": "训练选择",
......
......@@ -1350,6 +1350,7 @@ export default {
.chart {
height: calc(100% - 70px);
min-height: 150px;
overflow: hidden;
}
}
.chart-wrap.highlight {
......
......@@ -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>
</el-table-column>
......@@ -147,10 +147,9 @@
</el-tab-pane>
<el-tab-pane label="AI CPU"
class="cpu-tab"
name="cpu"
v-if="false">
name="cpu">
<div class="cl-profiler-top"
v-if="cpuCharts.data.length">
v-if="false">
<div>
<span class="profiler-title">
{{ $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}<br>${
params[0].marker
}${params[0].value.toFixed(4)}`;
return `${params[0].axisValue}<br>${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;
}
}
......
......@@ -292,10 +292,33 @@ limitations under the License.
<div class="title-wrap">
<div class="title">{{ $t('profiling.timeLine') }}</div>
<div class="view-detail">
<button @click="toPerfetto()"
:disabled="perfetto.waiting"
:class="{disabled:perfetto.waiting}">{{ $t('profiling.viewDetail') }}
<i class="el-icon-d-arrow-right"></i></button>
<button @click="downloadPerfetto()"
:disabled="timeLine.waiting"
:class="{disabled:timeLine.waiting}">{{ $t('profiling.downloadTimeline') }}
</button>
</div>
<div class="tip-icon">
<el-tooltip placement="bottom"
effect="light">
<div slot="content"
class="tooltip-container">
<div class="font-size-style">{{$t("profiling.features")}}</div>
<div class="font-style">{{$t("profiling.timelineTips.title1")}}</div>
<div>{{$t("profiling.timelineTips.content11")}}</div>
<div>{{$t("profiling.timelineTips.content12")}}</div>
<div>{{$t("profiling.timelineTips.content13")}}</div>
<br>
<div class="font-style">{{$t("profiling.timelineTips.title2")}}</div>
<div>{{$t("profiling.timelineTips.content21")}}</div>
<div>{{$t("profiling.timelineTips.content22")}}</div>
<div>{{$t("profiling.timelineTips.content23")}}</div>
<br>
<div class="font-style">{{$t("profiling.timelineTips.title3")}}</div>
<div>{{$t("profiling.timelineTips.content31")}}</div>
<div>{{$t("profiling.timelineTips.content32")}}</div>
</div>
<i class="el-icon-info"></i>
</el-tooltip>
</div>
</div>
<div class="timeline-info"
......@@ -374,10 +397,8 @@ export default {
topN: [],
colorList: ['#6C92FA', '#6CBFFF', '#4EDED2', '#7ADFA0', '#A6DD82'],
},
perfetto: {
url: 'https://ui.perfetto.dev/#!',
timeLine: {
data: null,
delay: 5000,
waiting: true,
},
timelineInfo: {
......@@ -584,7 +605,7 @@ export default {
.map((i) => {
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);
......
......@@ -29,6 +29,7 @@ limitations under the License.
<el-input ref="step"
v-model.number="steps.step"
:disabled="steps.disabled"
@blur="resetStep"
@keyup.native.enter="changeStep">
</el-input>
<el-button @click="changeStep"
......@@ -150,6 +151,7 @@ export default {
bp_end: '--',
steps: {
step: null,
trueStep: null,
max: 0,
disabled: true,
label: this.$t('profiling.stepInputTip'),
......@@ -269,19 +271,26 @@ export default {
changeStep(value) {
if (value === 0) {
this.steps.step = null;
this.steps.trueStep = null;
this.queryTrainingTrace(0);
} else if (
/^[0-9]*[1-9][0-9]*$/.test(this.steps.step) &&
this.steps.step <= this.steps.max
) {
this.steps.trueStep = this.steps.step;
this.queryTrainingTrace(this.steps.step);
} else {
this.steps.step = null;
this.steps.step = this.steps.trueStep;
this.$message.error(
this.$t('profiling.inputError').replace('{max}', this.steps.max),
);
}
},
resetStep() {
setTimeout(() => {
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');
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册