
CANN ascend-transformer-boost SliceOperation 切片算子 C Demo 实战指南【免费下载链接】ascend-transformer-boost本项目是CANN提供的是一款高效、可靠的Transformer加速库基于华为Ascend AI处理器提供Transformer定制化场景的高性能融合算子。项目地址: https://gitcode.com/cann/ascend-transformer-boost导读SliceOperation 是 CANN ascend-transformer-boost 加速库提供的切片算子用于从输入张量的指定起始位置提取指定大小的子张量。本文以仓库中的 SliceOperation C Demo 为骨架完整讲解环境准备、编译运行步骤、C 调用代码逐段剖析并结合 SliceParam 参数定义、算子实现 与 Python 精度用例 等仓库源码说明参数语义、校验规则与底层 Runner 调度原理。读完本文你将能独立编译运行该 Demo并在此基础上编写自己的 SliceOperation 调用程序。目录Demo 概览目录结构与文件说明环境准备source 两个 set_env.sh编译与运行build.sh 与 cxx_abi 匹配规则源码逐段剖析从建 Context 到 Execute 的完整调用链SliceParam 参数语义与源码级校验规则底层 Runner 调度Ops 图执行与 aclnn 两套后端与 Python 精度用例的对应关系常见问题与排查建议1. Demo 概览目录结构与文件说明example/op_demo/slice 目录下共包含 3 个文件文件作用slice_demo.cppSliceOperation 的 C 调用主程序演示从环境初始化、创建算子、准备输入输出张量到执行与资源释放的完整流程README.md中文使用说明README_en.md英文使用说明即本文依托的原始文档其中slice_demo.cpp引入了同级的工具头文件 example/op_demo/demo_util.h其中提供了CreateTensor、CreateTensorFromVector、CHECK_STATUS等通用辅助函数用于封装 ACL 张量创建与错误码检查是整个 op_demo 系列示例共用的基础设施。该 Demo 演示的典型场景是对一个3×6的 float32 张量执行offsets{1,2}、size{2,4}的切片得到2×4的输出。这也是 Transformer 推理中常见的从中间位置截取一段数据操作的直观示例。2. 环境准备source 两个 set_env.sh运行该 Demo 前需要完成 CANN 工具链与 NNAL 加速库两个软件包的环境变量加载原始 README 给出了两条命令# 1. 加载 CANN 工具包环境默认安装路径 source /usr/local/Ascend/ascend-toolkit/set_env.sh # 2. 加载 NNALATB加速库环境默认安装路径 source /usr/local/Ascend/nnal/atb/set_env.sh针对使用加速库源码的场景README 特别说明如果使用加速库源码自行编译应改为 source 编译产物目录下的环境脚本source ./ascend-transformer-boost/output/atb/set_env.sh也就是说output/atb/set_env.sh 对应的产物路径由安装包nnal/atb/set_env.sh与源码编译产物output/atb/set_env.sh二选一具体取决于你使用的是预编译安装包还是源码构建。加载这两个脚本的目的是让编译链接时能找到 ATB 头文件与库文件、运行时能加载算子实现与设备侧资源。3. 编译与运行build.sh 与 cxx_abi 匹配规则环境就绪后在example/op_demo/slice目录下执行bash build.shREADME 特别强调了一个关键编译细节cxx_abi 必须与编译库时使用的 ABI 保持一致。使用cxx_abi0默认时编译命令需显式指定D_GLIBCXX_USE_CXX11_ABI0g -D_GLIBCXX_USE_CXX11_ABI0 -I ...使用cxx_abi1时改为g -D_GLIBCXX_USE_CXX11_ABI1 -I ..._GLIBCXX_USE_CXX11_ABI决定 libstdc 的std::string等标准库类型采用旧版cxx_abi0还是新版cxx_abi1二进制布局。ATB 对外头文件大量使用SVector、std::string等标准库类型若 Demo 的 ABI 设置与加速库编译时不一致链接阶段会出现符号找不到或运行时内存布局错乱的问题。因此务必先确认加速库构建时的 cxx_abi 选项再设置相同的宏。4. 源码逐段剖析从建 Context 到 Execute 的完整调用链slice_demo.cpp 的main函数完整展示了 ATB 算子调用六步法这是所有 op_demo 示例通用的编程范式。4.1 初始化 ACL 与创建 ContextCHECK_STATUS(aclInit(nullptr)); int32_t deviceId 0; CHECK_STATUS(aclrtSetDevice(deviceId)); atb::Context *context nullptr; CHECK_STATUS(atb::CreateContext(context)); void *stream nullptr; CHECK_STATUS(aclrtCreateStream(stream)); CHECK_STATUS(context-SetExecuteStream(stream));aclInit初始化 ACL 运行时aclrtSetDevice(0)指定使用 0 号 NPU 设备atb::CreateContext创建 ATB 上下文所有算子执行都绑定在该上下文上创建 ACL stream 后通过SetExecuteStream将其设置进 ATB Context后续算子任务将提交到该 stream 上执行。4.2 准备输入张量uint32_t dim0 3; uint32_t dim1 6; std::vectorfloat tensorzero{1, 2, ..., 18}; atb::Tensor tensorZero; CHECK_STATUS(CreateTensorFromVector(contextPtr, stream, tensorzero, ACL_FLOAT, aclFormat::ACL_FORMAT_ND, {dim0, dim1}, tensorZero)); inTensors {tensorZero};这里通过demo_util.h中的CreateTensorFromVector辅助函数把 18 个 float 数据组织为形状{3, 6}、ACL_FORMAT_ND格式的 device 侧张量并按序放入atb::VariantPack的inTensors。4.3 创建 SliceOperation 并设置参数atb::infer::SliceParam sliceParam; sliceParam.offsets {1, 2}; sliceParam.size {2, 4}; return atb::CreateOperation(sliceParam, op);atb::CreateOperation是模板函数针对infer::SliceParam有专门的特化实现见 slice_operation.cpp。特化实现会先做OP_PARAM_RSV_CHECK校验预留字段再根据平台类型判断是否加载 aclnn 接口Ascend 950 平台需要最后new出SliceOperation对象。这也说明CreateOperation返回的是堆上新建的算子实例后续必须用DestroyOperation释放。4.4 创建输出张量并组装 VariantPackatb::Tensor tensorOut; CHECK_STATUS(CreateTensor(ACL_FLOAT, aclFormat::ACL_FORMAT_ND, {2, 4}, tensorOut)); variantPack.outTensors.push_back(tensorOut);输出张量的形状{2, 4}必须与切片结果形状严格一致——offsets{1,2}、size{2,4}在3×6输入上恰好切出2×4。如果输出形状与参数推导结果不符SetupCheckImpl会返回ERROR_INVALID_TENSOR_DIM见下文第 5 节。4.5 Setup 计算 workspace 并 Execute 执行uint64_t workspaceSize 0; CHECK_STATUS(op-Setup(variantPack, workspaceSize, context)); uint8_t *workspacePtr nullptr; if (workspaceSize 0) { CHECK_STATUS(aclrtMalloc((void **)(workspacePtr), workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST)); } CHECK_STATUS(op-Execute(variantPack, workspacePtr, workspaceSize, context)); CHECK_STATUS(aclrtSynchronizeStream(stream));这是 ATB 算子执行的标准三段式Setup完成 shape 推导、参数校验、选择 Runner 并准备算子依赖如 Kernel 缓存、tiling buffer输出所需的 workspace 大小分配 workspace按 Setup 返回的大小用aclrtMalloc申请设备内存ACL_MEM_MALLOC_HUGE_FIRST优先分配大页内存Execute提交算子计算任务随后aclrtSynchronizeStream同步等待 device 侧任务完成。4.6 资源释放for (atb::Tensor inTensor : variantPack.inTensors) { CHECK_STATUS(aclrtFree(inTensor.deviceData)); } if (workspaceSize 0) { CHECK_STATUS(aclrtFree(workspacePtr)); } CHECK_STATUS(atb::DestroyOperation(op)); CHECK_STATUS(aclrtDestroyStream(stream)); CHECK_STATUS(atb::DestroyContext(context)); CHECK_STATUS(aclFinalize());释放顺序有讲究先释放输入张量与 workspace 设备内存再销毁算子对象随后销毁 stream最后销毁 Context 并调用aclFinalize。代码注释也明确提示operation 是对象概念先释放context 是全局资源后释放。5. SliceParam 参数语义与源码级校验规则SliceParam定义于 include/atb/infer_op_params.h包含两个核心成员与 8 字节预留字段struct SliceParam { SVectorint64_t offsets; // 每个维度切片的起始位置 SVectorint64_t size; // 每个维度切片的大小 uint8_t rsv[8] {0}; // 预留参数 };结合头文件注释与 slice_operation.cpp 的ParamCheck实现参数语义可归纳为offsets起始位置非负时表示该维切片的起点索引为负时表示从该维末尾往前数如offsets-1等价于起点dimNum-1源码校验offsetValue -xDim时报ERROR_INVALID_PARAM即负偏移不能超过该维大小。size切片大小非负时表示该维切片长度size-1表示一直切到该维末尾等价于size xDim - offset小于-1的取值是非法的。跨维约束校验核心offsets长度必须等于size长度size长度必须等于输入张量维数dimNum每个维必须满足offset size xDim且offset size不得溢出int64_t。这些规则同时在三个环节被执行InferShapeCheckImplshape 推导前校验、SetupCheckImplSetup 阶段校验含输出形状一致性检查、ParamCheck公共参数校验。其中SetupCheckImpl还会逐一比对输出张量各维与参数推导结果不一致即报ERROR_INVALID_TENSOR_DIM。InferShapeImpl的实现则展示了输出 shape 的推导逻辑先复制输入 desc再对每个维度按负 offset 加 xDim 归一化、size-1 补全为 xDim-offset的规则计算输出维大小见 slice_operation.cpp。6. 底层 Runner 调度Ops 图执行与 aclnn 两套后端从源码结构看SliceOperation 的算子执行通过CreateRunner按平台分发到两个后端见 slice_operation.cppAscend 950 平台创建SliceAclnnRunnerslice_aclnn_runner.cpp走 aclnn 接口执行。其CalcWorkspaceSize/Execute实现中会把SliceParam的 offsets/size 翻译成 aclnn 的 starts/ends 语义——负 offset 加 xDim 归一化、size-1时 ends 取该维末尾然后填充aclnnVariantPack调用aclnnSlice系列接口见 slice_aclnn_runner.cpp。其他平台创建SliceOpsRunnerslice_ops_runner.cpp把SliceParam通过TensorUtil::AtbSVector2OpsSVector转换为AsdOps::OpParam::Slice节点参数构造kernelGraph_单节点图后由 Ops 图执行框架调度。另外算子支持的 dtype/format 组合在算子信息表 ops_configs/atb_ops_info.ini 中登记SliceOperation支持float16,float,int8,bool,int32,uint32,bf16共 7 种 dtype格式为ND输入输出各 1 个。这为编写调用代码时的 dtype 选择提供了官方依据。7. 与 Python 精度用例的对应关系原始 README 在额外说明中指出Demo 中生成的数据不代表实际运行结果真实的数据生成与精度对比逻辑可参考根目录下的 Python 用例目录tests/apitest/opstest/python/operations/slice/该目录包含 test_slice.py 与test_slice2.py两个用例。以test_slice.py为例参数设置为{offsets: [2, 8], size: [10, 100]}输入为torch.randn(32, 128)golden_calc用 PyTorch 原生切片作为黄金基准in_tensors[0][2:12, 8:108]即第 0 维取[2, 12)、第 1 维取[8, 108)与 offsets/size 语义一一对应分别用half与bfloat16仅 Ascend910B两种 dtype 通过operation_test.OperationTest.execute执行算子并做精度比对。这为 C 侧验证结果提供了可对照的 Python 参考实现C Demo 中offsets{1,2}, size{2,4}的输出等价于 Python 侧tensor[1:3, 2:6]。8. 常见问题与排查建议结合上述源码分析运行该 Demo 时可能遇到的问题及排查方向如下现象可能原因排查/解决编译报链接错误或符号找不到cxx_abi 与加速库编译时不一致按第 3 节将D_GLIBCXX_USE_CXX11_ABI设为与库一致的 0/1找不到 ATB 头文件或库文件未正确 source set_env.sh确认已加载 CANN 与 nnal/atb或源码产物 output/atb环境aclrtMalloc或设备初始化失败设备号不存在或驱动未就绪检查aclrtSetDevice的设备号确认npu-smi info可见设备Setup 返回ERROR_INVALID_PARAMoffsets/size 长度不等于输入维数或 offsetsize 越界对照第 5 节校验规则检查参数可先用 Python 用例验证参数合法性Execute 返回ERROR_INVALID_TENSOR_DIM输出张量形状与切片结果不符确保输出 shape 等于各维size含 size-1 补全后的值Ascend 950 上报ERROR_CANN_ERRORaclnn 接口加载失败检查 CANN 版本与算子信息表 atb_ops_info.ini 中的 dtype 支持范围总结本文以 example/op_demo/slice/README_en.md 为骨架完整还原了 SliceOperation C Demo 的环境配置、编译运行与代码执行流程并借助仓库源码将SliceParam的参数语义、校验规则、双后端 Runner 调度以及 Python 精度用例的对应关系逐层展开。掌握这套创建 Context → 组装 VariantPack → Setup → Execute → 释放资源的调用范式后你可以快速迁移到仓库中其他 op_demo如 reshape_and_cache、paged_attention以及自己的业务算子调用中。【免费下载链接】ascend-transformer-boost本项目是CANN提供的是一款高效、可靠的Transformer加速库基于华为Ascend AI处理器提供Transformer定制化场景的高性能融合算子。项目地址: https://gitcode.com/cann/ascend-transformer-boost创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考