Skip to content

Commit 1c3e240

Browse files
authored
Adjust strategy layer for new API (#766)
* refactor conf Signed-off-by: yiliu30 <[email protected]> * copy strategy layer into experimental Signed-off-by: yiliu30 <[email protected]> * adjusted the import relationship Signed-off-by: yiliu30 <[email protected]> * replace strategy with exp_strategy Signed-off-by: yiliu30 <[email protected]> * fixed import bug Signed-off-by: yiliu30 <[email protected]> * refactor ut Signed-off-by: yiliu30 <[email protected]> * refactor strategy Signed-off-by: yiliu30 <[email protected]> * update obj config Signed-off-by: yiliu30 <[email protected]> * fixed ut Signed-off-by: yiliu30 <[email protected]> * remove set framwork Signed-off-by: yiliu30 <[email protected]> * remove some comments Signed-off-by: yiliu30 <[email protected]> --------- Signed-off-by: yiliu30 <[email protected]>
1 parent 842a6e8 commit 1c3e240

32 files changed

+5403
-389
lines changed

neural_compressor/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
# we need to set a global 'NA' backend, or Model can't be used
2323
from .utils.utility import set_random_seed, set_tensorboard, set_workspace
2424
from .utils import options
25-
from .config import conf
25+
# from .config import conf
2626
from .config import DistillationConfig, PostTrainingQuantConfig, \
2727
WeightPruningConfig, QuantizationAwareTrainingConfig, \
2828
MixedPrecisionConfig

neural_compressor/adaptor/mxnet.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
dump_elapsed_time, singleton)
2626
from neural_compressor.adaptor.mxnet_utils.util import *
2727
from collections import OrderedDict
28-
from ..experimental.data.dataloaders.base_dataloader import BaseDataLoader
28+
from neural_compressor.data.dataloaders.base_dataloader import BaseDataLoader
2929
from copy import deepcopy
3030
import math
3131

neural_compressor/adaptor/onnxrt.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from neural_compressor.utils.utility import LazyImport, dump_elapsed_time, \
3232
GLOBAL_STATE, MODE
3333
from neural_compressor.utils.utility import Statistics
34-
from neural_compressor.experimental.data.dataloaders.base_dataloader import BaseDataLoader
34+
from neural_compressor.data.dataloaders.base_dataloader import BaseDataLoader
3535
from neural_compressor.conf.dotdict import deep_get
3636
from neural_compressor.utils.utility import CpuInfo
3737
import math

neural_compressor/contrib/strategy/tpe.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ def stop(self, timeout, trials_count):
505505

506506
if timeout == 0 and self.best_tune_result:
507507
need_stop = True
508-
elif trials_count >= self.cfg.tuning.exit_policy.max_trials:
508+
elif trials_count >= self.conf.quantization.tuning_criterion.max_trials:
509509
need_stop = True
510510
else:
511511
need_stop = False

neural_compressor/experimental/graph_optimization.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import yaml
2626
from ..conf.config import Graph_Optimization_Conf
2727
from ..conf.dotdict import deep_get, deep_set, DotDict
28-
from ..strategy import STRATEGIES
28+
from .strategy import EXP_STRATEGIES
2929
from ..utils import logger
3030
from ..utils.create_obj_from_config import create_dataloader
3131
from ..utils.utility import CpuInfo, time_limit
@@ -139,7 +139,7 @@ def __call__(self):
139139

140140
strategy = cfg.tuning.strategy.name.lower()
141141

142-
assert strategy in STRATEGIES, "Tuning strategy {} is NOT supported".format(strategy)
142+
assert strategy in EXP_STRATEGIES, "Tuning strategy {} is NOT supported".format(strategy)
143143

144144
_resume = None
145145
# check if interrupted tuning procedure exists. if yes, it will resume the
@@ -152,7 +152,7 @@ def __call__(self):
152152
with open(self.resume_file, 'rb') as f:
153153
_resume = pickle.load(f).__dict__
154154

155-
self.strategy = STRATEGIES[strategy](
155+
self.strategy = EXP_STRATEGIES[strategy](
156156
self._model,
157157
self.conf,
158158
None,

neural_compressor/experimental/mixed_precision.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from ..conf.config import MixedPrecision_Conf
2525
from ..conf.pythonic_config import Config
2626
from ..conf.dotdict import deep_get
27-
from ..strategy import STRATEGIES
27+
from .strategy import EXP_STRATEGIES
2828
from ..utils import logger
2929
from ..utils.create_obj_from_config import create_dataloader
3030
from ..utils.utility import CpuInfo, time_limit
@@ -149,7 +149,7 @@ def __call__(self):
149149

150150
strategy = cfg.tuning.strategy.name.lower()
151151

152-
assert strategy in STRATEGIES, "Tuning strategy {} is NOT supported".format(strategy)
152+
assert strategy in EXP_STRATEGIES, "Tuning strategy {} is NOT supported".format(strategy)
153153

154154
_resume = None
155155
# check if interrupted tuning procedure exists. if yes, it will resume the
@@ -162,7 +162,7 @@ def __call__(self):
162162
with open(self.resume_file, 'rb') as f:
163163
_resume = pickle.load(f).__dict__
164164

165-
self.strategy = STRATEGIES[strategy](
165+
self.strategy = EXP_STRATEGIES[strategy](
166166
self._model,
167167
self.conf,
168168
None,

neural_compressor/experimental/quantization.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import numpy as np
2424
from .component import Component
2525
from ..conf.dotdict import deep_get, deep_set, DotDict
26-
from ..strategy import STRATEGIES
26+
from .strategy import EXP_STRATEGIES
2727
from ..utils import logger
2828
from ..utils.utility import time_limit
2929
from ..utils.create_obj_from_config import create_dataloader
@@ -144,7 +144,7 @@ def pre_process(self):
144144
strategy = "basic"
145145
logger.warning(f"MSE_v2 does not support {self.framework} now, use basic instead.")
146146
logger.warning("Only tensorflow, pytorch_fx is supported by MSE_v2 currently.")
147-
assert strategy in STRATEGIES, "Tuning strategy {} is NOT supported".format(strategy)
147+
assert strategy in EXP_STRATEGIES, "Tuning strategy {} is NOT supported".format(strategy)
148148

149149
_resume = None
150150
# check if interrupted tuning procedure exists. if yes, it will resume the
@@ -157,7 +157,7 @@ def pre_process(self):
157157
with open(self.resume_file, 'rb') as f:
158158
_resume = pickle.load(f).__dict__
159159

160-
self.strategy = STRATEGIES[strategy](
160+
self.strategy = EXP_STRATEGIES[strategy](
161161
self._model,
162162
self.conf,
163163
self._calib_dataloader,
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
#
4+
# Copyright (c) 2021 Intel Corporation
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
18+
"""Intel Neural Compressor Strategy."""
19+
20+
from .strategy import EXP_STRATEGIES
21+
from os.path import dirname, basename, isfile, join
22+
import glob
23+
24+
modules = glob.glob(join(dirname(__file__), "*.py"))
25+
26+
for f in modules:
27+
if isfile(f) and not f.startswith('__') and not f.endswith('__init__.py'):
28+
__import__(basename(f)[:-3], globals(), locals(), level=1)
29+
30+
__all__ = ["EXP_STRATEGIES"]
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
#
4+
# Copyright (c) 2021 Intel Corporation
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
18+
"""The auto-mixed precision strategy."""
19+
20+
import copy
21+
import numpy as np
22+
from collections import OrderedDict
23+
from .strategy import strategy_registry, TuneStrategy
24+
from ...utils import logger
25+
26+
from .utils.tuning_sampler import OpTypeWiseTuningSampler, FallbackTuningSampler
27+
from .utils.tuning_structs import OpTuningConfig
28+
29+
30+
@strategy_registry
31+
class AutoMixedPrecisionTuneStrategy(TuneStrategy):
32+
"""Tuning strategy for auto mixed precision."""
33+
34+
def next_tune_cfg(self):
35+
"""Generate the next tuning config.
36+
37+
Tuning configurations are generated according to the following rules:
38+
1. First, it tries to convert all ops into target date type as many as possible.
39+
2. If the accuracy does not meets the requirements, it starts the stage of fallback
40+
which converts ops into higher precision.
41+
42+
Yields:
43+
tune_config (dict): A dict containing the tuning configuration.
44+
"""
45+
from copy import deepcopy
46+
47+
# filter quantization dtype
48+
# TODO align with the old mixed-precison
49+
target_dtypes = self.cfg.graph_optimization.precisions if self.cfg.graph_optimization \
50+
else self.cfg.mixed_precision.precisions
51+
target_dtypes = list(set(target_dtypes) - set(['fp32']))
52+
tuning_space = self.tuning_space
53+
initial_op_tuning_cfg = {}
54+
for item in tuning_space.root_item.options:
55+
if item.item_type == 'op':
56+
op_name, op_type = item.name
57+
initial_op_tuning_cfg[item.name] = OpTuningConfig(op_name, op_type, 'fp32', tuning_space)
58+
59+
if not target_dtypes:
60+
target_dtypes = ['bf16']
61+
# step1. target_dtype AMAP, collect the ops that support target_dtype
62+
bf16_items_name = []
63+
op_tuning_cfg = {}
64+
for idx, target_dtype in enumerate(target_dtypes):
65+
bf16_items = tuning_space.query_items_by_quant_mode(target_dtype)
66+
if len(bf16_items) == 0 and \
67+
not (idx == len(target_dtypes) - 1 and len(bf16_items_name) == 0):
68+
continue
69+
bf16_items_name = [item.name for item in bf16_items]
70+
op_tuning_cfg = deepcopy(initial_op_tuning_cfg)
71+
for op_name_type in bf16_items_name:
72+
op_tuning_cfg[op_name_type] = \
73+
OpTuningConfig(op_name_type[0], op_name_type[1], target_dtype, tuning_space)
74+
calib_sampling_size = 1
75+
op_tuning_cfg['calib_sampling_size'] = calib_sampling_size
76+
yield op_tuning_cfg
77+
78+
# step2. fallback
79+
target_dtype = 'fp32'
80+
fallback_items_name_lst = bf16_items_name[::-1]
81+
if fallback_items_name_lst:
82+
logger.info(f"Start to fallback op to {target_dtype} one by one.")
83+
self._fallback_started()
84+
op_dtypes = OrderedDict(zip(fallback_items_name_lst, [target_dtype] * len(fallback_items_name_lst)))
85+
initial_op_tuning_cfg = deepcopy(op_tuning_cfg)
86+
fallback_sampler = FallbackTuningSampler(tuning_space, tuning_order_lst=[],
87+
initial_op_tuning_cfg=initial_op_tuning_cfg,
88+
op_dtypes=op_dtypes, accumulate=False)
89+
op_fallback_acc_impact = OrderedDict()
90+
for op_index, op_tuning_cfg in enumerate(fallback_sampler):
91+
op_tuning_cfg['calib_sampling_size'] = calib_sampling_size
92+
yield op_tuning_cfg
93+
acc, _ = self.last_tune_result
94+
op_fallback_acc_impact[fallback_items_name_lst[op_index]] = acc
95+
96+
# do accumulated fallback according to the order in the previous stage
97+
if len(op_fallback_acc_impact) > 0:
98+
ordered_ops = sorted(op_fallback_acc_impact.keys(), key=lambda key: op_fallback_acc_impact[key],
99+
reverse=self.higher_is_better)
100+
op_dtypes = OrderedDict(zip(ordered_ops, [target_dtype] * len(fallback_items_name_lst)))
101+
logger.info("Start to accumulate fallback to {target_dtype}.")
102+
initial_op_tuning_cfg = deepcopy(op_tuning_cfg)
103+
fallback_sampler = FallbackTuningSampler(tuning_space, tuning_order_lst=[],
104+
initial_op_tuning_cfg=initial_op_tuning_cfg,
105+
op_dtypes=op_dtypes, accumulate=True)
106+
for op_tuning_cfg in fallback_sampler:
107+
op_tuning_cfg['calib_sampling_size'] = calib_sampling_size
108+
yield op_tuning_cfg
109+
110+
def traverse(self):
111+
"""Traverse the tuning space according to auto-mixed precision strategy."""
112+
# get fp32 model baseline
113+
self._eval_baseline()
114+
115+
trials_count = 0
116+
for op_tuning_cfg in self.next_tune_cfg():
117+
# add tune_cfg here as quantize use tune_cfg
118+
tune_cfg = self._tune_cfg_converter(op_tuning_cfg)
119+
trials_count += 1
120+
tuning_history = self._find_tuning_history(tune_cfg)
121+
if tuning_history and trials_count < self.cfg.tuning.exit_policy.max_trials:
122+
self.last_tune_result = tuning_history['last_tune_result']
123+
self.best_tune_result = tuning_history['best_tune_result']
124+
logger.warn("Find evaluated tuning config, skip.")
125+
continue
126+
127+
logger.debug("Dump current mixed precision configuration:")
128+
logger.debug(tune_cfg)
129+
self.last_qmodel = self.adaptor.quantize(
130+
tune_cfg, self.model, self.calib_dataloader, self.q_func)
131+
assert self.last_qmodel
132+
# Return the last quantized model as a result. if performance only.
133+
if self.cfg.tuning.exit_policy.performance_only:
134+
self.best_qmodel = self.last_qmodel
135+
self._add_tuning_history(copy.deepcopy(tune_cfg), (-1, [0]), q_config=self.last_qmodel.q_config)
136+
return
137+
self.last_tune_cfg = copy.deepcopy(tune_cfg)
138+
if self.eval_dataloader or self.eval_func:
139+
q_config = copy.deepcopy(self.last_qmodel.q_config)
140+
self.last_tune_result = self._evaluate(self.last_qmodel)
141+
self.cur_best_acc, self.cur_best_tuning_cfg = self.update_best_op_tuning_cfg(op_tuning_cfg)
142+
need_stop = self.stop(self.cfg.tuning.exit_policy.timeout, trials_count)
143+
# record the tuning history
144+
saved_tune_cfg = copy.deepcopy(tune_cfg)
145+
saved_last_tune_result = copy.deepcopy(self.last_tune_result)
146+
self._add_tuning_history(saved_tune_cfg, saved_last_tune_result, q_config=q_config)
147+
else:
148+
# If the eval_dataloader was not specified under the config yaml file,
149+
# We only converted the model with customized precisions.
150+
self.best_qmodel = self.last_qmodel
151+
need_stop = True
152+
153+
if need_stop:
154+
break
155+
156+

0 commit comments

Comments
 (0)