昇腾社区首页
中文
注册
开发者
下载

算子工程编译拓展

使用msOpGen工具创建算子工程时,相关编译脚本被固化在本地,若需使用算子工程提供的新特性(比如支持MC2算子等),需重新运行msOpGen工具生成工程。为了解决开发者因功能更新而频繁重建工程的问题,将算子工程的cmake脚本打包到CANN软件包中。开发者可通过find_package的形式来查找对应的cmake modules包,从而使用算子工程对外提供的cmake函数接口。

该开发方式下,开发者参考如下工程目录,自行组织算子工程。目录结构与通过msOpGen生成的目录结构类似, 但无需再创建cmake与scripts目录,这些目录被打包置CANN软件包中。以AddCustom算子为例,目录结构如下:

AddCustom
├── CMakeLists.txt              // 算子工程顶层CMakeLists.txt
├── CMakePresets.json           // 编译配置项,cmake内置功能,若使能则需3.19及以上cmake版本
├── framework                   // AI框架适配时,算子插件实现文件目录
├── op_host                     // Host侧实现文件
│   ├── add_custom.cpp         // 算子原型注册、Shape推导、Tiling实现等内容文件
│   ├── add_custom_tiling.h    // 算子Tiling定义文件
│   └── CMakeLists.txt         // Host侧CMakeLists文件
├── op_kernel                   // Kernel侧实现文件
│   ├── Add
│   │   ├── add_custom.cpp    // 算子代码实现文件
└   └── CMakeLists.txt         // Kernel侧CMakeLists文件

CMakeLists.txt编写方法

  • 算子工程顶层CMakeLists.txt
    1. 使用find_package找到对应的编译库。
    2. 使用npu_op_package设置算子工程的编译产物形态,支持RUN/SHARED/STATIC, 分别对应算子run包形式、算子动态库形式与算子静态库形式,同时,该接口还可配置package(即编译产物)的内容和package的安装位置。
    3. 添加需要进行编译的子目录。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    cmake_minimum_required(VERSION 3.16.0)            # 指定所需的最低cmake版本号
    project(opp)
    # 1、使用find_package找到对应的编译库。
    # ${ASCEND_CANN_PACKAGE_PATH}为对应的CANN软件包路径,开发者可直接使用
    find_package(ASC REQUIRED HINTS ${ASCEND_CANN_PACKAGE_PATH}/compiler/tikcpp/ascendc_kernel_cmake)
    # 2、使用npu_op_package设置算子工程的编译产物形态。
    set(package_name ${vendor_name})
    npu_op_package(${package_name}                     # package name
                                                       # RUN模式下会使用该name命名算子部署后的目录,静态库模式下输出产物为lib${package_name}.a
        TYPE RUN                                       # 指定编译产物形态[RUN|STATIC|SHARED]
        CONFIG
            ENABLE_SOURCE_PACKAGE True                 # 是否将源码打包到run包中
            ENABLE_BINARY_PACKAGE True                 # 是否编译Kernel二进制, SHARED/STATIC模式下必须指定为True, 默认值为True
            INSTALL_PATH ${CMAKE_BINARY_DIR}/          # package的安装位置
    )
    #3、添加需要进行编译的子目录。
    if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/op_host)
        add_subdirectory(op_host)                      # 添加子目录op_host进行编译
    endif()
    if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/op_kernel)
        add_subdirectory(op_kernel)                    # 添加子目录op_kernel进行编译
    endif()
    
  • Host侧CMakeLists.txt
    1. 使用npu_op_code_gen生成aclnn单算子调用代码、入图所需的原型定义代码等。
    2. 单算子调用场景,使用npu_op_library编译aclnn单算子调用库。
    3. 算子入图场景,使用npu_op_library编译算子入图所需的算子原型库。
    4. 使用npu_op_library编译Tiling相关库。
    5. 使用npu_op_package_add添加上述Host侧库至对应package中。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} ops_srcs)
    #1、使用npu_op_code_gen生成aclnn单算子调用代码、入图所需的原型定义代码等。
    npu_op_code_gen(
         SRC ${ops_srcs}                                                           # Host侧实现文件集合
         PACKAGE ${package_name}                                                   # 与npu_op_package的package_name对应
         COMPILE_OPTIONS -g                                                        # 编译选项
         OUT_DIR ${ASCEND_AUTOGEN_PATH}                                            # 指定生成文件的保存路径
    )
    #2、单算子调用场景,使用npu_op_library编译aclnn单算子调用库。
    file(GLOB autogen_aclnn_src ${ASCEND_AUTOGEN_PATH}/aclnn_*.cpp)                # 将通过npu_op_code_gen生成的aclnn相关源文件添加至源文件列表中
                                                                                   
    set_source_files_properties(${autogen_aclnn_src} PROPERTIES GENERATED TRUE)    # 设置对应的文件属性为编译过程中生成的文件
    npu_op_library(cust_opapi ACLNN                                                # 指定library名称与类型以及参与编译的源文件
         ${autogen_aclnn_src}
    )
    target_compile_options(cust_opapi PRIVATE                                      # 为对应library添加编译选项与通用的cmake语法一致
         -fvisibility=hidden
    )
    
    #3、算子入图场景,使用npu_op_library编译算子入图所需的算子原型库。
    file(GLOB proto_src ${ASCEND_AUTOGEN_PATH}/op_proto.cc)                        # 将通过npu_op_code_gen生成的原型定义相关源文件添加至源文件列表中
    set_source_files_properties(${proto_src} PROPERTIES GENERATED TRUE)            # 设置对应的文件属性为编译过程中生成的文件
    npu_op_library(cust_op_proto GRAPH                                             # 指定library名称与类型以及参与编译的源文件
         ${ops_srcs}
         ${proto_src}
    )
    target_compile_options(cust_op_proto PRIVATE                                   # 为对应library添加编译选项与通用的cmake语法一致
         -fvisibility=hidden
    )
    
    #4、使用npu_op_library编译Tiling相关库。
    file(GLOB fallback_src ${ASCEND_AUTOGEN_PATH}/fallback_*.cpp)                  # 将通过npu_op_code_gen生成的Tiling相关源文件添加至源文件列表中
                                                                                   # 若算子配置了EnableFallBack会生成该文件
    set_source_files_properties(${fallback_src} PROPERTIES GENERATED TRUE)         # 设置对应的文件属性为编译过程中生成的文件
    npu_op_library(cust_optiling  TILING                                           # 指定library名称与类型以及参与编译的源文件
         ${ops_srcs}
         ${fallback_src}
    )
    target_compile_options(cust_optiling PRIVATE                                   # 为对应library添加编译选项与通用的cmake语法一致
         -fvisibility=hidden
    )
    
    #5、使用npu_op_package_add添加上述Host侧库到对应package中。
    npu_op_package_add(${package_name}                                             # 与npu_op_package的package_name对应
         LIBRARY                                                                   # 添加Host侧相关librarylibrary名称与前述步骤的library名称对应 
              cust_optiling
              cust_opapi
              cust_op_proto
    )
    
  • Kernel侧CMakeList.txt
    1. 使用npu_op_kernel_options添加算子编译选项。支持的编译选项可参考编译选项
    2. 使用npu_op_kernel_sources指定算子特定目录与编译源文件。
      • 若算子的源码文件没有平铺在SRC_BASE目录(通过npu_op_kernel_library设置)下,可以通过KERNEL_DIR指定特定目录
      • 若算子的Kernel实现cpp文件需要自定义命名,需同时指定OP_TYPE(算子类型)和KERNEL_FILE(Kernel实现cpp文件名),以配置两者之间的对应关系。不配置时,Kernel实现cpp文件名和OpType之间需满足转换规则
    3. 使用npu_op_kernel_library编译Kernel库。
    4. 使用npu_op_package_add添加上述Kernel侧库到对应package中。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #1、使用npu_op_kernel_options添加算子编译选项。
    npu_op_kernel_options(ascendc_kernels ALL OPTIONS --save-temp-files -g)# 为算子添加编译选项
    
    #2、使用npu_op_kernel_sources指定算子特定目录与编译源文件。
    npu_op_kernel_sources(ascendc_kernels                                  # 对应的Kernel库名称与npu_op_kernel_library保持一致
        OP_TYPE AddCustom                                                  # 若算子的Kernel实现cpp文件需要自定义命名需配置算子类型
        KERNEL_DIR ./Add                                                   # 将KERNEL_DIR目录与SRC_BASE目录进行拼接作为Kernel实现cpp文件所在的目录
        COMPUTE_UNIT Ascendxxxyy                                           # 设置KERNEL_FILE在Ascendxxxyy型号生效
        KERNEL_FILE add_custom.cpp                                         # 若算子的Kernel实现cpp文件需要自定义命名需配置Kernel实现cpp文件名
    )
    
    #3、使用npu_op_kernel_library编译Kernel库。
    npu_op_kernel_library(ascendc_kernels                                  # Kernel库名称
        SRC_BASE ${CMAKE_SOURCE_DIR}/op_kernel/                            # 指定kernel侧源码的根目录
        TILING_LIBRARY cust_optiling                                       # 指定依赖的Tiling库
    )
    #4、添加kernel侧library到package
    npu_op_package_add(${package_name}                                     # 与npu_op_package的package_name对应
        LIBRARY ascendc_kernels                                            # 添加Kernel侧相关librarylibrary名称与前述步骤的library名称对应
    )
    

编译环境选项说明

下表列出了供用户配置和使用的编译环境选项:

  • 暂不支持设置Release、Debug版本相关选项。
  • 暂不支持交叉编译相关选项。
表1 编译环境选项

类型

环境选项

默认值

说明

STRING

vendor_name

customize

标识自定义算子所属厂商的名称。建议开发者自行指定所属厂商名称,避免和其他厂商提供的算子包冲突。

STRING

ASCEND_COMPUTE_UNIT

-

昇腾AI处理器型号。编译对应型号的package。

PATH

ASCEND_AUTOGEN_PATH

<CMAKE_BINARY_DIR>/autogen

通过npu_op_code_gen生成的aclnn单算调用、入图所需算子原型库等源文件存放路径。

BOOL

ENABLE_SOURCE_PACKAGE

TRUE

是否开启源码编译。

如果使用npu_op_package配置了源码和二进制编译相关配置,npu_op_package配置的优先级更高。

BOOL

ENABLE_BINARY_PACKAGE

TRUE

是否开启二进制编译。

package的类型配置为SHARED或STATIC时,必须指定为TRUE。

如果使用npu_op_package配置了源码和二进制编译相关配置,npu_op_package配置的优先级更高。

PATH

ASCEND_CANN_PACKAGE_PATH

-

CANN软件包路径,默认情况下用户无需配置。开发者可以在编写cmake文件时直接使用。

路径示例如下:/usr/local/Ascend/ascend-toolkit/latest。

上述编译环境选项可通过两种方式进行配置:

  • 支持直接通过set命令进行设置。
    # CMakeLists.txt直接使用
    set(vendor_name "customize")
    set(ASCEND_COMPUTE_UNIT "ascendxxxyy")
  • 通过CMakePresets.json进行设置,若通过该方式设置,则需要安装3.19及以上的cmake。
    {
        "version": 1,
        "cmakeMinimumRequired": {
            "major": 3,
            "minor": 19,
            "patch": 0
        },
        "configurePresets": [
            {
                "name": "default",
                "displayName": "Default Config",
                "description": "Default build using Unix Makefiles generator",
                "generator": "Unix Makefiles",
                "binaryDir": "${sourceDir}/build_out",
                "cacheVariables": {
                    "ASCEND_COMPUTE_UNIT": {
                        "type": "STRING",
                        "value": "ascendxxxyy"
                    },
                    "vendor_name": {
                        "type": "STRING",
                        "value": "customize"
                    }
                }
            }
        ]
    }

    然后使用如下命令进行构建,根据--preset指定的preset进行编译

    // Shell环境中cmake构建编译
    cmake -S . -B build_out --preset=default // 在当前目录(.)中寻找CMakePresets.json

编译命令说明

package的类型配置为RUN时,可参考如下编译命令进行编译,使用cmake的pack能力生成run包。

1
2
3
4
5
6
# 工程根目录下执行
mkdir -p build_out
rm -rf build_out/*
cmake -S . -B build_out --preset=default
cmake --build build_out --target binary -j${nproc}
cmake --build build_out --target package -j${nproc}

package的类型配置为SHARED或STATIC时,可参考如下编译命令进行编译:

1
2
3
4
5
6
# 工程根目录下执行
mkdir -p build_out
rm -rf build_out/*
cmake -S . -B build_out --preset=default
cmake --build build_out --target binary -j${nproc}
cmake --build build_out --target install -j${nproc}

cmake函数说明

提供如下cmake函数供开发者使用:

类型

接口

功能

package

npu_op_package

创建一个package。

npu_op_package_add

将目标或文件添加到package中。

library

npu_op_library

创建Host侧库。

npu_op_kernel_library

创建Kernel侧库。

npu_op_kernel_options

添加Kernel目标编译选项。

npu_op_kernel_sources

描述Kernel目标的源码信息。

npu_op_device_tiling_library

创建Device侧Tiling库。

其他

npu_op_code_gen

执行代码生成过程,生成aclnn单算子调用代码和入图所需的原型定义代码。

  1. npu_op_package

    创建一个package。

    npu_op_package(<package_name> TYPE <type> [CONFIG] [ENABLE_SOURCE_PKG <value>] [ENABLE_BINARY_PACKAGE <value>] [INSTALL_PATH <path>])
    参数说明如下:
    • <package_name>:必选,package的名称。
    • TYPE <type>:必选,package的类型,取值为RUN、SHARED、STATIC。分别对应算子run包形式、算子动态库形式与算子静态库形式。
    • [CONFIG]:可选,用于配置package的内容和安装位置。
      • [ENABLE_SOURCE_PKG <value>]:可选,是否将源码打包到package中,默认为True。
      • [ENABLE_BINARY_PACKAGE <value>] :可选,是否将二进制文件打包到package中,默认为True。
      • [INSTALL_PATH <path>]):可选,指定包的安装路径,默认为CMAKE_BINARY_DIR。
  2. npu_op_package_add

    将目标或文件添加到package中。

    # 添加目标
    npu_op_package_add(<package_name> LIBRARY <target_name1> [<target_name2>...] ) 
    # 添加文件,仅给run包模式使用
    npu_op_package_add(<package_name> FILES <file_name1> [<file_name2>...] [TYPE <target_type>] [PACKAGE_PATH <pkg_path>])

    参数说明如下:

    • <package_name>:必选,package的名称。
    • LIBRARY:必选,指定需要添加到package中的目标名称。
      • <target_name1> [<target_name2>...]:必选,目标名称列表。
    • FILES:必选,指定需要添加到package中的文件名称。
      • <file_name1> [<file_name2>...]:必选,文件名称列表。
    • [TYPE <target_type>]:可选,指定文件类型,将文件安装到对应的目录中,取值为ACLNN、GRAPH。配置为ACLNN,会将文件打包至run包目录下aclnn单算子调用头文件所在目录,配置为GRAPH,会将文件打包至run包目录下入图原型定义头文件目录下。
    • [PACKAGE_PATH <pkg_path>]:可选,指定文件在包中的相对路径位置。TYPE和PACKAGE_PATH参数互斥,即只能选择其中一个进行配置。
  3. npu_op_library

    创建Host侧库。

    npu_op_library(<library_name> TYPE <library_type> <files>) 

    参数说明如下:

    • <library_name>:必选,Host侧库的名称。
    • TYPE <library_type>:必选,Host库的类型,可选值为TILING、ACLNN、GRAPH、TF_PLUGIN。
      • TILING,Tiling相关库。
      • ACLNN,aclnn单算子调用库。
      • GRAPH,算子入图所需的算子原型库。
      • TF_PLUGIN,TensorFlow框架适配相关库。
    • <files>:必选,设置参与编译的源文件。
  4. npu_op_kernel_library

    创建Kernel侧库。

    npu_op_kernel_library(<target_name> SRC_BASE <path> TILING_LIBRARY <tiling_target>) 

    参数说明如下:

    • <target_name>:必选,目标的名称。
    • SRC_BASE <path>:必选,指定Kernel源码的base目录,要求配置绝对路径。比如示例中的op_kernel目录的绝对路径。
    • TILING_LIBRARY <tiling_target>:必选,指定依赖的Tiling目标。
  5. npu_op_kernel_options
    添加Kernel目标编译选项。
    npu_op_kernel_options(<target_name> <op_type> [COMPUTE_UNIT <soc_version>] OPTIONS …) 

    参数说明如下:

    • <target_name>:必选,目标的名称。
    • <op_type>:必选,定义配置生效的范围,取值为ALL、OP_TYPE。ALL表示对所有算子生效,OP_TYPE表示对特定算子生效。
    • [COMPUTE_UNIT <soc_version>]:可选,用于设置算子在具体AI处理器型号上的编译选项,不填写该选项时默认对所有型号生效。

      <soc_version>具体配置如下:

      • 针对如下产品型号:在安装昇腾AI处理器的服务器执行npu-smi info命令进行查询,获取Name信息。实际配置值为AscendName,例如Name取值为xxxyy,实际配置值为Ascendxxxyy

        Atlas A2 训练系列产品/Atlas 800I A2 推理产品/A200I A2 Box 异构组件

        Atlas 200I/500 A2 推理产品

        Atlas 推理系列产品

        Atlas 训练系列产品

      • 针对如下产品型号,在安装昇腾AI处理器的服务器执行npu-smi info -t board -i id -c chip_id命令进行查询,获取Chip NameNPU Name信息,实际配置值为Chip Name_NPU Name。例如Chip Name取值为AscendxxxNPU Name取值为1234,实际配置值为Ascendxxx_1234。其中:
        • id:设备id,通过npu-smi info -l命令查出的NPU ID即为设备id。
        • chip_id:芯片id,通过npu-smi info -m命令查出的Chip ID即为芯片id。

        Atlas A3 训练系列产品/Atlas A3 推理系列产品

    • OPTION...: 必选,传递给编译器的编译选项。
  6. npu_op_kernel_sources

    描述Kernel目标的源码信息,包括设置算子的Kernel实现文件和源码路径等。

    npu_op_kernel_sources(<target_name> [OP_TYPE <op_type>] [KERNEL_DIR <path>] [COMPUTE_UNIT <soc_version>] [KERNEL_FILE <file>]) 

    参数说明如下:

    • <target_name>:必选,目标的名称。
    • [OP_TYPE <op_type>]:可选,算子类型,必须与KERNEL_FILE同时存在。
    • [KERNEL_DIR <path>]:可选,指定Kernel源码相对于SRC_BASE的相对路径。

      若算子的源码文件没有平铺在SRC_BASE目录(通过npu_op_kernel_library设置)下,可以通过KERNEL_DIR指定特定目录

    • [COMPUTE_UNIT <soc_version>] :可选,设置KERNEL_FILE在<soc_version>型号生效。默认KERNEL_FILE对所有型号生效。
    • [KERNEL_FILE <file>]:可选,指定算子入口的Kernel实现文件名。

      若算子的Kernel实现cpp文件需要自定义命名,需同时指定OP_TYPE(算子类型)和KERNEL_FILE(Kernel实现cpp文件名),以配置两者之间的对应关系。不配置时,Kernel实现cpp文件名和OpType之间需满足转换规则

  7. npu_op_device_tiling_library

    创建Device侧Tiling库。使用该选项时,package的类型仅支持配置为RUN(run包模式)。

    npu_op_device_tiling_library(<target_name> <type> <files>) 

    参数说明如下:

    • <target_name>:必选,目标的名称。
    • <type>:必选,指定Tiling产物的类型。支持取值为SHARED、STATIC。
    • <files>:必选,指定Tiling源码文件。
  8. npu_op_code_gen

    执行代码生成过程,生成aclnn单算子调用代码和入图所需的原型定义代码。

    npu_op_code_gen(SRC <src_files> OUT_DIR <output_dir> PACKAGE <pkg_name> [COMPILE_OPTIONS ...] 

    参数说明如下:

    • SRC <src_files>:必选,参与代码生成的源文件范围。
    • OUT_DIR <output_dir>:必选,生成代码的输出路径。
    • PACKAGE <pkg_name>:必选,指定生成代码的package名称。
    • [COMPILE_OPTIONS ...]:可选,自定义编译过程中的编译选项。