针对不同场景合理使用归约指令
【优先级】中
【描述】对于需要将一段连续buffer上的元素全部累加到一个元素上的场景。使用WholeReduceSum的累加效率较高,但是单条指令的执行速度不如BlockReduceSum,因此,为了兼顾累加的效率以及尽量使用执行较快的指令,需要根据不同的shape,通过不同的指令组合达到最佳的性能。
例如在float类型输入,shape大小为256时,使用两次WholeReduceSum或者三次BlockReduceSum都可以得到256个float的累加结果。考虑规约指令之间的组合,一次BlockReduceSum加一次WholeReduceSum也可以完成上述累加效果。由于单条指令,BlockReduceSum执行速度更快,所以性能更优于两次WholeReduceSum,并且由于只使用了两次规约指令,所以性能同样优于三次BlockReduceSum的方案。
【反例】
反例1: ... static constexpr uint32_t REP_LEN = 256; TBuf<QuePosition::VECCALC> calcBuf; pipe.InitBuffer(calcBuf, totalLength * sizeof(float)); AscendC::LocalTensor<float> tempTensor1 = calcBuf.Get<float>(); constexpr uint32_t repCount = REP_LEN / sizeof(float); const uint32_t repNum0 = (totalLength + repCount - 1) / repCount; AscendC::SetMaskCount(); AscendC::SetVectorMask<float>(0, totalLength); AscendC::WholeReduceSum<float, false>(tempTensor1, xLocal, AscendC::MASK_PLACEHOLDER, 1, DEFAULT_BLK_STRIDE, DEFAULT_BLK_STRIDE, DEFAULT_REP_STRIDE); AscendC::PipeBarrier<PIPE_V>(); AscendC::SetVectorMask<float>(0, repNum0); AscendC::WholeReduceSum<float, false>(zLocal, tempTensor1, AscendC::MASK_PLACEHOLDER, 1, DEFAULT_BLK_STRIDE, DEFAULT_BLK_STRIDE, DEFAULT_REP_STRIDE); AscendC::PipeBarrier<PIPE_V>(); AscendC::SetMaskNorm(); ... 反例2 ... constexpr uint32_t c0Count = BLK_LEN / sizeof(DTYPE_X); const uint32_t blockNum0 = (totalLength + c0Count - 1) / c0Count; const uint32_t blockNum1 = (blockNum0 + c0Count - 1) / c0Count; AscendC::SetMaskCount(); AscendC::SetVectorMask<DTYPE_X>(0, totalLength); AscendC::BlockReduceSum<DTYPE_X, false>(tempTensor1, xLocal, AscendC::MASK_PLACEHOLDER, 1, DEFAULT_BLK_STRIDE, DEFAULT_BLK_STRIDE, DEFAULT_REP_STRIDE); AscendC::PipeBarrier<PIPE_V>(); AscendC::SetVectorMask<DTYPE_X>(0, blockNum0); AscendC::BlockReduceSum<DTYPE_X, false>(tempTensor1, tempTensor1, AscendC::MASK_PLACEHOLDER, 1, DEFAULT_BLK_STRIDE, DEFAULT_BLK_STRIDE, DEFAULT_REP_STRIDE); AscendC::PipeBarrier<PIPE_V>(); AscendC::SetVectorMask<DTYPE_X>(0, blockNum1); AscendC::BlockReduceSum<DTYPE_X, false>(zLocal, tempTensor1, AscendC::MASK_PLACEHOLDER, 1, DEFAULT_BLK_STRIDE, DEFAULT_BLK_STRIDE, DEFAULT_REP_STRIDE); AscendC::PipeBarrier<PIPE_V>(); AscendC::SetMaskNorm(); ...
【正例】
当输入shape为256,输入类型为float时。采用一次BlockReduceSum加一次WholeReduceSum的组合方式实现将256个float元素求和。完整样例链接请参考ReduceCustom。
... static constexpr uint32_t BLK_LEN = 32; TBuf<QuePosition::VECCALC> calcBuf; pipe.InitBuffer(calcBuf, totalLength * sizeof(float)); AscendC::LocalTensor<float> tempTensor1 = calcBuf.Get<float>(); constexpr uint32_t c0Count = BLK_LEN / sizeof(float); const uint32_t blockNum0 = (totalLength + c0Count - 1) / c0Count; AscendC::SetMaskCount(); AscendC::SetVectorMask<float>(0, totalLength); AscendC::BlockReduceSum<float, false>(tempTensor1, xLocal, AscendC::MASK_PLACEHOLDER, 1, DEFAULT_BLK_STRIDE, DEFAULT_BLK_STRIDE, DEFAULT_REP_STRIDE); AscendC::PipeBarrier<PIPE_V>(); AscendC::SetVectorMask<float>(0, blockNum0); AscendC::WholeReduceSum<float, false>(zLocal, tempTensor1, AscendC::MASK_PLACEHOLDER, 1, DEFAULT_BLK_STRIDE, DEFAULT_BLK_STRIDE, DEFAULT_REP_STRIDE); AscendC::PipeBarrier<PIPE_V>(); AscendC::SetMaskNorm(); ...
【性能数据】
输入shape为256,数据类型为float。上述示例的性能数据如下:
反例1 |
反例2 |
正例 |
---|---|---|
13us |
13.94us |
8.44us |
父主题: API使用优化