Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
OpenDAS
nni
Commits
ea665155
Commit
ea665155
authored
Nov 24, 2019
by
quzha
Browse files
Merge branch 'master' of github.com:Microsoft/nni into dev-nas-refactor
parents
73b2221b
ae36373c
Changes
48
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
525 additions
and
47 deletions
+525
-47
src/sdk/pynni/nni/trial.py
src/sdk/pynni/nni/trial.py
+6
-4
src/sdk/pynni/tests/test_builtin_tuners.py
src/sdk/pynni/tests/test_builtin_tuners.py
+1
-1
src/sdk/pynni/tests/test_compressor.py
src/sdk/pynni/tests/test_compressor.py
+77
-27
src/sdk/pynni/tests/test_msg_dispatcher.py
src/sdk/pynni/tests/test_msg_dispatcher.py
+1
-10
src/webui/src/components/Modal/CustomizedTrial.tsx
src/webui/src/components/Modal/CustomizedTrial.tsx
+317
-0
src/webui/src/components/Modal/customized.scss
src/webui/src/components/Modal/customized.scss
+71
-0
src/webui/src/components/trial-detail/TableList.tsx
src/webui/src/components/trial-detail/TableList.tsx
+51
-4
tools/nni_gpu_tool/gpu_metrics_collector.py
tools/nni_gpu_tool/gpu_metrics_collector.py
+1
-1
No files found.
src/sdk/pynni/nni/trial.py
View file @
ea665155
...
...
@@ -126,9 +126,10 @@ def report_intermediate_result(metric):
serializable object.
"""
global
_intermediate_seq
assert
_params
is
not
None
,
'nni.get_next_parameter() needs to be called before report_intermediate_result'
assert
_params
or
trial_env_vars
.
NNI_PLATFORM
is
None
,
\
'nni.get_next_parameter() needs to be called before report_intermediate_result'
metric
=
json_tricks
.
dumps
({
'parameter_id'
:
_params
[
'parameter_id'
],
'parameter_id'
:
_params
[
'parameter_id'
]
if
_params
else
None
,
'trial_job_id'
:
trial_env_vars
.
NNI_TRIAL_JOB_ID
,
'type'
:
'PERIODICAL'
,
'sequence'
:
_intermediate_seq
,
...
...
@@ -147,9 +148,10 @@ def report_final_result(metric):
metric:
serializable object.
"""
assert
_params
is
not
None
,
'nni.get_next_parameter() needs to be called before report_final_result'
assert
_params
or
trial_env_vars
.
NNI_PLATFORM
is
None
,
\
'nni.get_next_parameter() needs to be called before report_final_result'
metric
=
json_tricks
.
dumps
({
'parameter_id'
:
_params
[
'parameter_id'
],
'parameter_id'
:
_params
[
'parameter_id'
]
if
_params
else
None
,
'trial_job_id'
:
trial_env_vars
.
NNI_TRIAL_JOB_ID
,
'type'
:
'FINAL'
,
'sequence'
:
0
,
...
...
src/sdk/pynni/tests/test_tuner.py
→
src/sdk/pynni/tests/test_
builtin_
tuner
s
.py
View file @
ea665155
...
...
@@ -41,7 +41,7 @@ logging.basicConfig(level=logging.INFO)
logger
=
logging
.
getLogger
(
'test_tuner'
)
class
TunerTestCase
(
TestCase
):
class
Builtin
Tuner
s
TestCase
(
TestCase
):
"""
Targeted at testing functions of built-in tuners, including
- [ ] load_checkpoint
...
...
src/sdk/pynni/tests/test_compressor.py
View file @
ea665155
from
unittest
import
TestCase
,
main
import
numpy
as
np
import
tensorflow
as
tf
import
torch
import
torch.nn.functional
as
F
...
...
@@ -7,11 +8,11 @@ import nni.compression.torch as torch_compressor
if
tf
.
__version__
>=
'2.0'
:
import
nni.compression.tensorflow
as
tf_compressor
def
get_tf_
mnist_
model
():
def
get_tf_model
():
model
=
tf
.
keras
.
models
.
Sequential
([
tf
.
keras
.
layers
.
Conv2D
(
filters
=
32
,
kernel_size
=
7
,
input_shape
=
[
28
,
28
,
1
],
activation
=
'relu'
,
padding
=
"SAME"
),
tf
.
keras
.
layers
.
Conv2D
(
filters
=
5
,
kernel_size
=
7
,
input_shape
=
[
28
,
28
,
1
],
activation
=
'relu'
,
padding
=
"SAME"
),
tf
.
keras
.
layers
.
MaxPooling2D
(
pool_size
=
2
),
tf
.
keras
.
layers
.
Conv2D
(
filters
=
64
,
kernel_size
=
3
,
activation
=
'relu'
,
padding
=
"SAME"
),
tf
.
keras
.
layers
.
Conv2D
(
filters
=
10
,
kernel_size
=
3
,
activation
=
'relu'
,
padding
=
"SAME"
),
tf
.
keras
.
layers
.
MaxPooling2D
(
pool_size
=
2
),
tf
.
keras
.
layers
.
Flatten
(),
tf
.
keras
.
layers
.
Dense
(
units
=
128
,
activation
=
'relu'
),
...
...
@@ -23,43 +24,51 @@ def get_tf_mnist_model():
metrics
=
[
"accuracy"
])
return
model
class
TorchM
nist
(
torch
.
nn
.
Module
):
class
TorchM
odel
(
torch
.
nn
.
Module
):
def
__init__
(
self
):
super
().
__init__
()
self
.
conv1
=
torch
.
nn
.
Conv2d
(
1
,
20
,
5
,
1
)
self
.
conv2
=
torch
.
nn
.
Conv2d
(
20
,
5
0
,
5
,
1
)
self
.
fc1
=
torch
.
nn
.
Linear
(
4
*
4
*
5
0
,
5
00
)
self
.
fc2
=
torch
.
nn
.
Linear
(
5
00
,
10
)
self
.
conv1
=
torch
.
nn
.
Conv2d
(
1
,
5
,
5
,
1
)
self
.
conv2
=
torch
.
nn
.
Conv2d
(
5
,
1
0
,
5
,
1
)
self
.
fc1
=
torch
.
nn
.
Linear
(
4
*
4
*
1
0
,
1
00
)
self
.
fc2
=
torch
.
nn
.
Linear
(
1
00
,
10
)
def
forward
(
self
,
x
):
x
=
F
.
relu
(
self
.
conv1
(
x
))
x
=
F
.
max_pool2d
(
x
,
2
,
2
)
x
=
F
.
relu
(
self
.
conv2
(
x
))
x
=
F
.
max_pool2d
(
x
,
2
,
2
)
x
=
x
.
view
(
-
1
,
4
*
4
*
5
0
)
x
=
x
.
view
(
-
1
,
4
*
4
*
1
0
)
x
=
F
.
relu
(
self
.
fc1
(
x
))
x
=
self
.
fc2
(
x
)
return
F
.
log_softmax
(
x
,
dim
=
1
)
def
tf2
(
func
):
def
test_tf2_func
(
self
):
def
test_tf2_func
(
*
args
):
if
tf
.
__version__
>=
'2.0'
:
func
()
func
(
*
args
)
return
test_tf2_func
k1
=
[[
1
]
*
3
]
*
3
k2
=
[[
2
]
*
3
]
*
3
k3
=
[[
3
]
*
3
]
*
3
k4
=
[[
4
]
*
3
]
*
3
k5
=
[[
5
]
*
3
]
*
3
w
=
[[
k1
,
k2
,
k3
,
k4
,
k5
]]
*
10
class
CompressorTestCase
(
TestCase
):
def
test_torch_pruner
(
self
):
model
=
TorchM
nist
()
def
test_torch_
level_
pruner
(
self
):
model
=
TorchM
odel
()
configure_list
=
[{
'sparsity'
:
0.8
,
'op_types'
:
[
'default'
]}]
torch_compressor
.
LevelPruner
(
model
,
configure_list
).
compress
()
def
test_torch_fpgm_pruner
(
self
):
model
=
TorchMnist
()
configure_list
=
[{
'sparsity'
:
0.
5
,
'op_types'
:
[
'
Conv2d
'
]}]
t
orch
_compressor
.
FPGM
Pruner
(
model
,
configure_list
).
compress
()
@
tf2
def
test_tf_level_pruner
(
self
):
configure_list
=
[{
'sparsity'
:
0.
8
,
'op_types'
:
[
'
default
'
]}]
t
f
_compressor
.
Level
Pruner
(
get_tf_
model
()
,
configure_list
).
compress
()
def
test_torch_quantizer
(
self
):
model
=
TorchM
nist
()
def
test_torch_
naive_
quantizer
(
self
):
model
=
TorchM
odel
()
configure_list
=
[{
'quant_types'
:
[
'weight'
],
'quant_bits'
:
{
...
...
@@ -70,18 +79,59 @@ class CompressorTestCase(TestCase):
torch_compressor
.
NaiveQuantizer
(
model
,
configure_list
).
compress
()
@
tf2
def
test_tf_pruner
(
self
):
configure_list
=
[{
'sparsity'
:
0.8
,
'op_types'
:
[
'default'
]}]
tf_compressor
.
LevelPruner
(
get_tf_mnist_model
(),
configure_list
).
compress
()
def
test_tf_naive_quantizer
(
self
):
tf_compressor
.
NaiveQuantizer
(
get_tf_model
(),
[{
'op_types'
:
[
'default'
]}]).
compress
()
@
tf2
def
test_tf_quantizer
(
self
):
tf_compressor
.
NaiveQuantizer
(
get_tf_mnist_model
(),
[{
'op_types'
:
[
'default'
]}]).
compress
()
def
test_torch_fpgm_pruner
(
self
):
"""
With filters(kernels) defined as above (k1 - k5), it is obvious that k3 is the Geometric Median
which minimize the total geometric distance by defination of Geometric Median in this paper:
Filter Pruning via Geometric Median for Deep Convolutional Neural Networks Acceleration,
https://arxiv.org/pdf/1811.00250.pdf
So if sparsity is 0.2, the expected masks should mask out all k3, this can be verified through:
`all(torch.sum(masks, (0, 2, 3)).numpy() == np.array([90., 90., 0., 90., 90.]))`
If sparsity is 0.6, the expected masks should mask out all k2, k3, k4, this can be verified through:
`all(torch.sum(masks, (0, 2, 3)).numpy() == np.array([90., 0., 0., 0., 90.]))`
"""
model
=
TorchModel
()
config_list
=
[{
'sparsity'
:
0.2
,
'op_types'
:
[
'Conv2d'
]},
{
'sparsity'
:
0.6
,
'op_types'
:
[
'Conv2d'
]}]
pruner
=
torch_compressor
.
FPGMPruner
(
model
,
config_list
)
model
.
conv2
.
weight
.
data
=
torch
.
tensor
(
w
).
float
()
layer
=
torch_compressor
.
compressor
.
LayerInfo
(
'conv2'
,
model
.
conv2
)
masks
=
pruner
.
calc_mask
(
layer
,
config_list
[
0
])
assert
all
(
torch
.
sum
(
masks
,
(
0
,
2
,
3
)).
numpy
()
==
np
.
array
([
90.
,
90.
,
0.
,
90.
,
90.
]))
pruner
.
update_epoch
(
1
)
model
.
conv2
.
weight
.
data
=
torch
.
tensor
(
w
).
float
()
masks
=
pruner
.
calc_mask
(
layer
,
config_list
[
1
])
assert
all
(
torch
.
sum
(
masks
,
(
0
,
2
,
3
)).
numpy
()
==
np
.
array
([
90.
,
0.
,
0.
,
0.
,
90.
]))
@
tf2
def
test_tf_fpgm_pruner
(
self
):
configure_list
=
[{
'sparsity'
:
0.5
,
'op_types'
:
[
'Conv2D'
]}]
tf_compressor
.
FPGMPruner
(
get_tf_mnist_model
(),
configure_list
).
compress
()
model
=
get_tf_model
()
config_list
=
[{
'sparsity'
:
0.2
,
'op_types'
:
[
'Conv2D'
]},
{
'sparsity'
:
0.6
,
'op_types'
:
[
'Conv2D'
]}]
pruner
=
tf_compressor
.
FPGMPruner
(
model
,
config_list
)
weights
=
model
.
layers
[
2
].
weights
weights
[
0
]
=
np
.
array
(
w
).
astype
(
np
.
float32
).
transpose
([
2
,
3
,
0
,
1
]).
transpose
([
0
,
1
,
3
,
2
])
model
.
layers
[
2
].
set_weights
([
weights
[
0
],
weights
[
1
].
numpy
()])
layer
=
tf_compressor
.
compressor
.
LayerInfo
(
model
.
layers
[
2
])
masks
=
pruner
.
calc_mask
(
layer
,
config_list
[
0
]).
numpy
()
masks
=
masks
.
transpose
([
2
,
3
,
0
,
1
]).
transpose
([
1
,
0
,
2
,
3
])
assert
all
(
masks
.
sum
((
0
,
2
,
3
))
==
np
.
array
([
90.
,
90.
,
0.
,
90.
,
90.
]))
pruner
.
update_epoch
(
1
)
model
.
layers
[
2
].
set_weights
([
weights
[
0
],
weights
[
1
].
numpy
()])
masks
=
pruner
.
calc_mask
(
layer
,
config_list
[
1
]).
numpy
()
masks
=
masks
.
transpose
([
2
,
3
,
0
,
1
]).
transpose
([
1
,
0
,
2
,
3
])
assert
all
(
masks
.
sum
((
0
,
2
,
3
))
==
np
.
array
([
90.
,
0.
,
0.
,
0.
,
90.
]))
if
__name__
==
'__main__'
:
...
...
src/sdk/pynni/tests/test_msg_dispatcher.py
View file @
ea665155
...
...
@@ -80,8 +80,6 @@ class MsgDispatcherTestCase(TestCase):
send
(
CommandType
.
ReportMetricData
,
'{"parameter_id":0,"type":"PERIODICAL","value":10}'
)
send
(
CommandType
.
ReportMetricData
,
'{"parameter_id":1,"type":"FINAL","value":11}'
)
send
(
CommandType
.
UpdateSearchSpace
,
'{"name":"SS0"}'
)
send
(
CommandType
.
AddCustomizedTrialJob
,
'{"param":-1}'
)
send
(
CommandType
.
ReportMetricData
,
'{"parameter_id":2,"type":"FINAL","value":22}'
)
send
(
CommandType
.
RequestTrialJobs
,
'1'
)
send
(
CommandType
.
KillTrialJob
,
'null'
)
_restore_io
()
...
...
@@ -99,14 +97,7 @@ class MsgDispatcherTestCase(TestCase):
self
.
_assert_params
(
0
,
2
,
[],
None
)
self
.
_assert_params
(
1
,
4
,
[],
None
)
command
,
data
=
receive
()
# this one is customized
data
=
json
.
loads
(
data
)
self
.
assertIs
(
command
,
CommandType
.
NewTrialJob
)
self
.
assertEqual
(
data
[
'parameter_id'
],
2
)
self
.
assertEqual
(
data
[
'parameter_source'
],
'customized'
)
self
.
assertEqual
(
data
[
'parameters'
],
{
'param'
:
-
1
})
self
.
_assert_params
(
3
,
6
,
[[
1
,
4
,
11
,
False
],
[
2
,
-
1
,
22
,
True
]],
{
'name'
:
'SS0'
})
self
.
_assert_params
(
2
,
6
,
[[
1
,
4
,
11
,
False
]],
{
'name'
:
'SS0'
})
self
.
assertEqual
(
len
(
_out_buf
.
read
()),
0
)
# no more commands
...
...
src/webui/src/components/Modal/CustomizedTrial.tsx
0 → 100644
View file @
ea665155
import
*
as
React
from
'
react
'
;
import
axios
from
'
axios
'
;
import
{
Row
,
Col
,
Input
,
Modal
,
Form
,
Button
,
Icon
}
from
'
antd
'
;
import
{
MANAGER_IP
}
from
'
../../static/const
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
FormComponentProps
}
from
'
antd/lib/form
'
;
const
FormItem
=
Form
.
Item
;
import
'
./customized.scss
'
;
interface
CustomizeProps
extends
FormComponentProps
{
visible
:
boolean
;
copyTrialId
:
string
;
closeCustomizeModal
:
()
=>
void
;
}
interface
CustomizeState
{
isShowSubmitSucceed
:
boolean
;
isShowSubmitFailed
:
boolean
;
isShowWarning
:
boolean
;
searchSpace
:
object
;
copyTrialParameter
:
object
;
// user click the trial's parameters
customParameters
:
object
;
// customized trial, maybe user change trial's parameters
customID
:
number
;
// submit customized trial succeed, return the new customized trial id
}
class
Customize
extends
React
.
Component
<
CustomizeProps
,
CustomizeState
>
{
constructor
(
props
:
CustomizeProps
)
{
super
(
props
);
this
.
state
=
{
isShowSubmitSucceed
:
false
,
isShowSubmitFailed
:
false
,
isShowWarning
:
false
,
searchSpace
:
EXPERIMENT
.
searchSpace
,
copyTrialParameter
:
{},
customParameters
:
{},
customID
:
NaN
};
}
// [submit click] user add a new trial [submit a trial]
addNewTrial
=
()
=>
{
const
{
searchSpace
,
copyTrialParameter
}
=
this
.
state
;
// get user edited hyperParameter, ps: will change data type if you modify the input val
const
customized
=
this
.
props
.
form
.
getFieldsValue
();
// true: parameters are wrong
let
flag
=
false
;
Object
.
keys
(
customized
).
map
(
item
=>
{
if
(
item
!==
'
tag
'
)
{
// unified data type
if
(
typeof
copyTrialParameter
[
item
]
===
'
number
'
&&
typeof
customized
[
item
]
===
'
string
'
)
{
customized
[
item
]
=
JSON
.
parse
(
customized
[
item
]);
}
if
(
searchSpace
[
item
].
_type
===
'
choice
'
)
{
if
(
searchSpace
[
item
].
_value
.
find
((
val
:
string
|
number
)
=>
val
===
customized
[
item
])
===
undefined
)
{
flag
=
true
;
return
;
}
}
else
{
if
(
customized
[
item
]
<
searchSpace
[
item
].
_value
[
0
]
||
customized
[
item
]
>
searchSpace
[
item
].
_value
[
1
])
{
flag
=
true
;
return
;
}
}
}
});
if
(
flag
!==
false
)
{
// open the warning modal
this
.
setState
(()
=>
({
isShowWarning
:
true
,
customParameters
:
customized
}));
}
else
{
// submit a customized job
this
.
submitCustomize
(
customized
);
}
}
warningConfirm
=
()
=>
{
this
.
setState
(()
=>
({
isShowWarning
:
false
}));
const
{
customParameters
}
=
this
.
state
;
this
.
submitCustomize
(
customParameters
);
}
warningCancel
=
()
=>
{
this
.
setState
(()
=>
({
isShowWarning
:
false
}));
}
submitCustomize
=
(
customized
:
Object
)
=>
{
// delete `tag` key
for
(
let
i
in
customized
)
{
if
(
i
===
'
tag
'
)
{
delete
customized
[
i
];
}
}
axios
(
`
${
MANAGER_IP
}
/trial-jobs`
,
{
method
:
'
POST
'
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
},
data
:
customized
})
.
then
(
res
=>
{
if
(
res
.
status
===
200
)
{
this
.
setState
(()
=>
({
isShowSubmitSucceed
:
true
,
customID
:
res
.
data
.
sequenceId
}));
this
.
props
.
closeCustomizeModal
();
}
else
{
this
.
setState
(()
=>
({
isShowSubmitFailed
:
true
}));
}
})
.
catch
(
error
=>
{
this
.
setState
(()
=>
({
isShowSubmitFailed
:
true
}));
});
}
closeSucceedHint
=
()
=>
{
// also close customized trial modal
this
.
setState
(()
=>
({
isShowSubmitSucceed
:
false
}));
this
.
props
.
closeCustomizeModal
();
}
closeFailedHint
=
()
=>
{
// also close customized trial modal
this
.
setState
(()
=>
({
isShowSubmitFailed
:
false
}));
this
.
props
.
closeCustomizeModal
();
}
componentDidMount
()
{
const
{
copyTrialId
}
=
this
.
props
;
if
(
copyTrialId
!==
undefined
&&
TRIALS
.
getTrial
(
copyTrialId
)
!==
undefined
)
{
const
originCopyTrialPara
=
TRIALS
.
getTrial
(
copyTrialId
).
description
.
parameters
;
this
.
setState
(()
=>
({
copyTrialParameter
:
originCopyTrialPara
}));
}
}
componentWillReceiveProps
(
nextProps
:
CustomizeProps
)
{
const
{
copyTrialId
}
=
nextProps
;
if
(
copyTrialId
!==
undefined
&&
TRIALS
.
getTrial
(
copyTrialId
)
!==
undefined
)
{
const
originCopyTrialPara
=
TRIALS
.
getTrial
(
copyTrialId
).
description
.
parameters
;
this
.
setState
(()
=>
({
copyTrialParameter
:
originCopyTrialPara
}));
}
}
render
()
{
const
{
closeCustomizeModal
,
visible
}
=
this
.
props
;
const
{
isShowSubmitSucceed
,
isShowSubmitFailed
,
isShowWarning
,
customID
,
copyTrialParameter
}
=
this
.
state
;
const
{
form
:
{
getFieldDecorator
},
// form: { getFieldDecorator, getFieldValue },
}
=
this
.
props
;
const
warning
=
'
The parameters you set are not in our search space, this may cause the tuner to crash, Are
'
+
'
you sure you want to continue submitting?
'
;
return
(
<
Row
>
{
/* form: search space */
}
<
Modal
title
=
"Customized trial setting"
visible
=
{
visible
}
onCancel
=
{
closeCustomizeModal
}
footer
=
{
null
}
destroyOnClose
=
{
true
}
maskClosable
=
{
false
}
centered
=
{
true
}
>
{
/* search space form */
}
<
Row
className
=
"hyper-box"
>
<
Form
>
{
Object
.
keys
(
copyTrialParameter
).
map
(
item
=>
(
<
Row
key
=
{
item
}
className
=
"hyper-form"
>
<
Col
span
=
{
9
}
className
=
"title"
>
{
item
}
</
Col
>
<
Col
span
=
{
15
}
className
=
"inputs"
>
<
FormItem
key
=
{
item
}
style
=
{
{
marginBottom
:
0
}
}
>
{
getFieldDecorator
(
item
,
{
initialValue
:
copyTrialParameter
[
item
],
})(
<
Input
/>
)
}
</
FormItem
>
</
Col
>
</
Row
>
)
)
}
<
Row
key
=
"tag"
className
=
"hyper-form tag-input"
>
<
Col
span
=
{
9
}
className
=
"title"
>
Tag
</
Col
>
<
Col
span
=
{
15
}
className
=
"inputs"
>
<
FormItem
key
=
"tag"
style
=
{
{
marginBottom
:
0
}
}
>
{
getFieldDecorator
(
'
tag
'
,
{
initialValue
:
'
Customized
'
,
})(
<
Input
/>
)
}
</
FormItem
>
</
Col
>
</
Row
>
</
Form
>
</
Row
>
<
Row
className
=
"modal-button"
>
<
Button
type
=
"primary"
className
=
"tableButton distance"
onClick
=
{
this
.
addNewTrial
}
>
Submit
</
Button
>
<
Button
className
=
"tableButton cancelSty"
onClick
=
{
this
.
props
.
closeCustomizeModal
}
>
Cancel
</
Button
>
</
Row
>
{
/* control button */
}
</
Modal
>
{
/* clone: prompt succeed or failed */
}
<
Modal
visible
=
{
isShowSubmitSucceed
}
footer
=
{
null
}
destroyOnClose
=
{
true
}
maskClosable
=
{
false
}
closable
=
{
false
}
centered
=
{
true
}
>
<
Row
className
=
"resubmit"
>
<
Row
>
<
h2
className
=
"title"
>
<
span
>
<
Icon
type
=
"check-circle"
className
=
"color-succ"
/>
<
b
>
Submit successfully
</
b
>
</
span
>
</
h2
>
<
div
className
=
"hint"
>
<
span
>
You can find your customized trial by Trial No.
{
customID
}
</
span
>
</
div
>
</
Row
>
<
Row
className
=
"modal-button"
>
<
Button
className
=
"tableButton cancelSty"
onClick
=
{
this
.
closeSucceedHint
}
>
OK
</
Button
>
</
Row
>
</
Row
>
</
Modal
>
<
Modal
visible
=
{
isShowSubmitFailed
}
footer
=
{
null
}
destroyOnClose
=
{
true
}
maskClosable
=
{
false
}
closable
=
{
false
}
centered
=
{
true
}
>
<
Row
className
=
"resubmit"
>
<
Row
>
<
h2
className
=
"title"
>
<
span
>
<
Icon
type
=
"check-circle"
className
=
"color-error"
/>
Submit Failed
</
span
>
</
h2
>
<
div
className
=
"hint"
>
<
span
>
Unknown error.
</
span
>
</
div
>
</
Row
>
<
Row
className
=
"modal-button"
>
<
Button
className
=
"tableButton cancelSty"
onClick
=
{
this
.
closeFailedHint
}
>
OK
</
Button
>
</
Row
>
</
Row
>
</
Modal
>
{
/* hyperParameter not match search space, warning modal */
}
<
Modal
visible
=
{
isShowWarning
}
footer
=
{
null
}
destroyOnClose
=
{
true
}
maskClosable
=
{
false
}
closable
=
{
false
}
centered
=
{
true
}
>
<
Row
className
=
"resubmit"
>
<
Row
>
<
h2
className
=
"title"
>
<
span
>
<
Icon
className
=
"color-warn"
type
=
"warning"
/>
Warning
</
span
>
</
h2
>
<
div
className
=
"hint"
>
<
span
>
{
warning
}
</
span
>
</
div
>
</
Row
>
<
Row
className
=
"modal-button center"
>
<
Button
className
=
"tableButton cancelSty distance"
onClick
=
{
this
.
warningConfirm
}
>
Confirm
</
Button
>
<
Button
className
=
"tableButton cancelSty"
onClick
=
{
this
.
warningCancel
}
>
Cancel
</
Button
>
</
Row
>
</
Row
>
</
Modal
>
</
Row
>
);
}
}
export
default
Form
.
create
<
FormComponentProps
>
()(
Customize
);
\ No newline at end of file
src/webui/src/components/Modal/customized.scss
0 → 100644
View file @
ea665155
.ant-modal-body
{
border-radius
:
none
;
}
.ant-modal-title
{
font-size
:
18px
;
}
/* resubmit confirm modal style */
.resubmit
{
.title
{
font-size
:
16px
;
color
:
#000
;
.color-warn
,
.color-error
{
color
:
red
;
}
i
{
margin-right
:
10px
;
}
}
.hint
{
padding
:
15px
0
;
color
:
#333
;
margin-left
:
30px
;
}
.color-succ
{
color
:
green
;
}
}
.hyper-box
{
padding
:
16px
18px
16px
16px
;
}
.hyper-form
{
height
:
32px
;
margin-bottom
:
8px
;
.title
{
font-size
:
14px
;
font-family
:
'Segoe UI'
,
Tahoma
,
Geneva
,
Verdana
,
sans-serif
;
line-height
:
32px
;
}
.inputs
{
height
:
32px
;
}
input
{
height
:
32px
;
}
}
.tag-input
{
margin-top
:
25px
;
}
/* submit & cancel buttons style*/
.modal-button
{
text-align
:
right
;
height
:
28px
;
/* cancel button style*/
.cancelSty
{
width
:
80px
;
background-color
:
#dadada
;
border
:
none
;
color
:
#333
;
}
.cancelSty
:hover
,
.cancelSty
:active
,
.cancelSty
:focus
{
background-color
:
#dadada
;
}
.distance
{
margin-right
:
8px
;
}
}
.center
{
text-align
:
center
;
}
src/webui/src/components/trial-detail/TableList.tsx
View file @
ea665155
...
...
@@ -7,10 +7,11 @@ const Option = Select.Option;
const
CheckboxGroup
=
Checkbox
.
Group
;
import
{
MANAGER_IP
,
trialJobStatus
,
COLUMN_INDEX
,
COLUMNPro
}
from
'
../../static/const
'
;
import
{
convertDuration
,
formatTimestamp
,
intermediateGraphOption
,
killJob
}
from
'
../../static/function
'
;
import
{
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
TableRecord
}
from
'
../../static/interface
'
;
import
OpenRow
from
'
../public-child/OpenRow
'
;
import
Compare
from
'
../Modal/Compare
'
;
import
Customize
from
'
../Modal/CustomizedTrial
'
;
import
'
../../static/style/search.scss
'
;
require
(
'
../../static/style/tableStatus.css
'
);
require
(
'
../../static/style/logPath.scss
'
);
...
...
@@ -45,6 +46,8 @@ interface TableListState {
intermediateData
:
Array
<
object
>
;
// a trial's intermediate results (include dict)
intermediateId
:
string
;
intermediateOtherKeys
:
Array
<
string
>
;
isShowCustomizedModal
:
boolean
;
copyTrialId
:
string
;
// user copy trial to submit a new customized trial
}
interface
ColumnIndex
{
...
...
@@ -71,7 +74,9 @@ class TableList extends React.Component<TableListProps, TableListState> {
selectedRowKeys
:
[],
// close selected trial message after modal closed
intermediateData
:
[],
intermediateId
:
''
,
intermediateOtherKeys
:
[]
intermediateOtherKeys
:
[],
isShowCustomizedModal
:
false
,
copyTrialId
:
''
};
}
...
...
@@ -236,17 +241,36 @@ class TableList extends React.Component<TableListProps, TableListState> {
this
.
setState
({
isShowCompareModal
:
false
,
selectedRowKeys
:
[],
selectRows
:
[]
});
}
// open customized trial modal
setCustomizedTrial
=
(
trialId
:
string
)
=>
{
this
.
setState
({
isShowCustomizedModal
:
true
,
copyTrialId
:
trialId
});
}
closeCustomizedTrial
=
()
=>
{
this
.
setState
({
isShowCustomizedModal
:
false
,
copyTrialId
:
''
});
}
render
()
{
const
{
pageSize
,
columnList
}
=
this
.
props
;
const
tableSource
:
Array
<
TableRecord
>
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
props
.
tableSource
));
const
{
intermediateOption
,
modalVisible
,
isShowColumn
,
selectRows
,
isShowCompareModal
,
selectedRowKeys
,
intermediateOtherKeys
}
=
this
.
state
;
selectRows
,
isShowCompareModal
,
selectedRowKeys
,
intermediateOtherKeys
,
isShowCustomizedModal
,
copyTrialId
}
=
this
.
state
;
const
rowSelection
=
{
selectedRowKeys
:
selectedRowKeys
,
onChange
:
(
selected
:
string
[]
|
number
[],
selectedRows
:
Array
<
TableRecord
>
)
=>
{
this
.
fillSelectedRowsTostate
(
selected
,
selectedRows
);
}
};
// [supportCustomizedTrial: true]
const
supportCustomizedTrial
=
(
EXPERIMENT
.
multiPhase
===
true
)
?
false
:
true
;
const
disabledAddCustomizedTrial
=
[
'
DONE
'
,
'
ERROR
'
,
'
STOPPED
'
].
includes
(
EXPERIMENT
.
status
);
let
showTitle
=
COLUMNPro
;
const
showColumn
:
Array
<
object
>
=
[];
...
...
@@ -361,6 +385,22 @@ class TableList extends React.Component<TableListProps, TableListState> {
</
Button
>
</
Popconfirm
>
}
{
/* Add a new trial-customized trial */
}
{
supportCustomizedTrial
?
<
Button
type
=
"primary"
className
=
"common-style"
disabled
=
{
disabledAddCustomizedTrial
}
onClick
=
{
this
.
setCustomizedTrial
.
bind
(
this
,
record
.
id
)
}
title
=
"Customized trial"
>
<
Icon
type
=
"copy"
/>
</
Button
>
:
null
}
</
Row
>
);
},
...
...
@@ -398,7 +438,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
expandedRowRender
=
{
this
.
openRow
}
dataSource
=
{
tableSource
}
className
=
"commonTableStyle"
scroll
=
{
{
x
:
'
max-content
'
}
}
scroll
=
{
{
x
:
'
max-content
'
}
}
pagination
=
{
pageSize
>
0
?
{
pageSize
}
:
false
}
/>
{
/* Intermediate Result Modal */
}
...
...
@@ -458,7 +498,14 @@ class TableList extends React.Component<TableListProps, TableListState> {
className
=
"titleColumn"
/>
</
Modal
>
{
/* compare trials based message */
}
<
Compare
compareRows
=
{
selectRows
}
visible
=
{
isShowCompareModal
}
cancelFunc
=
{
this
.
hideCompareModal
}
/>
{
/* clone trial parameters and could submit a customized trial */
}
<
Customize
visible
=
{
isShowCustomizedModal
}
copyTrialId
=
{
copyTrialId
}
closeCustomizeModal
=
{
this
.
closeCustomizedTrial
}
/>
</
Row
>
);
}
...
...
tools/nni_gpu_tool/gpu_metrics_collector.py
View file @
ea665155
...
...
@@ -35,7 +35,7 @@ def check_ready_to_run():
pidList
.
remove
(
os
.
getpid
())
return
not
pidList
else
:
pgrep_output
=
subprocess
.
check_output
(
'pgrep -fx
\'
python3 -m nni_gpu_tool.gpu_metrics_collector
\'
'
,
shell
=
True
)
pgrep_output
=
subprocess
.
check_output
(
'pgrep -fx
u "$(whoami)"
\'
python3 -m nni_gpu_tool.gpu_metrics_collector
\'
'
,
shell
=
True
)
pidList
=
[]
for
pid
in
pgrep_output
.
splitlines
():
pidList
.
append
(
int
(
pid
))
...
...
Prev
1
2
3
Next
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