16
csrc/scripts/util/__init__.py
Normal file
16
csrc/scripts/util/__init__.py
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
# Copyright (c) 2025 Huawei Technologies Co., Ltd.
|
||||
# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
|
||||
# CANN Open Software License Agreement Version 2.0 (the "License").
|
||||
# Please refer to the License for details. You may not use this file except in compliance with the License.
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
||||
# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See LICENSE in the root of the software repository for the full text of the License.
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
PYF_PATH = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.append(PYF_PATH)
|
||||
779
csrc/scripts/util/build_opp_kernel_static.py
Normal file
779
csrc/scripts/util/build_opp_kernel_static.py
Normal file
@@ -0,0 +1,779 @@
|
||||
#!/usr/bin/env python3
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
# Copyright (c) 2025 Huawei Technologies Co., Ltd.
|
||||
# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
|
||||
# CANN Open Software License Agreement Version 2.0 (the "License").
|
||||
# Please refer to the License for details. You may not use this file except in compliance with the License.
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
||||
# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See LICENSE in the root of the software repository for the full text of the License.
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
"""
|
||||
build_opp_kernel_static.py
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import concurrent.futures
|
||||
import contextlib
|
||||
import glob
|
||||
import json
|
||||
import logging as log
|
||||
import multiprocessing
|
||||
import os
|
||||
import platform
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
|
||||
import regex as re
|
||||
|
||||
|
||||
class Const:
|
||||
x86 = "x86_64"
|
||||
arm = "aarch64"
|
||||
|
||||
|
||||
def shell_exec(cmd, shell=False):
|
||||
try:
|
||||
ps = subprocess.Popen(cmd, shell)
|
||||
ps.communicate(timeout=180)
|
||||
except BaseException as e:
|
||||
log.error("shell_exec error: %s", e)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def shell_checkout_key_func(symbol_file, key_str):
|
||||
process = subprocess.Popen(("cat", symbol_file), stdout=subprocess.PIPE)
|
||||
awk_out = subprocess.check_output(("awk", "{print $8}"), stdin=process.stdout)
|
||||
process.wait()
|
||||
cppfilt = subprocess.check_output(("c++filt",), input=awk_out)
|
||||
if key_str not in cppfilt.decode("utf-8"):
|
||||
return b""
|
||||
grep_out = subprocess.check_output(("grep", key_str), input=cppfilt)
|
||||
return grep_out.decode("utf-8")
|
||||
|
||||
|
||||
def to_upper_camel_case(x) -> str:
|
||||
"""转大驼峰法命名"""
|
||||
s = re.sub("_([a-zA-Z])", lambda m: (m.group(1).upper()), x.lower())
|
||||
return s[0].upper() + s[1:]
|
||||
|
||||
|
||||
def generate_symbol(args):
|
||||
library_file = args.library_file
|
||||
symbol_file = args.symbol_file
|
||||
if not os.path.exists(library_file):
|
||||
raise FileExistsError(f"generate_symbol input library error, file <{library_file}> not exists.")
|
||||
process = subprocess.Popen(("readelf", "-Ws", library_file), stdout=subprocess.PIPE)
|
||||
output = process.communicate(timeout=180)[0].decode("utf-8")
|
||||
with open(symbol_file, "w") as fd:
|
||||
fd.write(output)
|
||||
|
||||
|
||||
def parser_generate_symbol(subparsers):
|
||||
generate_symbol_parser = subparsers.add_parser(name="GenerateSymbol", help="Generate Symbol file of input library")
|
||||
generate_symbol_parser.add_argument(
|
||||
"-l", "--library_file", type=str, required=False, dest="library_file", default="", help="Input the library file"
|
||||
)
|
||||
generate_symbol_parser.add_argument(
|
||||
"-s",
|
||||
"--symbol_file",
|
||||
type=str,
|
||||
required=False,
|
||||
dest="symbol_file",
|
||||
default="",
|
||||
help="The symbol file for output",
|
||||
)
|
||||
generate_symbol_parser.set_defaults(func=generate_symbol)
|
||||
|
||||
|
||||
class CompileOpStaticLib:
|
||||
def __init__(self, ops_compile_files: dict, out_path: str, dist_index: int, arch: str):
|
||||
self.ops_compile_files = ops_compile_files
|
||||
self.out_path = out_path
|
||||
self.part_index = dist_index
|
||||
self.cpu_arch = arch
|
||||
if self.cpu_arch not in [Const.x86, Const.arm]:
|
||||
raise Exception(f"CompileOpStaticLib Error, input arch<{arch}> error...")
|
||||
|
||||
def compile_link_single(self, file_path, file_o):
|
||||
(dir_path, file_name) = os.path.split(file_path)
|
||||
if self.cpu_arch == Const.x86:
|
||||
shell_exec(
|
||||
[
|
||||
"bash",
|
||||
"-c",
|
||||
f"cd {dir_path} && "
|
||||
f"objcopy --input-target binary --output-target elf64-x86-64 "
|
||||
f"--binary-architecture i386 "
|
||||
f"{file_name} {file_o}",
|
||||
],
|
||||
shell=False,
|
||||
)
|
||||
elif self.cpu_arch == Const.arm and platform.machine() != Const.x86:
|
||||
shell_exec(
|
||||
[
|
||||
"bash",
|
||||
"-c",
|
||||
f"cd {dir_path} && "
|
||||
f"objcopy --input-target binary "
|
||||
f"--output-target elf64-littleaarch64 --binary-architecture aarch64 "
|
||||
f"{file_name} {file_o}",
|
||||
],
|
||||
shell=False,
|
||||
)
|
||||
elif self.cpu_arch == Const.arm:
|
||||
shell_exec(
|
||||
[
|
||||
"bash",
|
||||
"-c",
|
||||
f"cd {dir_path} && "
|
||||
f"aarch64-linux-gnu-objcopy --input-target binary "
|
||||
f"--output-target elf64-littleaarch64 --binary-architecture aarch64 "
|
||||
f"{file_name} {file_o}",
|
||||
],
|
||||
shell=False,
|
||||
)
|
||||
|
||||
def compile_link_o(self, out_path, file_path, is_need_path=True):
|
||||
file_pre = os.path.basename(file_path).replace(".", "_").replace("-", "_")
|
||||
path_o_prefix = os.path.join(out_path, f"data_{file_pre}_{self.cpu_arch}.o")
|
||||
# 向json文件中写入"filePath"参数
|
||||
if is_need_path and file_path.name.endswith(".json"):
|
||||
with open(file_path, encoding="UTF-8") as json_fd:
|
||||
json_dict = json.load(json_fd)
|
||||
soc = str(file_path).split("/binary/")[-1].split("/bin/")[0]
|
||||
json_dict["filePath"] = os.path.join(soc, str(file_path).split("/bin/")[-1].split("/kernel/")[-1])
|
||||
if "opp/built-in/" in str(file_path):
|
||||
json_dict["filePath"] = (
|
||||
str(file_path).split("/bin/")[-1].split("/kernel/")[-1].replace("/ops_transformer", "")
|
||||
)
|
||||
file_path = os.path.join(out_path, os.path.basename(file_path))
|
||||
with open(file_path, "w", encoding="UTF-8") as new_json_fd:
|
||||
new_json_fd.write(json.dumps(json_dict, indent=4))
|
||||
file_path = os.path.realpath(file_path)
|
||||
self.compile_link_single(file_path, path_o_prefix)
|
||||
return
|
||||
|
||||
def compile_ops_part_o(self, out_path):
|
||||
path_data_o = os.path.join(out_path, f"data_*{self.cpu_arch}.o")
|
||||
path_data_o_list = glob.glob(path_data_o)
|
||||
if not path_data_o_list:
|
||||
return
|
||||
(dir_path, ops_name) = os.path.split(out_path)
|
||||
file_part_o = f"{ops_name}_{self.cpu_arch}_part{self.part_index}.o" # eg: floor_mod_aarch64_1.a
|
||||
path_part_o = os.path.join(dir_path, file_part_o)
|
||||
if self.cpu_arch == Const.x86 or (self.cpu_arch == Const.arm and platform.machine() != Const.x86):
|
||||
shell_exec(["bash", "-c", f"cd {out_path} && ld -r {path_data_o} -o {path_part_o}"], shell=False)
|
||||
if self.cpu_arch == Const.arm and platform.machine() == Const.x86:
|
||||
shell_exec(
|
||||
["bash", "-c", f"cd {out_path} && aarch64-linux-gnu-ld -r {path_data_o} -o {path_part_o}"], shell=False
|
||||
)
|
||||
return
|
||||
|
||||
def exec_compile(self):
|
||||
"""
|
||||
编译算子静态库
|
||||
:return:
|
||||
"""
|
||||
|
||||
def get_parallel_num() -> int:
|
||||
"""
|
||||
获取多线程最大并发数量
|
||||
"""
|
||||
num = multiprocessing.cpu_count() * 2
|
||||
if num == 0:
|
||||
num = 16
|
||||
return num
|
||||
|
||||
job_num = get_parallel_num()
|
||||
for op in self.ops_compile_files:
|
||||
compile_files = self.ops_compile_files[op].kernel_files
|
||||
json_files = self.ops_compile_files[op].binary_config_files
|
||||
runtime_kb_files = self.ops_compile_files[op].runtime_kb_files
|
||||
op_out_path = os.path.join(self.out_path, op)
|
||||
if not os.path.exists(op_out_path):
|
||||
os.makedirs(op_out_path, exist_ok=True)
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=job_num) as executor:
|
||||
for file in compile_files:
|
||||
executor.submit(self.compile_link_o, op_out_path, file.resolve())
|
||||
for file in json_files:
|
||||
executor.submit(self.compile_link_o, op_out_path, file.resolve(), False)
|
||||
for file in runtime_kb_files:
|
||||
executor.submit(self.compile_link_o, op_out_path, file.resolve(), False)
|
||||
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=job_num) as executor:
|
||||
executor.submit(self.compile_ops_part_o, op_out_path)
|
||||
return 0
|
||||
|
||||
|
||||
def compile_static_library(args):
|
||||
index_num = args.index_num
|
||||
cpu_aarch = args.cpu_aarch
|
||||
|
||||
if cpu_aarch not in [Const.x86, Const.arm]:
|
||||
raise Exception(f"Input cpu_aarch<{cpu_aarch}> Error, Please input parase.")
|
||||
|
||||
ops_compile_files = GenOpResourceIni(args.soc_version, args.build_dir, args.jit).analyze_ops_files()
|
||||
|
||||
csl = CompileOpStaticLib(
|
||||
ops_compile_files, os.path.join(args.build_dir, f"bin_tmp/{args.soc_version}"), index_num, cpu_aarch
|
||||
)
|
||||
ret = csl.exec_compile()
|
||||
return ret
|
||||
|
||||
|
||||
def parser_compile_static_library(subparsers):
|
||||
"""配置静态编译参数及执行信息"""
|
||||
compile_lib_parser = subparsers.add_parser(
|
||||
name="StaticCompile", help="Compile static libraries(.a) on distributed server"
|
||||
)
|
||||
compile_lib_parser.add_argument(
|
||||
"-s",
|
||||
"--soc_version",
|
||||
type=str,
|
||||
required=True,
|
||||
dest="soc_version",
|
||||
help="Operator Name, eg: ascend910b, ascend310p",
|
||||
)
|
||||
compile_lib_parser.add_argument(
|
||||
"-b", "--build_dir", type=str, required=True, dest="build_dir", help="Input build dir for this project"
|
||||
)
|
||||
compile_lib_parser.add_argument(
|
||||
"-j", "--jit", action="store_true", dest="jit", help="Compile static libraries(.a) with cann package"
|
||||
)
|
||||
compile_lib_parser.add_argument(
|
||||
"-n", "--index_num", type=int, required=True, dest="index_num", help="Please input distributed compilation idx"
|
||||
)
|
||||
compile_lib_parser.add_argument(
|
||||
"-a", "--cpu_aarch", type=str, required=True, dest="cpu_aarch", help="Please input cpu aarch, eg:x86_64,aarch64"
|
||||
)
|
||||
compile_lib_parser.set_defaults(func=compile_static_library)
|
||||
|
||||
|
||||
@dataclass
|
||||
class OpResource:
|
||||
"""算子资源"""
|
||||
|
||||
# tiling 注册函数
|
||||
tiling_register: str = field(default=None)
|
||||
extend_register: str = field(default_factory=list)
|
||||
# InferShape 注册函数
|
||||
infer_shape_register: str = field(default=None)
|
||||
# 知识库注册
|
||||
tuning_bank_key_register: str = field(default=None)
|
||||
tuning_bank_parse_register: str = field(default=None)
|
||||
tuning_tiling_helper: str = field(default=None)
|
||||
# 二进制配置
|
||||
binary_config_files: list = field(default_factory=list)
|
||||
# kernel 编译产出文件
|
||||
kernel_files: list = field(default_factory=list)
|
||||
# 知识库文件
|
||||
runtime_kb_files: list = field(default_factory=list)
|
||||
|
||||
|
||||
class GenOpResourceIni:
|
||||
def __init__(self, soc_version: str, build_dir: str, build_with_package: bool):
|
||||
self._soc_version = soc_version
|
||||
self._build_dir = Path(build_dir)
|
||||
opp_path = os.environ.get("ASCEND_OPP_PATH")
|
||||
if build_with_package and opp_path:
|
||||
opp_path = Path(opp_path)
|
||||
self._binary_path = opp_path / "built-in/op_impl/ai_core/tbe/kernel"
|
||||
self._tuning_basic_path = opp_path / "built-in/data/op"
|
||||
ops_info = opp_path / "built-in/op_impl/ai_core/tbe/config" / self._soc_version
|
||||
ops_info = list(ops_info.glob(f"aic-{self._soc_version}-ops-info-transformer.json"))
|
||||
self._ops_info = ops_info[0] if len(ops_info) != 0 else None
|
||||
else:
|
||||
self._binary_path = self._build_dir / "binary" / self._soc_version / "bin"
|
||||
self._tuning_basic_path = self._build_dir / "tbe/config" / self._soc_version
|
||||
# transformer aic*.json 适配
|
||||
ops_info = self._build_dir / "custom/op_impl/ai_core/tbe/config" / self._soc_version
|
||||
ops_info = list(ops_info.glob(f"aic-{self._soc_version}-ops-info*.json"))
|
||||
self._ops_info = ops_info[0] if len(ops_info) != 0 else None
|
||||
self._op_resource_path = self._build_dir / "autogen" / self._soc_version / "aclnnop_resource"
|
||||
self._op_res: dict[str, OpResource] = defaultdict(OpResource)
|
||||
self._l0op_list = []
|
||||
|
||||
TILING_REG_DECL_FMT = """
|
||||
namespace {namespace} {{
|
||||
extern gert::OpImplRegisterV2 {func_name};
|
||||
}}
|
||||
"""
|
||||
EXTEND_REG_DECL_FMT = """
|
||||
namespace {namespace} {{
|
||||
extern uint32_t {func_name};
|
||||
}}
|
||||
"""
|
||||
TILING_REG_RES_FUNC_FMT = """
|
||||
void * {op_type}TilingRegisterResource() {{
|
||||
return {reference_code};
|
||||
}}
|
||||
"""
|
||||
INFER_SHAPE_REG_DECL_FMT = """
|
||||
namespace {namespace} {{
|
||||
extern gert::OpImplRegisterV2 {func_name};
|
||||
}}
|
||||
"""
|
||||
INFER_SHAPE_REG_RES_FUNC_FMT = """
|
||||
void * {op_type}InferShapeRegisterResource() {{
|
||||
return {reference_code};
|
||||
}}
|
||||
"""
|
||||
TUNING_REG_DECL_FMT = """
|
||||
namespace {namespace} {{
|
||||
class {class_type};
|
||||
extern {class_type} {func_name};
|
||||
}}
|
||||
"""
|
||||
EXTLEND_REG_RES_FUNC_FMT = """
|
||||
void * {op_type}ExtendRegisterResource() {{
|
||||
static std::vector<void *> resource = {{{reference_code}}};
|
||||
return &resource;
|
||||
}}
|
||||
"""
|
||||
TUNING_REG_RES_FUNC_FMT = """
|
||||
void * {op_type}TuningRegisterResource() {{
|
||||
static std::vector<void *> resource = {{{tuning_bank_key}, {tuning_bank_parse}, {tuning_helper}}};
|
||||
return &resource;
|
||||
}}
|
||||
"""
|
||||
KERNEL_BINARY_RES_FUNC_FMT = """
|
||||
const OP_BINARY_RES& {op_type}KernelResource() {{
|
||||
static const OP_BINARY_RES resource = {{
|
||||
{binary_config_ref_code}
|
||||
{kernel_files_ref_code}
|
||||
}};
|
||||
return resource;
|
||||
}}
|
||||
"""
|
||||
TUNING_KB_BINARY_RES_FUNC_FMT = """
|
||||
const OP_RUNTIME_KB_RES& {op_type}TuningResource() {{
|
||||
static const OP_RUNTIME_KB_RES resource = {{
|
||||
{reference_code}
|
||||
}};
|
||||
return resource;
|
||||
}}
|
||||
"""
|
||||
OP_RESOURCE_CPP_FMT = """/******************{op_type}算子的所有资源**********************/
|
||||
#include "register/op_impl_registry.h"
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <map>
|
||||
#include <graph/ascend_string.h>
|
||||
#include <static_space.h>
|
||||
|
||||
using OP_HOST_FUNC_HANDLE = std::vector<void *>;
|
||||
using OP_RES = std::tuple<const uint8_t *, const uint8_t *>;
|
||||
using OP_BINARY_RES = std::vector<OP_RES>;
|
||||
using OP_RUNTIME_KB_RES = std::vector<OP_RES>;
|
||||
using OP_RESOURCES = std::map<ge::AscendString,
|
||||
std::tuple<OP_HOST_FUNC_HANDLE, OP_BINARY_RES, OP_RUNTIME_KB_RES>>;
|
||||
namespace {op_type} {{
|
||||
auto initializer = StaticSpaceInitializer::GetInstance();;
|
||||
}}
|
||||
|
||||
// 资源声明
|
||||
// extend resource
|
||||
{extend_declaration}
|
||||
// Tiling
|
||||
{tiling_declaration}
|
||||
// InferShape
|
||||
{infer_shape_declaration}
|
||||
// Tuning
|
||||
{tuning_bank_key_declaration}
|
||||
{tuning_bank_parse_declaration}
|
||||
{tuning_helper_declaration}
|
||||
// kernel 二进制
|
||||
{binary_config_declaration}
|
||||
{kernel_files_declaration}
|
||||
// kb 二进制
|
||||
{tuning_kb_declaration}
|
||||
|
||||
namespace l0op {{
|
||||
// 资源函数
|
||||
// Tiling register resource func
|
||||
{tiling_reg_func}
|
||||
// InferShape register resource func
|
||||
{infer_shape_reg_func}
|
||||
// Tuning register resource func
|
||||
{tuning_reg_func}
|
||||
// kernel resource func
|
||||
{kernel_resource}
|
||||
// Tuning resource func
|
||||
{tuning_kb_resource}
|
||||
}}
|
||||
|
||||
// extend resource func
|
||||
{extend_reg_func}
|
||||
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _extract_op_symbol_pair(symbol_file: str, search_key: str, prefix: str, suffix: str):
|
||||
symbol_ret = shell_checkout_key_func(symbol_file, search_key)
|
||||
for symbol in symbol_ret.splitlines():
|
||||
symbol_name = symbol.split("::")[-1]
|
||||
if not (symbol_name.startswith(prefix) and symbol_name.endswith(suffix)):
|
||||
log.warning("symbol not satisfied with the format:%s<op_type>%s, skip", prefix, suffix)
|
||||
continue
|
||||
op_type = symbol_name
|
||||
if prefix:
|
||||
op_type = op_type[len(prefix) :]
|
||||
if suffix:
|
||||
op_type = op_type[: -len(suffix)]
|
||||
yield op_type, symbol
|
||||
|
||||
@staticmethod
|
||||
def _extract_op_symbol_pair_v2(symbol_file: str, search_key: str, prefix: str):
|
||||
symbol_ret = shell_checkout_key_func(symbol_file, search_key)
|
||||
for symbol in symbol_ret.splitlines():
|
||||
symbol_name = symbol.split("::")[-1]
|
||||
if not (symbol_name.startswith(prefix)):
|
||||
log.warning("symbol not satisfied with the format:%s, skip", prefix)
|
||||
continue
|
||||
op_type = symbol_name
|
||||
if prefix:
|
||||
op_type = op_type[len(prefix) :]
|
||||
op_type = op_type.split("_")[0]
|
||||
yield op_type, symbol
|
||||
|
||||
@staticmethod
|
||||
def _extract_register_symbol(register_symbol: str):
|
||||
if not register_symbol:
|
||||
return "", "", "nullptr"
|
||||
|
||||
symbol_data = register_symbol.split("::")
|
||||
namespace = "::".join(symbol_data[:-1])
|
||||
if "anonymous" in namespace:
|
||||
return "", "", "nullptr"
|
||||
func_name = symbol_data[-1]
|
||||
reference_code = f"&{register_symbol}"
|
||||
return namespace, func_name, reference_code
|
||||
|
||||
@staticmethod
|
||||
def _gen_binary_res_code(files):
|
||||
declaration = ""
|
||||
reference_code = ""
|
||||
for binary_file in files:
|
||||
# static not support supperkernel
|
||||
if "relocatable" in binary_file.name:
|
||||
continue
|
||||
binary_name = binary_file.name.replace(".", "_").replace("-", "_")
|
||||
declaration += f"""// {binary_file.name}
|
||||
extern const uint8_t _binary_{binary_name}_start[];
|
||||
extern const uint8_t _binary_{binary_name}_end[];
|
||||
"""
|
||||
reference_code += f"{{_binary_{binary_name}_start, _binary_{binary_name}_end}},\n"
|
||||
return declaration, reference_code
|
||||
|
||||
def gen_ops_ini_files(self):
|
||||
self.analyze_ops_files()
|
||||
self._analyze_symbols()
|
||||
self._analyze_ops_l0op()
|
||||
if not os.path.exists(self._op_resource_path):
|
||||
os.makedirs(self._op_resource_path)
|
||||
for op_type in self._l0op_list:
|
||||
ini_content = self.generate_op_resouce_ini(op_type)
|
||||
self._save_op_resource(op_type, ini_content)
|
||||
for op_type in self._op_res:
|
||||
if op_type in self._l0op_list:
|
||||
continue
|
||||
ini_content = self.generate_op_resouce_ini(op_type)
|
||||
self._save_op_resource(op_type, ini_content)
|
||||
|
||||
def generate_op_resouce_ini(self, op_type: str) -> str:
|
||||
value_dict = {
|
||||
"op_type": op_type,
|
||||
}
|
||||
value_dict.update(self._gen_register_resouce_code(op_type))
|
||||
value_dict.update(self._gen_tuning_register_resouce_code(op_type))
|
||||
value_dict.update(self._gen_binary_resource_code(op_type))
|
||||
# 处理特殊的共用算子kernel资源的算子
|
||||
sepical_ops = {"MatMulV2": "MatMul"}
|
||||
if op_type in sepical_ops:
|
||||
value_dict["kernel_files_declaration"] = ""
|
||||
value_dict["kernel_resource"] = f"""
|
||||
extern const OP_BINARY_RES& {sepical_ops[op_type]}KernelResource();
|
||||
const OP_BINARY_RES& {op_type}KernelResource() {{
|
||||
return {sepical_ops[op_type]}KernelResource();
|
||||
}}
|
||||
"""
|
||||
return self.OP_RESOURCE_CPP_FMT.format_map(value_dict)
|
||||
|
||||
def analyze_ops_files(self):
|
||||
if not self._ops_info:
|
||||
return self._op_res
|
||||
with open(self._ops_info) as autogen_fd:
|
||||
ops_info_json = json.load(autogen_fd)
|
||||
|
||||
for ops in ops_info_json:
|
||||
if "opFile" in ops_info_json[ops]:
|
||||
json_file = f"{ops_info_json[ops]['opFile']['value']}.json"
|
||||
else:
|
||||
o_lists = list(Path(self._binary_path).rglob(f"{self._soc_version}/**/*{ops}*.o"))
|
||||
if len(o_lists) == 0:
|
||||
continue
|
||||
else:
|
||||
json_file = f"{os.path.basename(os.path.dirname(o_lists[0]))}.json"
|
||||
# json_path = self._binary_path / "config" / self._soc_version / json_file
|
||||
json_path = self._binary_path / json_file
|
||||
if "opp/built-in/" in str(self._binary_path):
|
||||
json_path = self._binary_path / "config" / self._soc_version / "ops_transformer" / json_file
|
||||
if not os.path.exists(json_path):
|
||||
continue
|
||||
with open(json_path) as op_json_fd:
|
||||
op_json_content = json.load(op_json_fd)
|
||||
if "binList" not in op_json_content or len(op_json_content["binList"]) == 0:
|
||||
continue
|
||||
# 算子.json内 kernel json路径适配
|
||||
bin_json_file = (
|
||||
self._binary_path / op_json_content["binList"][0]["binInfo"]["jsonFilePath"].split("/", 1)[1]
|
||||
)
|
||||
if "opp/built-in/" in str(self._binary_path):
|
||||
bin_json_file = (
|
||||
self._binary_path
|
||||
/ self._soc_version
|
||||
/ "ops_transformer"
|
||||
/ op_json_content["binList"][0]["binInfo"]["jsonFilePath"].split("/", 1)[1]
|
||||
)
|
||||
ops_path = os.path.dirname(bin_json_file)
|
||||
self._op_res[ops].binary_config_files.append(json_path)
|
||||
self._op_res[ops].kernel_files.extend(sorted(Path(ops_path).iterdir()))
|
||||
for kb_json in list(Path(self._tuning_basic_path).rglob("*_AiCore_*_runtime_kb.json")):
|
||||
ops = kb_json.name.split("_AiCore_")[-1].split("_runtime_kb")[0]
|
||||
self._op_res[ops].runtime_kb_files.append(kb_json)
|
||||
self._op_res[ops].runtime_kb_files.sort(key=lambda p: p.name)
|
||||
return self._op_res
|
||||
|
||||
def _analyze_ops_l0op(self):
|
||||
opapi_symbol = self._build_dir / "opapi_transformer.txt"
|
||||
if not os.path.exists(opapi_symbol):
|
||||
return
|
||||
# infershape
|
||||
for op_type, _ in self._extract_op_symbol_pair(opapi_symbol, "_kernelName_Be_Defined_Multi_Times__", "", ""):
|
||||
self._l0op_list.append(op_type.split("_kernelName_")[0])
|
||||
self._l0op_list.sort()
|
||||
|
||||
def _save_op_resource(self, op_type, res_content):
|
||||
res_cpp_file = self._op_resource_path / f"{op_type}_op_resource.cpp"
|
||||
with contextlib.suppress(FileNotFoundError):
|
||||
res_cpp_file.unlink()
|
||||
|
||||
flags = os.O_WRONLY | os.O_CREAT
|
||||
modes = stat.S_IWUSR | stat.S_IRUSR
|
||||
with os.fdopen(os.open(res_cpp_file, flags, modes), "w") as fd:
|
||||
fd.write(res_content)
|
||||
|
||||
def _analyze_symbols(self):
|
||||
# ophost txt 适配
|
||||
ophost_symbol = self._build_dir / "ophost_transformer.txt"
|
||||
if not os.path.exists(ophost_symbol):
|
||||
return
|
||||
# infershape
|
||||
for op_type, symbol in self._extract_op_symbol_pair(
|
||||
ophost_symbol, "op_impl_register_infershape_", "op_impl_register_infershape_", ""
|
||||
):
|
||||
self._op_res[op_type].infer_shape_register = symbol
|
||||
# tiling
|
||||
for op_type, symbol in self._extract_op_symbol_pair(
|
||||
ophost_symbol, "op_impl_register_optiling_", "op_impl_register_optiling_", ""
|
||||
):
|
||||
self._op_res[op_type].tiling_register = symbol
|
||||
for op_type, symbol in self._extract_op_symbol_pair_v2(
|
||||
ophost_symbol, "op_impl_register_template_", "op_impl_register_template_"
|
||||
):
|
||||
self._op_res[op_type].extend_register.append(symbol)
|
||||
# 知识库
|
||||
for op_type, symbol in self._extract_op_symbol_pair(
|
||||
ophost_symbol, "BankKeyRegistryInterf", "g_", "BankKeyRegistryInterf"
|
||||
):
|
||||
self._op_res[op_type].tuning_bank_key_register = symbol
|
||||
for op_type, symbol in self._extract_op_symbol_pair(ophost_symbol, "BankParseInterf", "g_", "BankParseInterf"):
|
||||
self._op_res[op_type].tuning_bank_parse_register = symbol
|
||||
for op_type, symbol in self._extract_op_symbol_pair(
|
||||
ophost_symbol, "g_tuning_tiling_", "g_tuning_tiling_", "Helper"
|
||||
):
|
||||
self._op_res[op_type].tuning_tiling_helper = symbol
|
||||
|
||||
def _gen_register_resouce_code(self, op_type: str):
|
||||
"""注册函数"""
|
||||
# Tiling
|
||||
namespace, func_name, reference_code = self._extract_register_symbol(self._op_res[op_type].tiling_register)
|
||||
symbol_map = {
|
||||
"op_type": op_type,
|
||||
"namespace": namespace,
|
||||
"func_name": func_name,
|
||||
"reference_code": reference_code,
|
||||
}
|
||||
tiling_declaration = self.TILING_REG_DECL_FMT.format_map(symbol_map) if func_name else ""
|
||||
tiling_reg_func = self.TILING_REG_RES_FUNC_FMT.format_map(symbol_map) if func_name else ""
|
||||
|
||||
reference_code_list = []
|
||||
extend_declaration = ""
|
||||
for symbol in self._op_res[op_type].extend_register:
|
||||
namespace, func_name, reference_code = self._extract_register_symbol(symbol)
|
||||
if func_name:
|
||||
extend_declaration += self.EXTEND_REG_DECL_FMT.format(namespace=namespace, func_name=func_name)
|
||||
reference_code_list.append(reference_code)
|
||||
reference_code = ", ".join(reference_code_list)
|
||||
extend_reg_func = self.EXTLEND_REG_RES_FUNC_FMT.format(op_type=op_type, reference_code=reference_code)
|
||||
|
||||
# InferShape
|
||||
namespace, func_name, reference_code = self._extract_register_symbol(self._op_res[op_type].infer_shape_register)
|
||||
symbol_map = {
|
||||
"op_type": op_type,
|
||||
"namespace": namespace,
|
||||
"func_name": func_name,
|
||||
"reference_code": reference_code,
|
||||
}
|
||||
infer_shape_declaration = self.INFER_SHAPE_REG_DECL_FMT.format_map(symbol_map) if func_name else ""
|
||||
infer_shape_reg_func = self.INFER_SHAPE_REG_RES_FUNC_FMT.format_map(symbol_map) if func_name else ""
|
||||
|
||||
return {
|
||||
"tiling_declaration": tiling_declaration,
|
||||
"infer_shape_declaration": infer_shape_declaration,
|
||||
"tiling_reg_func": tiling_reg_func,
|
||||
"infer_shape_reg_func": infer_shape_reg_func,
|
||||
"extend_reg_func": extend_reg_func,
|
||||
"extend_declaration": extend_declaration,
|
||||
}
|
||||
|
||||
def _gen_tuning_register_resouce_code(self, op_type: str):
|
||||
"""知识库注册函数"""
|
||||
# Tuning
|
||||
namespace, func_name, tuning_bank_key_ref_code = self._extract_register_symbol(
|
||||
self._op_res[op_type].tuning_bank_key_register
|
||||
)
|
||||
tuning_bank_key_declaration = (
|
||||
self.TUNING_REG_DECL_FMT.format(
|
||||
namespace=namespace,
|
||||
class_type="OpBankKeyFuncRegistryV2",
|
||||
func_name=func_name,
|
||||
)
|
||||
if func_name
|
||||
else ""
|
||||
)
|
||||
namespace, func_name, tuning_bank_parse_ref_code = self._extract_register_symbol(
|
||||
self._op_res[op_type].tuning_bank_parse_register
|
||||
)
|
||||
tuning_bank_parse_declaration = (
|
||||
self.TUNING_REG_DECL_FMT.format(
|
||||
namespace=namespace,
|
||||
class_type="OpBankKeyFuncRegistryV2",
|
||||
func_name=func_name,
|
||||
)
|
||||
if func_name
|
||||
else ""
|
||||
)
|
||||
namespace, func_name, tuning_helper_ref_code = self._extract_register_symbol(
|
||||
self._op_res[op_type].tuning_tiling_helper
|
||||
)
|
||||
tuning_helper_declaration = (
|
||||
self.TUNING_REG_DECL_FMT.format(
|
||||
namespace=namespace,
|
||||
class_type=f"{op_type}ClassHelper",
|
||||
func_name=func_name,
|
||||
)
|
||||
if func_name
|
||||
else ""
|
||||
)
|
||||
tuning_reg_func = self.TUNING_REG_RES_FUNC_FMT.format(
|
||||
op_type=op_type,
|
||||
tuning_bank_key=tuning_bank_key_ref_code,
|
||||
tuning_bank_parse=tuning_bank_parse_ref_code,
|
||||
tuning_helper=tuning_helper_ref_code,
|
||||
)
|
||||
return {
|
||||
"tuning_bank_key_declaration": tuning_bank_key_declaration,
|
||||
"tuning_bank_parse_declaration": tuning_bank_parse_declaration,
|
||||
"tuning_helper_declaration": tuning_helper_declaration,
|
||||
"tuning_reg_func": tuning_reg_func,
|
||||
}
|
||||
|
||||
def _gen_binary_resource_code(self, op_type: str) -> str:
|
||||
"""二进制"""
|
||||
# kernel
|
||||
binary_config_declaration, binary_config_ref_code = self._gen_binary_res_code(
|
||||
self._op_res[op_type].binary_config_files
|
||||
)
|
||||
kernel_files_declaration, kernel_files_ref_code = self._gen_binary_res_code(self._op_res[op_type].kernel_files)
|
||||
kernel_resource = (
|
||||
self.KERNEL_BINARY_RES_FUNC_FMT.format(
|
||||
op_type=op_type,
|
||||
binary_config_ref_code=binary_config_ref_code,
|
||||
kernel_files_ref_code=kernel_files_ref_code,
|
||||
)
|
||||
if kernel_files_ref_code
|
||||
else ""
|
||||
)
|
||||
# 知识库
|
||||
tuning_kb_declaration, tuning_kb_ref_code = self._gen_binary_res_code(self._op_res[op_type].runtime_kb_files)
|
||||
tuning_kb_resource = self.TUNING_KB_BINARY_RES_FUNC_FMT.format(
|
||||
op_type=op_type,
|
||||
reference_code=tuning_kb_ref_code,
|
||||
)
|
||||
return {
|
||||
"binary_config_declaration": binary_config_declaration,
|
||||
"kernel_files_declaration": kernel_files_declaration,
|
||||
"tuning_kb_declaration": tuning_kb_declaration,
|
||||
"kernel_resource": kernel_resource,
|
||||
"tuning_kb_resource": tuning_kb_resource,
|
||||
}
|
||||
|
||||
|
||||
def generate_op_resource_h_file(args):
|
||||
soc_version: str = args.soc_version
|
||||
build_dir = args.build_dir
|
||||
|
||||
gen_ini = GenOpResourceIni(soc_version, build_dir, args.jit)
|
||||
gen_ini.gen_ops_ini_files()
|
||||
return
|
||||
|
||||
|
||||
def parser_generate_op_resource_h_file(subparsers):
|
||||
gen_resource_ini_parser = subparsers.add_parser(
|
||||
name="GenStaticOpResourceIni", help="Generate xxx_op_resource.h on consolidation server"
|
||||
)
|
||||
gen_resource_ini_parser.add_argument(
|
||||
"-s",
|
||||
"--soc_version",
|
||||
type=str,
|
||||
required=True,
|
||||
dest="soc_version",
|
||||
help="Operator Name, eg: ascend910b, ascend310p",
|
||||
)
|
||||
gen_resource_ini_parser.add_argument(
|
||||
"-b", "--build_dir", type=str, required=True, dest="build_dir", help="Input build dir for this project"
|
||||
)
|
||||
gen_resource_ini_parser.add_argument(
|
||||
"-j", "--jit", action="store_true", dest="jit", help="Generate xxx_op_resource.h with cann package"
|
||||
)
|
||||
gen_resource_ini_parser.set_defaults(func=generate_op_resource_h_file)
|
||||
|
||||
|
||||
def execute_argus_parse_func():
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
subparsers = parser.add_subparsers(help="Subparsers Commands")
|
||||
|
||||
""" 配置静态编译参数及执行信息 """
|
||||
parser_compile_static_library(subparsers)
|
||||
|
||||
""" 配置头文件生成功能参数及执行信息 """
|
||||
parser_generate_op_resource_h_file(subparsers)
|
||||
|
||||
""" 生成指定库的symbol文件 """
|
||||
parser_generate_symbol(subparsers)
|
||||
|
||||
""" 执行函数功能 """
|
||||
args = parser.parse_args()
|
||||
args.func(args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
execute_argus_parse_func()
|
||||
exit(0)
|
||||
77
csrc/scripts/util/const_var.py
Normal file
77
csrc/scripts/util/const_var.py
Normal file
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
# ----------------------------------------------------------------------------
|
||||
# Copyright (c) 2025 Huawei Technologies Co., Ltd.
|
||||
# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
|
||||
# CANN Open Software License Agreement Version 2.0 (the "License").
|
||||
# Please refer to the License for details. You may not use this file except in compliance with the License.
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
||||
# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See LICENSE in the root of the software repository for the full text of the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
Function:
|
||||
The replay function entry
|
||||
Copyright Information:
|
||||
Huawei Technologies Co., Ltd. All Rights Reserved © 2020
|
||||
"""
|
||||
|
||||
import os
|
||||
import stat
|
||||
|
||||
REPLAY_BATCH = "batch"
|
||||
REPLAY_ITERATE = "iterate"
|
||||
CFG_IMPL_DIR = "impl_dir"
|
||||
CFG_OUT_DIR = "out_dir"
|
||||
AUTO_GEN_DIR = "auto_gen_dir"
|
||||
WFLAGS = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
|
||||
WMODES = stat.S_IWUSR | stat.S_IRUSR
|
||||
SOC_MAP_EXT = {
|
||||
"ascend310p": "Ascend310P3",
|
||||
"ascend310b": "Ascend310B1",
|
||||
"ascend910": "Ascend910A",
|
||||
"ascend910b": "Ascend910B1",
|
||||
"ascend910_93": "Ascend910_9391",
|
||||
"ascend950": "Ascend950",
|
||||
"kirinx90": "KirinX90",
|
||||
}
|
||||
BIN_CMD = "asc_opc $1 --main_func={fun} --input_param={param} --soc_version={soc} \
|
||||
--output=$2 --impl_mode={impl} --simplified_key_mode=0 --op_mode=dynamic\n"
|
||||
SET_PLOG_LEVEL_ERROR = "export ASCEND_GLOBAL_LOG_LEVEL=3\n"
|
||||
SET_PLOG_STDOUT = "export ASCEND_SLOG_PRINT_TO_STDOUT=1\n"
|
||||
SRC_ENV = """
|
||||
while true; do
|
||||
case "$1" in
|
||||
--kernel-src=*)
|
||||
export BUILD_KERNEL_SRC=$(echo "$1" | cut -d"=" -f2-)
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"""
|
||||
CHK_CMD = """
|
||||
if ! test -f $2/{res_file} ; then
|
||||
echo "$2/{res_file} not generated!"
|
||||
exit 1
|
||||
fi
|
||||
"""
|
||||
ATTR_DEF_VAL = {
|
||||
"str": "",
|
||||
"int": 0,
|
||||
"float": 0.0,
|
||||
"bool": False,
|
||||
"list_bool": [],
|
||||
"list_int": [],
|
||||
"list_float": [],
|
||||
"list_list_int": [[]],
|
||||
}
|
||||
|
||||
|
||||
def conv_soc_ver(ver: str):
|
||||
return SOC_MAP_EXT.get(ver)
|
||||
41
csrc/scripts/util/insert_op_info.py
Normal file
41
csrc/scripts/util/insert_op_info.py
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python3
|
||||
# ----------------------------------------------------------------------------
|
||||
# Copyright (c) 2025 Huawei Technologies Co., Ltd.
|
||||
# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
|
||||
# CANN Open Software License Agreement Version 2.0 (the "License").
|
||||
# Please refer to the License for details. You may not use this file except in compliance with the License.
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
||||
# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See LICENSE in the root of the software repository for the full text of the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
import const_var
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 3:
|
||||
print(sys.argv)
|
||||
print("argv error, inert_op_info.py your_op_file lib_op_file")
|
||||
sys.exit(2)
|
||||
|
||||
with open(sys.argv[1]) as load_f:
|
||||
insert_operator = json.load(load_f)
|
||||
|
||||
all_operators = {}
|
||||
if os.path.exists(sys.argv[2]):
|
||||
if os.path.getsize(sys.argv[2]) != 0:
|
||||
with open(sys.argv[2]) as load_f:
|
||||
all_operators = json.load(load_f)
|
||||
|
||||
for k in insert_operator:
|
||||
if k in all_operators:
|
||||
print("replace op:[", k, "] success")
|
||||
else:
|
||||
print("insert op:[", k, "] success")
|
||||
all_operators[k] = insert_operator[k]
|
||||
|
||||
with os.fdopen(os.open(sys.argv[2], const_var.WFLAGS, const_var.WMODES), "w") as json_file:
|
||||
json_file.write(json.dumps(all_operators, indent=4))
|
||||
37
csrc/scripts/util/merge_aicpu_info_json.sh
Normal file
37
csrc/scripts/util/merge_aicpu_info_json.sh
Normal file
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
# Copyright (c) 2025 Huawei Technologies Co., Ltd.
|
||||
# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
|
||||
# CANN Open Software License Agreement Version 2.0 (the "License").
|
||||
# Please refer to the License for details. You may not use this file except in compliance with the License.
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
||||
# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See LICENSE in the root of the software repository for the full text of the License.
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
echo "$@"
|
||||
top_dir=$1
|
||||
output_json=$2
|
||||
first_json=$3
|
||||
shift 3
|
||||
|
||||
merge_json_tool="${top_dir}/scripts/util/insert_op_info.py"
|
||||
>$output_json
|
||||
|
||||
if [[ -f "$first_json" ]]
|
||||
then
|
||||
cp -f $first_json $output_json
|
||||
else
|
||||
echo "[ERROR] ${first_json} is not a file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for single_json in "$@"
|
||||
do
|
||||
if [[ -f "${single_json}" ]]
|
||||
then
|
||||
python3 ${top_dir}/scripts/util/insert_op_info.py ${single_json} ${output_json}
|
||||
else
|
||||
echo "[ERROR] ${single_json} is not a file"
|
||||
fi
|
||||
done
|
||||
77
csrc/scripts/util/merge_proto.py
Normal file
77
csrc/scripts/util/merge_proto.py
Normal file
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
# Copyright (c) 2025 Huawei Technologies Co., Ltd.
|
||||
# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
|
||||
# CANN Open Software License Agreement Version 2.0 (the "License").
|
||||
# Please refer to the License for details. You may not use this file except in compliance with the License.
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
||||
# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See LICENSE in the root of the software repository for the full text of the License.
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
import regex as re
|
||||
|
||||
|
||||
def match_op_proto(file_path):
|
||||
with open(file_path, encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
op_def_pattern = re.compile(r"REG_OP\((.+)\).*OP_END_FACTORY_REG\(\1\)", re.DOTALL)
|
||||
match = op_def_pattern.search(content)
|
||||
|
||||
if match:
|
||||
op_name = match.group(1)
|
||||
op_def = match.group(0)
|
||||
return op_name, op_def
|
||||
else:
|
||||
return None, None
|
||||
|
||||
|
||||
def merge_op_proto(protos_path, output_file):
|
||||
op_defs = []
|
||||
for proto_path in protos_path:
|
||||
if not proto_path.endswith("_proto.h"):
|
||||
continue
|
||||
print(f"proto_path: {proto_path}")
|
||||
op_name, op_def = match_op_proto(proto_path)
|
||||
if op_def:
|
||||
op_defs.append(op_def)
|
||||
|
||||
# merge op_proto
|
||||
merged_content = f"""#ifndef OP_TRANSFORMER_PROTO_H_
|
||||
#define OP_TRANSFORMER_PROTO_H_
|
||||
|
||||
#include "graph/operator_reg.h"
|
||||
#include "register/op_impl_registry.h"
|
||||
|
||||
namespace ge{{
|
||||
|
||||
{os.linesep.join([f"{op_def}{os.linesep}" for op_def in op_defs])}
|
||||
}} // namespace ge
|
||||
|
||||
#endif // OP_TRANSFORMER_PROTO_H_
|
||||
"""
|
||||
|
||||
with open(output_file, "w", encoding="utf-8") as f:
|
||||
f.write(merged_content)
|
||||
|
||||
print(f"merged op transformer proto file: {output_file}")
|
||||
|
||||
|
||||
def parse_args(argv):
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("protos", nargs="+")
|
||||
parser.add_argument("--output-file", nargs=1, default=None)
|
||||
return parser.parse_args(argv)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = parse_args(sys.argv)
|
||||
|
||||
protos_path = args.protos[1:]
|
||||
output_file = args.output_file[0]
|
||||
merge_op_proto(protos_path, output_file)
|
||||
58
csrc/scripts/util/modify_gen_aclnn.py
Normal file
58
csrc/scripts/util/modify_gen_aclnn.py
Normal file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
# Copyright (c) 2025 Huawei Technologies Co., Ltd.
|
||||
# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
|
||||
# CANN Open Software License Agreement Version 2.0 (the "License").
|
||||
# Please refer to the License for details. You may not use this file except in compliance with the License.
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
||||
# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See LICENSE in the root of the software repository for the full text of the License.
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
import logging as log
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def shell_exec(cmd, shell=False):
|
||||
try:
|
||||
ps = subprocess.Popen(cmd, shell)
|
||||
ps.communicate(timeout=180)
|
||||
except BaseException as e:
|
||||
log.error("shell_exec error: %s", e)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def search_file(aclnn_cpp):
|
||||
op_type = None
|
||||
index = 0
|
||||
with open(aclnn_cpp) as f:
|
||||
for line in f.readlines():
|
||||
index = index + 1
|
||||
if "_op_resource.h" in line:
|
||||
op_type = line.replace('_op_resource.h"', "").replace('#include "', "").strip()
|
||||
if "EXTERN_OP_RESOURCE" in line or "namespace op {" in line:
|
||||
break
|
||||
return (op_type, index)
|
||||
|
||||
|
||||
def modify_gen_aclnn(build_path):
|
||||
auto_gen_cpps = Path(os.path.join(build_path, "autogen")).rglob("aclnn*.cpp")
|
||||
for aclnn_cpp in auto_gen_cpps:
|
||||
(op_type, index) = search_file(aclnn_cpp)
|
||||
if op_type:
|
||||
shell_exec(
|
||||
["bash", "-c", f"""sed -i 's/{op_type}_op_resource.h/op_resource.h/g' {aclnn_cpp}"""], shell=False
|
||||
)
|
||||
shell_exec(
|
||||
["bash", "-c", f"""sed -i 's/{op_type}_RESOURCES/AUTO_GEN_OP_RESOURCE({op_type})/g' {aclnn_cpp}"""],
|
||||
shell=False,
|
||||
)
|
||||
shell_exec(["bash", "-c", f"sed -i '{index}i\\EXTERN_OP_RESOURCE({op_type})' {aclnn_cpp}"], shell=False)
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
modify_gen_aclnn(sys.argv[1])
|
||||
Reference in New Issue
Block a user