CANN Runtime TDT Channel 入门:基于 acltdt 接口实现 Tensor 的单进程收发与数据校验
【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime
TDT Channel 是 CANN Runtime 提供的一种基于队列的数据传输通道,用于在 Host 与 Device 之间按序传递封装为 Dataset 的 Tensor 数据。本文以example/2_advanced_features/tdt_channel/0_simple_channel示例为主体,完整讲解 Channel、Dataset、DataItem 的创建、发送、接收与资源释放全流程,并结合include/external/acl/acl_tdt.h头文件与示例源码给出可复现、可校验的实战方案。
一、示例概述与适用产品
0_simple_channel是一个聚焦 TDT Channel 基础数据传输的最小可运行样例,核心覆盖以下能力:
- 创建一个 TDT Channel,并构造浮点 Tensor 对应的 DataItem;
- 使用 Dataset 封装单个 Tensor 并通过 Channel 发送;
- 在同一进程中接收 Dataset,并读取维度、数据类型、数据地址和首元素值;
- 查询 Channel 当前尺寸,并完成停止、清理与销毁。
该样例关键接口在不同产品上的支持情况如下(数据来源于示例 README 的产品支持表):
| 产品 | 是否支持 |
|---|---|
| Ascend 950PR / Ascend 950DT | × |
| Atlas A3 训练系列产品 / Atlas A3 推理系列产品 | √ |
| Atlas A2 训练系列产品 / Atlas A2 推理系列产品 | √ |
产品支持表仅列出当前样例已完成验证或已明确声明支持情况的产品,未在表格中列出的产品不代表不支持。如果你需要在其他产品上体验 TDT Channel,可参考带容量限制的进阶样例 1_channel_capacity。
二、核心概念:Channel、Dataset 与 DataItem
TDT Channel 的数据模型由三层结构组成,分别对应头文件 acl_tdt.h 中定义的不透明句柄类型:
acltdtChannelHandle:TDT 通道句柄,通过acltdtCreateChannelWithCapacity/acltdtCreateChannel创建,承载通道的名称、所属 Device 与容量信息;acltdtDataset:数据集句柄,一个 Dataset 对应一次完整的数据传递单元,内部可包含多个 DataItem;acltdtDataItem:数据项句柄,封装单个 Tensor 的元信息(Tensor 类型、维度、数据类型)与数据指针,一个 Dataset 可挂载多个 DataItem。
示例采用“一进程内收发”的模式:发送方构造 Dataset 后通过acltdtSendTensor投递到通道,接收方通过acltdtReceiveTensor取出 Dataset,从而实现单进程内的数据闭环,便于快速验证接口语义。
从数据结构看(acl_tdt.h),Tensor 类型枚举acltdtTensorType除常规的ACL_TENSOR_DATA_TENSOR外,还包含ACL_TENSOR_DATA_END_OF_SEQUENCE、ACL_TENSOR_DATA_ABNORMAL、ACL_TENSOR_DATA_SLICE_TENSOR、ACL_TENSOR_DATA_END_TENSOR等特殊类型,用于表达流式数据的序列结束、异常数据或切片数据等语义。本样例使用的是最基础的ACL_TENSOR_DATA_TENSOR类型。
三、环境准备与编译运行
编译运行前需获取固件、驱动及 CANN 软件包并安装,环境安装与运行详情可参考 example 目录下的 README。本样例的编译运行步骤如下:
# ${install_root} 替换为 CANN 安装根目录,默认安装在 /usr/local/Ascend 目录 source ${install_root}/cann/set_env.sh export ASCEND_INSTALL_PATH=${install_root}/cann # 编译运行 bash run.shrun.sh(run.sh)的执行逻辑分为三步:先通过source $_ASCEND_INSTALL_PATH/bin/setenv.bash加载编译环境,再以ASCEND_CANN_PACKAGE_PATH作为 CANN 包路径执行 CMake 配置与make编译,最后运行生成的./build/main可执行文件。
编译配置(CMakeLists.txt)中有两点值得注意:
- 编译选项为
-O2 -std=c++17 -D_GLIBCXX_USE_CXX11_ABI=0 -Wall -Werror,其中-D_GLIBCXX_USE_CXX11_ABI=0用于与 CANN 运行时库的 ABI 保持一致,避免因双 ABI 模式不匹配导致链接或运行异常; - 链接阶段显式依赖两个库:
libacl_tdt_channel.so(TDT Channel 能力)与libascendcl.so(AscendCL 基础能力),头文件搜索路径为${ASCEND_CANN_PACKAGE_PATH}/include,库搜索路径为${ASCEND_CANN_PACKAGE_PATH}/lib64。
四、示例主流程详解
示例主程序(main.cpp)的执行流程如下:
- 初始化:调用
aclInit(nullptr)完成 AscendCL 配置初始化,随后调用aclrtSetDevice(0)指定 Device 0; - 创建 Channel:调用
acltdtCreateChannelWithCapacity(deviceId, "simple_tdt_channel", kChannelCapacity)创建容量为 2 的通道。若当前 Runtime 未启用队列式 TDT Channel 能力,该接口返回nullptr,样例将记录告警并正常结束; - 构造发送 Dataset:通过工具函数
tdt::CreateFloatDataset将{1.0F, 2.0F, 3.0F, 4.0F}浮点向量封装为 DataItem 并挂载进 Dataset; - 发送与查询:调用
acltdtSendTensor(channel, sendDataset, kTimeoutMs)发送,再调用acltdtQueryChannelSize查询通道当前大小; - 接收与校验:调用
acltdtReceiveTensor(channel, recvDataset, kTimeoutMs)接收,并通过DumpDataset校验接收数据的维度、类型、字节数、首元素值; - 资源释放:依次调用
acltdtCleanChannel、acltdtStopChannel、acltdtDestroyChannel清理通道,随后释放 Dataset/DataItem,最后调用aclrtResetDeviceForce复位 Device 并调用aclFinalize完成去初始化。
4.1 DataItem 的构造:acltdtCreateDataItem
发送侧数据构造依赖 tdt_common_utils.h 中的工具函数,其关键调用为:
acltdtDataItem* item = acltdtCreateDataItem( ACL_TENSOR_DATA_TENSOR, // TDT Tensor 类型 dims, // 维度数组 {1, 4} dimNum, // 维度个数 2 ACL_FLOAT, // 数据类型 values.data(), // 数据指针 values.size() * sizeof(float)); // 数据字节数其中dims被设置为{1, values.size()}(即{1, 4}),ACL_FLOAT对应单精度浮点。随后通过acltdtCreateDataset()创建空 Dataset,并调用acltdtAddDataItem(dataset, item)将 DataItem 挂载到 Dataset 中;任一环节失败时,工具函数会调用acltdtDestroyDataItem或acltdtDestroyDataset及时释放已创建对象。
4.2 发送与接收:acltdtSendTensor / acltdtReceiveTensor
发送与接收接口的签名(见 acl_tdt.h)均包含timeout参数,单位为毫秒,用于控制阻塞等待时长。本样例中kTimeoutMs = 1000,即发送方在通道不可写、接收方在通道无数据时最多等待 1000ms:
CHECK_ERROR(acltdtSendTensor(channel, sendDataset, kTimeoutMs)); CHECK_ERROR(acltdtReceiveTensor(channel, recvDataset, kTimeoutMs));发送完成后立即查询通道大小,可观察到通道中积压的 Dataset 数量;接收完成后再次查询,可确认数据已被消费。
4.3 接收侧校验:DumpDataset
接收侧通过DumpDataset完成数据校验,依次调用:
acltdtGetDatasetSize获取 Dataset 中 DataItem 数量;acltdtGetDataItem(dataset, 0)取出首个 DataItem;acltdtGetDimNumFromItem/acltdtGetDimsFromItem读取维度个数与维度值;acltdtGetDataAddrFromItem获取数据地址,acltdtGetDataSizeFromItem获取数据字节数;acltdtGetTensorTypeFromItem/acltdtGetDataTypeFromItem读取 Tensor 类型与数据类型;- 通过数据地址读取首元素值并与发送侧
1.0F对比,验证数据完整性。
五、涉及的 CANN RUNTIME API 全景
该样例覆盖的关键接口按功能分组如下:
- 初始化:
aclInit初始化 AscendCL 配置;aclFinalize实现 AscendCL 去初始化。 - Device 管理:
aclrtSetDevice指定用于运算的 Device;aclrtResetDeviceForce强制复位当前 Device,回收其上的资源(单机单进程样例使用强制复位,避免多进程场景下影响同机其他进程)。 - Channel 与 Dataset 创建:
acltdtCreateChannelWithCapacity创建带容量 TDT Channel;acltdtCreateDataItem基于 Tensor 构造 DataItem;acltdtCreateDataset与acltdtAddDataItem封装 Dataset。 - Tensor 收发与信息查询:
acltdtSendTensor/acltdtReceiveTensor完成 Dataset 发送与接收;acltdtGetDatasetSize/acltdtGetDataItem读取 Dataset 内容;acltdtGetDataAddrFromItem、acltdtGetDataSizeFromItem、acltdtGetDataTypeFromItem、acltdtGetTensorTypeFromItem、acltdtGetDimNumFromItem、acltdtGetDimsFromItem查看数据、类型与维度信息。 - Channel 状态与资源释放:
acltdtQueryChannelSize查询 Channel 当前大小;acltdtStopChannel、acltdtCleanChannel、acltdtDestroyChannel依次完成停止、清理与销毁;acltdtDestroyDataItem/acltdtDestroyDataset释放 Dataset 资源。
各查询类接口的返回值语义可直接对照头文件注释:acltdtGetDataTypeFromItem在dataItem为空时返回ACL_DT_UNDEFINED;acltdtGetDataSizeFromItem失败时返回 0;acltdtGetDataAddrFromItem失败时返回null;acltdtGetDimNumFromItem失败时返回 0。
六、示例输出与容错行为
正常运行时,样例输出如下:
[INFO] Dataset size: 1 [INFO] Tensor type=..., data type=..., bytes=16, dims=(2, 2), firstValue=1.000 [INFO] Channel size after send: 1 [INFO] Dataset size: 1 [INFO] Tensor type=..., data type=..., bytes=16, dims=(2, 2), firstValue=1.000 [INFO] Channel size after receive: 0 [INFO] Run the simple_channel sample successfully.其中bytes=16对应4 × sizeof(float),dims=(2, 2)对应维度展开后的形状,发送与接收两侧输出一致,说明数据在通道中无损传递。Channel size after send: 1与Channel size after receive: 0验证了通道的队列语义:发送后积压 1 个 Dataset,接收后归零。
若当前运行环境未启用队列式 TDT Channel 能力,acltdtCreateChannelWithCapacity返回nullptr,样例输出如下告警并正常结束(返回码为 0):
[WARN] acltdtCreateChannelWithCapacity returned nullptr: this sample needs a queue-backed TDT channel so it can send and receive within one host process这种“降级为告警并正常退出”的处理方式,使得样例在能力受限环境(如底层队列初始化/创建失败的产品或构建版本)下也能安全运行,不会因接口不可用而崩溃。
七、进一步阅读与进阶样例
- tdt_channel 目录 README:TDT Channel 基础数据传输与容量控制能力总览;
- 1_channel_capacity 样例:演示带容量限制的 Channel(容量最小值为 2)、非阻塞发送下的容量压力观察,以及
acltdtGetSliceInfoFromItem、acltdtGetTensorTypeFromItem、acltdtGetDatasetName等附加信息查询接口; - TDT Channel 接口声明:include/external/acl/acl_tdt.h,包含全部
acltdt*接口的签名与返回值语义说明; - 样例公共工具:example/2_advanced_features/tdt_common_utils.h,包含 DataItem/Dataset 的构造、销毁与错误处理封装;
- example 目录总览:example/README.md,涵盖环境准备、产品支持表说明与 Device 复位接口使用约定。
【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考