CANN Runtime TDT 数据传输接口详解:Tensor 通道创建、发送与接收
【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime
导读
本文围绕 CANN Runtime 中的 TDT(Tensor Data Transfer)通道接口展开,系统讲解用于 Host 与 Device 之间 Tensor 数据通道创建、发送、接收、停止与销毁的完整接口族:acltdtCreateChannel、acltdtCreateChannelWithCapacity、acltdtSendTensor、acltdtReceiveTensor、acltdtStopChannel、acltdtDestroyChannel、acltdtQueryChannelSize、acltdtGetSliceInfoFromItem与acltdtCleanChannel。读完本文后,你将掌握每个接口的参数语义、超时行为、产品支持范围,并能结合仓库源码理解其底层基于 TDT 进程通道与队列(Memory Queue)式通道的双路径实现,最终可在实际业务中正确完成 Tensor 数据的收发与资源管理。
一、接口总览与两种通道实现路径
TDT 接口解决的核心问题是:业务侧(Host 侧)如何把预处理好的 Tensor 数据送入 Device 侧的队列,或者从 Device 侧队列取出数据。文档定义的全部接口如下:
| 接口 | 一句话说明 |
|---|---|
acltdtCreateChannel | 创建通道,可用于向 Device 发送数据或从 Device 接收数据 |
acltdtCreateChannelWithCapacity | 创建带容量的通道 |
acltdtSendTensor | 从 Host 向 Device 发送预处理好的数据 |
acltdtReceiveTensor | 在 Host 接收 Device 发过来的数据 |
acltdtStopChannel | 唤醒阻塞在发送/接收上的线程,便于安全退出 |
acltdtDestroyChannel | 销毁通道句柄,释放通道资源 |
acltdtQueryChannelSize | 查询队列通道内的消息数量 |
acltdtGetSliceInfoFromItem | 输出 Tensor 分片信息(分片数量、分片索引) |
acltdtCleanChannel | 清空通道中的所有数据 |
从源码看通道句柄的双路径设计
从实现看,通道句柄acltdtChannelHandle内部有一个关键标志位isTdtProcess(见 tensor_data_transfer.h),它把通道实现区分为两条路径:
- TDT 进程路径(isTdtProcess = true):通过动态加载
libdatatransfer.so,调用TdtHostInit、TdtHostPushData、TdtHostPopData、TdtHostStop、TdtHostDestroy等符号完成收发。该路径下timeout只能取-1(阻塞等待),且acltdtCleanChannel、acltdtQueryChannelSize均不支持(返回ACL_ERROR_FEATURE_UNSUPPORTED)。 - 队列式通道路径(isTdtProcess = false):通过
acltdtCreateChannelWithCapacity创建,底层走 Runtime 的 Memory Queue 机制(rtMemQueueInit、rtMemQueueCreate、rtMemQueueEnQueueBuff、rtMemQueueDeQueueBuff、rtMemQueueQueryInfo、rtMemQueueReset、rtMemQueueDestroy),支持超时、容量控制、通道清理与大小查询。
这两条路径的入口分别位于 acltdtSendTensor 与 acltdtReceiveTensor(TDT 路径),以及acl::acltdtSendTensorV2与acl::acltdtReceiveTensorV2(队列路径,见 tensor_data_transfer.cpp)。
二、先认识三个核心数据结构与配套接口
在收发 Tensor 之前,需要理解 TDT 的数据组织模型:Tensor → DataItem → Dataset。三者关系在 acl_tdt.h 中声明,实现在 tensor_data_transfer.h 中定义:
acltdtDataItem:标识一个业务上的 Tensor,携带 Tensor 类型、维度(dims)、数据类型、数据指针与长度,以及分片信息sliceNum/sliceId。acltdtDataset:一组 DataItem 的集合(内部为std::vector<acltdtDataItem*> blobs),并维护memType(数据来自 Host 还是 Device)与freeSelf标志。接收路径还内置了共享内存复用字段sharedMemSize_/sharedMem_用于性能优化。acltdtChannelHandle:通道句柄,保存通道名name、接收通道名recvName(以TF_RECEIVE_前缀识别,见 tensor_data_transfer.h)、Device IDdevId、队列 IDqid与路径标志isTdtProcess。
acltdtTensorType枚举定义了五类 Tensor 类型(见 acl_tdt.h):
| 枚举值 | 含义 |
|---|---|
ACL_TENSOR_DATA_UNDEFINED = -1 | 未定义 |
ACL_TENSOR_DATA_TENSOR | 普通 Tensor |
ACL_TENSOR_DATA_END_OF_SEQUENCE | 序列结束标志 |
ACL_TENSOR_DATA_ABNORMAL | 异常数据 |
ACL_TENSOR_DATA_SLICE_TENSOR | 分片 Tensor |
ACL_TENSOR_DATA_END_TENSOR | 分片结束标志 |
配套的数据组装与读取接口(详见 acl_tdt.h)包括:acltdtCreateDataItem、acltdtDestroyDataItem、acltdtCreateDataset、acltdtDestroyDataset、acltdtAddDataItem、acltdtGetDataItem、acltdtGetDatasetSize、acltdtGetTensorTypeFromItem、acltdtGetDataTypeFromItem、acltdtGetDataAddrFromItem、acltdtGetDataSizeFromItem、acltdtGetDimNumFromItem、acltdtGetDimsFromItem、acltdtGetDatasetName。
其中acltdtCreateDataItem的参数校验值得注意(见 tensor_data_transfer.cpp):
dims与dimNum必须保持一致(要么同时为 0,要么同时非 0);dimNum不能超过MAX_DIM_CNT = 128;- 当
tdtType不是ACL_TENSOR_DATA_TENSOR时,dims必须为nullptr; - 支持的数据类型包括
bool/int8/uint8/half/int16/uint16/float/int32/uint32/int64/uint64/double/string,与aclDataType一一映射(映射表见 tensor_data_transfer.cpp)。
acltdtAddDataItem则会校验一个 Dataset 内的数据地址类型必须一致(不能混用 Host 地址与 Device 地址),且已处于freeSelf状态(内部已解析出数据项)的 Dataset 不允许再追加数据项(见 tensor_data_transfer.cpp)。
三、创建通道:acltdtCreateChannel 与 acltdtCreateChannelWithCapacity
3.1 acltdtCreateChannel
acltdtChannelHandle *acltdtCreateChannel(uint32_t deviceId, const char *name)功能说明:创建acltdtChannelHandle类型的数据,表示可以用于向 Device 发送数据或是从 Device 接收数据的通道。通道使用完成后,需及时依次调用acltdtStopChannel、acltdtDestroyChannel接口释放通道资源。
产品支持情况:
- Ascend 950PR/Ascend 950DT:不支持
- Atlas A3 训练系列产品/Atlas A3 推理系列产品:不支持
- Atlas A2 训练系列产品/Atlas A2 推理系列产品:不支持
- Atlas 200I/500 A2 推理产品:不支持
- Atlas 推理系列产品:不支持
- Atlas 训练系列产品:支持(仅支持在昇腾虚拟化实例场景下使用本接口)
- IPV350:不支持
参数说明:
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| deviceId | 输入 | Device ID。用户调用 aclrtGetDeviceCount 接口获取可用的 Device 数量后,这个 Device ID 的取值范围:[0, (可用的 Device 数量-1)] |
| name | 输入 | 队列通道名称的指针。 |
返回值:返回acltdtChannelHandle类型的指针表示成功;返回nullptr表示失败。
源码要点:该接口在实现中会先通过GetFunction("TdtHostInit")获取并调用TdtHostInit(deviceId)完成 TDT 主机侧初始化,然后创建句柄;若通道名以TF_RECEIVE_开头,则视为接收通道并调用TdtHostPreparePopData()做接收准备,最后把句柄登记到全局aclChannleMap中(见 tensor_data_transfer.cpp)。
3.2 acltdtCreateChannelWithCapacity
acltdtChannelHandle *acltdtCreateChannelWithCapacity(uint32_t deviceId, const char *name, size_t capacity)功能说明:创建带容量的通道,适用于需要精确控制队列积压量的场景。
产品支持情况:
- Ascend 950PR/Ascend 950DT:支持
- Atlas A3 训练系列产品/Atlas A3 推理系列产品:支持
- Atlas A2 训练系列产品/Atlas A2 推理系列产品:支持
- Atlas 200I/500 A2 推理产品:不支持
- Atlas 推理系列产品:不支持
- Atlas 训练系列产品:支持
- IPV350:不支持
参数说明:
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| deviceId | 输入 | Device ID。用户调用 aclrtGetDeviceCount 接口获取可用的 Device 数量后,这个 Device ID 的取值范围:[0, (可用的 Device 数量-1)] |
| name | 输入 | 队列通道名称的指针。 |
| capacity | 输入 | 队列通道容量,取值范围:[2, 8192]。 |
返回值:返回acltdtChannelHandle类型的指针表示成功;返回nullptr表示失败。
源码要点:队列式通道的创建链路可以拆解为(见 tensor_data_transfer.cpp):
- 校验通道名长度,要求
strnlen(name, RT_MQ_MAX_NAME_LEN) + 1 <= RT_MQ_MAX_NAME_LEN(即名称不能超过 Runtime 内存队列名称上限); - 组装
acltdtQueueAttr属性:attr.depth = capacity(容量即队列深度)、workMode = RT_MQ_MODE_DEFAULT、flowCtrlFlag = false(关闭流控)、overWriteFlag = false(禁止覆盖写); - 调用
rtMemQueueInit(deviceId)完成队列模块初始化(重复初始化返回ACL_ERROR_RT_REPEATED_INIT可容忍,ACL_ERROR_RT_FEATURE_NOT_SUPPORT表示产品不支持); - 调用
rtMemQueueCreate(deviceId, &attr, &handle->qid)真正创建队列并取得队列 ID。
从depth到capacity的映射说明:通道容量对应队列深度,文档明确取值范围为 [2, 8192],超出该范围将创建失败。
四、数据发送与接收:acltdtSendTensor / acltdtReceiveTensor
4.1 acltdtSendTensor
aclError acltdtSendTensor(const acltdtChannelHandle *handle, const acltdtDataset *dataset, int32_t timeout)功能说明:从 Host 向 Device 发送预处理好的数据。
产品支持情况:Ascend 950PR/Ascend 950DT、Atlas A3 训练/推理系列产品、Atlas A2 训练/推理系列产品、Atlas 训练系列产品支持;Atlas 200I/500 A2 推理产品、Atlas 推理系列产品、IPV350 不支持。
参数说明:
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| handle | 输入 | 指定通道。需提前调用acltdtCreateChannel接口或acltdtCreateChannelWithCapacity接口创建acltdtChannelHandle类型的数据。 |
| dataset | 输入 | 向 Device 发送的数据的指针。类型定义请参见 acltdtDataset。 |
| timeout | 输入 | 等待超时时间。取值范围如下: --1:阻塞方式,一直等待直到数据发送完成。 -0:非阻塞方式,当通道满时,直接返回通道满这个错误,这时由用户自行设定重试间隔。 ->0:配置具体的超时时间,单位为毫秒。通道满时,等待达到超时时间后返回报错。超时时间受操作系统影响,一般偏差在操作系统的一个时间片内,例如,操作系统的一个时间片为 4ms,用户设置的超时时间为 1ms,则实际的超时时间在 1ms 到 5ms 范围内。在 CPU 负载高场景下,超时时间仍可能存在波动。 |
返回值:返回 0 表示成功,返回其他值表示失败,错误码请参见 aclError。典型错误为ACL_ERROR_RT_QUEUE_FULL(通道满)。
源码要点:队列路径下,发送过程分三步完成(见 acltdtSendTensorV2):
- 序列化:
TensorDatasetSerializesV2把 Dataset 中的每个 DataItem 转换为aclTdtDataItemInfo(携带控制信息、dims、数据指针); - 打包:
TensorDataitemSerialize将控制头ItemInfo与 dims 按64 字节对齐(TDT_TENSOR_ALIGNE_UNIT = 64)写入控制缓冲,数据缓冲紧随其后,形成rtMemQueueBuffInfo向量(见 tensor_data_transfer.cpp); - 入队:调用
rtMemQueueEnQueueBuff(handle->devId, handle->qid, &queueBuf, timeout),若返回ACL_ERROR_RT_QUEUE_FULL则直接透传该错误码,由上层根据 timeout 语义处理。
4.2 acltdtReceiveTensor
aclError acltdtReceiveTensor(const acltdtChannelHandle *handle, acltdtDataset *dataset, int32_t timeout)功能说明:在 Host 接收 Device 发过来的数据。
产品支持情况:与acltdtSendTensor相同(Ascend 950PR/DT、Atlas A3、Atlas A2、Atlas 训练系列产品支持;Atlas 200I/500 A2、Atlas 推理系列、IPV350 不支持)。
参数说明:
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| handle | 输入 | 指定通道。需提前调用acltdtCreateChannel接口或acltdtCreateChannelWithCapacity接口创建acltdtChannelHandle类型的数据。 |
| dataset | 输出 | 接收到的 Device 数据的指针。类型定义请参见 acltdtDataset。 |
| timeout | 输入 | 等待超时时间。取值范围如下: --1:阻塞方式,一直等待直到数据接收完成。 -0:非阻塞方式,当通道空时,直接返回通道空这个错误,这时由用户自行设定重试间隔。 ->0:配置具体的超时时间,单位为毫秒。通道空时,等待达到超时时间后返回报错。超时时间受操作系统影响,一般偏差在操作系统的一个时间片内,例如,操作系统的一个时间片为 4ms,用户设置的超时时间为 1ms,则实际的超时时间在 1ms 到 5ms 范围内。在 CPU 负载高场景下,超时时间仍可能存在波动。 |
返回值:返回 0 表示成功,返回其他值表示失败,错误码请参见 aclError。典型错误为ACL_ERROR_RT_QUEUE_EMPTY(通道空)。
源码要点:队列路径下接收过程如下(见 acltdtReceiveTensorV2):
rtMemQueuePeek窥视队首缓冲长度(不弹栈),为空时返回ACL_ERROR_RT_QUEUE_EMPTY;GetOrMallocHostMem申请 Host 侧接收缓冲,并做内存复用优化:申请大小按档位(1MB / 10MB / 100MB / 500MB,定义于 tensor_data_transfer.cpp)向上取整并保存在dataset->sharedMem_中,后续接收若所需长度不超过已申请大小则直接复用,避免反复rtMallocHost/rtFreeHost;同时该函数会通过EnsureCurrentThreadHasContext确保当前线程有可用的 Runtime Context;rtMemQueueDeQueueBuff弹出队首数据到 Host 缓冲;UnpackageRecvDataInfo解析控制头与 dims,还原出aclTdtDataItemInfo向量;TensorDatasetDeserializesV2反序列化为acltdtDataItem并装入用户传入的 Dataset(注意:接收后 Dataset 处于freeSelf = true状态,析构时会自动释放内部 DataItem)。
五、通道生命周期:停止、销毁与清理
5.1 acltdtStopChannel —— 唤醒阻塞线程
aclError acltdtStopChannel(acltdtChannelHandle *handle)功能说明:调用acltdtSendTensor接口发送数据时或调用acltdtReceiveTensor接口接收数据时,用户线程可能在没有数据时会卡住,此时如果需要退出的话,需要先将线程唤醒,该接口用于唤醒处于阻塞状态的线程。需要用户在发送、接收线程之外的另一个线程里调用这个函数,来唤醒处于阻塞状态的发送/接收线程。
参数说明:handle为指定通道,需提前通过acltdtCreateChannel或acltdtCreateChannelWithCapacity创建。
返回值:返回 0 表示成功,返回其他值表示失败。
源码要点:TDT 进程路径下,对以TF_RECEIVE_开头的接收通道调用TdtHostStop(handle->recvName)以唤醒阻塞线程(见 tensor_data_transfer.cpp);队列式通道路径下,该接口直接返回成功("new process, stop channel is no use")。
5.2 acltdtDestroyChannel —— 销毁通道
aclError acltdtDestroyChannel(acltdtChannelHandle *handle)功能说明:销毁acltdtChannelHandle类型的数据,只能销毁通过acltdtCreateChannel接口或acltdtCreateChannelWithCapacity接口创建的acltdtChannelHandle类型数据。
参数说明:handle为待销毁的acltdtChannelHandle类型的指针。
返回值:返回 0 表示成功,返回其他值表示失败。
源码要点:队列式通道路径调用rtMemQueueDestroy销毁底层队列并释放句柄(见 tensor_data_transfer.cpp);TDT 进程路径则从全局aclChannleMap中移除该通道,当 map 为空时调用TdtHostDestroy()做全局清理,随后释放句柄。
5.3 acltdtCleanChannel —— 清空通道数据
aclError acltdtCleanChannel(acltdtChannelHandle *handle)功能说明:清空通道中的所有数据。
参数说明:handle为指定通道,需提前通过acltdtCreateChannelWithCapacity接口创建。
返回值:返回 0 表示成功,返回其他值表示失败。
源码要点:队列式通道路径通过rtMemQueueReset(handle->devId, handle->qid)复位队列实现清空;TDT 进程路径不支持该操作,返回ACL_ERROR_FEATURE_UNSUPPORTED(见 tensor_data_transfer.cpp)。
六、通道状态查询:acltdtQueryChannelSize
aclError acltdtQueryChannelSize(const acltdtChannelHandle *handle, size_t *size)功能说明:查询队列通道内的消息数量。
参数说明:
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| handle | 输入 | 指定通道。需提前通过acltdtCreateChannelWithCapacity接口创建acltdtChannelHandle类型的数据。 |
| size | 输出 | 消息数量的指针。 |
返回值:返回 0 表示成功,返回其他值表示失败。
源码要点:队列式通道路径通过rtMemQueueQueryInfo获取rtMemQueueInfo_t并返回info.size(见 tensor_data_transfer.cpp);TDT 进程路径不支持,返回ACL_ERROR_FEATURE_UNSUPPORTED。结合文档可知,该接口与acltdtCreateChannelWithCapacity配套使用——只有带容量的队列式通道才有"消息数量"这一概念。
七、Tensor 分片信息:acltdtGetSliceInfoFromItem
aclError acltdtGetSliceInfoFromItem(const acltdtDataItem *dataItem, size_t *sliceNum, size_t *sliceId)功能说明:用于输出 Tensor 分片信息。
使用场景:OutfeedEnqueueOpV2 算子由于其功能要求需申请 Device 上的大块内存存放数据,在 Device 内存不足时,可能会导致内存申请失败,进而导致某些算子无法正常执行。该场景下,用户可以调用本接口获取 Tensor 分片信息(分片数量、分片索引),再根据分片信息拼接算子的 Tensor 数据。
参数说明:
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| dataItem | 输入 | acltdtDataItem类型的指针。acltdtDataItem用于标识一个业务上的 Tensor。类型定义请参见 acltdtDataItem。需提前调用 acltdtCreateDataItem 接口创建acltdtDataItem类型的数据。 |
| sliceNum | 输出 | 单个 Tensor 被切片的数量。 |
| sliceId | 输出 | 被切片 Tensor 的数据段索引。 |
返回值:返回 0 表示成功,返回其他值表示失败。
源码要点:分片信息在数据项内部以uint16_t存储(acltdtDataItem::sliceNum与acltdtDataItem::sliceId),该接口对三个入参做空指针校验后直接输出(见 tensor_data_transfer.cpp)。分片信息随ItemInfo控制头在收发路径中传递(见 tensor_data_transfer.h 中的sliceNum/sliceId字段),并在反序列化时回填到acltdtDataItem上。
产品支持情况:Ascend 950PR/Ascend 950DT、Atlas A3 训练/推理系列产品、Atlas A2 训练/推理系列产品、Atlas 训练系列产品支持;Atlas 200I/500 A2 推理产品、Atlas 推理系列产品、IPV350 不支持。
八、实战示例:基于仓库样例打通收发全流程
仓库 example/2_advanced_features/tdt_channel 目录提供了两个可直接编译运行的 TDT 样例,是理解上述接口用法的权威参考。
8.1 示例一:0_simple_channel —— 单进程内发送与接收
主流程位于 main.cpp,其关键步骤如下:
- 初始化:调用
aclInit(nullptr)初始化 AscendCL,aclrtSetDevice(0)指定 Device; - 创建通道:
acltdtCreateChannelWithCapacity(0, "simple_tdt_channel", 2),容量取 2; - 构造发送 Dataset:通过
tdt::CreateFloatDataset(见 tdt_common_utils.h)把std::vector<float>构造成 DataItem(ACL_TENSOR_DATA_TENSOR类型、dims = {1, N}、ACL_FLOAT)再放入 Dataset:acltdtDataItem* item = acltdtCreateDataItem( ACL_TENSOR_DATA_TENSOR, dims, sizeof(dims) / sizeof(dims[0]), ACL_FLOAT, values.data(), values.size() * sizeof(float)); acltdtDataset* dataset = acltdtCreateDataset(); acltdtAddDataItem(dataset, item); - 发送:
acltdtSendTensor(channel, sendDataset, 1000)(超时 1000ms); - 查询:
acltdtQueryChannelSize(channel, &channelSize),发送后通道大小为 1; - 接收:
acltdtReceiveTensor(channel, recvDataset, 1000); - 校验:用
acltdtGetDatasetSize、acltdtGetDataItem、acltdtGetDimNumFromItem、acltdtGetDimsFromItem、acltdtGetDataAddrFromItem、acltdtGetDataTypeFromItem、acltdtGetTensorTypeFromItem、acltdtGetDataSizeFromItem读取并打印接收到的 Tensor 元信息,接收后通道大小恢复为 0; - 清理:依次调用
acltdtCleanChannel、acltdtStopChannel、acltdtDestroyChannel释放通道,再销毁 Dataset/DataItem,最后aclrtResetDeviceForce与aclFinalize退出。
运行方式(详见 README.md):
# ${install_root} 替换为 CANN 安装根目录,默认安装在 /usr/local/Ascend 目录 source ${install_root}/cann/set_env.sh export ASCEND_INSTALL_PATH=${install_root}/cann bash run.sh典型输出:
[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.若当前运行环境未启用队列式 TDT Channel 能力,acltdtCreateChannelWithCapacity会返回nullptr,样例打印告警后正常结束——这也再次印证了"队列式通道能力取决于产品与构建形态"的结论。
8.2 示例二:1_channel_capacity —— 容量压力测试
该样例(见 main.cpp)演示容量上限与"通道满"错误处理:
- 通道容量固定为 2,连续以
timeout=0(非阻塞)发送三个 Dataset; - 当队列被占满时,
acltdtSendTensor立即返回ACL_ERROR_RT_QUEUE_FULL,样例据此打印容量压力告警,而不是卡死; - 同时演示了
acltdtGetSliceInfoFromItem与acltdtGetDatasetName的调用方式,以及acltdtCleanChannel/acltdtStopChannel/acltdtDestroyChannel的清理顺序。
这个样例恰好对应本文第四章 timeout 语义中0(非阻塞)的典型用法:通道满时直接返回错误,由用户自行设定重试间隔或采取降级策略。
九、使用建议与注意事项
- 接口配对使用:通道创建后,释放顺序务必是
acltdtStopChannel→acltdtDestroyChannel;acltdtDestroyChannel只能销毁由acltdtCreateChannel/acltdtCreateChannelWithCapacity创建的句柄,不能混用。 - 超时语义差异:TDT 进程路径(
acltdtCreateChannel创建的通道)下acltdtSendTensor/acltdtReceiveTensor的 timeout 只能为-1;而队列式通道(acltdtCreateChannelWithCapacity)支持 -1 / 0 / 正数三种语义,正数超时存在约一个操作系统时间片的偏差,CPU 高负载下仍可能有波动。 - 通道命名规范:若通道用于接收数据,通道名建议以
TF_RECEIVE_开头,这样句柄会识别出recvName,在 TDT 进程路径下才能正确执行接收与停止唤醒(详见 tensor_data_transfer.h)。 - Dataset 内存类型一致:同一个 Dataset 内的 DataItem 数据地址必须全部来自 Host 侧或全部来自 Device 侧,混合使用会返回
ACL_ERROR_INVALID_PARAM。 - 接收缓冲复用:
acltdtReceiveTensor会在 Dataset 内按 1MB/10MB/100MB/500MB 档位缓存 Host 缓冲,高频接收相同量级数据时可显著降低内存申请开销;如果数据集大小波动较大,可关注档位机制以预估内存峰值。 - 产品支持差异:
acltdtCreateChannel目前仅 Atlas 训练系列产品(昇腾虚拟化实例场景)支持;acltdtCreateChannelWithCapacity等其余接口在 Ascend 950PR/DT、Atlas A3、Atlas A2、Atlas 训练系列产品上支持。编码时建议按产品能力做条件编译或运行时探测。
十、总结
TDT 数据传输接口是 CANN Runtime 中 Host-Device 间 Tensor 数据通道的标准入口。本文从接口契约、参数语义、产品支持矩阵到源码实现,完整覆盖了通道创建(acltdtCreateChannel/acltdtCreateChannelWithCapacity)、收发(acltdtSendTensor/acltdtReceiveTensor)、生命周期管理(acltdtStopChannel/acltdtDestroyChannel/acltdtCleanChannel)、状态查询(acltdtQueryChannelSize)与分片处理(acltdtGetSliceInfoFromItem)九大接口,并结合 src/acl/acl_tdt_channel/tensor_data_transfer.cpp、include/external/acl/acl_tdt.h 与 example/2_advanced_features/tdt_channel 示例给出了可验证的底层依据。开发者可在此基础上直接构建可靠的 Tensor 数据传输链路,并在遇到"通道满/通道空"等典型错误时依据 timeout 语义与错误码快速定位。
【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考