Skip to content

Commit

Permalink
Merge pull request #61 from microsoft/master
Browse files Browse the repository at this point in the history
pull code
  • Loading branch information
chicm-ms authored Dec 23, 2019
2 parents 0b7321e + 9d01d08 commit 60058d4
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 232 deletions.
1 change: 1 addition & 0 deletions docs/en_US/Tuner/BuiltinTuner.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ Similar to TPE, SMAC is also a black-box tuner which can be tried in various sce
**Requirement of classArgs**

* **optimize_mode** (*maximize or minimize, optional, default = maximize*) - If 'maximize', the tuner will target to maximize metrics. If 'minimize', the tuner will target to minimize metrics.
* **config_dedup** (*True or False, optional, default = False*) - If True, the tuner will not generate a configuration that has been already generated. If False, a configuration may be generated twice, but it is rare for relatively large search space.

**Usage example**

Expand Down
6 changes: 3 additions & 3 deletions src/nni_manager/common/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ interface ExperimentParams {
versionCheck?: boolean;
logCollection?: string;
tuner?: {
className: string;
className?: string;
builtinTunerName?: string;
codeDir?: string;
classArgs?: any;
Expand All @@ -37,15 +37,15 @@ interface ExperimentParams {
gpuIndices?: string;
};
assessor?: {
className: string;
className?: string;
builtinAssessorName?: string;
codeDir?: string;
classArgs?: any;
classFileName?: string;
checkpointDir: string;
};
advisor?: {
className: string;
className?: string;
builtinAdvisorName?: string;
codeDir?: string;
classArgs?: any;
Expand Down
90 changes: 6 additions & 84 deletions src/nni_manager/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import * as util from 'util';

import { Database, DataStore } from './datastore';
import { ExperimentStartupInfo, getExperimentStartupInfo, setExperimentStartupInfo } from './experimentStartupInfo';
import { Manager } from './manager';
import { ExperimentParams, Manager } from './manager';
import { HyperParameters, TrainingService, TrialJobStatus } from './trainingService';

function getExperimentRootDir(): string {
Expand Down Expand Up @@ -130,15 +130,6 @@ function parseArg(names: string[]): string {
return '';
}

function encodeCmdLineArgs(args: any): any {
if(process.platform === 'win32'){
return JSON.stringify(args);
}
else{
return JSON.stringify(JSON.stringify(args));
}
}

function getCmdPy(): string {
let cmd = 'python3';
if(process.platform === 'win32'){
Expand All @@ -150,83 +141,14 @@ function getCmdPy(): string {
/**
* Generate command line to start automl algorithm(s),
* either start advisor or start a process which runs tuner and assessor
* @param tuner : For builtin tuner:
* {
* className: 'EvolutionTuner'
* classArgs: {
* optimize_mode: 'maximize',
* population_size: 3
* }
* }
* customized:
* {
* codeDir: '/tmp/mytuner'
* classFile: 'best_tuner.py'
* className: 'BestTuner'
* classArgs: {
* optimize_mode: 'maximize',
* population_size: 3
* }
* }
*
* @param assessor: similiar as tuner
* @param advisor: similar as tuner
* @param expParams: experiment startup parameters
*
*/
function getMsgDispatcherCommand(tuner: any, assessor: any, advisor: any, multiPhase: boolean = false, multiThread: boolean = false): string {
if ((tuner || assessor) && advisor) {
throw new Error('Error: specify both tuner/assessor and advisor is not allowed');
}
if (!tuner && !advisor) {
throw new Error('Error: specify neither tuner nor advisor is not allowed');
}
let command: string = `${getCmdPy()} -m nni`;
if (multiPhase) {
command += ' --multi_phase';
}

if (multiThread) {
command += ' --multi_thread';
}

if (advisor) {
command += ` --advisor_class_name ${advisor.className}`;
if (advisor.classArgs !== undefined) {
command += ` --advisor_args ${encodeCmdLineArgs(advisor.classArgs)}`;
}
if (advisor.codeDir !== undefined && advisor.codeDir.length > 1) {
command += ` --advisor_directory ${advisor.codeDir}`;
}
if (advisor.classFileName !== undefined && advisor.classFileName.length > 1) {
command += ` --advisor_class_filename ${advisor.classFileName}`;
}
} else {
command += ` --tuner_class_name ${tuner.className}`;
if (tuner.classArgs !== undefined) {
command += ` --tuner_args ${encodeCmdLineArgs(tuner.classArgs)}`;
}
if (tuner.codeDir !== undefined && tuner.codeDir.length > 1) {
command += ` --tuner_directory ${tuner.codeDir}`;
}
if (tuner.classFileName !== undefined && tuner.classFileName.length > 1) {
command += ` --tuner_class_filename ${tuner.classFileName}`;
}

if (assessor !== undefined && assessor.className !== undefined) {
command += ` --assessor_class_name ${assessor.className}`;
if (assessor.classArgs !== undefined) {
command += ` --assessor_args ${encodeCmdLineArgs(assessor.classArgs)}`;
}
if (assessor.codeDir !== undefined && assessor.codeDir.length > 1) {
command += ` --assessor_directory ${assessor.codeDir}`;
}
if (assessor.classFileName !== undefined && assessor.classFileName.length > 1) {
command += ` --assessor_class_filename ${assessor.classFileName}`;
}
}
}

return command;
function getMsgDispatcherCommand(expParams: ExperimentParams): string {
const clonedParams = Object.assign({}, expParams);
delete clonedParams.searchSpace;
return `${getCmdPy()} -m nni --exp_params ${Buffer.from(JSON.stringify(clonedParams)).toString('base64')}`;
}

/**
Expand Down
6 changes: 2 additions & 4 deletions src/nni_manager/core/nnimanager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,7 @@ class NNIManager implements Manager {
this.trainingService.setClusterMetadata('log_collection', expParams.logCollection.toString());
}

const dispatcherCommand: string = getMsgDispatcherCommand(expParams.tuner, expParams.assessor, expParams.advisor,
expParams.multiPhase, expParams.multiThread);
const dispatcherCommand: string = getMsgDispatcherCommand(expParams);
this.log.debug(`dispatcher command: ${dispatcherCommand}`);
const checkpointDir: string = await this.createCheckpointDir();
this.setupTuner(
Expand Down Expand Up @@ -211,8 +210,7 @@ class NNIManager implements Manager {
this.trainingService.setClusterMetadata('version_check', expParams.versionCheck.toString());
}

const dispatcherCommand: string = getMsgDispatcherCommand(expParams.tuner, expParams.assessor, expParams.advisor,
expParams.multiPhase, expParams.multiThread);
const dispatcherCommand: string = getMsgDispatcherCommand(expParams);
this.log.debug(`dispatcher command: ${dispatcherCommand}`);
const checkpointDir: string = await this.createCheckpointDir();
this.setupTuner(
Expand Down
32 changes: 20 additions & 12 deletions src/nni_manager/core/test/ipcInterfaceTerminate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,26 @@ function startProcess(): void {
const dispatcherCmd: string = getMsgDispatcherCommand(
// Mock tuner config
{
className: 'DummyTuner',
codeDir: './',
classFileName: 'dummy_tuner.py'
},
// Mock assessor config
{
className: 'DummyAssessor',
codeDir: './',
classFileName: 'dummy_assessor.py'
},
// advisor
undefined
experimentName: 'exp1',
maxExecDuration: 3600,
searchSpace: '',
trainingServicePlatform: 'local',
authorName: '',
trialConcurrency: 1,
maxTrialNum: 5,
tuner: {
className: 'DummyTuner',
codeDir: './',
classFileName: 'dummy_tuner.py',
checkpointDir: './'
},
assessor: {
className: 'DummyAssessor',
codeDir: './',
classFileName: 'dummy_assessor.py',
checkpointDir: './'
}
}
);
const proc: ChildProcess = getTunerProc(dispatcherCmd, stdio, 'core/test', process.env);
proc.on('error', (error: Error): void => {
Expand Down
14 changes: 7 additions & 7 deletions src/nni_manager/core/test/nnimanager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,17 @@ describe('Unit test for nnimanager', function () {
maxExecDuration: 5,
maxTrialNum: 3,
trainingServicePlatform: 'local',
searchSpace: '{"x":1}',
searchSpace: '{"lr": {"_type": "choice", "_value": [0.01,0.001]}}',
tuner: {
className: 'TPE',
builtinTunerName: 'TPE',
classArgs: {
optimize_mode: 'maximize'
},
checkpointDir: '',
gpuNum: 0
},
assessor: {
className: 'Medianstop',
builtinAssessorName: 'Medianstop',
checkpointDir: '',
gpuNum: 1
}
Expand All @@ -65,17 +65,17 @@ describe('Unit test for nnimanager', function () {
maxExecDuration: 6,
maxTrialNum: 2,
trainingServicePlatform: 'local',
searchSpace: '{"y":2}',
searchSpace: '{"lr": {"_type": "choice", "_value": [0.01,0.001]}}',
tuner: {
className: 'TPE',
builtinTunerName: 'TPE',
classArgs: {
optimize_mode: 'maximize'
},
checkpointDir: '',
gpuNum: 0
},
assessor: {
className: 'Medianstop',
builtinAssessorName: 'Medianstop',
checkpointDir: '',
gpuNum: 1
}
Expand Down Expand Up @@ -198,7 +198,7 @@ describe('Unit test for nnimanager', function () {
it('test updateExperimentProfile SEARCH_SPACE', () => {
return nniManager.updateExperimentProfile(experimentProfile, 'SEARCH_SPACE').then(() => {
nniManager.getExperimentProfile().then((updateProfile) => {
expect(updateProfile.params.searchSpace).to.be.equal('{"y":2}');
expect(updateProfile.params.searchSpace).to.be.equal('{"lr": {"_type": "choice", "_value": [0.01,0.001]}}');
});
}).catch((error) => {
assert.fail(error);
Expand Down
Loading

0 comments on commit 60058d4

Please sign in to comment.