| @@ -269,7 +269,6 @@ | |||||
| "sidebarTip": "Select computational graph files to be viewed. A maximum of 10 files are supported. When the number of files exceeds 10, some files are not displayed. To view files that are not displayed, move them to other summary log path. " | "sidebarTip": "Select computational graph files to be viewed. A maximum of 10 files are supported. When the number of files exceeds 10, some files are not displayed. To view files that are not displayed, move them to other summary log path. " | ||||
| }, | }, | ||||
| "operator": { | "operator": { | ||||
| "titleText": "Profiling", | |||||
| "currentCard": "Number of cards", | "currentCard": "Number of cards", | ||||
| "pie": "Pie", | "pie": "Pie", | ||||
| "bar": "Bar", | "bar": "Bar", | ||||
| @@ -284,9 +283,10 @@ | |||||
| "searchByCoreFullName": "Enter operator full name" | "searchByCoreFullName": "Enter operator full name" | ||||
| }, | }, | ||||
| "profiling": { | "profiling": { | ||||
| "titleText": "Profiling - Single-host", | |||||
| "profilingDashboard": "Profiling Dashboard", | "profilingDashboard": "Profiling Dashboard", | ||||
| "showAverage": "Average value", | "showAverage": "Average value", | ||||
| "iterationGapTime": "Step interval", | |||||
| "iterationGapTime": "Step Interval", | |||||
| "fpBpTime": "Forward and Backward Propagation", | "fpBpTime": "Forward and Backward Propagation", | ||||
| "fpTime": "Forward Propagation", | "fpTime": "Forward Propagation", | ||||
| "tailTime": "Step Tail", | "tailTime": "Step Tail", | ||||
| @@ -295,8 +295,8 @@ | |||||
| "avgCost": "Average total consumed time:", | "avgCost": "Average total consumed time:", | ||||
| "getCost": "Average data obtaining time:", | "getCost": "Average data obtaining time:", | ||||
| "pushCost": "Average data push time:", | "pushCost": "Average data push time:", | ||||
| "lterationGap": "Step Interval", | |||||
| "lterationTail": "Step Tail", | |||||
| "iterationGap": "Step Interval", | |||||
| "iterationTail": "Step Tail", | |||||
| "minddataTitle": "Data Preparation Details", | "minddataTitle": "Data Preparation Details", | ||||
| "dataQueue": "Data Queues", | "dataQueue": "Data Queues", | ||||
| "smartHelper": "Helper", | "smartHelper": "Helper", | ||||
| @@ -525,6 +525,12 @@ | |||||
| "analysisTwo": "2. If the performance is abnormal during data processing and transmission, check the host queue. If the host queue is empty at a high probability, the exception may occur during data transmission.", | "analysisTwo": "2. If the performance is abnormal during data processing and transmission, check the host queue. If the host queue is empty at a high probability, the exception may occur during data transmission.", | ||||
| "chipInfo": "Ratio of empty data queues:" | "chipInfo": "Ratio of empty data queues:" | ||||
| }, | }, | ||||
| "profilingCluster": { | |||||
| "titleText": "Profiling - Cluster Overview", | |||||
| "clusterView": "Cluster Overview", | |||||
| "rankID": "Rank ID", | |||||
| "timeTitle": "time(ms)" | |||||
| }, | |||||
| "components": { | "components": { | ||||
| "summaryTitle": "Training Selection", | "summaryTitle": "Training Selection", | ||||
| "tagSelectTitle": "Tag Selection", | "tagSelectTitle": "Tag Selection", | ||||
| @@ -822,7 +828,8 @@ | |||||
| "nonnegative": "The parameter value cannot be less than 0.", | "nonnegative": "The parameter value cannot be less than 0.", | ||||
| "allPositive": "he parameter value must be greater than 0.", | "allPositive": "he parameter value must be greater than 0.", | ||||
| "watchOverflow": "The asynchronous full overflow watching function must be enabled before the training starts." | "watchOverflow": "The asynchronous full overflow watching function must be enabled before the training starts." | ||||
| } | |||||
| }, | |||||
| "paramValueTip": "Preset Value: {value}" | |||||
| }, | }, | ||||
| "explain": { | "explain": { | ||||
| "explain": "Model Explanation", | "explain": "Model Explanation", | ||||
| @@ -267,7 +267,6 @@ | |||||
| "sidebarTip": "选择要查看的计算图文件,当前最多支持展示10个文件的计算图。当超出10个文件时,部分文件将不展示。如果要查看其他未展示的文件,请将未展示的文件移动到其他训练日志目录中。" | "sidebarTip": "选择要查看的计算图文件,当前最多支持展示10个文件的计算图。当超出10个文件时,部分文件将不展示。如果要查看其他未展示的文件,请将未展示的文件移动到其他训练日志目录中。" | ||||
| }, | }, | ||||
| "operator": { | "operator": { | ||||
| "titleText": "性能分析", | |||||
| "currentCard": "当前卡片", | "currentCard": "当前卡片", | ||||
| "pie": "饼图", | "pie": "饼图", | ||||
| "bar": "柱状图", | "bar": "柱状图", | ||||
| @@ -281,7 +280,8 @@ | |||||
| "operatorInfo": "算子信息", | "operatorInfo": "算子信息", | ||||
| "kernelInfo": "内核信息" | "kernelInfo": "内核信息" | ||||
| }, | }, | ||||
| "profiling": { | |||||
| "profiling": { | |||||
| "titleText": "性能分析 - 单机", | |||||
| "profilingDashboard": "性能看板", | "profilingDashboard": "性能看板", | ||||
| "showAverage": "展示平均值", | "showAverage": "展示平均值", | ||||
| "iterationGapTime": "迭代间隙时间", | "iterationGapTime": "迭代间隙时间", | ||||
| @@ -293,8 +293,8 @@ | |||||
| "avgCost": "平均总耗时:", | "avgCost": "平均总耗时:", | ||||
| "getCost": "平均取数据耗时:", | "getCost": "平均取数据耗时:", | ||||
| "pushCost": "平均推送数据耗时:", | "pushCost": "平均推送数据耗时:", | ||||
| "lterationGap": "迭代间隙", | |||||
| "lterationTail": "迭代拖尾", | |||||
| "iterationGap": "迭代间隙", | |||||
| "iterationTail": "迭代拖尾", | |||||
| "minddataTitle": "数据准备详情", | "minddataTitle": "数据准备详情", | ||||
| "title": "迭代间隙流程分析", | "title": "迭代间隙流程分析", | ||||
| "dataQueue": "数据队列", | "dataQueue": "数据队列", | ||||
| @@ -524,6 +524,12 @@ | |||||
| "analysisTwo": "2、如果通过1定位为数据处理、数据传输阶段异常,则查看主机队列情况,如果大概率为空,则可能为数据处理阶段导致异常,如果大概率不为空,则可能数据传输阶段异常;", | "analysisTwo": "2、如果通过1定位为数据处理、数据传输阶段异常,则查看主机队列情况,如果大概率为空,则可能为数据处理阶段导致异常,如果大概率不为空,则可能数据传输阶段异常;", | ||||
| "chipInfo": "数据队列为空比例:" | "chipInfo": "数据队列为空比例:" | ||||
| }, | }, | ||||
| "profilingCluster": { | |||||
| "titleText": "性能分析 - 集群概览", | |||||
| "clusterView": "集群概览", | |||||
| "rankID": "逻辑卡号", | |||||
| "timeTitle": "时间(ms)" | |||||
| }, | |||||
| "components": { | "components": { | ||||
| "summaryTitle": "训练选择", | "summaryTitle": "训练选择", | ||||
| "tagSelectTitle": "标签选择", | "tagSelectTitle": "标签选择", | ||||
| @@ -145,6 +145,14 @@ export default new Router({ | |||||
| }, | }, | ||||
| ], | ], | ||||
| }, | }, | ||||
| { | |||||
| path: '/profiling-cluster', | |||||
| component: () => import('./views/profiling/profiling-cluster.vue'), | |||||
| }, | |||||
| { | |||||
| path: '/profiling-gpu-cluster', | |||||
| component: () => import('./views/profiling/profiling-cluster.vue'), | |||||
| }, | |||||
| { | { | ||||
| path: '/debugger', | path: '/debugger', | ||||
| component: () => import('./views/debugger/debugger.vue'), | component: () => import('./views/debugger/debugger.vue'), | ||||
| @@ -498,4 +498,12 @@ export default { | |||||
| params: params, | params: params, | ||||
| }); | }); | ||||
| }, | }, | ||||
| getClusterInfo(params) { | |||||
| return axios({ | |||||
| method: 'post', | |||||
| params: params.params, | |||||
| data: params.body, | |||||
| url: 'v1/mindinsight/profile/cluster-step-trace-summary', | |||||
| }); | |||||
| }, | |||||
| }; | }; | ||||
| @@ -1036,7 +1036,7 @@ export default { | |||||
| let name = ''; | let name = ''; | ||||
| switch (data.name) { | switch (data.name) { | ||||
| case 'iteration_interval': | case 'iteration_interval': | ||||
| name = this.$t('profiling.lterationGap'); | |||||
| name = this.$t('profiling.iterationGap'); | |||||
| break; | break; | ||||
| case 'fp_and_bp': | case 'fp_and_bp': | ||||
| name = this.$t('profiling.deviceQueueOpTip'); | name = this.$t('profiling.deviceQueueOpTip'); | ||||
| @@ -1045,7 +1045,7 @@ export default { | |||||
| name = this.$t('profiling.deviceQueueOpFpTip'); | name = this.$t('profiling.deviceQueueOpFpTip'); | ||||
| break; | break; | ||||
| case 'tail': | case 'tail': | ||||
| name = this.$t('profiling.lterationTail'); | |||||
| name = this.$t('profiling.iterationTail'); | |||||
| break; | break; | ||||
| default: | default: | ||||
| name = data.name; | name = data.name; | ||||
| @@ -16,7 +16,7 @@ limitations under the License. | |||||
| <template> | <template> | ||||
| <div class="prof-wrap"> | <div class="prof-wrap"> | ||||
| <div class="prof-head"> | <div class="prof-head"> | ||||
| <span class="cl-title-left">{{$t('summaryManage.viewProfiler')}}</span> | |||||
| <span class="cl-title-left">{{$t('profiling.titleText')}}</span> | |||||
| <div class="path-message"> | <div class="path-message"> | ||||
| <span>{{$t('symbols.leftbracket')}}</span> | <span>{{$t('symbols.leftbracket')}}</span> | ||||
| <span>{{$t('trainingDashboard.summaryDirPath')}}</span> | <span>{{$t('trainingDashboard.summaryDirPath')}}</span> | ||||
| @@ -142,6 +142,9 @@ export default { | |||||
| this.tabData.activeName = | this.tabData.activeName = | ||||
| this.$route.query.activePane || this.tabData.tabPanes[0].name; | this.$route.query.activePane || this.tabData.tabPanes[0].name; | ||||
| this.summaryPath = decodeURIComponent(this.$route.query.id); | this.summaryPath = decodeURIComponent(this.$route.query.id); | ||||
| if (!isNaN(this.$route.query.deviceid)) { | |||||
| this.curDashboardInfo.curCardNum = this.$route.query.deviceid; | |||||
| } | |||||
| this.getDeviceList(); | this.getDeviceList(); | ||||
| } else { | } else { | ||||
| this.curDashboardInfo.query.trainingJobId = ''; | this.curDashboardInfo.query.trainingJobId = ''; | ||||
| @@ -177,7 +180,9 @@ export default { | |||||
| value: item, | value: item, | ||||
| }); | }); | ||||
| }); | }); | ||||
| this.curDashboardInfo.curCardNum = this.CardNumArr[0].value; | |||||
| if (this.curDashboardInfo.curCardNum === null) { | |||||
| this.curDashboardInfo.curCardNum = this.CardNumArr[0].value; | |||||
| } | |||||
| this.getDataOfProfileHelper(); | this.getDataOfProfileHelper(); | ||||
| } else { | } else { | ||||
| this.CardNumArr = []; | this.CardNumArr = []; | ||||
| @@ -408,6 +413,7 @@ export default { | |||||
| line-height: 20px; | line-height: 20px; | ||||
| padding: 18px 0; | padding: 18px 0; | ||||
| font-weight: bold; | font-weight: bold; | ||||
| margin-left: 5px; | |||||
| } | } | ||||
| .prof-wrap .prof-content { | .prof-wrap .prof-content { | ||||
| height: calc(100% - 50px); | height: calc(100% - 50px); | ||||
| @@ -0,0 +1,522 @@ | |||||
| <!-- | |||||
| Copyright 2021 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. | |||||
| --> | |||||
| <template> | |||||
| <!-- cl-cluster--> | |||||
| <div class="cl-cluster"> | |||||
| <div class="cl-cluster-bk"> | |||||
| <div class="cl-cluster-title"> | |||||
| <div class="cl-cluster-title-left">{{$t("profilingCluster.titleText")}}</div> | |||||
| <div class="path-message"> | |||||
| <span>{{$t('symbols.leftbracket')}}</span> | |||||
| <span>{{$t('trainingDashboard.summaryDirPath')}}</span> | |||||
| <span>{{summaryPath}}</span> | |||||
| <span>{{$t('symbols.rightbracket')}}</span> | |||||
| </div> | |||||
| </div> | |||||
| <div class="cl-step-filter"> | |||||
| <label>{{stepTip}}</label> | |||||
| <el-input class="step-input" clearable | |||||
| @clear="viewStepFilter" | |||||
| v-model.number="step.showStep"></el-input> | |||||
| <el-button @click="viewStepFilter">{{$t("public.sure")}}</el-button> | |||||
| </div> | |||||
| <div class="cl-cluster-chart" | |||||
| ref="clusterChart"> | |||||
| </div> | |||||
| <div class="cl-cluster-table"> | |||||
| <el-table :data="tableData" | |||||
| height="100%" | |||||
| width="100%" | |||||
| ref="table" | |||||
| stripe | |||||
| @sort-change="tabeSortChange"> | |||||
| <el-table-column width="120" | |||||
| prop="rank_id" | |||||
| :label="$t('profilingCluster.rankID')"> | |||||
| </el-table-column> | |||||
| <el-table-column prop="iteration_interval" | |||||
| sortable="custom"> | |||||
| <template slot="header"> | |||||
| <span class="thSpan">|</span> | |||||
| <span :title="`${$t('profiling.iterationGapTime')}(ms)`">{{$t("profiling.iterationGapTime")}}(ms)</span> | |||||
| </template> | |||||
| </el-table-column> | |||||
| <el-table-column prop="fp_and_bp" | |||||
| sortable="custom"> | |||||
| <template slot="header"> | |||||
| <span class="thSpan">|</span> | |||||
| <span :title="`${$t('profiling.fpBpTime')}(ms)`">{{$t("profiling.fpBpTime")}}(ms)</span> | |||||
| </template> | |||||
| </el-table-column> | |||||
| <el-table-column prop="tail" | |||||
| sortable="custom"> | |||||
| <template slot="header"> | |||||
| <span class="thSpan">|</span> | |||||
| <span :title="`${$t('profiling.tailTime')}(ms)`">{{$t("profiling.tailTime")}}(ms)</span> | |||||
| </template> | |||||
| </el-table-column> | |||||
| <el-table-column fixed="right" | |||||
| width="180"> | |||||
| <template slot="header"> | |||||
| <span class="thSpan">|</span>{{$t("summaryManage.operation")}} | |||||
| </template> | |||||
| <template slot-scope="scope"> | |||||
| <el-button type="text" | |||||
| size="small" | |||||
| @click="viewProfilingDetail(scope.row)">{{$t("profiling.viewDetail")}}</el-button> | |||||
| </template> | |||||
| </el-table-column> | |||||
| </el-table> | |||||
| </div> | |||||
| <div class="cl-cluster-page"> | |||||
| <el-pagination @current-change="currentPageChange" | |||||
| @size-change="currentPageSizeChange" | |||||
| :page-sizes="pageSizes" | |||||
| :page-size="group_condition.limit" | |||||
| :current-page="group_condition.offset+1" | |||||
| layout="total,sizes,prev,pager,next,jumper" | |||||
| :total="totalCount"> | |||||
| </el-pagination> | |||||
| </div> | |||||
| </div> | |||||
| <div class="no-data-img" | |||||
| v-show="!chartData.length"> | |||||
| <div> | |||||
| <img :src="require('@/assets/images/nodata.png')" alt=""> | |||||
| <p>{{initOver?$t("public.noData"):$t("public.dataLoading")}}</p> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </template> | |||||
| <script> | |||||
| import echarts from 'echarts'; | |||||
| import RequestService from '../../services/request-service'; | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| summaryPath: '', | |||||
| trainingJobId: this.$route.query.id, // ID of the current training job | |||||
| chartObj: null, // chart obj | |||||
| chartData: [], // chart data | |||||
| chartOption: { // chart option | |||||
| color: ['#6B92FA', '#6CBFFF', '#F6DF66'], // bar color | |||||
| tooltip: { | |||||
| trigger: 'axis', | |||||
| axisPointer: { | |||||
| type: 'shadow', | |||||
| }, | |||||
| }, | |||||
| legend: { | |||||
| right: 70, | |||||
| top: 8, | |||||
| data: '', | |||||
| }, | |||||
| grid: { | |||||
| top: 35, | |||||
| left: 80, | |||||
| right: 80, | |||||
| }, | |||||
| dataset: {}, | |||||
| xAxis: { | |||||
| name: this.$t('profilingCluster.rankID'), | |||||
| nameTextStyle: { | |||||
| align: 'left', | |||||
| padding: [0, 5], | |||||
| color: '#9EA4B3', | |||||
| }, | |||||
| type: 'category', | |||||
| axisLine: { | |||||
| lineStyle: { | |||||
| color: '#E6EBF5', | |||||
| width: 2, | |||||
| }, | |||||
| }, | |||||
| axisLabel: { | |||||
| color: '#9EA4B3', | |||||
| }, | |||||
| }, | |||||
| yAxis: { | |||||
| name: this.$t('profilingCluster.timeTitle'), | |||||
| nameGap: 20, | |||||
| nameTextStyle: { | |||||
| align: 'right', | |||||
| padding: [0, 5], | |||||
| color: '#9EA4B3', | |||||
| }, | |||||
| axisLine: { | |||||
| lineStyle: { | |||||
| color: '#E6EBF5', | |||||
| width: 2, | |||||
| }, | |||||
| }, | |||||
| axisLabel: { | |||||
| color: '#9EA4B3', | |||||
| formatter: (value) => { | |||||
| return value.toExponential(4); | |||||
| }, | |||||
| }, | |||||
| splitLine: { | |||||
| lineStyle: { | |||||
| color: ['#E6EBF5'], | |||||
| width: 1, | |||||
| type: 'dashed', | |||||
| }, | |||||
| }, | |||||
| }, | |||||
| series: [ | |||||
| {type: 'bar', barWidth: 8}, | |||||
| {type: 'bar', barWidth: 8}, | |||||
| {type: 'bar', barWidth: 8}, | |||||
| ], | |||||
| dataZoom: [], | |||||
| }, | |||||
| chartResizeTimer: null, // delay after the window size is changed | |||||
| tableData: [], // table data | |||||
| initOver: false, // init over | |||||
| pageSizes: [10, 20, 50], | |||||
| group_condition: { | |||||
| offset: 0, | |||||
| limit: 10, | |||||
| }, | |||||
| sort_condition: { | |||||
| name: 'iteration_interval', | |||||
| type: 'descending', | |||||
| }, | |||||
| totalCount: 0, | |||||
| step: { | |||||
| maxStep: '', | |||||
| filterStep: '', | |||||
| showStep: '', | |||||
| }, | |||||
| stepTip: this.$t('profiling.stepInputTip'), | |||||
| stepInfoCol: { | |||||
| iteration_interval: this.$t('profiling.iterationGapTime'), | |||||
| fp_and_bp: this.$t('profiling.fpBpTime'), | |||||
| tail: this.$t('profiling.tailTime'), | |||||
| }, | |||||
| }; | |||||
| }, | |||||
| mounted() { | |||||
| if (!this.trainingJobId) { | |||||
| this.$message.error(this.$t('trainingDashboard.invalidId')); | |||||
| document.title = `${this.$t('profilingCluster.clusterView')}-MindInsight`; | |||||
| this.initOver = true; | |||||
| return; | |||||
| } | |||||
| this.summaryPath = decodeURIComponent(this.trainingJobId); | |||||
| document.title = `${this.summaryPath}-${this.$t( | |||||
| 'profilingCluster.clusterView', | |||||
| )}-MindInsight`; | |||||
| // adding a Listener | |||||
| window.addEventListener('resize', this.resizeCallback, false); | |||||
| this.chartOption.legend.data = Object.values(this.stepInfoCol); | |||||
| this.queryStepTraceInfo(true, true); | |||||
| }, | |||||
| destroyed() { | |||||
| // remove the size of a window and change the listener | |||||
| window.removeEventListener('resize', this.resizeCallback); | |||||
| // remove chart calculation delay | |||||
| if (this.chartResizeTimer) { | |||||
| clearTimeout(this.chartResizeTimer); | |||||
| this.chartResizeTimer = null; | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| /** | |||||
| * initialize | |||||
| * @param {Boolean} isInit whether get all data | |||||
| * @param {Boolean} isSort whether sort table | |||||
| */ | |||||
| queryStepTraceInfo(isInit, isSort) { | |||||
| const params = {}; | |||||
| params.params = { | |||||
| train_id: this.trainingJobId, | |||||
| }; | |||||
| params.body = { | |||||
| sort_condition: this.sort_condition, | |||||
| filter_condition: {}, | |||||
| }; | |||||
| if (!isInit) { | |||||
| params.body.group_condition = this.group_condition; | |||||
| } | |||||
| if (this.step.filterStep !== '') { | |||||
| params.body.filter_condition = {step_id: this.step.filterStep}; | |||||
| } | |||||
| RequestService.getClusterInfo(params) | |||||
| .then((res) => { | |||||
| if (res && res.data && res.data.step_trace && res.data.step_trace.length) { | |||||
| this.initOver = true; | |||||
| this.step.maxStep = res.data.total_step_num; | |||||
| this.stepTip = this.$t('profiling.stepInputTip', {max: this.step.maxStep}); | |||||
| this.totalCount = res.data.size; | |||||
| const tempChartData = []; | |||||
| if (isInit) { | |||||
| res.data.step_trace.forEach((item)=>{ | |||||
| const chartItem = [item.rank_id].concat(item.step_trace_info); | |||||
| tempChartData.push(chartItem); | |||||
| }); | |||||
| this.chartData = tempChartData; | |||||
| this.initChart(); | |||||
| } | |||||
| if (isSort) { | |||||
| this.$nextTick(()=>{ | |||||
| const tableDom = this.$refs.table; | |||||
| if (tableDom) { | |||||
| tableDom.sort(this.sort_condition.name, this.sort_condition.type); | |||||
| } | |||||
| }); | |||||
| } else { | |||||
| const tempTableData = res.data.step_trace.slice(0, this.group_condition.limit); | |||||
| this.initTable(tempTableData); | |||||
| } | |||||
| } | |||||
| }) | |||||
| .catch((error) => { | |||||
| this.initOver = true; | |||||
| this.chartData = []; | |||||
| this.tableData = []; | |||||
| }); | |||||
| }, | |||||
| /** | |||||
| * init table data | |||||
| * @param {Array} resData response data | |||||
| */ | |||||
| initTable(resData) { | |||||
| this.tableData = []; | |||||
| resData.forEach((item) => { | |||||
| const tableItem = {}; | |||||
| tableItem.rank_id = item.rank_id; | |||||
| tableItem.host_ip = item.host_ip; | |||||
| tableItem.profiler_dir = item.profiler_dir; | |||||
| tableItem.device_id = item.device_id; | |||||
| const stepTraceInfo = item.step_trace_info; | |||||
| tableItem.iteration_interval = stepTraceInfo[0]; | |||||
| tableItem.fp_and_bp = stepTraceInfo[1]; | |||||
| tableItem.tail = stepTraceInfo[2]; | |||||
| this.tableData.push(tableItem); | |||||
| }); | |||||
| }, | |||||
| /** | |||||
| * init chart | |||||
| */ | |||||
| initChart() { | |||||
| this.chartOption.dataset = { | |||||
| dimensions: ['rankID'].concat(Object.values(this.stepInfoCol)), | |||||
| source: this.chartData, | |||||
| }, | |||||
| this.chartOption.dataZoom = this.chartData.length > 25 // show bar numbers as default | |||||
| ? [ | |||||
| { | |||||
| show: true, | |||||
| startValue: 0, | |||||
| endValue: 25, | |||||
| }, | |||||
| ] | |||||
| : [], | |||||
| this.$nextTick(()=> { | |||||
| if (!this.chartObj) { | |||||
| this.chartObj = echarts.init(this.$refs.clusterChart, null); | |||||
| } | |||||
| this.chartObj.setOption(this.chartOption, true); | |||||
| }); | |||||
| }, | |||||
| /** | |||||
| * window resize | |||||
| */ | |||||
| resizeCallback() { | |||||
| if (this.chartResizeTimer) { | |||||
| clearTimeout(this.chartResizeTimer); | |||||
| this.chartResizeTimer = null; | |||||
| } | |||||
| this.chartResizeTimer = setTimeout(() => { | |||||
| if (this.chartObj) { | |||||
| this.chartObj.resize(); | |||||
| } | |||||
| }, 200); | |||||
| }, | |||||
| /** | |||||
| * route jump | |||||
| * @param {Object} row | |||||
| */ | |||||
| viewProfilingDetail(row) { | |||||
| const path = this.$route.path.indexOf('profiling-gpu-cluster') > 0 ? '/profiling-gpu' : '/profiling'; | |||||
| const routeUrl = this.$router.resolve({ | |||||
| path: path, | |||||
| query: { | |||||
| id: this.trainingJobId + '/cluster_profiler/' + row.host_ip, | |||||
| dir: row.profiler_dir, | |||||
| path: this.trainingJobId + '/cluster_profiler/' + row.host_ip, | |||||
| deviceid: row.device_id.toString(), | |||||
| }, | |||||
| }); | |||||
| window.open(routeUrl.href, '_blank'); | |||||
| }, | |||||
| /** | |||||
| * current page change | |||||
| * @param {Number} val current page | |||||
| */ | |||||
| currentPageChange(val) { | |||||
| this.group_condition.offset = val - 1; | |||||
| this.queryStepTraceInfo(false, false); | |||||
| }, | |||||
| /** | |||||
| * current page size change | |||||
| * @param {Number} pageSize current page size | |||||
| */ | |||||
| currentPageSizeChange(pageSize) { | |||||
| this.group_condition.offset = 0; | |||||
| this.group_condition.limit = pageSize; | |||||
| this.queryStepTraceInfo(false, false); | |||||
| }, | |||||
| /** | |||||
| * table sort change | |||||
| * @param {Object} column current column | |||||
| */ | |||||
| tabeSortChange(column) { | |||||
| this.sort_condition = { | |||||
| name: column.prop, | |||||
| type: column.order, | |||||
| }; | |||||
| this.group_condition.offset = 0; | |||||
| this.queryStepTraceInfo(false, false); | |||||
| }, | |||||
| /** | |||||
| * filter step to overview | |||||
| */ | |||||
| viewStepFilter() { | |||||
| if (/^[0-9]*[1-9][0-9]*$/.test(this.step.showStep) && | |||||
| this.step.showStep <= this.step.maxStep) { | |||||
| this.step.filterStep = this.step.showStep; | |||||
| this.group_condition.offset = 0; | |||||
| this.queryStepTraceInfo(true, false); | |||||
| } else if (this.step.showStep === '') { | |||||
| this.step.filterStep = ''; | |||||
| this.group_condition.offset = 0; | |||||
| this.queryStepTraceInfo(true, false); // show average data | |||||
| } else { | |||||
| this.step.showStep = this.step.filterStep; | |||||
| this.$message.error(this.$t('profiling.inputError').replace('{max}', this.step.maxStep)); | |||||
| } | |||||
| }, | |||||
| }, | |||||
| }; | |||||
| </script> | |||||
| <style> | |||||
| .cl-cluster { | |||||
| height: 100%; | |||||
| background-color: #fff; | |||||
| position: relative; | |||||
| } | |||||
| .cl-cluster .cl-cluster-bk { | |||||
| height: 100%; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| padding: 0 32px 24px 32px; | |||||
| } | |||||
| .cl-cluster .no-data-img { | |||||
| background: #fff; | |||||
| text-align: center; | |||||
| position: absolute; | |||||
| top: 56px; | |||||
| bottom: 0px; | |||||
| width: 100%; | |||||
| z-index: 999; | |||||
| display: flex; | |||||
| justify-content: center; | |||||
| align-items: center; | |||||
| } | |||||
| .cl-cluster .no-data-img p { | |||||
| font-size: 16px; | |||||
| padding-top: 10px; | |||||
| } | |||||
| .cl-cluster .el-table th > .cell { | |||||
| color: #282b33; | |||||
| } | |||||
| .cl-cluster .el-table td > .cell { | |||||
| margin-left: 10px; | |||||
| } | |||||
| .cl-cluster .el-table td:first-child .cell { | |||||
| margin-left: 0; | |||||
| } | |||||
| .cl-cluster .el-table th { | |||||
| user-select: auto; | |||||
| } | |||||
| .cl-cluster .thSpan { | |||||
| color: #d4d9e6; | |||||
| margin-right: 8px; | |||||
| } | |||||
| .cl-cluster .cl-cluster-title { | |||||
| height: 56px; | |||||
| line-height: 56px; | |||||
| position: relative; | |||||
| flex-shrink: 0; | |||||
| } | |||||
| .cl-cluster .cl-cluster-title .cl-cluster-title-left { | |||||
| display: inline-block; | |||||
| font-size: 20px; | |||||
| font-weight: bold; | |||||
| left: 0; | |||||
| } | |||||
| .cl-cluster .cl-cluster-title .path-message { | |||||
| display: inline-block; | |||||
| line-height: 20px; | |||||
| padding: 18px 0; | |||||
| font-weight: bold; | |||||
| margin-left: 5px; | |||||
| } | |||||
| .cl-cluster .cl-cluster-chart { | |||||
| height: 280px; | |||||
| margin-top: 5px; | |||||
| flex-shrink: 0; | |||||
| } | |||||
| .cl-cluster .cl-cluster-table { | |||||
| flex: 1; | |||||
| margin-top: 20px; | |||||
| overflow: hidden; | |||||
| } | |||||
| .cl-cluster .cl-cluster-page { | |||||
| padding-top: 10px; | |||||
| text-align: right; | |||||
| } | |||||
| .cl-cluster .cl-step-filter .cl-step-filter { | |||||
| display: inline-block; | |||||
| } | |||||
| .cl-cluster .cl-step-filter .el-input { | |||||
| width: 120px; | |||||
| margin: 0 20px; | |||||
| } | |||||
| .cl-cluster .cl-step-filter .el-button { | |||||
| border: 1px solid #00a5a7; | |||||
| border-radius: 2px; | |||||
| background-color: white; | |||||
| color: #00a5a7; | |||||
| padding: 7px 15px; | |||||
| } | |||||
| .cl-cluster .cl-step-filter .el-button:hover { | |||||
| background: rgb(230, 246, 246); | |||||
| } | |||||
| </style> | |||||
| @@ -913,7 +913,7 @@ export default { | |||||
| let name = ''; | let name = ''; | ||||
| switch (data.name) { | switch (data.name) { | ||||
| case 'iteration_interval': | case 'iteration_interval': | ||||
| name = this.$t('profiling.lterationGap'); | |||||
| name = this.$t('profiling.iterationGap'); | |||||
| break; | break; | ||||
| case 'fp_and_bp': | case 'fp_and_bp': | ||||
| name = this.$t('profiling.deviceQueueOpTip'); | name = this.$t('profiling.deviceQueueOpTip'); | ||||
| @@ -922,7 +922,7 @@ export default { | |||||
| name = this.$t('profiling.deviceQueueOpFpTip'); | name = this.$t('profiling.deviceQueueOpFpTip'); | ||||
| break; | break; | ||||
| case 'tail': | case 'tail': | ||||
| name = this.$t('profiling.lterationTail'); | |||||
| name = this.$t('profiling.iterationTail'); | |||||
| break; | break; | ||||
| default: | default: | ||||
| name = data.name; | name = data.name; | ||||
| @@ -16,7 +16,7 @@ limitations under the License. | |||||
| <template> | <template> | ||||
| <div class="prof-wrap"> | <div class="prof-wrap"> | ||||
| <div class="prof-head"> | <div class="prof-head"> | ||||
| <span class="cl-title-left">{{$t('summaryManage.viewProfiler')}}</span> | |||||
| <span class="cl-title-left">{{$t('profiling.titleText')}}</span> | |||||
| <div class="path-message"> | <div class="path-message"> | ||||
| <span>{{$t('symbols.leftbracket')}}</span> | <span>{{$t('symbols.leftbracket')}}</span> | ||||
| <span>{{$t('trainingDashboard.summaryDirPath')}}</span> | <span>{{$t('trainingDashboard.summaryDirPath')}}</span> | ||||
| @@ -145,6 +145,9 @@ export default { | |||||
| this.tabData.activeName = | this.tabData.activeName = | ||||
| this.$route.query.activePane || this.tabData.tabPanes[0].name; | this.$route.query.activePane || this.tabData.tabPanes[0].name; | ||||
| this.summaryPath = decodeURIComponent(this.$route.query.id); | this.summaryPath = decodeURIComponent(this.$route.query.id); | ||||
| if (!isNaN(this.$route.query.deviceid)) { | |||||
| this.curDashboardInfo.curCardNum = this.$route.query.deviceid; | |||||
| } | |||||
| this.getDeviceList(); | this.getDeviceList(); | ||||
| } else { | } else { | ||||
| this.curDashboardInfo.query.trainingJobId = ''; | this.curDashboardInfo.query.trainingJobId = ''; | ||||
| @@ -180,7 +183,9 @@ export default { | |||||
| value: item, | value: item, | ||||
| }); | }); | ||||
| }); | }); | ||||
| this.curDashboardInfo.curCardNum = this.CardNumArr[0].value; | |||||
| if (this.curDashboardInfo.curCardNum === null) { | |||||
| this.curDashboardInfo.curCardNum = this.CardNumArr[0].value; | |||||
| } | |||||
| this.getDataOfProfileHelper(); | this.getDataOfProfileHelper(); | ||||
| } else { | } else { | ||||
| this.CardNumArr = []; | this.CardNumArr = []; | ||||
| @@ -411,6 +416,7 @@ export default { | |||||
| line-height: 20px; | line-height: 20px; | ||||
| padding: 18px 0; | padding: 18px 0; | ||||
| font-weight: bold; | font-weight: bold; | ||||
| margin-left: 5px; | |||||
| } | } | ||||
| .prof-wrap .prof-content { | .prof-wrap .prof-content { | ||||
| height: calc(100% - 50px); | height: calc(100% - 50px); | ||||
| @@ -196,11 +196,11 @@ export default { | |||||
| initOver: false, | initOver: false, | ||||
| }, | }, | ||||
| deviceId: 0, | deviceId: 0, | ||||
| radio: this.$t('profiling.lterationGap'), | |||||
| radio: this.$t('profiling.iterationGap'), | |||||
| tabsArr: [ | tabsArr: [ | ||||
| // Detailed chart of data in step trace | // Detailed chart of data in step trace | ||||
| { | { | ||||
| name: this.$t('profiling.lterationGap'), | |||||
| name: this.$t('profiling.iterationGap'), | |||||
| id: 'iter-gap', | id: 'iter-gap', | ||||
| timeSummary: {}, | timeSummary: {}, | ||||
| rate: 'iteration_interval', | rate: 'iteration_interval', | ||||
| @@ -222,7 +222,7 @@ export default { | |||||
| initOver: false, | initOver: false, | ||||
| }, | }, | ||||
| { | { | ||||
| name: this.$t('profiling.lterationTail'), | |||||
| name: this.$t('profiling.iterationTail'), | |||||
| id: 'tailing', | id: 'tailing', | ||||
| timeSummary: {}, | timeSummary: {}, | ||||
| rate: 'tail', | rate: 'tail', | ||||
| @@ -245,9 +245,7 @@ export default { | |||||
| this.deviceId = newValue.curCardNum; | this.deviceId = newValue.curCardNum; | ||||
| this.relativePath = newValue.query.path; | this.relativePath = newValue.query.path; | ||||
| if (this.train_id) { | if (this.train_id) { | ||||
| document.title = `${decodeURIComponent(this.train_id)}-${this.$t( | |||||
| 'profiling.stepTrace', | |||||
| )}-MindInsight`; | |||||
| document.title = `${decodeURIComponent(this.train_id)}-${this.$t('profiling.stepTrace')}-MindInsight`; | |||||
| } else { | } else { | ||||
| document.title = `${this.$t('profiling.stepTrace')}-MindInsight`; | document.title = `${this.$t('profiling.stepTrace')}-MindInsight`; | ||||
| } | } | ||||
| @@ -734,7 +732,7 @@ export default { | |||||
| let name = ''; | let name = ''; | ||||
| switch (data.name) { | switch (data.name) { | ||||
| case 'iteration_interval': | case 'iteration_interval': | ||||
| name = this.$t('profiling.lterationGap'); | |||||
| name = this.$t('profiling.iterationGap'); | |||||
| break; | break; | ||||
| case 'fp_and_bp': | case 'fp_and_bp': | ||||
| name = this.$t('profiling.deviceQueueOpTip'); | name = this.$t('profiling.deviceQueueOpTip'); | ||||
| @@ -743,7 +741,7 @@ export default { | |||||
| name = this.$t('profiling.deviceQueueOpFpTip'); | name = this.$t('profiling.deviceQueueOpFpTip'); | ||||
| break; | break; | ||||
| case 'tail': | case 'tail': | ||||
| name = this.$t('profiling.lterationTail'); | |||||
| name = this.$t('profiling.iterationTail'); | |||||
| break; | break; | ||||
| default: | default: | ||||
| name = data.name; | name = data.name; | ||||
| @@ -345,7 +345,14 @@ export default { | |||||
| const profilerDir = encodeURIComponent(row.profiler_dir); | const profilerDir = encodeURIComponent(row.profiler_dir); | ||||
| const trainId = encodeURIComponent(row.train_id); | const trainId = encodeURIComponent(row.train_id); | ||||
| const path = encodeURIComponent(row.relative_path); | const path = encodeURIComponent(row.relative_path); | ||||
| const router = `/profiling${row.profiler_type === 'gpu' ? '-gpu' : ''}`; | |||||
| let router = '/profiling'; | |||||
| if (row.profiler_type === 'gpu') { | |||||
| router = '/profiling-gpu'; | |||||
| } else if (row.profiler_type === 'cluster_ascend') { | |||||
| router = '/profiling-cluster'; | |||||
| } else if (row.profiler_type === 'cluster_gpu') { | |||||
| router = '/profiling-gpu-cluster'; | |||||
| } | |||||
| this.$router.push({ | this.$router.push({ | ||||
| path: router, | path: router, | ||||
| @@ -378,8 +385,12 @@ export default { | |||||
| const profilerDir = encodeURIComponent(row.profiler_dir); | const profilerDir = encodeURIComponent(row.profiler_dir); | ||||
| const trainId = encodeURIComponent(row.train_id); | const trainId = encodeURIComponent(row.train_id); | ||||
| const path = encodeURIComponent(row.relative_path); | const path = encodeURIComponent(row.relative_path); | ||||
| const router = `/profiling${row.profiler_type === 'gpu' ? '-gpu' : ''}`; | |||||
| let router = '/profiling'; | |||||
| if (row.profiler_type === 'gpu') { | |||||
| router = '/profiling-gpu'; | |||||
| } else if (row.profiler_type === 'cluster_ascend') { | |||||
| router = '/profiling-cluster'; | |||||
| } | |||||
| const routeUrl = this.$router.resolve({ | const routeUrl = this.$router.resolve({ | ||||
| path: router, | path: router, | ||||
| query: { | query: { | ||||