from typing import Optional
from pydantic import BaseModel
from atk.common.log import Logger
logging = Logger().get_logger()
class PerfStandardConfig(BaseModel):
aver_radio_bm: Optional[float] = None
radio_bm: Optional[float] = None
def update(self, **kwargs):
if kwargs.get("aver_radio_bm"):
self.aver_radio_bm = kwargs.get("aver_radio_bm")
if kwargs.get("radio_bm"):
self.radio_bm = kwargs.get("radio_bm")
class AccStandard:
def __init__(self, dtype, op_type="compute"):
self.default_standard = DefaultStandards()
self.standard_dict = self.default_standard.accuracy
if op_type == "compute":
dtype_str = str(dtype).split(".")[-1]
if dtype_str in self.standard_dict:
self.standard = self.standard_dict[dtype_str]
else:
raise ValueError(f"Unsupported dtype: {dtype}")
else:
self.standard = [0.0, 0.0, 0.1]
def get_standard(self):
if len(self.standard) == 3:
return self.standard
else:
raise ValueError(f"Incompleted accuary standards")
class PerfStandard:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super(PerfStandard, cls).__new__(cls)
cls._default_standard = DefaultStandards()
cls._instance._config = cls._default_standard.performance
cls._memory_standard = cls._default_standard.memory_standard["pass_ratio"]
return cls._instance
@property
def config(self):
return self._config
@property
def memory_standard(self):
return self._memory_standard
def get_standard(self, device: str = "800T_A2", opp_perf: str = "not_key") -> PerfStandardConfig:
perf_config = PerfStandardConfig()
device = "800T_A2" if device is None else device
try:
if isinstance(opp_perf, str):
compute_power = self.config["device_compute_map"][device]
cur_compute_config = self.config[compute_power]
elif isinstance(opp_perf, list) and len(opp_perf) == 2:
perf_config.aver_radio_bm = opp_perf[0]
perf_config.radio_bm = opp_perf[1]
return perf_config
else:
logging.warning(f"no support opp_perf, now will use default config [1.0, 1.0]")
cur_compute_config = self.config["default"]
except KeyError as exception:
logging.warning(f"no perf standard exist for current device: {device}, please add in DefaultStandards, "
f"now will use default config [1.0, 1.0]")
cur_compute_config = self.config["default"]
perf_config.aver_radio_bm = cur_compute_config[opp_perf][0]
perf_config.radio_bm = cur_compute_config[opp_perf][1]
return perf_config
class PassStandard:
def __init__(self, **kwargs):
self.default_standard = DefaultStandards()
self.memory_pass_ratio = self.default_standard.pass_ratio["memory_pass"]
self.acc_pass_ratio = self.default_standard.pass_ratio["acc_pass"]
if kwargs.get("acc_pass_ratio"):
self.acc_pass_ratio = kwargs.get("acc_pass_ratio")
def get_memory_pass_ratio(self):
return self.memory_pass_ratio
def get_acc_pass_ratio(self):
return self.acc_pass_ratio
class DefaultStandards:
def __init__(self):
self.config = {
'Performance': {
'default': {
'key': [0.95, 0.98],
'not_key': [0.95, 0.98],
'DSA': [0.95, 0.98]
},
'device_compute_map': {
'800T_A2': 'default'
}
},
'Accuracy': {
'float32': [0.0001, 0.0001, 0.1],
'float64': [0.0001, 0.0001, 0.1],
'int32': [0.0001, 0.0001, 0.1],
'int64': [0.0001, 0.0001, 0.1],
'float16': [0.001, 0.001, 0.1],
'bfloat16': [0.004, 0.004, 0.1],
'hfloat32': [0.001, 0.001, 0.1],
'bool': [0.0, 0.0, 0.1],
'uint8': [1, 0.01, 0.1],
'int8': [1, 0.001, 0.1],
'int16': [1, 0.001, 0.1]
},
'Memory_Standard': {
'pass_ratio': 1.1
},
'Pass_Ratio': {
'memory_pass': 1,
'acc_pass': 1,
'mem_check_pass': 1
}
}
self.performance = self.config['Performance']
self.accuracy = self.config['Accuracy']
self.memory_standard = self.config['Memory_Standard']
self.pass_ratio = self.config['Pass_Ratio']
def get(self, *keys, default=None) -> Optional[object]:
"""
通用获取方法,支持多级键访问
示例: get('Performance', 'default', 'key')
"""
current = self.config
for key in keys:
if isinstance(current, dict) and key in current:
current = current[key]
else:
return default
return current