CANN opbase 算子开发指南:aclTensor::SetFloatData 主机侧 Tensor 浮点数据写入详解
CANN opbase 算子开发指南aclTensor::SetFloatData 主机侧 Tensor 浮点数据写入详解【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase导读SetFloatData是 CANN opbase 基础框架库include/nnopbase/opdev/common_types.h为aclTensor提供的主机侧数据写入接口用于将一块float类型的内存数据按指定数据类型转换后批量写入由AllocHostTensor分配的主机 Tensor。本文以官方 API 文档 SetFloatData.md 为骨架结合源码实现与单元测试完整讲解接口原型、参数语义、类型转换规则、使用约束及底层调用链帮助算子开发者在编写 host 侧算子逻辑时正确、安全地初始化 Tensor 数据。接口总览SetFloatData隶属于aclTensor的主机侧数据写入接口族common_types 系列。该接口族在 common_types.h 中集中声明除SetFloatData外还包括SetBoolData、SetIntData、SetFp16Data、SetBf16Data等完整清单可参考索引文档 common_types.md。接口的功能定位十分明确将一段float类型的主机内存value 指针指向按元素逐个写入某个主机侧aclTensor的数据区。它并非简单的内存拷贝而是带有按目标数据类型转换语义的写入操作——这正是它区别于通用memcpy的关键。函数原型与参数说明函数原型void SetFloatData(const float *value, uint64_t size, op::DataType dataType)参数说明参数输入/输出说明value输入指向待写入aclTensor的数据内存的指针类型为const float *。size输入待写入的元素个数类型为uint64_t表示从value指向的首地址开始连续读取size个float元素。dataType输入目标数据类型类型为op::DataType即ge::DataType。写入时每个源元素会被转换为该指定数据类型后再写入aclTensor。返回值无void。约束输入指针不能为空null调用方必须保证value指向合法的、长度至少为size * sizeof(float)字节的可读内存。目标aclTensor必须是主机侧 Tensor即通过AllocHostTensor分配写入操作仅对kOnHost放置placement的 Tensor 生效详见下文源码分析。源码级实现原理入口声明与实现位置类声明class aclTensor位于 common_types.hSetFloatData声明于 common_types.h。实现位置src/nnopbase/common/utils/common_types.cpp。三级调用链SetFloatData → SetData → SetData(index)SetFloatData的实现非常简洁本质上是模板接口SetData(const T *value, uint64_t size, op::DataType dataType)的float特化转发void aclTensor::SetFloatData(const float* value, uint64_t size, op::DataType dataType) { SetData(value, size, dataType); }其中批量版SetDatacommon_types.cpp的核心逻辑是先校验 Tensor 放置位置再逐元素写入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); } } }这里有一个容易被忽略的实现事实当目标 Tensor 不是kOnHost放置时该写入操作会被静默跳过既不报错也不写入。因此调用方必须先通过AllocHostTensor得到主机侧 Tensor再调用SetFloatData这一点与原文档allocated byAllocHostTensor的定位完全一致。逐元素转换与写入单元素版SetData(int64_t index, const T value, op::DataType dataType)common_types.cpp根据dataType做 switch 分发通过SetDataByDataTypeT, dataType完成类型转换后写入目标地址template typename T, typename dataType static void SetDataByDataType(int64_t index, void* dataAddr, const T value) { dataType* tmpDataAddr static_castdataType*(dataAddr); if constexpr (op::internal::IsCustomFloattypename std::decayT::type::value) { // For custom float types, convert through double to avoid ambiguity *(tmpDataAddr index) static_castdataType(static_castdouble(value)); } else { *(tmpDataAddr index) static_castdataType(value); } }可以看到两个关键设计标准类型直接static_cast转换例如源为float、目标为DT_INT32时执行*(int32_t*)(addr index) static_castint32_t(value)即 C 风格截断转换。自定义浮点类型custom float经由double中转仓库中定义的fp16_t、bfloat16、Float8E5M2、Float8E4M3FN、Float6E3M2、Float4E2M1等低精度浮点类型先转double再转目标类型以避免直接static_cast产生的歧义保证数值转换语义明确。目标地址的计算方式单元素写入时目标数据区首地址取自this-GetStorageAddr()common_types.cpp即 Tensor 底层存储的基地址逐元素写入则在基地址上按index偏移。由于value数组中的每个元素被连续写入下标0..size-1只要 Tensor 的存储容量不小于size即可保证写入不越界。支持的 dataType 取值范围SetFloatData的dataType参数决定了转换与写入的目标类型。从 common_types.cpp 的 switch 分发来看当前实现支持以下op::DataType枚举值C 目标类型说明DT_FLOATfloat源、目标同为 32 位浮点无精度损失DT_FLOAT16op::fp16_t半精度浮点DT_BF16op::bfloat16Brain Float 16DT_INT8 / DT_UINT8int8_t / uint8_t8 位整数DT_INT16 / DT_UINT16int16_t / uint16_t16 位整数DT_INT32 / DT_UINT32int32_t / uint32_t32 位整数DT_INT64 / DT_UINT64int64_t / uint64_t64 位整数DT_DOUBLEdouble64 位浮点源 float 升精度DT_BOOLbool布尔走SetDataByBool特殊转换当传入不在上述范围内的类型例如DT_STRING时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)]特殊的布尔转换语义当目标是DT_BOOL时走SetDataByBoolcommon_types.cpp其浮点源值的判定规则为*(tmpDataAddr index) std::abs(static_castfloat(value)) std::numeric_limitsfloat::epsilon();即浮点源元素取绝对值后与float机器精度 epsilon 比较非零大于 epsilon视为 true而不是简单地! 0这避免了极小浮点误差被误判为 true 的问题。使用示例官方示例完整继承// Initialize a float memory block and assign the values to the first 10 elements of the input. void Func(const aclTensor *input) { float myArray[10]; input-SetFloatData(myArray, 10, DT_FLOAT); }可运行的标准流程示例结合AllocHostTensor的完整写法如下executor为算子执行器上下文AllocHostTensor负责在主机侧分配 Tensor 存储// 1. 分配主机侧 Tensorfloat32共 100 个元素 aclTensor *tensor executor.AllocHostTensor(nullptr, 100, op::DataType::DT_FLOAT); // 2. 准备 float 数据块 float data[100] {1.0f, 2.0f, 3.0f /* ... */}; // 3. 批量写入将 data 的前 100 个元素写入 tensor tensor-SetFloatData(data, 100, op::DataType::DT_FLOAT); // 4. 也可以将 float 数据转换为其他目标类型写入 tensor-SetFloatData(data, 100, op::DataType::DT_FLOAT16); // 转半精度 tensor-SetFloatData(data, 100, op::DataType::DT_INT32); // 转 32 位整数单元测试佐证仓库单元测试 tests/nnopbase/ut/composite_op/test_op_executor.cpp 展示了完整的接口族调用矩阵其中对SetFloatData的验证如下int64_t data[100] {1}; tensor10-SetIntData(data, 100, DataType::DT_INT64); tensor10-SetIntData(data, 100, DataType::DT_UINT64); // ... tensor10-SetBoolData((bool*)data, 100, DataType::DT_BOOL); tensor10-SetFloatData((float*)data, 100, DataType::DT_FLOAT); tensor10-SetFp16Data((fp16_t*)data, 100, DataType::DT_FLOAT16); tensor10-SetBf16Data((bfloat16*)data, 100, DataType::DT_BF16);测试中tensor10由executor.AllocHostTensor(...)分配随后以同一数据源分别调用SetBoolData、SetFloatData、SetFp16Data、SetBf16Data等接口写入不同目标类型直接印证了同一float源数据块可经类型转换写入多种 dtype 的 host Tensor这一核心能力。同源测试还覆盖了DT_INT8/16/32/64、DT_UINT8/16/32/64、DT_DOUBLE等转换路径test_op_executor.cpp与上文支持的dataType范围一致。与同族接口的关系及选型建议SetFloatData是同族接口中的浮点源版本。opbase 在 common_types.h 中还提供了其他源类型的批量写入接口选型时按源数据块的实际类型对应选择接口源指针类型典型目标类型SetBoolDataconst bool *DT_BOOLSetIntDataconst int64_t *各整数类型SetFloatDataconst float *DT_FLOAT 及各类可转换类型SetFp16Dataconst op::fp16_t *DT_FLOAT16SetBf16Dataconst op::bfloat16 *DT_BF16此外common_types.cpp 中还实现了SetFloat8E5M2Data、SetFloat8E4M3FNData、SetFloat8E8M0Data、SetFloat6E3M2Data、SetFloat4E1M2Data、SetHiFloat4Data、SetHiFloat8Data等扩展浮点写入接口部分可能属于保留接口详见 reserved_interface_common_types.md均复用同一套SetData模板转换机制。当需要按单个下标写入单个值而非批量写入时可改用通用模板接口SetData(int64_t index, const T value, op::DataType dataType)用法参见 SetData.md如input-SetData(10, myArray[0], DT_INT64)可设置第 11 个元素。常见误用与排查建议对设备侧 Tensor 调用无效SetFloatData仅在GetPlacement() op::TensorPlacement::kOnHost时执行写入设备侧 Tensor 调用会被静默忽略。使用前务必确认 Tensor 由AllocHostTensor分配。空指针传入value为空指针时会导致未定义行为。官方约束明确输入指针不能为空调用前应做判空。size 超过 Tensor 容量写入按value起始地址连续偏移size个元素若 Tensor 存储容量小于size将越界写。应保证size Numel()元素个数查询见 Numel.md。类型截断风险float → 整数类型为截断转换存在精度丢失float → float16/bfloat16 等低精度类型存在舍入误差属于预期行为但需要开发者根据算子精度要求自行评估。总结SetFloatData是 opbase common_types 数据写入接口族中面向float源数据的标准入口声明于 common_types.h实现于 common_types.cpp内部经模板SetData逐元素完成类型转换 主机侧写入。开发者只需遵循AllocHostTensor分配 → 准备 float 数据块 → 按目标 dtype 调用SetFloatData三步流程即可高效完成 host 侧 Tensor 的初始化配合同族SetIntData、SetFp16Data等接口可以覆盖算子开发中绝大多数主机侧数据准备场景。【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →