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
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