[AscendC算子开发]AllGatherAdd开发Tensor踩踏问题记录
算子功能
完成AllGather通信与Add计算融合。

算子语义示例:(两张卡参与计算,输入前缀分别为rank0和rank1)
-
- 输入:
rank0_a = [1,2,3];
rank0_b = [4,5,6,7,8,9];
rank1_a = [10,11,12];
rank1_b = [13,14,15,16,17,18]; - 输出:
rank0_c = AllGatherAdd(rank0_a, rank1_a, rank0_b)
= AllGather(rank0_a,rank1_a) + rank0_b
= [1,2,3,10,11,12] + [4,5,6,7,8,9]
= [5,7,9,17,19,21]
- 输入:
rank1_c = AllGatherAdd(rank0_a, rank1_a, rank1_b)
= AllGather(rank0_a,rank1_a) + rank1_b
= [1,2,3,10,11,12] + [13,14,15,16,17,18]
= [14,16,18,26,28,30]
详细算子信息请参考开源仓算子说明:https://gitcode.com/cann/ops-transformer/blob/master/examples/mc2/all_gather_add/README.md
问题背景
AllGatherAdd算子计算结果与golden数据对比精度不通过,打印计算结果发现AllGather的数据存在后半全0的情况。(此处的精度对比要求开发者可以根据具体需求自行设置,本问题背景中的精度对比要求是千分之一。)
从计算结果输出全0的现象推测问题出现在计算进行之前的数据搬运阶段,可能是数据搬运位置错误导致操作数本身不正确。

定位过程
使用AscendC::DumpTensor接口将kernel侧的数据Dump出来,查看搬运错误出现在哪里。
(具体使用方法参考:DumpTensor-CANN商用版8.3.RC1-昇腾社区)
在每个核SetGlobalBuffer之后、使用初始化好的GlobalTensor计算之前将GlobalTensor Dump出来:

再次运行查看日志,可以观察到每个AIV核的dump结果,发现靠前核的内容正常,靠后核的dump内容为全0:


推测是在SetGlobalBuffer时,使用全局数据初始化GlobalTensor时bufferSize过大,导致靠后的核读到了预期之外的数据,因此靠前的核输出有数据但后面的核输出全0。
(参考:SetGlobalBuffer-CANN商用版8.3.RC1-昇腾社区)
查看两个核DumpTensor的地址(addr)之间的差值,判断是否与预期每个核分到的数据大小blockLength相等,打印出SetGlobalBuffer的偏移:

根据打印,相邻两个核DumpTensor的位置相差0x3000。
该算子固定shape[480,256],数据类型fp16_t(半精度浮点数)为2字节,当前AIV核数为40,若按字节编址,则预期的偏移大小为blockLength=480*256/40=6144 
0x3000的十进制是12288,刚好是预期的两倍。
说明实际SetGlobalBuffer时给的偏移大了一倍,查看代码:![]()
发现起始地址多乘以了元素大小orz,fp16_t(半精度浮点数即half)恰好为2字节,因此起始地址大小翻倍,去掉后精度正常。
更多推荐


所有评论(0)