| @@ -50,29 +50,18 @@ class _BasicTrainJob: | |||
| Basic info about train job. | |||
| Args: | |||
| train_id (str): Id of the train job. | |||
| abs_summary_base_dir (str): The canonical path of summary base directory. It should be the return value of | |||
| realpath(). | |||
| abs_summary_dir (str): The canonical path of summary directory. It should be the return value of realpath(). | |||
| create_time (DateTime): The create time of summary directory. | |||
| update_time (DateTime): The latest modify time of summary files directly in the summary directory. | |||
| profiler_dir (str): The relative path of profiler directory. | |||
| profiler_type (str): The profiler device type. | |||
| entry (dict): The summary dir entry listed by SummaryWatcher. | |||
| """ | |||
| def __init__(self, train_id, abs_summary_base_dir, abs_summary_dir, create_time, update_time, profiler_dir, | |||
| profiler_type=""): | |||
| self._train_id = train_id | |||
| def __init__(self, abs_summary_base_dir, entry): | |||
| self._abs_summary_base_dir = abs_summary_base_dir | |||
| self._abs_summary_dir = abs_summary_dir | |||
| self._create_time = create_time | |||
| self._update_time = update_time | |||
| self._profiler_dir = profiler_dir | |||
| self._profiler_type = profiler_type | |||
| self._entry = entry | |||
| @property | |||
| def abs_summary_dir(self): | |||
| """Get summary directory path.""" | |||
| return self._abs_summary_dir | |||
| return os.path.realpath(os.path.join(self._abs_summary_base_dir, self._entry['relative_path'])) | |||
| @property | |||
| def summary_base_dir(self): | |||
| @@ -82,27 +71,46 @@ class _BasicTrainJob: | |||
| @property | |||
| def train_id(self): | |||
| """Get train id.""" | |||
| return self._train_id | |||
| return self._entry['relative_path'] | |||
| @property | |||
| def profiler_dir(self): | |||
| """Get profiler directory path.""" | |||
| return self._profiler_dir | |||
| if self._entry['profiler'] is not None: | |||
| return self._entry['profiler']['directory'] | |||
| return None | |||
| @property | |||
| def create_time(self): | |||
| """Get create time.""" | |||
| return self._create_time | |||
| return self._entry['create_time'] | |||
| @property | |||
| def update_time(self): | |||
| """Get update time.""" | |||
| return self._update_time | |||
| return self._entry['update_time'] | |||
| @property | |||
| def profiler_type(self): | |||
| """Get profiler type""" | |||
| return self._profiler_type | |||
| if self._entry['profiler'] is not None: | |||
| return self._entry['profiler']['profiler_type'] | |||
| return '' | |||
| @property | |||
| def summary_files(self): | |||
| """Get the summary files count in the summary dir.""" | |||
| return self._entry['summary_files'] | |||
| @property | |||
| def graph_files(self): | |||
| """Get the graph pb files count in the summary dir.""" | |||
| return self._entry['graph_files'] | |||
| @property | |||
| def lineage_files(self): | |||
| """Get the lineage files count in the summary dir.""" | |||
| return self._entry['lineage_files'] | |||
| class CachedTrainJob: | |||
| @@ -377,18 +385,9 @@ class _BriefCacheManager(_BaseCacheManager): | |||
| basic_train_jobs = [] | |||
| for info in summaries_info: | |||
| profiler = info['profiler'] | |||
| basic_train_jobs.append(_BasicTrainJob( | |||
| train_id=info['relative_path'], | |||
| abs_summary_base_dir=self._summary_base_dir, | |||
| abs_summary_dir=os.path.realpath(os.path.join( | |||
| self._summary_base_dir, | |||
| info['relative_path'] | |||
| )), | |||
| create_time=info['create_time'], | |||
| update_time=info['update_time'], | |||
| profiler_dir=None if profiler is None else profiler['directory'], | |||
| profiler_type="" if profiler is None else profiler['profiler_type'], | |||
| entry=info | |||
| )) | |||
| with self._lock: | |||
| @@ -26,6 +26,7 @@ from mindinsight.datavisual.utils.utils import contains_null_byte | |||
| from mindinsight.datavisual.common.exceptions import MaxCountExceededError | |||
| from mindinsight.utils.exceptions import FileSystemPermissionError | |||
| LINEAGE_SUMMARY_SUFFIX = '_lineage' | |||
| class SummaryWatcher: | |||
| """SummaryWatcher class.""" | |||
| @@ -99,18 +100,8 @@ class SummaryWatcher: | |||
| for key, value in summary_dict.items(): | |||
| directory = { | |||
| 'relative_path': key, | |||
| 'profiler': None, | |||
| 'create_time': value['ctime'], | |||
| 'update_time': value['mtime'], | |||
| **value | |||
| } | |||
| profiler = value.get('profiler') | |||
| if profiler is not None: | |||
| directory['profiler'] = { | |||
| 'directory': profiler['directory'], | |||
| 'create_time': profiler['ctime'], | |||
| 'update_time': profiler['mtime'], | |||
| 'profiler_type': profiler['profiler_type'] | |||
| } | |||
| directories.append(directory) | |||
| # sort by update time in descending order and relative path in ascending order | |||
| @@ -215,15 +206,24 @@ class SummaryWatcher: | |||
| return | |||
| if relative_path not in summary_dict: | |||
| summary_dict[relative_path] = { | |||
| 'ctime': ctime, | |||
| 'mtime': mtime, | |||
| 'create_time': ctime, | |||
| 'update_time': mtime, | |||
| 'summary_files': 0, | |||
| 'lineage_files': 0, | |||
| 'graph_files': 0, | |||
| 'profiler': None, | |||
| } | |||
| elif summary_dict[relative_path]['ctime'] < ctime: | |||
| if summary_dict[relative_path]['create_time'] < ctime: | |||
| summary_dict[relative_path].update({ | |||
| 'ctime': ctime, | |||
| 'mtime': mtime, | |||
| 'create_time': ctime, | |||
| 'update_time': mtime, | |||
| }) | |||
| if not summary_pattern: | |||
| summary_dict[relative_path]['graph_files'] += 1 | |||
| elif entry.name.endswith(LINEAGE_SUMMARY_SUFFIX): | |||
| summary_dict[relative_path]['lineage_files'] += 1 | |||
| else: | |||
| summary_dict[relative_path]['summary_files'] += 1 | |||
| elif entry.is_dir(): | |||
| profiler_pattern = re.search(self.PROFILER_DIRECTORY_REGEX, entry.name) | |||
| full_dir_path = os.path.join(summary_base_dir, relative_path, entry.name) | |||
| @@ -233,16 +233,22 @@ class SummaryWatcher: | |||
| profiler = { | |||
| 'directory': os.path.join('.', entry.name), | |||
| 'ctime': ctime, | |||
| 'mtime': mtime, | |||
| 'create_time': ctime, | |||
| 'update_time': mtime, | |||
| "profiler_type": profiler_type | |||
| } | |||
| summary_dict[relative_path] = { | |||
| 'ctime': ctime, | |||
| 'mtime': mtime, | |||
| 'profiler': profiler, | |||
| } | |||
| if relative_path in summary_dict: | |||
| summary_dict[relative_path]['profiler'] = profiler | |||
| else: | |||
| summary_dict[relative_path] = { | |||
| 'create_time': ctime, | |||
| 'summary_files': 0, | |||
| 'lineage_files': 0, | |||
| 'graph_files': 0, | |||
| 'update_time': mtime, | |||
| 'profiler': profiler | |||
| } | |||
| def is_summary_directory(self, summary_base_dir, relative_path): | |||
| """ | |||
| @@ -145,6 +145,9 @@ class TrainTaskManager(BaseProcessor): | |||
| profiler_dir=basic_info.profiler_dir, | |||
| cache_status=train_job.cache_status.value, | |||
| profiler_type=basic_info.profiler_type, | |||
| summary_files=basic_info.summary_files, | |||
| graph_files=basic_info.graph_files, | |||
| lineage_files=basic_info.lineage_files | |||
| ) | |||
| if train_job.cache_status == CacheStatus.CACHED: | |||
| @@ -51,6 +51,8 @@ | |||
| "dataTraceback": "Dataset Lineage", | |||
| "comparePlate": "Comparison Dashboard", | |||
| "disableProfilerTip": "Failed to view profiling because no profiler log is available.", | |||
| "disableDashboardTip": "Failed to view training dashboard because no summary log or pb files are available.", | |||
| "disableParameterTip": "Failed to view parameter details because no lineage log is available.", | |||
| "openNewTab": "Open Link in New Tab", | |||
| "paramDetails": "Parameter Details", | |||
| "trainingParamDetails": "Training Parameter Details", | |||
| @@ -51,6 +51,8 @@ | |||
| "dataTraceback": "数据溯源", | |||
| "comparePlate": "对比看板", | |||
| "disableProfilerTip": "无profiler日志,无法查看性能分析", | |||
| "disableDashboardTip": "无summary日志或pb文件,无法查看训练看板", | |||
| "disableParameterTip": "无lineage日志,无法查看参数详情", | |||
| "openNewTab": "打开新页签", | |||
| "paramDetails": "参数详情", | |||
| "trainingParamDetails": "训练参数详情", | |||
| @@ -74,10 +74,16 @@ limitations under the License. | |||
| class-name="operate-container" | |||
| width="400"> | |||
| <template slot-scope="scope"> | |||
| <span class="menu-item" | |||
| <span class="menu-item operate-btn" | |||
| v-if="scope.row.viewDashboard" | |||
| @contextmenu.prevent="rightClick(scope.row, $event, 0)" | |||
| @click.stop="goToTrainDashboard(scope.row)"> | |||
| {{$t('summaryManage.viewDashboard')}} </span> | |||
| <span class="menu-item operate-btn button-disable" | |||
| v-else | |||
| :title="$t('summaryManage.disableDashboardTip')"> | |||
| {{$t('summaryManage.viewDashboard')}} | |||
| </span> | |||
| <span class="menu-item operate-btn" | |||
| v-if="scope.row.viewProfiler" | |||
| @contextmenu.prevent="rightClick(scope.row, $event, 1)" | |||
| @@ -89,9 +95,14 @@ limitations under the License. | |||
| {{$t('summaryManage.viewProfiler')}} | |||
| </span> | |||
| <span class="menu-item operate-btn" | |||
| v-if="scope.row.paramDetails" | |||
| @click.stop="showModelDialog(scope.row)"> | |||
| {{$t('summaryManage.paramDetails')}} </span> | |||
| <span class="menu-item operate-btn button-disable" | |||
| v-else | |||
| :title="$t('summaryManage.disableParameterTip')"> | |||
| {{$t('summaryManage.paramDetails')}} | |||
| </span> | |||
| </template> | |||
| </el-table-column> | |||
| </el-table> | |||
| @@ -267,6 +278,8 @@ export default { | |||
| i.relative_path = i.relative_path ? i.relative_path : '--'; | |||
| i.update_time = i.update_time ? i.update_time : '--'; | |||
| i.viewProfiler = i.profiler_dir && i.profiler_dir.length; | |||
| i.viewDashboard = i.summary_files || i.graph_files || i.lineage_files; | |||
| i.paramDetails = i.lineage_files; | |||
| }); | |||
| this.currentFolder = res.data.name ? res.data.name : '--'; | |||
| this.pagination.total = res.data.total; | |||