ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

make_tuple 一文讲透:CANN 昇腾算子开发里最省心的元组创建方式

make_tuple 一文讲透:CANN 昇腾算子开发里最省心的元组创建方式

make_tuple 一文讲透:CANN 昇腾算子开发里最省心的元组创建方式

【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit

这里讲的是 CANN 昇腾算子开发中 AscendC::Std::make_tuple 的用法:一行代码创建轻量元组,元素类型自动推断,多路结果打包不用你手写类型列表。

一、什么时候你会用到它

你是不是也遇到过:kernel 里同时要传偏移量、行数和标志位,要么开三个独立变量,要么自己定义一个小结构体逐个塞值,用起来都很别扭?而用 tuple<...> 时还得把那一长串元素类型手动敲全,又累又容易写错。make_tuple 就是为这种场景准备的。

二、30 秒上手

先花三十秒看这条官方示例里的典型写法,直接拷进你的算子代码就能跑:

AscendC::Std::tuple<uint32_t, float, bool> test = AscendC::Std::make_tuple(22, 3.3, true);

白话一点:你把值扔进去,它替你推断元素类型、打包成元组,类型清单都不用逐个写出来。

三、签名与参数逐个拆

会写调用还不够,把完整签名摊开看看每个部分在做什么:

template <typename ...Tps> __aicore__ inline constexpr tuple<unwrap_decay_t<Tps>...> make_tuple(Tps&& ...args)
参数名类型取值范围支持的数据类型
Tps...模板参数包,元素静态类型由它推断参数个数 [0, 64]覆盖下方列出的全部类型
args...函数参数包,实际传入的值参数个数 [0, 64]与 Tps... 一一对应

各支持设备均覆盖以下类型:bool、int4b_t、int8_t、uint8_t、fp8_e8m0_t、int16_t、uint16_t、half、bfloat16_t、int32_t、uint32_t、float、int64_t、uint64_t、LocalTensor、GlobalTensor。

四、避坑清单

调用跑通了,下面提前把新人最常踩的几个坑排掉:

  • ⚠️ 坑:元组的可实例化深度上限是 64,硬塞超过 64 个元素时,模板根本实例化不出来。正确姿势:元素数量控制在 64 以内,超了就重新组织数据结构。
  • 📌 坑:想让某个元素用指定类型时,如果直接传原始值,编译器会按自己的规则推断,结果可能和你预期对不上。正确姿势:对该元素显式强转,比如写成(uint32_t)22。
  • 坑:数组这类可变长度类型放不进元组。正确姿势:元素改用定长标量,或者用 LocalTensor / GlobalTensor 承载数据。
  • 坑:没有隐式转换构造可用,类型对不上时代码直接编译失败。正确姿势:转换关系自己写强转,别指望构造函数偷偷帮你转。

五、返回值长什么样

最后看看交到你手里的是什么:make_tuple 返回一个 tuple 对象,里面每个元素都是你传入参数的副本,而不是原变量本身。类型推断交给签名里的 unwrap_decay_t:它会剥掉引用以及 const 等修饰,保留纯值类型再装进元组,所以传 const 变量进去,元组里存的也是对应值类型的副本。

六、跑在哪些设备上

知道了返回值,再确认一下你的目标芯片跑不跑得动:

设备是否支持
Ascend 950PR / Ascend 950DT√
Atlas A3 训练系列 / Atlas A3 推理系列√
Atlas A2 训练系列 / Atlas A2 推理系列√

延伸阅读

想多看几个场景的用法,官方文档里附带完整的调用示例集合,可以看 tuple 官方示例文档。

【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进