Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
nni
Commits
d7920fd2
Unverified
Commit
d7920fd2
authored
Feb 07, 2020
by
SparkSnail
Committed by
GitHub
Feb 07, 2020
Browse files
Add foreground mode in nnictl (#1956)
parent
26aa1136
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
80 additions
and
41 deletions
+80
-41
docs/en_US/Tutorial/Nnictl.md
docs/en_US/Tutorial/Nnictl.md
+2
-2
src/nni_manager/common/log.ts
src/nni_manager/common/log.ts
+22
-21
src/nni_manager/main.ts
src/nni_manager/main.ts
+27
-3
tools/nni_cmd/launcher.py
tools/nni_cmd/launcher.py
+27
-13
tools/nni_cmd/nnictl.py
tools/nni_cmd/nnictl.py
+2
-2
No files found.
docs/en_US/Tutorial/Nnictl.md
View file @
d7920fd2
...
...
@@ -49,7 +49,7 @@ nnictl support commands:
|--config, -c| True| |YAML configure file of the experiment|
|--port, -p|False| |the port of restful server|
|--debug, -d|False||set debug mode|
|--
watch
, -
w
|False||set
watch mode
|
|--
foreground
, -
f
|False||set
foreground mode, print log content to terminal
|
*
Examples
...
...
@@ -98,7 +98,7 @@ Debug mode will disable version check function in Trialkeeper.
|id| True| |The id of the experiment you want to resume|
|--port, -p| False| |Rest port of the experiment you want to resume|
|--debug, -d|False||set debug mode|
|--
watch
, -
w
|False||set
watch mode
|
|--
foreground
, -
f
|False||set
foreground mode, print log content to terminal
|
*
Example
...
...
src/nni_manager/common/log.ts
View file @
d7920fd2
...
...
@@ -4,13 +4,11 @@
'
use strict
'
;
import
*
as
fs
from
'
fs
'
;
import
*
as
path
from
'
path
'
;
import
{
Writable
}
from
'
stream
'
;
import
{
WritableStreamBuffer
}
from
'
stream-buffers
'
;
import
{
format
}
from
'
util
'
;
import
*
as
component
from
'
../common/component
'
;
import
{
getExperimentStartupInfo
,
isReadonly
}
from
'
./experimentStartupInfo
'
;
import
{
getLogDir
}
from
'
./utils
'
;
const
FATAL
:
number
=
1
;
const
ERROR
:
number
=
2
;
...
...
@@ -55,23 +53,21 @@ class BufferSerialEmitter {
@
component
.
Singleton
class
Logger
{
private
DEFAULT_LOGFILE
:
string
=
path
.
join
(
getLogDir
(),
'
nnimanager.log
'
);
private
level
:
number
=
INFO
;
private
bufferSerialEmitter
:
BufferSerialEmitter
;
private
writable
:
Writable
;
private
bufferSerialEmitter
?
:
BufferSerialEmitter
;
private
writable
?
:
Writable
;
private
readonly
:
boolean
=
false
;
constructor
(
fileName
?:
string
)
{
let
logFile
:
string
|
undefined
=
fileName
;
if
(
logFile
===
undefined
)
{
logFile
=
this
.
DEFAULT_LOGFILE
;
const
logFile
:
string
|
undefined
=
fileName
;
if
(
logFile
)
{
this
.
writable
=
fs
.
createWriteStream
(
logFile
,
{
flags
:
'
a+
'
,
encoding
:
'
utf8
'
,
autoClose
:
true
});
this
.
bufferSerialEmitter
=
new
BufferSerialEmitter
(
this
.
writable
);
}
this
.
writable
=
fs
.
createWriteStream
(
logFile
,
{
flags
:
'
a+
'
,
encoding
:
'
utf8
'
,
autoClose
:
true
});
this
.
bufferSerialEmitter
=
new
BufferSerialEmitter
(
this
.
writable
);
const
logLevelName
:
string
=
getExperimentStartupInfo
()
.
getLogLevel
();
...
...
@@ -84,7 +80,9 @@ class Logger {
}
public
close
():
void
{
this
.
writable
.
destroy
();
if
(
this
.
writable
)
{
this
.
writable
.
destroy
();
}
}
public
trace
(...
param
:
any
[]):
void
{
...
...
@@ -128,12 +126,15 @@ class Logger {
*/
private
log
(
level
:
string
,
param
:
any
[]):
void
{
if
(
!
this
.
readonly
)
{
const
buffer
:
WritableStreamBuffer
=
new
WritableStreamBuffer
();
buffer
.
write
(
`[
${(
new
Date
()).
toLocaleString
()}
]
${
level
}
`
);
buffer
.
write
(
format
(
param
));
buffer
.
write
(
'
\n
'
);
buffer
.
end
();
this
.
bufferSerialEmitter
.
feed
(
buffer
.
getContents
());
const
logContent
=
`[
${(
new
Date
()).
toLocaleString
()}
]
${
level
}
${
format
(
param
)}
\n`
;
if
(
this
.
writable
&&
this
.
bufferSerialEmitter
)
{
const
buffer
:
WritableStreamBuffer
=
new
WritableStreamBuffer
();
buffer
.
write
(
logContent
);
buffer
.
end
();
this
.
bufferSerialEmitter
.
feed
(
buffer
.
getContents
());
}
else
{
console
.
log
(
logContent
);
}
}
}
}
...
...
src/nni_manager/main.ts
View file @
d7920fd2
...
...
@@ -6,6 +6,7 @@
import
{
Container
,
Scope
}
from
'
typescript-ioc
'
;
import
*
as
fs
from
'
fs
'
;
import
*
as
path
from
'
path
'
;
import
*
as
component
from
'
./common/component
'
;
import
{
Database
,
DataStore
}
from
'
./common/datastore
'
;
import
{
setExperimentStartupInfo
}
from
'
./common/experimentStartupInfo
'
;
...
...
@@ -34,7 +35,7 @@ function initStartupInfo(
setExperimentStartupInfo
(
createNew
,
expId
,
basePort
,
logDirectory
,
experimentLogLevel
,
readonly
);
}
async
function
initContainer
(
platformMode
:
string
,
logFileName
?:
string
):
Promise
<
void
>
{
async
function
initContainer
(
foreground
:
boolean
,
platformMode
:
string
,
logFileName
?:
string
):
Promise
<
void
>
{
if
(
platformMode
===
'
local
'
)
{
Container
.
bind
(
TrainingService
)
.
to
(
LocalTrainingService
)
...
...
@@ -71,6 +72,12 @@ async function initContainer(platformMode: string, logFileName?: string): Promis
Container
.
bind
(
DataStore
)
.
to
(
NNIDataStore
)
.
scope
(
Scope
.
Singleton
);
const
DEFAULT_LOGFILE
:
string
=
path
.
join
(
getLogDir
(),
'
nnimanager.log
'
);
if
(
foreground
)
{
logFileName
=
undefined
;
}
else
if
(
logFileName
===
undefined
)
{
logFileName
=
DEFAULT_LOGFILE
;
}
Container
.
bind
(
Logger
).
provider
({
get
:
():
Logger
=>
new
Logger
(
logFileName
)
});
...
...
@@ -81,7 +88,7 @@ async function initContainer(platformMode: string, logFileName?: string): Promis
function
usage
():
void
{
console
.
info
(
'
usage: node main.js --port <port> --mode
\
<local/remote/pai/kubeflow/frameworkcontroller/paiYarn> --start_mode <new/resume> --experiment_id <id>
'
);
<local/remote/pai/kubeflow/frameworkcontroller/paiYarn> --start_mode <new/resume> --experiment_id <id>
--foreground <true/false>
'
);
}
const
strPort
:
string
=
parseArg
([
'
--port
'
,
'
-p
'
]);
...
...
@@ -90,6 +97,14 @@ if (!strPort || strPort.length === 0) {
process
.
exit
(
1
);
}
const
foregroundArg
:
string
=
parseArg
([
'
--foreground
'
,
'
-f
'
]);
if
(
!
(
'
true
'
||
'
false
'
).
includes
(
foregroundArg
.
toLowerCase
()))
{
console
.
log
(
`FATAL: foreground property should only be true or false`
);
usage
();
process
.
exit
(
1
);
}
const
foreground
:
boolean
=
foregroundArg
.
toLowerCase
()
===
'
true
'
?
true
:
false
;
const
port
:
number
=
parseInt
(
strPort
,
10
);
const
mode
:
string
=
parseArg
([
'
--mode
'
,
'
-m
'
]);
...
...
@@ -138,7 +153,7 @@ initStartupInfo(startMode, experimentId, port, logDir, logLevel, readonly);
mkDirP
(
getLogDir
())
.
then
(
async
()
=>
{
try
{
await
initContainer
(
mode
);
await
initContainer
(
foreground
,
mode
);
const
restServer
:
NNIRestServer
=
component
.
get
(
NNIRestServer
);
await
restServer
.
start
();
const
log
:
Logger
=
getLogger
();
...
...
@@ -162,6 +177,15 @@ function getStopSignal(): any {
}
}
function
getCtrlCSignal
():
any
{
return
'
SIGINT
'
;
}
process
.
on
(
getCtrlCSignal
(),
async
()
=>
{
const
log
:
Logger
=
getLogger
();
log
.
info
(
`Get SIGINT signal!`
);
});
process
.
on
(
getStopSignal
(),
async
()
=>
{
const
log
:
Logger
=
getLogger
();
let
hasError
:
boolean
=
false
;
...
...
tools/nni_cmd/launcher.py
View file @
d7920fd2
...
...
@@ -9,7 +9,7 @@ import random
import
site
import
time
import
tempfile
from
subprocess
import
Popen
,
check_call
,
CalledProcessError
from
subprocess
import
Popen
,
check_call
,
CalledProcessError
,
PIPE
,
STDOUT
from
nni_annotation
import
expand_annotations
,
generate_search_space
from
nni.constants
import
ModuleName
,
AdvisorModuleName
from
.launcher_utils
import
validate_all_content
...
...
@@ -20,7 +20,7 @@ from .common_utils import get_yml_content, get_json_content, print_error, print_
detect_port
,
get_user
,
get_python_dir
from
.constants
import
NNICTL_HOME_DIR
,
ERROR_INFO
,
REST_TIME_OUT
,
EXPERIMENT_SUCCESS_INFO
,
LOG_HEADER
,
PACKAGE_REQUIREMENTS
from
.command_utils
import
check_output_command
,
kill_command
from
.nnictl_utils
import
update_experiment
,
set_monitor
from
.nnictl_utils
import
update_experiment
def
get_log_path
(
config_file_name
):
'''generate stdout and stderr log path'''
...
...
@@ -78,17 +78,17 @@ def get_nni_installation_path():
print_error
(
'Fail to find nni under python library'
)
exit
(
1
)
def
start_rest_server
(
port
,
platform
,
mode
,
config_file_name
,
experiment_id
=
None
,
log_dir
=
None
,
log_level
=
None
):
def
start_rest_server
(
args
,
platform
,
mode
,
config_file_name
,
experiment_id
=
None
,
log_dir
=
None
,
log_level
=
None
):
'''Run nni manager process'''
if
detect_port
(
port
):
if
detect_port
(
args
.
port
):
print_error
(
'Port %s is used by another process, please reset the port!
\n
'
\
'You could use
\'
nnictl create --help
\'
to get help information'
%
port
)
'You could use
\'
nnictl create --help
\'
to get help information'
%
args
.
port
)
exit
(
1
)
if
(
platform
!=
'local'
)
and
detect_port
(
int
(
port
)
+
1
):
if
(
platform
!=
'local'
)
and
detect_port
(
int
(
args
.
port
)
+
1
):
print_error
(
'PAI mode need an additional adjacent port %d, and the port %d is used by another process!
\n
'
\
'You could set another port to start experiment!
\n
'
\
'You could use
\'
nnictl create --help
\'
to get help information'
%
((
int
(
port
)
+
1
),
(
int
(
port
)
+
1
)))
'You could use
\'
nnictl create --help
\'
to get help information'
%
((
int
(
args
.
port
)
+
1
),
(
int
(
args
.
port
)
+
1
)))
exit
(
1
)
print_normal
(
'Starting restful server...'
)
...
...
@@ -99,7 +99,7 @@ def start_rest_server(port, platform, mode, config_file_name, experiment_id=None
node_command
=
'node'
if
sys
.
platform
==
'win32'
:
node_command
=
os
.
path
.
join
(
entry_dir
[:
-
3
],
'Scripts'
,
'node.exe'
)
cmds
=
[
node_command
,
entry_file
,
'--port'
,
str
(
port
),
'--mode'
,
platform
]
cmds
=
[
node_command
,
entry_file
,
'--port'
,
str
(
args
.
port
),
'--mode'
,
platform
]
if
mode
==
'view'
:
cmds
+=
[
'--start_mode'
,
'resume'
]
cmds
+=
[
'--readonly'
,
'true'
]
...
...
@@ -111,6 +111,8 @@ def start_rest_server(port, platform, mode, config_file_name, experiment_id=None
cmds
+=
[
'--log_level'
,
log_level
]
if
mode
in
[
'resume'
,
'view'
]:
cmds
+=
[
'--experiment_id'
,
experiment_id
]
if
args
.
foreground
:
cmds
+=
[
'--foreground'
,
'true'
]
stdout_full_path
,
stderr_full_path
=
get_log_path
(
config_file_name
)
with
open
(
stdout_full_path
,
'a+'
)
as
stdout_file
,
open
(
stderr_full_path
,
'a+'
)
as
stderr_file
:
time_now
=
time
.
strftime
(
'%Y-%m-%d %H:%M:%S'
,
time
.
localtime
(
time
.
time
()))
...
...
@@ -120,9 +122,15 @@ def start_rest_server(port, platform, mode, config_file_name, experiment_id=None
stderr_file
.
write
(
log_header
)
if
sys
.
platform
==
'win32'
:
from
subprocess
import
CREATE_NEW_PROCESS_GROUP
process
=
Popen
(
cmds
,
cwd
=
entry_dir
,
stdout
=
stdout_file
,
stderr
=
stderr_file
,
creationflags
=
CREATE_NEW_PROCESS_GROUP
)
if
args
.
foreground
:
process
=
Popen
(
cmds
,
cwd
=
entry_dir
,
stdout
=
PIPE
,
stderr
=
STDOUT
,
creationflags
=
CREATE_NEW_PROCESS_GROUP
)
else
:
process
=
Popen
(
cmds
,
cwd
=
entry_dir
,
stdout
=
stdout_file
,
stderr
=
stderr_file
,
creationflags
=
CREATE_NEW_PROCESS_GROUP
)
else
:
process
=
Popen
(
cmds
,
cwd
=
entry_dir
,
stdout
=
stdout_file
,
stderr
=
stderr_file
)
if
args
.
foreground
:
process
=
Popen
(
cmds
,
cwd
=
entry_dir
,
stdout
=
PIPE
,
stderr
=
PIPE
)
else
:
process
=
Popen
(
cmds
,
cwd
=
entry_dir
,
stdout
=
stdout_file
,
stderr
=
stderr_file
)
return
process
,
str
(
time_now
)
def
set_trial_config
(
experiment_config
,
port
,
config_file_name
):
...
...
@@ -424,7 +432,7 @@ def launch_experiment(args, experiment_config, mode, config_file_name, experimen
if
log_level
not
in
[
'trace'
,
'debug'
]
and
(
args
.
debug
or
experiment_config
.
get
(
'debug'
)
is
True
):
log_level
=
'debug'
# start rest server
rest_process
,
start_time
=
start_rest_server
(
args
.
port
,
experiment_config
[
'trainingServicePlatform'
],
\
rest_process
,
start_time
=
start_rest_server
(
args
,
experiment_config
[
'trainingServicePlatform'
],
\
mode
,
config_file_name
,
experiment_id
,
log_dir
,
log_level
)
nni_config
.
set_config
(
'restServerPid'
,
rest_process
.
pid
)
# Deal with annotation
...
...
@@ -493,8 +501,14 @@ def launch_experiment(args, experiment_config, mode, config_file_name, experimen
experiment_config
[
'experimentName'
])
print_normal
(
EXPERIMENT_SUCCESS_INFO
%
(
experiment_id
,
' '
.
join
(
web_ui_url_list
)))
if
args
.
watch
:
set_monitor
(
True
,
3
,
args
.
port
,
rest_process
.
pid
)
if
args
.
foreground
:
try
:
while
True
:
log_content
=
rest_process
.
stdout
.
readline
().
strip
().
decode
(
'utf-8'
)
print
(
log_content
)
except
KeyboardInterrupt
:
kill_command
(
rest_process
.
pid
)
print_normal
(
'Stopping experiment...'
)
def
create_experiment
(
args
):
'''start a new experiment'''
...
...
tools/nni_cmd/nnictl.py
View file @
d7920fd2
...
...
@@ -51,7 +51,7 @@ def parse_args():
parser_start
.
add_argument
(
'--config'
,
'-c'
,
required
=
True
,
dest
=
'config'
,
help
=
'the path of yaml config file'
)
parser_start
.
add_argument
(
'--port'
,
'-p'
,
default
=
DEFAULT_REST_PORT
,
dest
=
'port'
,
help
=
'the port of restful server'
)
parser_start
.
add_argument
(
'--debug'
,
'-d'
,
action
=
'store_true'
,
help
=
' set debug mode'
)
parser_start
.
add_argument
(
'--
watch
'
,
'-
w
'
,
action
=
'store_true'
,
help
=
' set
watch mode
'
)
parser_start
.
add_argument
(
'--
foreground
'
,
'-
f
'
,
action
=
'store_true'
,
help
=
' set
foreground mode, print log content to terminal
'
)
parser_start
.
set_defaults
(
func
=
create_experiment
)
# parse resume command
...
...
@@ -59,7 +59,7 @@ def parse_args():
parser_resume
.
add_argument
(
'id'
,
nargs
=
'?'
,
help
=
'The id of the experiment you want to resume'
)
parser_resume
.
add_argument
(
'--port'
,
'-p'
,
default
=
DEFAULT_REST_PORT
,
dest
=
'port'
,
help
=
'the port of restful server'
)
parser_resume
.
add_argument
(
'--debug'
,
'-d'
,
action
=
'store_true'
,
help
=
' set debug mode'
)
parser_resume
.
add_argument
(
'--
watch
'
,
'-
w
'
,
action
=
'store_true'
,
help
=
' set
watch mode
'
)
parser_resume
.
add_argument
(
'--
foreground
'
,
'-
f
'
,
action
=
'store_true'
,
help
=
' set
foreground mode, print log content to terminal
'
)
parser_resume
.
set_defaults
(
func
=
resume_experiment
)
# parse view command
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment