已合并
fix(build): 跳过仅有信息库无 op_kernel 的算子的 kernel 编译 #4900
fix(build): 跳过仅有信息库无 op_kernel 的算子的 kernel 编译 #4900
已合并
songkai111创建于 16 天前
3 个文件变更+198-47
@@ -562,6 +562,13 @@ function(gen_ops_info_and_python)
562 foreach(OP_DIR ${COMPILED_OP_DIRS})562 foreach(OP_DIR ${COMPILED_OP_DIRS})
563 get_filename_component(op_name ${OP_DIR} NAME)563 get_filename_component(op_name ${OP_DIR} NAME)
564 564 
565+ # 仅定义了信息库、没有 kernel 实现的算子(如 bitcast),无需也无法编译 kernel 二进制,
566+ # 直接跳过 kernel 编译链路,与 get_op_type_and_validate 中 op_kernel 目录判断保持一致。
567+ if(NOT EXISTS "${OP_DIR}/op_kernel")
568+ message(STATUS "[INFO] On [${compute_unit}], [${op_name}] has no op_kernel directory, skip kernel binary compile.")
569+ continue()
570+ endif()
571+ 
565 set(op_type)572 set(op_type)
566 get_op_type_from_op_name("${op_name}" op_type)573 get_op_type_from_op_name("${op_name}" op_type)
567 if(NOT op_type)574 if(NOT op_type)
@@ -13,6 +13,7 @@
13"""13"""
14gen_opcinfo_from_opinfo.py14gen_opcinfo_from_opinfo.py
15"""15"""
16+ 
16import sys17import sys
17import os18import os
18import json19import json
@@ -74,6 +75,15 @@ def get_res_from_file(json_file):
74 op_file = convert_to_snake(op_type)75 op_file = convert_to_snake(op_type)
75 else:76 else:
76 op_file = op_file.get("value")77 op_file = op_file.get("value")
78+ # opFile.value=Null 表示算子只有信息库定义、没有 kernel 实现(如 bitcast),
79+ # 无需进入 kernel 二进制编译清单,否则会生成 dynamic/Null.py 导致编译失败。
80+ if op_file is None or str(op_file).strip().lower() in ("null", "none"):
81+ print(
82+ "[INFO] op {} has no kernel implementation (opFile={}), skip kernel compile.".format(
83+ op_type, op_file
84+ )
85+ )
86+ continue
77 if op_interface is None:87 if op_interface is None:
78 op_interface = convert_to_snake(op_type)88 op_interface = convert_to_snake(op_type)
79 else:89 else:
@@ -84,7 +94,7 @@ def get_res_from_file(json_file):
84 return output_res94 return output_res
85 95 
86 96 
87-if __name__ == '__main__':97+if __name__ == "__main__":
88 args = sys.argv98 args = sys.argv
89 99 
90 in_file_path_list = list()100 in_file_path_list = list()
@@ -97,7 +107,7 @@ if __name__ == '__main__':
97 out_csv_file = arg107 out_csv_file = arg
98 108 
99 res = dict()109 res = dict()
100- wr_header = ['op_type', 'file_name', 'file_func']110+ wr_header = ["op_type", "file_name", "file_func"]
101 wr_data = list()111 wr_data = list()
102 for ops_json_file in in_file_path_list:112 for ops_json_file in in_file_path_list:
103 _res = get_res_from_file(ops_json_file)113 _res = get_res_from_file(ops_json_file)
@@ -106,7 +116,13 @@ if __name__ == '__main__':
106 res[_op_type] = _op_value116 res[_op_type] = _op_value
107 file_name = _op_value[0]117 file_name = _op_value[0]
108 func_name = _op_value[1]118 func_name = _op_value[1]
109- wr_data.append({wr_header[0]: _op_type, wr_header[1]: file_name, wr_header[2]: func_name})119+ wr_data.append(
120+ {
121+ wr_header[0]: _op_type,
122+ wr_header[1]: file_name,
123+ wr_header[2]: func_name,
124+ }
125+ )
110 continue126 continue
111 global_op_value = res.get(_op_type)127 global_op_value = res.get(_op_type)
112 if global_op_value != _op_value:128 if global_op_value != _op_value:
@@ -12,7 +12,7 @@
12# Copyright 2020-2021 Huawei Technologies Co., Ltd.12# Copyright 2020-2021 Huawei Technologies Co., Ltd.
13# Licensed under the Apache License, Version 2.0 (the "License");13# Licensed under the Apache License, Version 2.0 (the "License");
14# You may obtain a copy of the License at14# You may obtain a copy of the License at
15-# 15+#
16# http://www.apache.org/licenses/LICENSE-2.016# http://www.apache.org/licenses/LICENSE-2.0
17# ----------------------------------------------------------------------------17# ----------------------------------------------------------------------------
18 18 
@@ -26,25 +26,120 @@ import stat
26import sys26import sys
27 27 
28 28 
29-ATTR_TYPE_LIST = ["int", "float", "bool", "str", "listInt", "listFloat", "listBool", "listStr", "listListInt",29+ATTR_TYPE_LIST = [
30- "type", "listType", "tensor", "listTensor"]30+ "int",
31+ "float",
32+ "bool",
33+ "str",
34+ "listInt",
35+ "listFloat",
36+ "listBool",
37+ "listStr",
38+ "listListInt",
39+ "type",
40+ "listType",
41+ "tensor",
42+ "listTensor",
43+]
31ATTR_PARAMTYPE_LIST = ["optional", "required"]44ATTR_PARAMTYPE_LIST = ["optional", "required"]
32-BOOL_FLAG_KEY = ["dynamicFormat", "dynamicShapeSupport", "dynamicRankSupport", "precision_reduce", "heavyOp",45+BOOL_FLAG_KEY = [
33- "needCheckSupport", "enableVectorCore"]46+ "dynamicFormat",
47+ "dynamicShapeSupport",
48+ "dynamicRankSupport",
49+ "precision_reduce",
50+ "heavyOp",
51+ "needCheckSupport",
52+ "enableVectorCore",
53+]
34BOOL_LIST = ["true", "false"]54BOOL_LIST = ["true", "false"]
35-DTYPE_LIST = ["float16", "float", "float32", "int8", "int16", "int32", "uint8", "uint16", "uint32", "bool",55+DTYPE_LIST = [
36- "int64", "uint64", "qint8", "qint16", "qint32", "quint8", "quint16", "double", "complex32", "complex64",56+ "float16",
37- "complex128", "string", "resource", "dual", "dual_sub_int8", "dual_sub_uint8", "string_ref",57+ "float",
38- "int4", "bfloat16", "uint1", "hifloat8", "float8_e4m3fn", "float8_e5m2", "float8_e8m0", "float4_e2m1",58+ "float32",
39- "float4_e1m2", "int2"]59+ "int8",
40-FORMAT_LIST = ["NCHW", "NHWC", "ND", "NC1HWC0", "FRACTAL_Z", "NC1C0HWPAD", "NHWC1C0", "FSR_NCHW", "FRACTAL_DECONV",60+ "int16",
41- "C1HWNC0", "FRACTAL_DECONV_TRANSPOSE", "FRACTAL_DECONV_SP_STRIDE_TRANS", "NC1HWC0_C04",61+ "int32",
42- "FRACTAL_Z_C04", "CHWN", "FRACTAL_DECONV_SP_STRIDE8_TRANS", "HWCN", "NC1KHKWHWC0", "BN_WEIGHT",62+ "uint8",
43- "FILTER_HWCK", "HASHTABLE_LOOKUP_LOOKUPS", "HASHTABLE_LOOKUP_KEYS", "HASHTABLE_LOOKUP_VALUE",63+ "uint16",
44- "HASHTABLE_LOOKUP_OUTPUT", "HASHTABLE_LOOKUP_HITS", "C1HWNCoC0", "MD", "NDHWC", "FRACTAL_ZZ",64+ "uint32",
45- "FRACTAL_NZ", "FRACTAL_NZ_C0_2", "FRACTAL_NZ_C0_4", "FRACTAL_NZ_C0_16", "FRACTAL_NZ_C0_32", "NCDHW", 65+ "bool",
46- "DHWCN", "NDC1HWC0", "FRACTAL_Z_3D", "CN", "NC", "DHWNC", "FRACTAL_Z_3D_TRANSPOSE", "FRACTAL_ZN_LSTM", 66+ "int64",
47- "FRACTAL_ZN_RNN", "FRACTAL_Z_G", "NULL"]67+ "uint64",
68+ "qint8",
69+ "qint16",
70+ "qint32",
71+ "quint8",
72+ "quint16",
73+ "double",
74+ "complex32",
75+ "complex64",
76+ "complex128",
77+ "string",
78+ "resource",
79+ "dual",
80+ "dual_sub_int8",
81+ "dual_sub_uint8",
82+ "string_ref",
83+ "int4",
84+ "bfloat16",
85+ "uint1",
86+ "hifloat8",
87+ "float8_e4m3fn",
88+ "float8_e5m2",
89+ "float8_e8m0",
90+ "float4_e2m1",
91+ "float4_e1m2",
92+ "int2",
93+]
94+FORMAT_LIST = [
95+ "NCHW",
96+ "NHWC",
97+ "ND",
98+ "NC1HWC0",
99+ "FRACTAL_Z",
100+ "NC1C0HWPAD",
101+ "NHWC1C0",
102+ "FSR_NCHW",
103+ "FRACTAL_DECONV",
104+ "C1HWNC0",
105+ "FRACTAL_DECONV_TRANSPOSE",
106+ "FRACTAL_DECONV_SP_STRIDE_TRANS",
107+ "NC1HWC0_C04",
108+ "FRACTAL_Z_C04",
109+ "CHWN",
110+ "FRACTAL_DECONV_SP_STRIDE8_TRANS",
111+ "HWCN",
112+ "NC1KHKWHWC0",
113+ "BN_WEIGHT",
114+ "FILTER_HWCK",
115+ "HASHTABLE_LOOKUP_LOOKUPS",
116+ "HASHTABLE_LOOKUP_KEYS",
117+ "HASHTABLE_LOOKUP_VALUE",
118+ "HASHTABLE_LOOKUP_OUTPUT",
119+ "HASHTABLE_LOOKUP_HITS",
120+ "C1HWNCoC0",
121+ "MD",
122+ "NDHWC",
123+ "FRACTAL_ZZ",
124+ "FRACTAL_NZ",
125+ "FRACTAL_NZ_C0_2",
126+ "FRACTAL_NZ_C0_4",
127+ "FRACTAL_NZ_C0_8",
128+ "FRACTAL_NZ_C0_16",
129+ "FRACTAL_NZ_C0_32",
130+ "NCDHW",
131+ "DHWCN",
132+ "NDC1HWC0",
133+ "FRACTAL_Z_3D",
134+ "CN",
135+ "NC",
136+ "DHWNC",
137+ "FRACTAL_Z_3D_TRANSPOSE",
138+ "FRACTAL_ZN_LSTM",
139+ "FRACTAL_ZN_RNN",
140+ "FRACTAL_Z_G",
141+ "NULL",
142+]
48 143 
49 144 
50def parse_ini_files(ini_files):145def parse_ini_files(ini_files):
@@ -69,8 +164,11 @@ def check_file_size(input_file):
69 except OSError as os_error:164 except OSError as os_error:
70 print('[ERROR] Failed to open "%s". %s' % (input_file, str(os_error)))165 print('[ERROR] Failed to open "%s". %s' % (input_file, str(os_error)))
71 raise OSError from os_error166 raise OSError from os_error
72- if file_size > 10*1024*1024:167+ if file_size > 10 * 1024 * 1024:
73- print('[WARN] The size of %s exceeds 10MB, it may take more time to run, please wait.' % input_file)168+ print(
169+ "[WARN] The size of %s exceeds 10MB, it may take more time to run, please wait."
170+ % input_file
171+ )
74 172 
75 173 
76def parse_ini_to_obj(ini_file, tbe_ops_info):174def parse_ini_to_obj(ini_file, tbe_ops_info):
@@ -98,16 +196,17 @@ def parse_ini_to_obj(ini_file, tbe_ops_info):
98 tbe_ops_info[op_name] = op_dict196 tbe_ops_info[op_name] = op_dict
99 find_op_type = True197 find_op_type = True
100 elif "=" in line:198 elif "=" in line:
101- key1 = line[:line.index("=")]199+ key1 = line[: line.index("=")]
102- key2 = line[line.index("=")+1:]200+ key2 = line[line.index("=") + 1 :]
103 key1_0, key1_1 = key1.split(".")201 key1_0, key1_1 = key1.split(".")
104 if key1_0 == "kernelSrc":202 if key1_0 == "kernelSrc":
105 continue203 continue
106 if key1_0 not in op_dict:204 if key1_0 not in op_dict:
107 op_dict[key1_0] = {}205 op_dict[key1_0] = {}
108 if key1_1 in op_dict.get(key1_0):206 if key1_1 in op_dict.get(key1_0):
109- raise RuntimeError("Op:" + op_name + " " + key1_0 + " " +207+ raise RuntimeError(
110- key1_1 + " is repeated!")208+ "Op:" + op_name + " " + key1_0 + " " + key1_1 + " is repeated!"
209+ )
111 dic_key = op_dict.get(key1_0)210 dic_key = op_dict.get(key1_0)
112 dic_key[key1_1] = key2211 dic_key[key1_1] = key2
113 else:212 else:
@@ -179,7 +278,10 @@ def check_attr(op_dict, is_valid):
179 is_valid = check_attr_dict(attr_dict, is_valid, attr)278 is_valid = check_attr_dict(attr_dict, is_valid, attr)
180 else:279 else:
181 is_valid = False280 is_valid = False
182- print("%s is required in .ini file, when attr.list is %s!" % (attr, attr_list_str))281+ print(
282+ "%s is required in .ini file, when attr.list is %s!"
283+ % (attr, attr_list_str)
284+ )
183 return is_valid285 return is_valid
184 286 
185 287 
@@ -228,7 +330,11 @@ def check_type_format(op_info, is_valid, op_info_key):
228 if op_info_dtype_num > 0 and op_info_format_num > 0:330 if op_info_dtype_num > 0 and op_info_format_num > 0:
229 if op_info_dtype_num != op_info_format_num:331 if op_info_dtype_num != op_info_format_num:
230 is_valid = False332 is_valid = False
231- print("The number of {0}.dtype not match the number of {0}.format.".format(op_info_key))333+ print(
334+ "The number of {0}.dtype not match the number of {0}.format.".format(
335+ op_info_key
336+ )
337+ )
232 return is_valid338 return is_valid
233 339 
234 340 
@@ -254,14 +360,25 @@ def check_op_info(tbe_ops):
254 if required_op_input_info_key not in op_input_info:360 if required_op_input_info_key not in op_input_info:
255 missing_keys.append(required_op_input_info_key)361 missing_keys.append(required_op_input_info_key)
256 if len(missing_keys) > 0:362 if len(missing_keys) > 0:
257- print("op: " + op_key + " " + op_info_key + " missing: " +363+ print(
258- ",".join(missing_keys))364+ "op: "
365+ + op_key
366+ + " "
367+ + op_info_key
368+ + " missing: "
369+ + ",".join(missing_keys)
370+ )
259 is_valid = False371 is_valid = False
260 else:372 else:
261- if not op_input_info["paramType"] in param_type_valid_value:373+ if op_input_info["paramType"] not in param_type_valid_value:
262- print("op: " + op_key + " " + op_info_key + \374+ print(
263- " paramType not valid, valid key:[dynamic, "375+ "op: "
264- "optional, required]")376+ + op_key
377+ + " "
378+ + op_info_key
379+ + " paramType not valid, valid key:[dynamic, "
380+ "optional, required]"
381+ )
265 is_valid = False382 is_valid = False
266 is_valid = check_type_format(op_input_info, is_valid, op_info_key)383 is_valid = check_type_format(op_input_info, is_valid, op_info_key)
267 if op_info_key.startswith("output"):384 if op_info_key.startswith("output"):
@@ -271,14 +388,25 @@ def check_op_info(tbe_ops):
271 if required_op_input_info_key not in op_input_info:388 if required_op_input_info_key not in op_input_info:
272 missing_keys.append(required_op_input_info_key)389 missing_keys.append(required_op_input_info_key)
273 if len(missing_keys) > 0:390 if len(missing_keys) > 0:
274- print("op: " + op_key + " " + op_info_key + " missing: " +391+ print(
275- ",".join(missing_keys))392+ "op: "
393+ + op_key
394+ + " "
395+ + op_info_key
396+ + " missing: "
397+ + ",".join(missing_keys)
398+ )
276 is_valid = False399 is_valid = False
277 else:400 else:
278- if not op_input_info["paramType"] in param_type_valid_value:401+ if op_input_info["paramType"] not in param_type_valid_value:
279- print("op: " + op_key + " " + op_info_key +402+ print(
280- " paramType not valid, valid key:[dynamic, "403+ "op: "
281- "optional, required]")404+ + op_key
405+ + " "
406+ + op_info_key
407+ + " paramType not valid, valid key:[dynamic, "
408+ "optional, required]"
409+ )
282 is_valid = False410 is_valid = False
283 is_valid = check_type_format(op_input_info, is_valid, op_info_key)411 is_valid = check_type_format(op_input_info, is_valid, op_info_key)
284 is_valid = check_attr(op_dict, is_valid)412 is_valid = check_attr(op_dict, is_valid)
@@ -299,12 +427,12 @@ def write_json_file(tbe_ops_info, json_file_path):
299 json_file_real_path = os.path.realpath(json_file_path)427 json_file_real_path = os.path.realpath(json_file_path)
300 wr_flag = os.O_WRONLY | os.O_CREAT428 wr_flag = os.O_WRONLY | os.O_CREAT
301 wr_mode = stat.S_IWUSR | stat.S_IRUSR429 wr_mode = stat.S_IWUSR | stat.S_IRUSR
302- with os.fdopen(os.open(json_file_real_path, wr_flag, wr_mode), 'w') as file_path:430+ with os.fdopen(os.open(json_file_real_path, wr_flag, wr_mode), "w") as file_path:
303 # The owner have all rights£¬group only have read rights431 # The owner have all rights£¬group only have read rights
304- os.chmod(json_file_real_path, stat.S_IWUSR + stat.S_IRGRP432+ os.chmod(json_file_real_path, stat.S_IWUSR + stat.S_IRGRP + stat.S_IRUSR)
305- + stat.S_IRUSR)433+ json.dump(
306- json.dump(tbe_ops_info, file_path, sort_keys=True, indent=4,434+ tbe_ops_info, file_path, sort_keys=True, indent=4, separators=(",", ":")
307- separators=(',', ':'))435+ )
308 print("Compile op info cfg successfully.")436 print("Compile op info cfg successfully.")
309 437 
310 438 
@@ -325,7 +453,7 @@ def parse_ini_to_json(ini_file_paths, outfile_path):
325 return True453 return True
326 454 
327 455 
328-if __name__ == '__main__':456+if __name__ == "__main__":
329 args = sys.argv457 args = sys.argv
330 458 
331 OUTPUT_FILE_PATH = "tbe_ops_info.json"459 OUTPUT_FILE_PATH = "tbe_ops_info.json"