def format_model_config(flags): with open(flags.config) as f: configs = yaml.load(f) library_name = configs.get(YAMLKeyword.library_name, "") mace_check( len(library_name) > 0, ModuleName.YAML_CONFIG, "library name should not be empty") if flags.target_abis: target_abis = flags.target_abis.split(',') else: target_abis = configs.get(YAMLKeyword.target_abis, []) mace_check((isinstance(target_abis, list) and len(target_abis) > 0), ModuleName.YAML_CONFIG, "target_abis list is needed") configs[YAMLKeyword.target_abis] = target_abis for abi in target_abis: mace_check(abi in ABITypeStrs, ModuleName.YAML_CONFIG, "target_abis must be in " + str(ABITypeStrs)) target_socs = configs.get(YAMLKeyword.target_socs, "") if flags.target_socs and flags.target_socs != TargetSOCTag.random \ and flags.target_socs != TargetSOCTag.all: configs[YAMLKeyword.target_socs] = \ [soc.lower() for soc in flags.target_socs.split(',')] elif not target_socs: configs[YAMLKeyword.target_socs] = [] elif not isinstance(target_socs, list): configs[YAMLKeyword.target_socs] = [target_socs] configs[YAMLKeyword.target_socs] = \ [soc.lower() for soc in configs[YAMLKeyword.target_socs]] if ABIType.armeabi_v7a in target_abis \ or ABIType.arm64_v8a in target_abis: available_socs = sh_commands.adb_get_all_socs() target_socs = configs[YAMLKeyword.target_socs] if TargetSOCTag.all in target_socs: mace_check( available_socs, ModuleName.YAML_CONFIG, "Android abi is listed in config file and " "build for all SOCs plugged in computer, " "But no android phone found, " "you at least plug in one phone") else: for soc in target_socs: mace_check( soc in available_socs, ModuleName.YAML_CONFIG, "Build specified SOC library, " "you must plug in a phone using the SOC") if flags.model_graph_format: model_graph_format = flags.model_graph_format else: model_graph_format = configs.get(YAMLKeyword.model_graph_format, "") mace_check( model_graph_format in ModelFormatStrs, ModuleName.YAML_CONFIG, 'You must set model_graph_format and ' "model_graph_format must be in " + str(ModelFormatStrs)) configs[YAMLKeyword.model_graph_format] = model_graph_format if flags.model_data_format: model_data_format = flags.model_data_format else: model_data_format = configs.get(YAMLKeyword.model_data_format, "") configs[YAMLKeyword.model_data_format] = model_data_format mace_check( model_data_format in ModelFormatStrs, ModuleName.YAML_CONFIG, 'You must set model_data_format and ' "model_data_format must be in " + str(ModelFormatStrs)) mace_check( not (model_graph_format == ModelFormat.file and model_data_format == ModelFormat.code), ModuleName.YAML_CONFIG, "If model_graph format is 'file'," " the model_data_format must be 'file' too") model_names = configs.get(YAMLKeyword.models, []) mace_check( len(model_names) > 0, ModuleName.YAML_CONFIG, "no model found in config file") model_name_reg = re.compile(r'^[a-zA-Z0-9_]+$') for model_name in model_names: # check model_name legality mace_check(model_name not in CPP_KEYWORDS, ModuleName.YAML_CONFIG, "model name should not be c++ keyword.") mace_check((model_name[0] == '_' or model_name[0].isalpha()) and bool(model_name_reg.match(model_name)), ModuleName.YAML_CONFIG, "model name should Meet the c++ naming convention" " which start with '_' or alpha" " and only contain alpha, number and '_'") model_config = configs[YAMLKeyword.models][model_name] platform = model_config.get(YAMLKeyword.platform, "") mace_check(platform in PlatformTypeStrs, ModuleName.YAML_CONFIG, "'platform' must be in " + str(PlatformTypeStrs)) for key in [ YAMLKeyword.model_file_path, YAMLKeyword.model_sha256_checksum ]: value = model_config.get(key, "") mace_check(value != "", ModuleName.YAML_CONFIG, "'%s' is necessary" % key) weight_file_path = model_config.get(YAMLKeyword.weight_file_path, "") if weight_file_path: weight_checksum = \ model_config.get(YAMLKeyword.weight_sha256_checksum, "") mace_check( weight_checksum != "", ModuleName.YAML_CONFIG, "'%s' is necessary" % YAMLKeyword.weight_sha256_checksum) else: model_config[YAMLKeyword.weight_sha256_checksum] = "" get_model_files(model_config, BUILD_DOWNLOADS_DIR) runtime = model_config.get(YAMLKeyword.runtime, "") mace_check(runtime in RuntimeTypeStrs, ModuleName.YAML_CONFIG, "'runtime' must be in " + str(RuntimeTypeStrs)) if ABIType.host in target_abis: mace_check(runtime == RuntimeType.cpu, ModuleName.YAML_CONFIG, "host only support cpu runtime now.") data_type = model_config.get(YAMLKeyword.data_type, "") if runtime == RuntimeType.dsp: if len(data_type) > 0: mace_check( data_type in DSPDataTypeStrs, ModuleName.YAML_CONFIG, "'data_type' must be in " + str(DSPDataTypeStrs) + " for dsp runtime") else: model_config[YAMLKeyword.data_type] = \ DSPDataType.uint8.value elif runtime == RuntimeType.apu: if len(data_type) > 0: mace_check( data_type in APUDataTypeStrs, ModuleName.YAML_CONFIG, "'data_type' must be in " + str(APUDataTypeStrs) + " for apu runtime") else: model_config[YAMLKeyword.data_type] = \ APUDataType.uint8.value else: if len(data_type) > 0: mace_check( data_type in FPDataTypeStrs, ModuleName.YAML_CONFIG, "'data_type' must be in " + str(FPDataTypeStrs) + " for cpu runtime") else: if runtime == RuntimeType.cpu: model_config[YAMLKeyword.data_type] = \ FPDataType.fp32_fp32.value else: model_config[YAMLKeyword.data_type] = \ FPDataType.fp16_fp32.value subgraphs = model_config.get(YAMLKeyword.subgraphs, "") mace_check( len(subgraphs) > 0, ModuleName.YAML_CONFIG, "at least one subgraph is needed") for subgraph in subgraphs: for key in [ YAMLKeyword.input_tensors, YAMLKeyword.input_shapes, YAMLKeyword.output_tensors, YAMLKeyword.output_shapes ]: value = subgraph.get(key, "") mace_check(value != "", ModuleName.YAML_CONFIG, "'%s' is necessary in subgraph" % key) if not isinstance(value, list): subgraph[key] = [value] subgraph[key] = [str(v) for v in subgraph[key]] # --inputs_shapes will be passed to ELF file `mace_run_static', if input_shapes # contains spaces, such as: '1, 3, 224, 224', because mace_run.cc use gflags to # parse command line arguments, --input_shapes 1, 3, 224, 224 will be passed as # `--input_shapes 1,'. So we strip out spaces here. if key in [ YAMLKeyword.input_shapes, YAMLKeyword.output_shapes ]: subgraph[key] = [e.replace(' ', '') for e in subgraph[key]] input_size = len(subgraph[YAMLKeyword.input_tensors]) output_size = len(subgraph[YAMLKeyword.output_tensors]) mace_check( len(subgraph[YAMLKeyword.input_shapes]) == input_size, ModuleName.YAML_CONFIG, "input shapes' size not equal inputs' size.") mace_check( len(subgraph[YAMLKeyword.output_shapes]) == output_size, ModuleName.YAML_CONFIG, "output shapes' size not equal outputs' size.") for key in [YAMLKeyword.check_tensors, YAMLKeyword.check_shapes]: value = subgraph.get(key, "") if value != "": if not isinstance(value, list): subgraph[key] = [value] subgraph[key] = [str(v) for v in subgraph[key]] else: subgraph[key] = [] for key in [ YAMLKeyword.input_data_types, YAMLKeyword.output_data_types ]: if key == YAMLKeyword.input_data_types: count = input_size else: count = output_size data_types = subgraph.get(key, "") if data_types: if not isinstance(data_types, list): subgraph[key] = [data_types] * count for data_type in subgraph[key]: mace_check( data_type in InOutDataTypeStrs, ModuleName.YAML_CONFIG, key + " must be in " + str(InOutDataTypeStrs)) else: subgraph[key] = [InOutDataType.float32] * count input_data_formats = subgraph.get(YAMLKeyword.input_data_formats, []) if input_data_formats: if not isinstance(input_data_formats, list): subgraph[YAMLKeyword.input_data_formats] = \ [input_data_formats] * input_size else: mace_check( len(input_data_formats) == input_size, ModuleName.YAML_CONFIG, "input_data_formats should match" " the size of input.") for input_data_format in \ subgraph[YAMLKeyword.input_data_formats]: mace_check( input_data_format in DataFormatStrs, ModuleName.YAML_CONFIG, "'input_data_formats' must be in " + str(DataFormatStrs) + ", but got " + input_data_format) else: subgraph[YAMLKeyword.input_data_formats] = \ [DataFormat.NHWC] * input_size output_data_formats = subgraph.get(YAMLKeyword.output_data_formats, []) if output_data_formats: if not isinstance(output_data_formats, list): subgraph[YAMLKeyword.output_data_formats] = \ [output_data_formats] * output_size else: mace_check( len(output_data_formats) == output_size, ModuleName.YAML_CONFIG, "output_data_formats should match" " the size of output") for output_data_format in \ subgraph[YAMLKeyword.output_data_formats]: mace_check( output_data_format in DataFormatStrs, ModuleName.YAML_CONFIG, "'output_data_formats' must be in " + str(DataFormatStrs)) else: subgraph[YAMLKeyword.output_data_formats] = \ [DataFormat.NHWC] * output_size validation_threshold = subgraph.get( YAMLKeyword.validation_threshold, {}) if not isinstance(validation_threshold, dict): raise argparse.ArgumentTypeError( 'similarity threshold must be a dict.') threshold_dict = { DeviceType.CPU: ValidationThreshold.cpu_threshold, DeviceType.GPU: ValidationThreshold.gpu_threshold, DeviceType.HEXAGON: ValidationThreshold.quantize_threshold, DeviceType.HTA: ValidationThreshold.quantize_threshold, DeviceType.APU: ValidationThreshold.quantize_threshold, DeviceType.QUANTIZE: ValidationThreshold.quantize_threshold, } for k, v in six.iteritems(validation_threshold): if k.upper() == 'DSP': k = DeviceType.HEXAGON if k.upper() not in (DeviceType.CPU, DeviceType.GPU, DeviceType.HEXAGON, DeviceType.HTA, DeviceType.QUANTIZE): raise argparse.ArgumentTypeError( 'Unsupported validation threshold runtime: %s' % k) threshold_dict[k.upper()] = v subgraph[YAMLKeyword.validation_threshold] = threshold_dict validation_inputs_data = subgraph.get( YAMLKeyword.validation_inputs_data, []) if not isinstance(validation_inputs_data, list): subgraph[YAMLKeyword.validation_inputs_data] = [ validation_inputs_data ] else: subgraph[YAMLKeyword.validation_inputs_data] = \ validation_inputs_data onnx_backend = subgraph.get(YAMLKeyword.backend, "tensorflow") subgraph[YAMLKeyword.backend] = onnx_backend validation_outputs_data = subgraph.get( YAMLKeyword.validation_outputs_data, []) if not isinstance(validation_outputs_data, list): subgraph[YAMLKeyword.validation_outputs_data] = [ validation_outputs_data ] else: subgraph[YAMLKeyword.validation_outputs_data] = \ validation_outputs_data input_ranges = subgraph.get(YAMLKeyword.input_ranges, []) if not isinstance(input_ranges, list): subgraph[YAMLKeyword.input_ranges] = [input_ranges] else: subgraph[YAMLKeyword.input_ranges] = input_ranges subgraph[YAMLKeyword.input_ranges] = \ [str(v) for v in subgraph[YAMLKeyword.input_ranges]] accuracy_validation_script = subgraph.get( YAMLKeyword.accuracy_validation_script, "") if isinstance(accuracy_validation_script, list): mace_check( len(accuracy_validation_script) == 1, ModuleName.YAML_CONFIG, "Only support one accuracy validation script") accuracy_validation_script = accuracy_validation_script[0] subgraph[YAMLKeyword.accuracy_validation_script] = \ accuracy_validation_script for key in [ YAMLKeyword.limit_opencl_kernel_time, YAMLKeyword.opencl_queue_window_size, YAMLKeyword.nnlib_graph_mode, YAMLKeyword.obfuscate, YAMLKeyword.winograd, YAMLKeyword.quantize, YAMLKeyword.quantize_large_weights, YAMLKeyword.change_concat_ranges ]: value = model_config.get(key, "") if value == "": model_config[key] = 0 mace_check( model_config[YAMLKeyword.quantize] == 0 or model_config[YAMLKeyword.quantize_large_weights] == 0, ModuleName.YAML_CONFIG, "quantize and quantize_large_weights should not be set to 1" " at the same time.") mace_check( model_config[YAMLKeyword.winograd] in WinogradParameters, ModuleName.YAML_CONFIG, "'winograd' parameters must be in " + str(WinogradParameters) + ". 0 for disable winograd convolution") return configs
def format_model_config(flags): with open(flags.config) as f: configs = yaml.load(f) library_name = configs.get(YAMLKeyword.library_name, "") mace_check( len(library_name) > 0, ModuleName.YAML_CONFIG, "library name should not be empty") if flags.target_abis: target_abis = flags.target_abis.split(',') else: target_abis = configs.get(YAMLKeyword.target_abis, []) mace_check((isinstance(target_abis, list) and len(target_abis) > 0), ModuleName.YAML_CONFIG, "target_abis list is needed") configs[YAMLKeyword.target_abis] = target_abis for abi in target_abis: mace_check(abi in ABITypeStrs, ModuleName.YAML_CONFIG, "target_abis must be in " + str(ABITypeStrs)) target_socs = configs.get(YAMLKeyword.target_socs, "") if flags.target_socs: configs[YAMLKeyword.target_socs] = \ [soc.lower() for soc in flags.target_socs.split(',')] elif not target_socs: configs[YAMLKeyword.target_socs] = [] elif not isinstance(target_socs, list): configs[YAMLKeyword.target_socs] = [target_socs] configs[YAMLKeyword.target_socs] = \ [soc.lower() for soc in configs[YAMLKeyword.target_socs]] if ABIType.armeabi_v7a in target_abis \ or ABIType.arm64_v8a in target_abis: available_socs = sh_commands.adb_get_all_socs() target_socs = configs[YAMLKeyword.target_socs] if ALL_SOC_TAG in target_socs: mace_check( available_socs, ModuleName.YAML_CONFIG, "Android abi is listed in config file and " "build for all SOCs plugged in computer, " "But no android phone found, " "you at least plug in one phone") else: for soc in target_socs: mace_check( soc in available_socs, ModuleName.YAML_CONFIG, "Build specified SOC library, " "you must plug in a phone using the SOC") if flags.model_graph_format: model_graph_format = flags.model_graph_format else: model_graph_format = configs.get(YAMLKeyword.model_graph_format, "") mace_check( model_graph_format in ModelFormatStrs, ModuleName.YAML_CONFIG, 'You must set model_graph_format and ' "model_graph_format must be in " + str(ModelFormatStrs)) configs[YAMLKeyword.model_graph_format] = model_graph_format if flags.model_data_format: model_data_format = flags.model_data_format else: model_data_format = configs.get(YAMLKeyword.model_data_format, "") configs[YAMLKeyword.model_data_format] = model_data_format mace_check( model_data_format in ModelFormatStrs, ModuleName.YAML_CONFIG, 'You must set model_data_format and ' "model_data_format must be in " + str(ModelFormatStrs)) mace_check( not (model_graph_format == ModelFormat.file and model_data_format == ModelFormat.code), ModuleName.YAML_CONFIG, "If model_graph format is 'file'," " the model_data_format must be 'file' too") model_names = configs.get(YAMLKeyword.models, []) mace_check( len(model_names) > 0, ModuleName.YAML_CONFIG, "no model found in config file") model_name_reg = re.compile(r'^[a-zA-Z0-9_]+$') for model_name in model_names: # check model_name legality mace_check(model_name not in CPP_KEYWORDS, ModuleName.YAML_CONFIG, "model name should not be c++ keyword.") mace_check((model_name[0] == '_' or model_name[0].isalpha()) and bool(model_name_reg.match(model_name)), ModuleName.YAML_CONFIG, "model name should Meet the c++ naming convention" " which start with '_' or alpha" " and only contain alpha, number and '_'") model_config = configs[YAMLKeyword.models][model_name] platform = model_config.get(YAMLKeyword.platform, "") mace_check(platform in PlatformTypeStrs, ModuleName.YAML_CONFIG, "'platform' must be in " + str(PlatformTypeStrs)) for key in [ YAMLKeyword.model_file_path, YAMLKeyword.model_sha256_checksum ]: value = model_config.get(key, "") mace_check(value != "", ModuleName.YAML_CONFIG, "'%s' is necessary" % key) weight_file_path = model_config.get(YAMLKeyword.weight_file_path, "") if weight_file_path: weight_checksum = \ model_config.get(YAMLKeyword.weight_sha256_checksum, "") mace_check( weight_checksum != "", ModuleName.YAML_CONFIG, "'%s' is necessary" % YAMLKeyword.weight_sha256_checksum) else: model_config[YAMLKeyword.weight_sha256_checksum] = "" runtime = model_config.get(YAMLKeyword.runtime, "") mace_check(runtime in RuntimeTypeStrs, ModuleName.YAML_CONFIG, "'runtime' must be in " + str(RuntimeTypeStrs)) if ABIType.host in target_abis: mace_check(runtime == RuntimeType.cpu, ModuleName.YAML_CONFIG, "host only support cpu runtime now.") data_type = model_config.get(YAMLKeyword.data_type, "") if runtime == RuntimeType.dsp: if len(data_type) > 0: mace_check( data_type in DSPDataTypeStrs, ModuleName.YAML_CONFIG, "'data_type' must be in " + str(DSPDataTypeStrs) + " for dsp runtime") else: model_config[YAMLKeyword.data_type] = \ DSPDataType.uint8.value else: if len(data_type) > 0: mace_check( data_type in FPDataTypeStrs, ModuleName.YAML_CONFIG, "'data_type' must be in " + str(FPDataTypeStrs) + " for cpu runtime") else: if runtime == RuntimeType.cpu: model_config[YAMLKeyword.data_type] = \ FPDataType.fp32_fp32.value else: model_config[YAMLKeyword.data_type] = \ FPDataType.fp16_fp32.value subgraphs = model_config.get(YAMLKeyword.subgraphs, "") mace_check( len(subgraphs) > 0, ModuleName.YAML_CONFIG, "at least one subgraph is needed") for subgraph in subgraphs: for key in [ YAMLKeyword.input_tensors, YAMLKeyword.input_shapes, YAMLKeyword.output_tensors, YAMLKeyword.output_shapes ]: value = subgraph.get(key, "") mace_check(value != "", ModuleName.YAML_CONFIG, "'%s' is necessary in subgraph" % key) if not isinstance(value, list): subgraph[key] = [value] subgraph[key] = [str(v) for v in subgraph[key]] for key in [YAMLKeyword.check_tensors, YAMLKeyword.check_shapes]: value = subgraph.get(key, "") if value != "": if not isinstance(value, list): subgraph[key] = [value] subgraph[key] = [str(v) for v in subgraph[key]] else: subgraph[key] = [] input_data_types = subgraph.get(YAMLKeyword.input_data_types, "") if input_data_types: if not isinstance(input_data_types, list): subgraph[YAMLKeyword.input_data_types] = [input_data_types] for input_data_type in subgraph[YAMLKeyword.input_data_types]: mace_check( input_data_type in InputDataTypeStrs, ModuleName.YAML_CONFIG, "'input_data_types' must be in " + str(InputDataTypeStrs)) else: subgraph[YAMLKeyword.input_data_types] = [] input_data_formats = subgraph.get(YAMLKeyword.input_data_formats, []) if input_data_formats: if not isinstance(input_data_formats, list): subgraph[YAMLKeyword.input_data_formats] =\ [input_data_formats] else: mace_check( len(input_data_formats) == len( subgraph[YAMLKeyword.input_tensors]), ModuleName.YAML_CONFIG, "input_data_formats should match" " the size of input") for input_data_format in\ subgraph[YAMLKeyword.input_data_formats]: mace_check( input_data_format in DataFormatStrs, ModuleName.YAML_CONFIG, "'input_data_formats' must be in " + str(DataFormatStrs) + ", but got " + input_data_format) else: subgraph[YAMLKeyword.input_data_formats] = [DataFormat.NHWC] output_data_formats = subgraph.get(YAMLKeyword.output_data_formats, []) if output_data_formats: if not isinstance(output_data_formats, list): subgraph[YAMLKeyword.output_data_formats] = \ [output_data_formats] else: mace_check( len(output_data_formats) == len( subgraph[YAMLKeyword.output_tensors]), ModuleName.YAML_CONFIG, "output_data_formats should match" " the size of output") for output_data_format in\ subgraph[YAMLKeyword.output_data_formats]: mace_check( output_data_format in DataFormatStrs, ModuleName.YAML_CONFIG, "'output_data_formats' must be in " + str(DataFormatStrs)) else: subgraph[YAMLKeyword.output_data_formats] = [DataFormat.NHWC] validation_threshold = subgraph.get( YAMLKeyword.validation_threshold, {}) if not isinstance(validation_threshold, dict): raise argparse.ArgumentTypeError( 'similarity threshold must be a dict.') threshold_dict = { DeviceType.CPU: ValidationThreshold.cpu_threshold, DeviceType.GPU: ValidationThreshold.gpu_threshold, DeviceType.HEXAGON + "_QUANTIZE": ValidationThreshold.hexagon_threshold, DeviceType.CPU + "_QUANTIZE": ValidationThreshold.cpu_quantize_threshold, } for k, v in six.iteritems(validation_threshold): if k.upper() == 'DSP': k = DeviceType.HEXAGON if k.upper() not in (DeviceType.CPU, DeviceType.GPU, DeviceType.HEXAGON, DeviceType.CPU + "_QUANTIZE"): raise argparse.ArgumentTypeError( 'Unsupported validation threshold runtime: %s' % k) threshold_dict[k.upper()] = v subgraph[YAMLKeyword.validation_threshold] = threshold_dict validation_inputs_data = subgraph.get( YAMLKeyword.validation_inputs_data, []) if not isinstance(validation_inputs_data, list): subgraph[YAMLKeyword.validation_inputs_data] = [ validation_inputs_data ] else: subgraph[YAMLKeyword.validation_inputs_data] = \ validation_inputs_data onnx_backend = subgraph.get(YAMLKeyword.backend, "tensorflow") subgraph[YAMLKeyword.backend] = onnx_backend input_ranges = subgraph.get(YAMLKeyword.input_ranges, []) if not isinstance(input_ranges, list): subgraph[YAMLKeyword.input_ranges] = [input_ranges] else: subgraph[YAMLKeyword.input_ranges] = input_ranges subgraph[YAMLKeyword.input_ranges] = \ [str(v) for v in subgraph[YAMLKeyword.input_ranges]] for key in [ YAMLKeyword.limit_opencl_kernel_time, YAMLKeyword.nnlib_graph_mode, YAMLKeyword.obfuscate, YAMLKeyword.winograd, YAMLKeyword.quantize, YAMLKeyword.change_concat_ranges ]: value = model_config.get(key, "") if value == "": model_config[key] = 0 mace_check( model_config[YAMLKeyword.winograd] in WinogradParameters, ModuleName.YAML_CONFIG, "'winograd' parameters must be in " + str(WinogradParameters) + ". 0 for disable winograd convolution") weight_file_path = model_config.get(YAMLKeyword.weight_file_path, "") model_config[YAMLKeyword.weight_file_path] = weight_file_path return configs