当前位置: 首页 > news >正文

昇腾CANN cmake:CANN 项目的 CMake 构建模块实战

从 ops-nn 到 cann-recipes-*,几乎所有 CANN 开源仓库都用 CMake 做构建系统。cann-cmake 仓库提供一套标准的 CMake 模块——FindCANN.cmake(找到 CANN 安装路径)、AscendCCore.cmake(Ascend C 编译规则)、AscendKernel.cmake(kernel 编译和链接)——让开发者的 CMakeLists.txt 从 200 行缩减到 20 行。

FindCANN.cmake:自动发现 CANN 安装

传统做法是手动设ASCEND_HOME_PATH环境变量,CMake 脚本里写死路径。cann-cmake 的 FindCANN 自动发现。

# CMakeLists.txt(最少配置) cmake_minimum_required(VERSION 3.16) project(my_ascend_op LANGUAGES CXX) # 引入 CANN CMake 模块 list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") include(FindCANN) # FindCANN 自动做了这些事: # 1. 搜索 $ASCEND_HOME_PATH 环境变量(用户自定义) # 2. 搜索 /usr/local/Ascend(默认安装路径) # 3. 设置 CANN_INCLUDE_DIRS(头文件路径) # 4. 设置 CANN_LIBRARIES(库文件路径) # 5. 检查 CANN 版本(通过 version.txt) # 6. 如果找不到 → 报错 + 提示安装 message(STATUS "CANN version: ${CANN_VERSION}") message(STATUS "CANN include: ${CANN_INCLUDE_DIRS}") message(STATUS "CANN libs: ${CANN_LIBRARIES}") # 版本检查(有些特性只在 8.0+ 可用) if(CANN_VERSION VERSION_LESS "8.0.0") message(FATAL_ERROR "CANN 8.0+ required (flash attention and MC2)") endif()

FindCANN 内部逻辑:

# FindCANN.cmake 核心实现 # 搜索优先级:$ASCEND_HOME_PATH > /usr/local/Ascend > pkg-config find_path(CANN_ROOT_DIR NAMES version.cfg PATHS $ENV{ASCEND_HOME_PATH} /usr/local/Ascend /opt/Ascend PATH_SUFFIXES ascend-toolkit/latest ascend-toolkit/8.0.0 ) if(NOT CANN_ROOT_DIR) message(FATAL_ERROR "CANN not found. Install CANN toolkit or set ASCEND_HOME_PATH.\n" "Download: https://www.hiascend.com/software/cann") endif() # 提取版本信息 file(READ "${CANN_ROOT_DIR}/version.cfg" CANN_VER_STR) string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" CANN_VERSION "${CANN_VER_STR}") # 自动找到子目录 set(CANN_INCLUDE_DIRS "${CANN_ROOT_DIR}/include" "${CANN_ROOT_DIR}/include/ascendc" "${CANN_ROOT_DIR}/opp/built-in/op_proto/custom" # 算子原型 ) set(CANN_LIBRARIES "${CANN_ROOT_DIR}/lib64/libascendcl.so" "${CANN_ROOT_DIR}/lib64/libge_executor.so" "${CANN_ROOT_DIR}/lib64/libascend_hal.so" ) find_package_handle_standard_args(CANN REQUIRED_VARS CANN_ROOT_DIR CANN_INCLUDE_DIRS CANN_LIBRARIES VERSION_VAR CANN_VERSION )

AscendCCore.cmake:Ascend C 源代码编译

Ascend C 的 kernel 代码(.cpp 文件,且内部用 Ascend C API)需要 TIKC 编译器编译,不是普通的 C++ 编译器。AscendCCore 封装了 tikcc 的调用规则。

# 引入 Ascend C 编译规则 include(AscendCCore) # 定义 Ascend C kernel 源文件 ascendc_add_library(my_ops STATIC kernels/matmul_tiling.cpp kernels/softmax_fusion.cpp kernels/gelu_activation.cpp LINK_LIBRARIES ${CANN_LIBRARIES} COMPILE_OPTIONS -DBLOCK_DIM=32 -DMATMUL_TILE_M=16 -DMATMUL_TILE_N=16 ) # ascendc_add_library 的底层操作: # 1. 用 tikcc(TIK 编译器)把 .cpp → .o(Ascend C → 二进制) # 2. 设置正确的目标架构(--soc-version=ascend910) # 3. 链接 runtime 和 driver 库 # 4. 生成适用于动态加载的 .so # 等价的手动命令(ascendc_add_library 内部执行) # tikcc kernels/matmul_tiling.cpp \ # --target=ascend910 \ # --opt-level=3 \ # -I${CANN_INCLUDE_DIRS} \ # -c -o matmul_tiling.o

关键:tikcc是 CANN 的 Ascend C 编译器。它和 GCC 是不同的工具链——GCC 编译的是给 CPU 执行的代码,tikcc 编译的是给 NPU 执行的代码。ascendc_add_library自动选择正确的编译器。

AscendKernel.cmake:多架构 kernel 编译

同一份 Ascend C 代码在不同 NPU 架构上需要不同的编译优化——Ascend 910 (达芬奇) 和 Ascend 950DT (下一代) 的 L1 缓存大小不同,tile 大小也不同。AscendKernel 支持多架构编译。

include(AscendKernel) # 为多架构编译 kernel ascend_multi_arch_kernel(my_ops_kernel SOURCES kernels/matmul.cpp ARCHITECTURES ascend910 ascend950 # 可选:下一代架构编译 COMPILE_FLAGS_ascend910 -DL1_CACHE_SIZE=32KB -DTILE_M=16 COMPILE_FLAGS_ascend950 -DL1_CACHE_SIZE=64KB # 更大的 L1 → 更大的 tile -DTILE_M=32 ) # 生成的文件结构: # build/ # ├── ascend910/ # │ └── my_ops_kernel.so (Architecture 910 optimized) # ├── ascend950/ # │ └── my_ops_kernel.so (Architecture 950 optimized) # └── generic/ # └── my_ops_kernel.so (通用实现,动态选择)

运行时自动选择对应架构的 kernel:

// CANN runtime 自动选择对应硬件架构的 .so// 不需要手动判断 NPU 型号auto*kernel=AscendRuntime::LoadKernel("my_ops_kernel");// runtime 内部:// if (npu_arch == "Ascend910") → load ascend910/my_ops_kernel.so// if (npu_arch == "Ascend950") → load ascend950/my_ops_kernel.so

ops-proto 自动生成

CANN 的算子库都有ops-proto目录——算子的 Protobuf 定义(输入输出描述)。cmake 仓库提供了 Protobuf 编译规则。

# 自动生成算子 Proto,不需要手动编译 include(AscendOpsProto) ascend_ops_proto_generate(MY_OPS PROTO_FILES ops-proto/matmul.proto ops-proto/softmax.proto ops-proto/gelu.proto OUTPUT_DIR ${CMAKE_BINARY_DIR}/generated ) # 生成的 C++ 文件: # generated/matmul.pb.h ← 包含 MatMulOp 的 Protobuf 结构 # generated/matmul.pb.cc # generated/softmax.pb.h # ... # 链接到最终的 .so target_link_libraries(my_ops PRIVATE MY_OPS_PROTO)

算子的 Proto 定义包含输入输出 tensor 的类型和形状信息——ge(图引擎)用这些信息做图优化。

完整项目的 CMakeLists.txt

组合 FindCANN + AscendCCore + AscendKernel + AscendOpsProto 四件套:

cmake_minimum_required(VERSION 3.16) project(ascend-ops-project VERSION 1.0.0 LANGUAGES CXX) # 引入 CANN CMake 模块(从 cann-cmake 仓库) list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/cann-cmake") include(FindCANN) include(AscendCCore) include(AscendKernel) include(AscendOpsProto) # 版本检查 if(CANN_VERSION VERSION_LESS "8.0.0") message(FATAL_ERROR "CANN 8.0+ required") endif() # 算子 Proto 生成 ascend_ops_proto_generate(OPS_PROTO PROTO_FILES ${CMAKE_CURRENT_SOURCE_DIR}/ops-proto/*.proto OUTPUT_DIR ${CMAKE_BINARY_DIR}/generated/proto ) # Ascend C kernel 编译 ascendc_add_library(ops_kernels STATIC ${CMAKE_CURRENT_SOURCE_DIR}/kernels/*.cpp COMPILE_OPTIONS -DBLOCK_DIM=32 LINK_LIBRARIES OPS_PROTO ${CANN_LIBRARIES} ) # 多架构编译 ascend_multi_arch_kernel(ops_kernels_opt SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/kernels/matmul_tuned.cpp ARCHITECTURES ascend910 ascend950DT # Atlas A2 服务器 ) # 最终产物 add_executable(ops_test test/main.cpp) target_link_libraries(ops_test PRIVATE ops_kernels ops_kernels_opt)

踩坑一:FindCANN 在新版安装路径下的版本文件路径

CANN 8.5 的安装路径变了:旧版/usr/local/Ascend/ascend-toolkit/8.0.0/version.cfg,新版/usr/local/Ascend/ascend-toolkit/latest/version.cfg。FindCANN.cmake 如果只搜固定路径,在新版 CANN 上会搜不到。

修复:在 FindCANN.cmake 里同时搜索*/latest/*/8.x.x/

# 同时搜索 latest 和带版本号的路径 find_path(CANN_ROOT_DIR NAMES version.cfg PATHS "${ASCEND_HOME}/ascend-toolkit/latest" "${ASCEND_HOME}/ascend-toolkit/8.5.0" "${ASCEND_HOME}/ascend-toolkit/8.0.0" "${ASCEND_HOME}/ascend-toolkit" DOC "Root directory of CANN toolkit" )

踩坑二:Ascend C 编译的预处理器宏不展开

ascendc_add_libraryCOMPILE_OPTIONS-D传递编译时参数。但-DTILE_M=16在 tikcc 里是TILE_M=16——tikcc 的预处理宏有特殊语法(不能和 GCC 混用)。

错误

ascendc_add_library(my_ops STATIC kernels/matmul.cpp COMPILE_OPTIONS -DTILE_M=16 -DTILE_N=16 # GCC 风格的预定义宏 )

tikcc 不接受空格式的-D——报unknown compiler flag

正确

ascendc_add_library(my_ops STATIC kernels/matmul.cpp COMPILE_DEFINITIONS TILE_M=16 TILE_N=16 # ascenc_add_library 内部会根据这些 DEFINITIONS 生成 tikcc 风格的 # --define=TILE_M=16 --define=TILE_N=16 )

踩坑三:Protobuf 编译依赖遗漏

ascend_ops_proto_generate自动生成的.pb.cc文件需要链接 Protobuf 运行时库。但默认不链接——因为假设系统中已经全局安装了 libprotobuf。

修复:在 CMakeLists.txt 里显式加find_package(Protobuf)

find_package(Protobuf REQUIRED) ascend_ops_proto_generate(OPS_PROTO PROTO_FILES ${CMAKE_CURRENT_SOURCE_DIR}/ops-proto/*.proto OUTPUT_DIR ${CMAKE_BINARY_DIR}/generated/proto ) target_link_libraries(ops_kernels PRIVATE OPS_PROTO protobuf::libprotobuf # ← 必须显式链接 ${CANN_LIBRARIES} )

如果不加protobuf::libprotobuf,链接时会报undefined reference to google::protobuf::...


cann-cmake 的价值不在复杂的构建逻辑——在于标准化。所有 CANN 开源仓库用同一套 CMake 模块(FindCANN + AscendCCore + AscendOpProto),开发者的 CMakeLists.txt 写 20 行就够。对着镜像的 CANN 版本找不同的 FindCANN 路径——标准化消除了这些重复劳动。

http://www.jsqmd.com/news/874331/

相关文章:

  • 使用SenseNova-U1开源模型生图新体验
  • 分享beat.ly ai换脸 换装 解锁会员版
  • 奇迹MU 荣耀出征官网下载:成长系统完善,荣耀稳步进阶!
  • 2026年5月更新:安徽市场优选,深度解析河北腾森环保设备有限公司的乙烯基酯树脂玻璃钢隔膜架实力 - 2026年企业推荐榜
  • 如何在Mac上实现NTFS完美读写:Free NTFS for Mac终极指南
  • 从SaTC 2.0报告看安全可信计算:硬件、AI与密码学的范式转移与工程实践
  • 昇腾CANN skills:社区技能与开发工具集的实战解读
  • 2026靠谱耐火砖厂家推荐榜:耐火砖厂家联系方式、耐火砖厂家联系电话、耐火砖哪家好、耐火砖采购、附近建筑砖厂、附近的耐火砖厂选择指南 - 优质品牌商家
  • 华硕笔记本性能优化终极指南:3步告别Armoury Crate臃肿,G-Helper轻量控制方案
  • 计算机视觉模型公平性优化:如何规避帕累托低效陷阱
  • 我的世界服务器官网源码1.0正式发布!
  • 荣耀出征官方下载地址|装备绑定与非绑定决策分析
  • Unity Device Simulator:深度解析UI适配调试核心机制
  • 2026矿山冶金场景加固笔记本深度评测报告:工业加固计算机/工业平板电脑/工控机/无人机地面站加固计算机/防爆计算机/选择指南 - 优质品牌商家
  • 商业AI公司与国防部合作:吸引力、障碍与深层博弈
  • Ubuntu下安装PostgreSQL的三种方式
  • 图像增强与半监督学习在语义分割中的应用
  • 【电子通识】贴片电阻上的丝印332、5R6、1502、01C怎么读出阻值?
  • Android HTTPS抓包全解:从Charles配置到证书固定绕过
  • boss app sig/sp/响应体 unidbg分析
  • 长沙全屋定制厂家排行:5家实力品牌实测盘点 - 互联网科技品牌测评
  • Midjourney颗粒度失控急救包:1键降噪工作流(含自研NoiseMap可视化插件+Discord私密调试频道入口)
  • 2026年5月更新:长治家装品牌深度解析,为何尚游欧派装饰备受青睐? - 2026年企业推荐榜
  • Keil C51中RTX51 Tiny任务列表显示异常的解决方案
  • 荣耀出征官方网站|装备分解与回收收益对比
  • 五轴联动机床:什么叫真正做出来了,什么叫组装贴牌
  • 【Midjourney饱和度调控黄金法则】:20年AI视觉调校专家亲授3类典型过曝/灰暗场景的7步精准校正流程
  • 2026年当下,安平县配电箱防护棚产业格局与核心企业深度解析 - 2026年企业推荐榜
  • AxonHub 轻量部署实录[1]-安装篇
  • AI量化交易中的信号相关性与认知依赖:系统性风险与应对策略