CANN opbase aclTensor::SetIntData 详解:向 Host 侧张量批量写入整型数据
【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase
导读
SetIntData是 CANN opbase 基础框架库中aclTensor提供的一组数据写入接口之一,专门用于将int64_t类型内存块中的数据批量写入由AllocHostTensor申请的 Host 侧张量,并在写入前按目标数据类型自动完成类型转换。本文以 SetIntData 官方英文文档 为主体,结合仓库源码与单元测试,完整讲解其函数原型、参数语义、返回值与约束、调用示例、底层实现原理及最佳实践,帮助算子开发者正确、高效地完成 Host 侧张量的初始化与数据填充。
功能概述
在编写自定义算子、构造aclnn入参或做算子调试时,经常需要在 Host 侧准备张量数据(例如构造输入、构造权重、准备用于校验的期望数据)。SetIntData正是为此提供的一条便捷通道:针对通过AllocHostTensor申请得到的 Host 侧aclTensor,用一块int64_t类型的内存初始化张量数据。
其核心价值在于「一处 int64 内存、多种目标数据类型」:数据源统一以int64_t形式提供,写入时按照dataType参数指定的目标类型做类型转换后再落盘到张量存储区,省去了开发者手工static_cast和逐元素拷贝的工作。
函数原型
void SetIntData(const int64_t *value, uint64_t size, op::DataType dataType)该接口是aclTensor的成员函数,声明位于 include/nnopbase/opdev/common_types.h,通过input->SetIntData(...)方式调用。
参数说明
| 参数 | 输入/输出 | 说明 |
|---|---|---|
| value | 输入 | 指向需要写入 aclTensor 的数据内存指针,类型为const int64_t*。 |
| size | 输入 | 需要写入的元素个数,类型为uint64_t,表示从value指向的数组中读取并写入的元素数量。 |
| dataType | 输入 | 目标数据类型,类型为op::DataType(即ge::DataType)。数据会先转换为该指定类型,再写入 aclTensor。 |
其中op::DataType枚举的常用取值及其数值对应关系(从源码中不支持类型的错误提示可以确认)包括:DT_FLOAT(0)、DT_FLOAT16(1)、DT_INT8(2)、DT_INT32(3)、DT_UINT8(4)、DT_INT16(6)、DT_UINT16(7)、DT_UINT32(8)、DT_INT64(9)、DT_UINT64(10)、DT_DOUBLE(11)、DT_BOOL(12)、DT_BF16(27)。
返回值说明
无返回值(void)。
约束说明
- 入参指针
value不能为空(nullptr)。 - 该接口仅对 Host 侧张量生效:从源码实现看,只有当张量的
TensorPlacement为kOnHost时才会执行数据写入(详见下文源码解析)。 size应不大于value指向数组的实际长度,也不应超过目标张量的元素个数,否则会造成越界读写。
调用示例
官方文档给出的最小示例:初始化一块 int64 内存,赋值给 input 的前 10 个元素。
// 初始化一块 int64 内存,赋值给 input 的前 10 个元素 void Func(const aclTensor *input) { int64_t myArray[10]; input->SetIntData(myArray, 10, DT_INT64); }更贴合实际工程场景的完整流程是「先申请 Host 张量,再写入数据」,例如:
#include "nnopbase/opdev/common_types.h" void InitTensor(aclOpExecutor &executor) { // 1. 通过 AllocHostTensor 申请 shape 为 {100} 的 host 侧张量 aclTensor *tensor = executor.AllocHostTensor({100}, op::DataType::DT_INT32, op::Format::FORMAT_ND); if (tensor == nullptr) { return; } // 2. 用 int64 内存块初始化数据,写入时自动转换为 DT_INT32 int64_t data[100] = {1}; tensor->SetIntData(data, 100, op::DataType::DT_INT32); }也可以对同一个张量以不同目标类型多次调用SetIntData,利用类型转换能力一次性完成多份数据准备。
源码级实现原理
1. 调用链:SetIntData → SetData → 逐元素类型转换
SetIntData本身只是一个薄封装,真正的逻辑在SetData模板中。实现位于 src/nnopbase/common/utils/common_types.cpp:
void aclTensor::SetIntData(const int64_t* value, uint64_t size, op::DataType dataType) { SetData(value, size, dataType); }而SetData模板(common_types.cpp#L658-L666)首先校验张量是否为 Host 侧(GetPlacement() == op::TensorPlacement::kOnHost),然后按元素循环调用单元素写入:
template <typename T> void aclTensor::SetData(const T* value, uint64_t size, op::DataType dataType) { if (this->GetPlacement() == op::TensorPlacement::kOnHost) { for (uint64_t i = 0; i < size; i++) { SetData(i, value[i], dataType); } } }2. 数据类型分派与转换规则
单元素写入函数SetData(int64_t index, const T value, op::DataType dataType)(common_types.cpp#L588-L656)按dataType做 switch 分派,将int64_t源值转换为目标类型后写入存储地址:
- 整型目标:
DT_INT8→int8_t、DT_INT16→int16_t、DT_INT32→int32_t、DT_INT64→int64_t,以及对应的无符号类型DT_UINT8/16/32/64; - 浮点目标:
DT_FLOAT→float、DT_DOUBLE→double、DT_FLOAT16→op::fp16_t、DT_BF16→op::bfloat16; - 布尔目标:
DT_BOOL走专门的SetDataByBool(common_types.cpp#L568-L586),对浮点及各类自定义浮点类型(fp16、bfloat16、Float8/Float6/Float4 系列、HiFloat4/8)按「绝对值是否大于等于float精度 epsilon」判定布尔值,其余类型直接static_cast<bool>; - 其余类型:落入
default分支,通过OP_LOGE_FOR_NOT_SUPPORTED_DATA_TYPE上报不支持的数据类型错误,并打印支持范围[DT_FLOAT(0), DT_FLOAT16(1), DT_INT8(2), DT_INT32(3), DT_UINT8(4), DT_INT16(6), DT_UINT16(7), DT_UINT32(8), DT_INT64(9), DT_UINT64(10), DT_DOUBLE(11), DT_BOOL(12), DT_BF16(27)]。
常规类型的转换通过SetDataByDataType(common_types.cpp#L556-L566)完成:直接static_cast<dataType>(value);对于自定义浮点类型,为避免类型转换歧义,先经double中转再转换。这意味着int64_t源数据写入浮点目标时可能存在精度损失,写入整型目标时可能存在截断/溢出,开发者需自行保证数值范围合理。
3. 前置依赖:AllocHostTensor
SetIntData的使用前提是张量由AllocHostTensor申请得到。aclOpExecutor提供了大量重载(src/nnopbase/composite_op/aclnn_engine/op_executor.cpp#L410-L527),典型形式包括:
AllocHostTensor(const op::Shape& shape, op::DataType datatype, op::Format format):按 shape 申请空 Host 张量,申请后配合SetIntData填充数据;AllocHostTensor(const int64_t* value, uint64_t size, op::DataType dataType):直接用int64_t数组初始化 Host 张量,等效于「申请 + SetIntData」两步合并。
从源码结构看,AllocHostTensor内部创建aclTensor对象并登记到allocatedObjList_/allocatedTensorList_中统一管理生命周期,返回值失败时(如非法数据类型)返回nullptr。接口族内同级的还有SetBoolData、SetFloatData、SetFp16Data、SetBf16Data以及 Float8/Float6/Float4/HiFloat 等各类自定义浮点数据写入接口(common_types.cpp#L677-L742),SetIntData与它们共用同一套SetData核心逻辑。
测试用例验证
仓库单元测试 tests/nnopbase/ut/composite_op/test_op_executor.cpp#L99-L112 对SetIntData的典型用法做了覆盖验证:先通过executor.AllocHostTensor({100}, DataType::DT_DOUBLE, Format::FORMAT_ND)申请一个 100 元素的 Host 张量,再以同一块int64_t data[100]分别以DT_INT64、DT_UINT64、DT_INT32、DT_UINT32、DT_INT16、DT_UINT16、DT_INT8、DT_UINT8、DT_DOUBLE等目标类型反复调用SetIntData,验证了「int64 数据源 + 任意受支持目标类型」的转换写入路径。功能测试 tests/nnopbase/st/composite_op/test_op_executor.cpp 中也有对应场景,读者可结合测试代码验证接口行为。
使用注意事项与最佳实践
- 仅限 Host 侧张量:
SetIntData只对TensorPlacement == kOnHost的张量写入生效(源码通过GetPlacement()判断)。如果对 Device 侧张量调用,数据不会写入,请改用其他设备侧数据搬运机制。 - 确保指针非空:
value传入nullptr属于未定义行为,调用前务必判空(文档约束亦明确「入参指针不能为空」)。 - 控制元素个数:
size是待写入的元素个数,而不是字节数。value数组长度与目标张量容量都要大于等于size,防止越界。 - 注意类型转换语义:
int64_t源数据写入窄整型(如DT_INT8)或浮点(如DT_FLOAT)时会按 C++ 转换规则发生截断或精度损失;写入DT_BOOL时采用「绝对值 ≥ float epsilon」的判定规则。业务上应保证数值范围在目标类型可表示范围内。 - 匹配数据类型枚举:
dataType需落在源码支持的枚举范围内,否则会触发OP_LOGE_FOR_NOT_SUPPORTED_DATA_TYPE错误日志。支持范围以源码中打印的[DT_FLOAT(0), DT_FLOAT16(1), DT_INT8(2), DT_INT32(3), DT_UINT8(4), DT_INT16(6), DT_UINT16(7), DT_UINT32(8), DT_INT64(9), DT_UINT64(10), DT_DOUBLE(11), DT_BOOL(12), DT_BF16(27)]为准。 - 与接口族协同使用:若源数据本身就是浮点或自定义浮点类型,可优先选用
SetFloatData、SetFp16Data、SetBf16Data等对应接口,避免不必要的 int64 中转转换。
相关文档
- SetIntData 英文文档 与 SetIntData 中文文档
- common_types 接口族总览(英文) 与 common_types 接口族总览(中文)
- 接口声明:include/nnopbase/opdev/common_types.h
- 核心实现:src/nnopbase/common/utils/common_types.cpp
- Host 张量申请实现:src/nnopbase/composite_op/aclnn_engine/op_executor.cpp
- 单元测试:tests/nnopbase/ut/composite_op/test_op_executor.cpp
【免费下载链接】opbase本项目是CANN算子库的基础框架库,为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考