308 lines
13 KiB
CMake
308 lines
13 KiB
CMake
# -----------------------------------------------------------------------------------------------------------
|
||
# 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.
|
||
# -----------------------------------------------------------------------------------------------------------
|
||
# ######################################################################################################################
|
||
# 调用opbuild工具,生成aclnn/aclnnInner/.ini的算子信息库 等文件
|
||
# generate outpath: ${ASCEND_AUTOGEN_PATH}/${sub_dir}
|
||
# ######################################################################################################################
|
||
function(gen_opbuild_target)
|
||
set(oneValueArgs TARGET PREFIX GENACLNN OUT_DIR OUT_SUB_DIR)
|
||
set(multiValueArgs IN_SRCS OUT_SRCS OUT_HEADERS)
|
||
cmake_parse_arguments(OPBUILD "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||
if(NOT OPBUILD_IN_SRCS)
|
||
message(STATUS "No ${OPBUILD_PREFIX} srcs, skip ${OPBUILD_TARGET}")
|
||
return()
|
||
endif()
|
||
|
||
add_library(gen_op_host_${OPBUILD_PREFIX} SHARED ${OPBUILD_IN_SRCS})
|
||
target_link_libraries(gen_op_host_${OPBUILD_PREFIX} PRIVATE
|
||
$<BUILD_INTERFACE:intf_pub_cxx17>
|
||
exe_graph
|
||
register
|
||
c_sec
|
||
)
|
||
target_compile_options(gen_op_host_${OPBUILD_PREFIX} PRIVATE
|
||
-fno-common
|
||
)
|
||
|
||
add_custom_command(OUTPUT ${OPBUILD_OUT_SRCS} ${OPBUILD_OUT_HEADERS}
|
||
COMMAND OPS_PROTO_SEPARATE=1
|
||
OPS_PROJECT_NAME=${OPBUILD_PREFIX}
|
||
OPS_ACLNN_GEN=${OPBUILD_GENACLNN}
|
||
OPS_PRODUCT_NAME=\"${ASCEND_COMPUTE_UNIT}\"
|
||
${OP_BUILD_TOOL}
|
||
$<TARGET_FILE:gen_op_host_${OPBUILD_PREFIX}>
|
||
${OPBUILD_OUT_DIR}/${OPBUILD_OUT_SUB_DIR}
|
||
)
|
||
|
||
add_custom_target(${OPBUILD_TARGET}
|
||
DEPENDS ${OPBUILD_OUT_SRCS} ${OPBUILD_OUT_HEADERS}
|
||
)
|
||
add_dependencies(${OPBUILD_TARGET} gen_op_host_${OPBUILD_PREFIX})
|
||
if(TARGET op_build)
|
||
add_dependencies(${OPBUILD_TARGET} op_build)
|
||
endif()
|
||
endfunction()
|
||
|
||
function(append_versioned_aclnn_outputs op_def_src file_prefix op_name out_dir out_srcs_var out_headers_var)
|
||
if(NOT EXISTS "${op_def_src}")
|
||
return()
|
||
endif()
|
||
|
||
file(READ "${op_def_src}" op_def_content)
|
||
string(REGEX MATCHALL "\\.Version\\([ \t]*[A-Za-z0-9_]+[ \t]*\\)" version_exprs "${op_def_content}")
|
||
if(NOT version_exprs)
|
||
return()
|
||
endif()
|
||
|
||
set(version_values)
|
||
foreach(version_expr ${version_exprs})
|
||
string(REGEX REPLACE ".*\\.Version\\([ \t]*([A-Za-z0-9_]+)[ \t]*\\).*" "\\1" version_token "${version_expr}")
|
||
set(version_value "")
|
||
if(version_token MATCHES "^[0-9]+$")
|
||
set(version_value "${version_token}")
|
||
else()
|
||
string(REGEX MATCH "[A-Za-z_][A-Za-z0-9_]*[ \t]+${version_token}[ \t]*=[ \t]*[0-9]+" version_decl "${op_def_content}")
|
||
if(version_decl)
|
||
string(REGEX REPLACE ".*=[ \t]*([0-9]+).*" "\\1" version_value "${version_decl}")
|
||
endif()
|
||
endif()
|
||
|
||
if(version_value AND version_value GREATER 1)
|
||
list(APPEND version_values "${version_value}")
|
||
endif()
|
||
endforeach()
|
||
|
||
if(NOT version_values)
|
||
return()
|
||
endif()
|
||
|
||
list(REMOVE_DUPLICATES version_values)
|
||
foreach(version_value ${version_values})
|
||
list(APPEND ${out_srcs_var} ${out_dir}/${file_prefix}_${op_name}_v${version_value}.cpp)
|
||
list(APPEND ${out_headers_var} ${out_dir}/${file_prefix}_${op_name}_v${version_value}.h)
|
||
endforeach()
|
||
|
||
set(${out_srcs_var} "${${out_srcs_var}}" PARENT_SCOPE)
|
||
set(${out_headers_var} "${${out_headers_var}}" PARENT_SCOPE)
|
||
endfunction()
|
||
|
||
function(gen_aclnn_classify host_obj prefix ori_out_srcs ori_out_headers opbuild_out_srcs opbuild_out_headers)
|
||
get_target_property(module_sources ${host_obj} INTERFACE_SOURCES)
|
||
set(sub_dir)
|
||
# aclnn\aclnnExc以aclnn开头,aclnnInner以aclnnInner开头
|
||
if("${prefix}" STREQUAL "aclnn")
|
||
set(file_prefix "aclnn")
|
||
set(need_gen_aclnn 1)
|
||
elseif("${prefix}" STREQUAL "aclnnInner")
|
||
set(sub_dir inner)
|
||
set(file_prefix "aclnnInner")
|
||
set(need_gen_aclnn 1)
|
||
elseif("${prefix}" STREQUAL "aclnnExc")
|
||
set(sub_dir exc)
|
||
set(file_prefix "aclnn")
|
||
set(need_gen_aclnn 0)
|
||
else()
|
||
message(FATAL_ERROR "UnSupported aclnn prefix type, must be in aclnn/aclnnInner/aclnnExc")
|
||
endif()
|
||
|
||
set(out_src_path ${ASCEND_AUTOGEN_PATH}/${sub_dir})
|
||
file(MAKE_DIRECTORY ${out_src_path})
|
||
get_filename_component(out_src_path ${out_src_path} REALPATH)
|
||
set(in_srcs)
|
||
set(out_srcs)
|
||
set(out_headers)
|
||
if(module_sources)
|
||
foreach(file ${module_sources})
|
||
get_filename_component(name_without_ext ${file} NAME_WE)
|
||
string(REGEX REPLACE "_def$" "" _op_name ${name_without_ext})
|
||
list(APPEND in_srcs ${file})
|
||
list(APPEND out_srcs ${out_src_path}/${file_prefix}_${_op_name}.cpp)
|
||
list(APPEND out_headers ${out_src_path}/${file_prefix}_${_op_name}.h)
|
||
if(need_gen_aclnn)
|
||
append_versioned_aclnn_outputs("${file}" "${file_prefix}" "${_op_name}" "${out_src_path}" out_srcs out_headers)
|
||
endif()
|
||
endforeach()
|
||
endif()
|
||
# opbuild_gen_aclnn/opbuild_gen_aclnnInner/opbuild_gen_aclnnExc
|
||
if("${prefix}" STREQUAL "aclnnExc")
|
||
get_target_property(exclude_headers ${OPHOST_NAME}_aclnn_exclude_headers INTERFACE_SOURCES)
|
||
if(exclude_headers)
|
||
set(${opbuild_out_headers} ${ori_out_headers} ${exclude_headers} PARENT_SCOPE)
|
||
endif()
|
||
else()
|
||
set(${opbuild_out_srcs} ${ori_out_srcs} ${out_srcs} PARENT_SCOPE)
|
||
set(${opbuild_out_headers} ${ori_out_headers} ${out_headers} PARENT_SCOPE)
|
||
endif()
|
||
endfunction()
|
||
|
||
function(gen_aclnn_master_header aclnn_master_header_name aclnn_master_header opbuild_out_headers)
|
||
# 规范化,防止生成的代码编译失败
|
||
string(REGEX REPLACE "[^a-zA-Z0-9_]" "_" aclnn_master_header_name "${aclnn_master_header_name}")
|
||
string(TOUPPER ${aclnn_master_header_name} aclnn_master_header_name)
|
||
|
||
# 生成include内容
|
||
set(aclnn_all_header_include_content "")
|
||
foreach(header_file ${opbuild_out_headers})
|
||
get_filename_component(header_name ${header_file} NAME)
|
||
set(aclnn_all_header_include_content "${aclnn_all_header_include_content}#include \"${header_name}\"\n")
|
||
endforeach()
|
||
|
||
# 根据模板生成头文件
|
||
message(STATUS "create aclnn master header file: ${aclnn_master_header}")
|
||
configure_file(
|
||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/aclnn_ops_transformer.h.in"
|
||
"${aclnn_master_header}"
|
||
@ONLY
|
||
)
|
||
endfunction()
|
||
|
||
function(gen_aclnn_with_opdef)
|
||
set(opbuild_out_srcs)
|
||
set(opbuild_out_headers)
|
||
gen_aclnn_classify(${OPHOST_NAME}_opdef_aclnn_obj aclnn "${opbuild_out_srcs}" "${opbuild_out_headers}"
|
||
opbuild_out_srcs opbuild_out_headers)
|
||
gen_aclnn_classify(${OPHOST_NAME}_opdef_aclnn_inner_obj aclnnInner "${opbuild_out_srcs}" "${opbuild_out_headers}"
|
||
opbuild_out_srcs opbuild_out_headers)
|
||
gen_aclnn_classify(${OPHOST_NAME}_opdef_aclnn_exclude_obj aclnnExc "${opbuild_out_srcs}" "${opbuild_out_headers}"
|
||
opbuild_out_srcs opbuild_out_headers)
|
||
|
||
# 创建汇总头文件
|
||
if(NOT ENABLE_BUILT_IN)
|
||
set(aclnn_master_header_name "aclnn_ops_transformer_${VENDOR_NAME}")
|
||
else()
|
||
set(aclnn_master_header_name "aclnn_ops_transformer")
|
||
endif()
|
||
set(aclnn_master_header "${CMAKE_CURRENT_BINARY_DIR}/${aclnn_master_header_name}.h")
|
||
gen_aclnn_master_header(${aclnn_master_header_name} "${aclnn_master_header}" "${opbuild_out_headers}")
|
||
|
||
set(mc2_op_aclnn_name
|
||
"all_gather_matmul"
|
||
"all_to_all_all_gather_batch_matmul"
|
||
"allto_allv_grouped_mat_mul"
|
||
"batch_matmul_reduce_scatter_all_to_all"
|
||
"distribute_barrier"
|
||
"distribute_barrier_v2"
|
||
"grouped_mat_mul_allto_allv"
|
||
"inplace_matmul_all_reduce_add_rms_norm"
|
||
"inplace_quant_matmul_all_reduce_add_rms_norm"
|
||
"inplace_weight_quant_matmul_all_reduce_add_rms_norm"
|
||
"matmul_all_reduce"
|
||
"matmul_all_reduce_add_rms_norm"
|
||
"matmul_all_reduce_v2"
|
||
"matmul_reduce_scatter"
|
||
"moe_distribute_combine"
|
||
"moe_distribute_combine_add_rms_norm"
|
||
"moe_distribute_combine_add_rms_norm_v2"
|
||
"moe_distribute_combine_v2"
|
||
"moe_distribute_combine_v3"
|
||
"moe_distribute_dispatch"
|
||
"moe_distribute_dispatch_v2"
|
||
"moe_distribute_dispatch_v3"
|
||
"moe_update_expert"
|
||
"weight_quant_matmul_all_reduce"
|
||
"weight_quant_matmul_all_reduce_add_rms_norm"
|
||
)
|
||
set(mc2_aclnn_master_headers "")
|
||
foreach(op_aclnn_name ${mc2_op_aclnn_name})
|
||
if (NOT ENABLE_BUILT_IN AND NOT ("${ASCEND_OP_NAME}" STREQUAL "ALL"))
|
||
foreach(op_name IN LISTS ASCEND_OP_NAME)
|
||
file(GLOB matching_file "${OPS_TRANSFORMER_DIR}/mc2/${op_name}/op_api/aclnn_${op_aclnn_name}.h")
|
||
list(APPEND mc2_aclnn_master_headers ${matching_file})
|
||
endforeach()
|
||
else()
|
||
file(GLOB matching_file "${OPS_TRANSFORMER_DIR}/mc2/*/op_api/aclnn_${op_aclnn_name}.h")
|
||
list(APPEND mc2_aclnn_master_headers ${matching_file})
|
||
endif()
|
||
endforeach()
|
||
|
||
# 将头文件安装到packages/vendors/vendor_name/op_api/include
|
||
if (NOT ENABLE_BUILT_IN)
|
||
install(FILES ${opbuild_out_headers} DESTINATION ${ACLNN_INC_INSTALL_DIR} OPTIONAL)
|
||
install(FILES ${aclnn_master_header} DESTINATION ${ACLNN_INC_INSTALL_DIR} OPTIONAL)
|
||
if (BUILD_OPEN_PROJECT AND mc2_aclnn_master_headers)
|
||
install(FILES ${mc2_aclnn_master_headers} DESTINATION ${ACLNN_INC_INSTALL_DIR} OPTIONAL)
|
||
endif()
|
||
else()
|
||
install(FILES ${opbuild_out_headers} DESTINATION ${ACLNN_INC_INSTALL_DIR} OPTIONAL)
|
||
install(FILES ${aclnn_master_header} DESTINATION ${ACLNN_INC_INSTALL_DIR} OPTIONAL)
|
||
install(FILES ${opbuild_out_headers} DESTINATION ${ACLNN_INC_LEVEL2_INSTALL_DIR} OPTIONAL)
|
||
install(FILES ${aclnn_master_header} DESTINATION ${ACLNN_INC_LEVEL2_INSTALL_DIR} OPTIONAL)
|
||
if (BUILD_OPEN_PROJECT)
|
||
install(FILES ${mc2_aclnn_master_headers} DESTINATION ${ACLNN_INC_INSTALL_DIR} OPTIONAL)
|
||
install(FILES ${mc2_aclnn_master_headers} DESTINATION ${ACLNN_INC_LEVEL2_INSTALL_DIR} OPTIONAL)
|
||
endif()
|
||
endif()
|
||
|
||
if (ENABLE_STATIC)
|
||
install(FILES ${opbuild_out_headers} DESTINATION ${CMAKE_BINARY_DIR}/static_library_files/include/aclnnop OPTIONAL)
|
||
install(FILES ${aclnn_master_header} DESTINATION ${CMAKE_BINARY_DIR}/static_library_files/include/aclnnop OPTIONAL)
|
||
install(FILES ${opbuild_out_headers} DESTINATION ${CMAKE_BINARY_DIR}/static_library_files/include/aclnnop/level2 OPTIONAL)
|
||
install(FILES ${aclnn_master_header} DESTINATION ${CMAKE_BINARY_DIR}/static_library_files/include/aclnnop/level2 OPTIONAL)
|
||
if (BUILD_OPEN_PROJECT)
|
||
install(FILES ${mc2_aclnn_master_headers} DESTINATION ${CMAKE_BINARY_DIR}/static_library_files/include/aclnnop OPTIONAL)
|
||
install(FILES ${mc2_aclnn_master_headers} DESTINATION ${CMAKE_BINARY_DIR}/static_library_files/include/aclnnop/level2 OPTIONAL)
|
||
endif()
|
||
endif()
|
||
|
||
# ascendc_impl_gen depends opbuild_custom_gen_aclnn_all, for opbuild will generate .ini
|
||
set(dependency_list)
|
||
if(TARGET opbuild_gen_aclnn)
|
||
list(APPEND dependency_list opbuild_gen_aclnn)
|
||
endif()
|
||
if(TARGET opbuild_gen_aclnnInner)
|
||
list(APPEND dependency_list opbuild_gen_aclnnInner)
|
||
endif()
|
||
if(TARGET opbuild_gen_aclnnExc)
|
||
list(APPEND dependency_list opbuild_gen_aclnnExc)
|
||
endif()
|
||
if(NOT dependency_list)
|
||
message(STATUS "no operator info to generate")
|
||
return()
|
||
endif()
|
||
add_custom_target(opbuild_custom_gen_aclnn_all)
|
||
add_dependencies(opbuild_custom_gen_aclnn_all ${dependency_list})
|
||
if(opbuild_out_srcs)
|
||
set_source_files_properties(${opbuild_out_srcs} PROPERTIES GENERATED TRUE)
|
||
add_library(opbuild_gen_aclnn_all OBJECT ${opbuild_out_srcs})
|
||
add_dependencies(
|
||
opbuild_gen_aclnn_all
|
||
opbuild_custom_gen_aclnn_all
|
||
)
|
||
target_include_directories(opbuild_gen_aclnn_all
|
||
PRIVATE
|
||
${OPAPI_INCLUDE}
|
||
)
|
||
endif()
|
||
endfunction()
|
||
|
||
function(merge_graph_headers)
|
||
set(oneValueArgs TARGET OUT_DIR)
|
||
cmake_parse_arguments(MGPROTO "" "${oneValueArgs}" "" ${ARGN})
|
||
get_target_property(proto_headers ${GRAPH_PLUGIN_NAME}_proto_headers INTERFACE_SOURCES)
|
||
|
||
add_custom_command(OUTPUT ${MGPROTO_OUT_DIR}/ops_proto_transformer.h
|
||
COMMAND ${ASCEND_PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/util/merge_proto.py
|
||
${proto_headers}
|
||
--output-file ${MGPROTO_OUT_DIR}/ops_proto_transformer.h
|
||
)
|
||
|
||
add_custom_command(
|
||
OUTPUT ${MGPROTO_OUT_DIR}/ops_proto_transformer.cpp
|
||
COMMAND ${CMAKE_COMMAND} -E copy
|
||
${MGPROTO_OUT_DIR}/ops_proto_transformer.h
|
||
${MGPROTO_OUT_DIR}/ops_proto_transformer.cpp
|
||
DEPENDS ${MGPROTO_OUT_DIR}/ops_proto_transformer.h
|
||
)
|
||
|
||
add_custom_target(${MGPROTO_TARGET} ALL
|
||
DEPENDS ${MGPROTO_OUT_DIR}/ops_proto_transformer.h ${MGPROTO_OUT_DIR}/ops_proto_transformer.cpp
|
||
)
|
||
endfunction()
|