算子功能

完成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字节,因此起始地址大小翻倍,去掉后精度正常。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐