Unverified Commit 817ec68b authored by liuzhe-lz's avatar liuzhe-lz Committed by GitHub
Browse files

Add native support for v2 config (#3466)

parent 6aaca5f7
...@@ -32,9 +32,6 @@ class ExperimentSummaryPanel extends React.Component<ExpDrawerProps, ExpDrawerSt ...@@ -32,9 +32,6 @@ class ExperimentSummaryPanel extends React.Component<ExpDrawerProps, ExpDrawerSt
getExperimentContent = (): void => { getExperimentContent = (): void => {
const experimentData = JSON.parse(JSON.stringify(this.props.experimentProfile)); const experimentData = JSON.parse(JSON.stringify(this.props.experimentProfile));
if (experimentData.params.searchSpace) {
experimentData.params.searchSpace = JSON.parse(experimentData.params.searchSpace);
}
const trialMessagesArr = TRIALS.getTrialJobList(); const trialMessagesArr = TRIALS.getTrialJobList();
const interResultList = TRIALS.getMetricsList(); const interResultList = TRIALS.getMetricsList();
Object.keys(trialMessagesArr).map(item => { Object.keys(trialMessagesArr).map(item => {
......
...@@ -11,24 +11,24 @@ export const Command1 = (): any => { ...@@ -11,24 +11,24 @@ export const Command1 = (): any => {
const builtinName: string[] = []; const builtinName: string[] = [];
if (tuner !== undefined) { if (tuner !== undefined) {
title.push('Tuner'); title.push('Tuner');
builtinName.push(tuner.builtinTunerName || tuner.className || 'unknown'); builtinName.push(tuner.name || tuner.className || 'unknown');
} }
if (advisor !== undefined) { if (advisor !== undefined) {
title.push('Advisor'); title.push('Advisor');
builtinName.push(advisor.builtinAdvisorName || advisor.className || 'unknown'); builtinName.push(advisor.name || advisor.className || 'unknown');
} }
if (assessor !== undefined) { if (assessor !== undefined) {
title.push('Assessor'); title.push('Assessor');
builtinName.push(assessor.builtinAssessorName || assessor.className || 'unknown'); builtinName.push(assessor.name || assessor.className || 'unknown');
} }
return ( return (
<div className='basic' style={rightEidtParam}> <div className='basic' style={rightEidtParam}>
<div> <div>
<p className='command'>Training platform</p> <p className='command'>Training platform</p>
<div className='ellipsis'>{EXPERIMENT.profile.params.trainingServicePlatform}</div> <div className='ellipsis'>{EXPERIMENT.trainingServicePlatform}</div>
<p className='lineMargin'>{title.join('/')}</p> <p className='lineMargin'>{title.join('/')}</p>
<div className='ellipsis'>{builtinName.join('/')}</div> <div className='ellipsis'>{builtinName.join('/')}</div>
</div> </div>
......
...@@ -6,21 +6,6 @@ import { TOOLTIP_BACKGROUND_COLOR } from '../../../static/const'; ...@@ -6,21 +6,6 @@ import { TOOLTIP_BACKGROUND_COLOR } from '../../../static/const';
import '../../../static/style/overview/command.scss'; import '../../../static/style/overview/command.scss';
export const Command2 = (): any => { export const Command2 = (): any => {
const clusterMetaData = EXPERIMENT.profile.params.clusterMetaData;
let trialCommand = 'unknown';
if (clusterMetaData !== undefined) {
for (const item of clusterMetaData) {
if (item.key === 'command') {
trialCommand = item.value as string;
}
if (item.key === 'trial_config') {
if (typeof item.value === 'object' && 'command' in item.value) {
trialCommand = item.value.command as string;
}
}
}
}
return ( return (
<div className='basic' style={leftProgress}> <div className='basic' style={leftProgress}>
<p className='command'>Log directory</p> <p className='command'>Log directory</p>
...@@ -45,7 +30,7 @@ export const Command2 = (): any => { ...@@ -45,7 +30,7 @@ export const Command2 = (): any => {
<p className='lineMargin'>Trial command</p> <p className='lineMargin'>Trial command</p>
<div className='ellipsis'> <div className='ellipsis'>
<TooltipHost <TooltipHost
content={trialCommand || 'unknown'} content={EXPERIMENT.config.trialCommand || 'unknown'}
className='ellipsis' className='ellipsis'
directionalHint={DirectionalHint.bottomCenter} directionalHint={DirectionalHint.bottomCenter}
tooltipProps={{ tooltipProps={{
...@@ -58,7 +43,7 @@ export const Command2 = (): any => { ...@@ -58,7 +43,7 @@ export const Command2 = (): any => {
} }
}} }}
> >
{trialCommand || 'unknown'} {EXPERIMENT.config.trialCommand || 'unknown'}
</TooltipHost> </TooltipHost>
</div> </div>
</div> </div>
......
...@@ -53,7 +53,7 @@ export const ExpDuration = (): any => ( ...@@ -53,7 +53,7 @@ export const ExpDuration = (): any => (
field: 'maxExecDuration', field: 'maxExecDuration',
title: 'Max duration', title: 'Max duration',
maxExecDuration: maxExecDurationStr, maxExecDuration: maxExecDurationStr,
maxTrialNum: EXPERIMENT.profile.params.maxTrialNum, maxTrialNum: EXPERIMENT.maxTrialNumber,
trialConcurrency: EXPERIMENT.profile.params.trialConcurrency, trialConcurrency: EXPERIMENT.profile.params.trialConcurrency,
updateOverviewPage updateOverviewPage
}} }}
......
import React from 'react'; import React from 'react';
export const ExpDurationContext = React.createContext({ export const ExpDurationContext = React.createContext({
maxExecDuration: 0, maxExecDuration: 0,
execDuration: 0, execDuration: 0,
......
...@@ -13,7 +13,7 @@ export const TrialCount = (): any => { ...@@ -13,7 +13,7 @@ export const TrialCount = (): any => {
const stoppedCount = count.get('USER_CANCELED')! + count.get('SYS_CANCELED')! + count.get('EARLY_STOPPED')!; const stoppedCount = count.get('USER_CANCELED')! + count.get('SYS_CANCELED')! + count.get('EARLY_STOPPED')!;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const bar2 = count.get('RUNNING')! + count.get('SUCCEEDED')! + count.get('FAILED')! + stoppedCount; const bar2 = count.get('RUNNING')! + count.get('SUCCEEDED')! + count.get('FAILED')! + stoppedCount;
const maxTrialNum = EXPERIMENT.profile.params.maxTrialNum; const maxTrialNum = EXPERIMENT.maxTrialNumber;
// support type [0, 1], not 98% // support type [0, 1], not 98%
const bar2Percent = bar2 / maxTrialNum; const bar2Percent = bar2 / maxTrialNum;
return ( return (
...@@ -85,7 +85,7 @@ export const TrialCount = (): any => { ...@@ -85,7 +85,7 @@ export const TrialCount = (): any => {
field: 'maxTrialNum', field: 'maxTrialNum',
editType: CONTROLTYPE[1], editType: CONTROLTYPE[1],
maxExecDuration: '', maxExecDuration: '',
maxTrialNum: EXPERIMENT.profile.params.maxTrialNum, maxTrialNum: EXPERIMENT.maxTrialNumber,
trialConcurrency: EXPERIMENT.profile.params.trialConcurrency, trialConcurrency: EXPERIMENT.profile.params.trialConcurrency,
updateOverviewPage updateOverviewPage
}} }}
...@@ -102,7 +102,7 @@ export const TrialCount = (): any => { ...@@ -102,7 +102,7 @@ export const TrialCount = (): any => {
editType: CONTROLTYPE[2], editType: CONTROLTYPE[2],
// maxExecDuration: EXPERIMENT.profile.params.maxExecDuration, // maxExecDuration: EXPERIMENT.profile.params.maxExecDuration,
maxExecDuration: '', maxExecDuration: '',
maxTrialNum: EXPERIMENT.profile.params.maxTrialNum, maxTrialNum: EXPERIMENT.maxTrialNumber,
trialConcurrency: EXPERIMENT.profile.params.trialConcurrency, trialConcurrency: EXPERIMENT.profile.params.trialConcurrency,
updateOverviewPage updateOverviewPage
}} }}
......
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
'use strict';
export interface TrainingServiceConfig {
platform: string;
}
/* Local */
export interface LocalConfig extends TrainingServiceConfig {
platform: 'local';
useActiveGpu?: boolean;
maxTrialNumberPerGpu: number;
gpuIndices?: number[];
}
/* Remote */
export interface RemoteMachineConfig {
host: string;
port: number;
user: string;
password?: string;
sshKeyFile: string;
sshPassphrase?: string;
useActiveGpu: boolean;
maxTrialNumberPerGpu: number;
gpuIndices?: number[];
pythonPath?: string;
}
export interface RemoteConfig extends TrainingServiceConfig {
platform: 'remote';
reuseMode: boolean;
machineList: RemoteMachineConfig[];
}
/* OpenPAI */
export interface OpenpaiConfig extends TrainingServiceConfig {
platform: 'openpai';
host: string;
username: string;
token: string;
trialCpuNumber: number;
trialMemorySize: string;
storageConfigName: string;
dockerImage: string;
localStorageMountPoint: string;
containerStorageMountPoint: string;
reuseMode: boolean;
openpaiConfig?: object;
}
/* AML */
export interface AmlConfig extends TrainingServiceConfig {
platform: 'aml';
subscriptionId: string;
resourceGroup: string;
workspaceName: string;
computeTarget: string;
dockerImage: string;
}
/* Kubeflow */
export interface KubeflowStorageConfig {
storage: string;
server?: string;
path?: string;
azureAccount?: string;
azureShare?: string;
keyVault?: string;
keyVaultSecret?: string;
}
export interface KubeflowRoleConfig {
replicas: number;
command: string;
gpuNumber: number;
cpuNumber: number;
memorySize: string;
dockerImage: string;
}
export interface KubeflowConfig extends TrainingServiceConfig {
platform: 'kubeflow';
operator: string;
apiVersion: string;
storage: KubeflowStorageConfig;
worker: KubeflowRoleConfig;
parameterServer?: KubeflowRoleConfig;
}
/* FrameworkController */
type FrameworkControllerStorageConfig = KubeflowStorageConfig;
export interface FrameworkControllerRoleConfig {
name: string;
dockerImage: string;
taskNumber: number;
command: string;
gpuNumber: number;
cpuNumber: number;
memorySize: string;
attemptCompletionMinFailedTasks: number;
attemptCompletionMinSucceededTasks: number;
}
export interface FrameworkControllerConfig extends TrainingServiceConfig {
platform: 'frameworkcontroller';
serviceAccountName: string;
storage: FrameworkControllerStorageConfig;
taskRoles: FrameworkControllerRoleConfig[];
}
/* common */
export interface AlgorithmConfig {
name?: string;
className?: string;
codeDirectory?: string;
classArgs?: object;
}
export interface ExperimentConfig {
experimentName?: string;
searchSpace: any;
trialCommand: string;
trialCodeDirectory: string;
trialConcurrency: number;
trialGpuNumber?: number;
maxExperimentDuration?: string;
maxTrialNumber?: number;
nniManagerIp?: string;
//useAnnotation: boolean;
debug: boolean;
logLevel?: string;
experimentWorkingDirectory?: string;
tunerGpuIndices?: number[];
tuner?: AlgorithmConfig;
assessor?: AlgorithmConfig;
advisor?: AlgorithmConfig;
trainingService: TrainingServiceConfig;
}
/* util functions */
const timeUnits = { d: 24 * 3600, h: 3600, m: 60, s: 1 };
export function toSeconds(time: string): number {
for (const [unit, factor] of Object.entries(timeUnits)) {
if (time.endsWith(unit)) {
const digits = time.slice(0, -1);
return Number(digits) * factor;
}
}
throw new Error(`Bad time string "${time}"`);
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { ExperimentConfig } from './experimentConfig';
/** /**
* Definition of single dimension in search space. * Definition of single dimension in search space.
*/ */
...@@ -145,62 +150,16 @@ interface TrialJobInfo { ...@@ -145,62 +150,16 @@ interface TrialJobInfo {
stderrPath?: string; stderrPath?: string;
} }
interface ExperimentParams {
authorName: string;
experimentName: string;
description?: string;
trialConcurrency: number;
maxExecDuration: number; // seconds
maxTrialNum: number;
searchSpace: string;
trainingServicePlatform: string;
multiThread?: boolean;
versionCheck?: boolean;
logCollection?: string;
tuner?: {
className: string;
builtinTunerName?: string;
codeDir?: string;
classArgs?: any;
classFileName?: string;
checkpointDir: string;
gpuNum?: number;
includeIntermediateResults?: boolean;
};
assessor?: {
className: string;
builtinAssessorName?: string;
codeDir?: string;
classArgs?: any;
classFileName?: string;
checkpointDir: string;
gpuNum?: number;
};
advisor?: {
className: string;
builtinAdvisorName?: string;
codeDir?: string;
classArgs?: any;
classFileName?: string;
checkpointDir: string;
gpuNum?: number;
};
clusterMetaData?: {
key: string;
value: string | ClusterItem;
}[];
}
interface ClusterItem { interface ClusterItem {
command?: string; command?: string;
} }
interface ExperimentProfile { interface ExperimentProfile {
params: ExperimentParams; params: ExperimentConfig;
id: string; id: string;
execDuration: number; execDuration: number;
logDir?: string; logDir: string;
startTime?: number; startTime: number;
endTime?: number; endTime?: number;
maxSequenceId: number; maxSequenceId: number;
revision: number; revision: number;
...@@ -250,7 +209,6 @@ export { ...@@ -250,7 +209,6 @@ export {
Intermedia, Intermedia,
MetricDataRecord, MetricDataRecord,
TrialJobInfo, TrialJobInfo,
ExperimentParams,
ExperimentProfile, ExperimentProfile,
NNIManagerStatus, NNIManagerStatus,
EventMap, EventMap,
......
import { MANAGER_IP } from '../const'; import { MANAGER_IP } from '../const';
import { ExperimentConfig, toSeconds } from '../experimentConfig';
import { ExperimentProfile, NNIManagerStatus } from '../interface'; import { ExperimentProfile, NNIManagerStatus } from '../interface';
import { requestAxios } from '../function'; import { requestAxios } from '../function';
import { SearchSpace } from './searchspace'; import { SearchSpace } from './searchspace';
...@@ -12,8 +13,27 @@ function compareProfiles(profile1?: ExperimentProfile, profile2?: ExperimentProf ...@@ -12,8 +13,27 @@ function compareProfiles(profile1?: ExperimentProfile, profile2?: ExperimentProf
return JSON.stringify(copy1) === JSON.stringify(copy2); return JSON.stringify(copy1) === JSON.stringify(copy2);
} }
const emptyProfile: ExperimentProfile = {
params: {
searchSpace: undefined,
trialCommand: '',
trialCodeDirectory: '',
trialConcurrency: 0,
debug: false,
trainingService: {
platform: ''
}
},
id: '',
execDuration: 0,
logDir: '',
startTime: 0,
maxSequenceId: 0,
revision: 0
};
class Experiment { class Experiment {
private profileField?: ExperimentProfile = undefined; private profileField?: ExperimentProfile;
private statusField?: NNIManagerStatus = undefined; private statusField?: NNIManagerStatus = undefined;
private isNestedExperiment: boolean = false; private isNestedExperiment: boolean = false;
private isexperimentError: boolean = false; private isexperimentError: boolean = false;
...@@ -34,7 +54,13 @@ class Experiment { ...@@ -34,7 +54,13 @@ class Experiment {
} }
public isNestedExp(): boolean { public isNestedExp(): boolean {
return this.isNestedExperiment; try {
return !!Object.values(this.config.searchSpace).find(
item => (item as any)._value && typeof (item as any)._value[0] == 'object'
);
} catch {
return false;
}
} }
public experimentError(): boolean { public experimentError(): boolean {
...@@ -82,80 +108,42 @@ class Experiment { ...@@ -82,80 +108,42 @@ class Experiment {
} }
get profile(): ExperimentProfile { get profile(): ExperimentProfile {
if (!this.profileField) { return this.profileField === undefined ? emptyProfile : this.profileField;
// throw Error('Experiment profile not initialized'); }
// set initProfile to prevent page broken
const initProfile = { get config(): ExperimentConfig {
data: { return this.profile.params;
id: '', }
revision: 0,
execDuration: 0, get maxExperimentDurationSeconds(): number {
logDir: '', const value = this.config.maxExperimentDuration;
nextSequenceId: 0, return value === undefined ? Infinity : toSeconds(value);
params: { }
authorName: '',
experimentName: '', get maxTrialNumber(): number {
trialConcurrency: 0, const value = this.config.maxTrialNumber;
maxExecDuration: 0, return value === undefined ? Infinity : value;
maxTrialNum: 0,
searchSpace: 'null',
trainingServicePlatform: '',
tuner: {
builtinTunerName: 'TPE',
// eslint-disable-next-line @typescript-eslint/camelcase
classArgs: { optimize_mode: '' },
checkpointDir: ''
},
versionCheck: true,
clusterMetaData: [
{ key: '', value: '' },
{ key: '', value: '' }
]
},
startTime: 0,
endTime: 0
}
};
this.profileField = initProfile.data as any;
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.profileField!;
} }
get trialConcurrency(): number { get trialConcurrency(): number {
return this.profile.params.trialConcurrency; return this.config.trialConcurrency;
} }
get optimizeMode(): string { get optimizeMode(): string {
const tuner = this.profile.params.tuner; for (const algo of [this.config.tuner, this.config.advisor, this.config.assessor]) {
const advisor = this.profile.params.advisor; if (algo && algo.classArgs && algo.classArgs['optimizeMode']) {
const assessor = this.profile.params.assessor; return algo.classArgs['optimizeMode'];
const resultTuner = }
tuner && tuner.classArgs && tuner.classArgs.optimize_mode ? tuner.classArgs.optimize_mode : undefined; }
const resultAdvisor = return 'unknown';
advisor && advisor.classArgs && advisor.classArgs.optimize_mode
? advisor.classArgs.optimize_mode
: undefined;
const resultAssessor =
assessor && assessor.classArgs && assessor.classArgs.optimize_mode
? assessor.classArgs.optimize_mode
: undefined;
return resultTuner || resultAdvisor || resultAssessor || 'unknown';
} }
get trainingServicePlatform(): string { get trainingServicePlatform(): string {
return this.profile.params.trainingServicePlatform; return this.config.trainingService.platform;
} }
get searchSpace(): object { get searchSpace(): object {
const result = JSON.parse(this.profile.params.searchSpace); return this.config.searchSpace;
for (const item in result) {
if (result[item]._value && typeof result[item]._value[0] === 'object') {
this.isNestedExperiment = true;
break;
}
}
return result;
} }
get searchSpaceNew(): SearchSpace { get searchSpaceNew(): SearchSpace {
...@@ -165,7 +153,7 @@ class Experiment { ...@@ -165,7 +153,7 @@ class Experiment {
} }
get logCollectionEnabled(): boolean { get logCollectionEnabled(): boolean {
return !!(this.profile.params.logCollection && this.profile.params.logCollection !== 'none'); return false;
} }
get status(): string { get status(): string {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment