* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
* \file quant_reduce_scatter_mte.h
* \brief quant_reduce_scatter mte通信kernel代码逻辑
*/
#ifndef QUANT_REDUCE_SCATTER_MTE_H
#define QUANT_REDUCE_SCATTER_MTE_H
#if ASC_DEVKIT_MAJOR >= 9
#include "basic_api/kernel_basic_intf.h"
#else
#include "kernel_operator.h"
#endif
#include "adv_api/hccl/hccl.h"
#include "adv_api/reduce/sum.h"
#include "adv_api/pad/broadcast.h"
#include "kernel_tiling/kernel_tiling.h"
#include "quant_reduce_scatter_tiling_data.h"
#include "utils.h"
#include "mte_comm.h"
#include "vec_comp.h"
namespace QuantReduceScatterImpl {
using namespace QuantMTECommImpl;
using namespace VectorComputeImpl;
using namespace AscendC;
constexpr static uint32_t X_PRE_BLOCK_NUM = 1024U;
constexpr static uint64_t MX_SCALES_LAST_DIM = 2U;
template<TemplateTypeClass>
class QuantReduceScatterMte {
public:
__aicore__ inline QuantReduceScatterMte() {};
__aicore__ inline void Init(GM_ADDR x, GM_ADDR scales, GM_ADDR output,
TPipe *pipe, const QuantReduceScatterTilingData *tilingData);
__aicore__ inline void Process();
private:
__aicore__ inline void ClearSumTensor();
__aicore__ inline void ReadDataBlockReduceSum(uint64_t curXOffset, uint64_t curScaleOffset);
__aicore__ inline void ExecuteReduceScatter();
MTECommunication<TemplateType> mteComm_;
VectorCompute<TemplateType> vecComp_;
GlobalTensor<XType> remoteWinXTensor_;
GlobalTensor<ScalesType> remoteWinScaleTensor_;
LocalTensor<float> sumTensor_;
TQue<QuePosition::VECIN, 1> xInQueue_, scaleInQue;
TBuf<> sumBuf_;
uint64_t xSize_{0};
uint64_t totalWinSize_{0};
uint64_t tailXNums_{0};
uint32_t totalBlockNums_{0};
uint64_t alignedXSize_{0};
uint64_t scaleSize_{0};
uint64_t xSliceSize_{0};
uint64_t xSliceSizeNums_{0};
uint64_t scaleSliceNums_{0};
};
template <TemplateTypeClass>
__aicore__ inline void QuantReduceScatterMte<TemplateType>::Init(GM_ADDR x, GM_ADDR scales,
GM_ADDR output, TPipe *tPipe, const QuantReduceScatterTilingData *tilingData)
{
mteComm_.InitHcclContext();
auto&& tiliingDatainfo = tilingData->quantReduceScatterTilingInfo;
totalWinSize_ = tiliingDatainfo.totalWinSize;
xSize_ = tiliingDatainfo.bs * tiliingDatainfo.hiddenSize * sizeof(XType);
scaleSize_ = tiliingDatainfo.bs * tiliingDatainfo.scaleHiddenSize * sizeof(ScalesType);
if constexpr(AscendC::IsSameType<ScalesType, fp8_e8m0_t>::value) {
scaleSize_ *= MX_SCALES_LAST_DIM;
}
xSliceSize_ = xSize_ / (mteComm_.hcclContext_->rankDim );
xSliceSizeNums_ = xSliceSize_ / sizeof(XType);
scaleSliceNums_ = scaleSize_ / (mteComm_.hcclContext_->rankDim * sizeof(ScalesType));
tailXNums_ = BlockAlignMod(xSliceSizeNums_, X_PRE_BLOCK_NUM);
totalBlockNums_ = CeilDiv(xSliceSize_, X_BLOCK_BYTES);
mteComm_.round_ = totalBlockNums_ / tiliingDatainfo.aivNum;
mteComm_.tailBlockNums_ = totalBlockNums_ % tiliingDatainfo.aivNum;
mteComm_.ComputeTailAivId(tiliingDatainfo.aivNum);
tPipe->Reset();
tPipe->InitBuffer(xInQueue_, BUFFER_NUM, X_BLOCK_BYTES);
tPipe->InitBuffer(scaleInQue, BUFFER_NUM, UB_ALIGN_BYTES);
tPipe->InitBuffer(sumBuf_, X_PRE_BLOCK_NUM * sizeof(float));
sumTensor_ = sumBuf_.Get<float>();
mteComm_.SetBlockSize(X_PRE_BLOCK_NUM, tiliingDatainfo.aivNum, tailXNums_);
vecComp_.SetBlockSize(X_PRE_BLOCK_NUM);
mteComm_.InitParams();
mteComm_.InitBuffer(tPipe);
vecComp_.InitBuffer(tPipe);
mteComm_.InitGMTensor(x, scales, output, xSize_, totalWinSize_);
}
template <TemplateTypeClass>
__aicore__ inline void QuantReduceScatterMte<TemplateType>::ReadDataBlockReduceSum(uint64_t curXOffset,
uint64_t curScaleOffset)
{
LocalTensor<XType> xTmpTensor = xInQueue_.AllocTensor<XType>();
DataCopy(xTmpTensor, remoteWinXTensor_[curXOffset], X_PRE_BLOCK_NUM);
xInQueue_.EnQue(xTmpTensor);
xTmpTensor = xInQueue_.DeQue<XType>();
LocalTensor<ScalesType> scaleTmpTensor = scaleInQue.AllocTensor<ScalesType>();
DataCopy(scaleTmpTensor, remoteWinScaleTensor_[curScaleOffset], mteComm_.scaleNumsPerBlcok_);
scaleInQue.EnQue(scaleTmpTensor);
scaleTmpTensor = scaleInQue.DeQue<ScalesType>();
vecComp_.DequantReduceSum(xTmpTensor, scaleTmpTensor, sumTensor_);
xInQueue_.FreeTensor(xTmpTensor);
scaleInQue.FreeTensor(scaleTmpTensor);
}
template <TemplateTypeClass>
__aicore__ inline void QuantReduceScatterMte<TemplateType>::ClearSumTensor()
{
Duplicate<float>(sumTensor_, (float)0.0, X_PRE_BLOCK_NUM);
}
template <TemplateTypeClass>
__aicore__ inline void QuantReduceScatterMte<TemplateType>::ExecuteReduceScatter()
{
mteComm_.ReadStatus();
for (uint64_t curBlock = 0; curBlock < mteComm_.assignedBlockNums_; ++curBlock) {
uint64_t curXOffset = mteComm_.xOffset_ + curBlock * X_PRE_BLOCK_NUM;
uint64_t curScaleOffset = mteComm_.scaleOffset_ + curBlock * mteComm_.scaleNumsPerBlcok_;
ClearSumTensor();
uint32_t startRankId = mteComm_.hcclContext_->rankId;
for (uint32_t i = 0; i < mteComm_.hcclContext_->rankDim; ++i) {
uint32_t remoteRankId = (startRankId + i) % mteComm_.hcclContext_->rankDim;
GM_ADDR remoteDataSpaceGm = mteComm_.GetWinDataAddrGm(remoteRankId, mteComm_.winBufferFlags_);
remoteWinXTensor_.SetGlobalBuffer((__gm__ XType*)remoteDataSpaceGm);
remoteWinScaleTensor_.SetGlobalBuffer((__gm__ ScalesType*)(remoteDataSpaceGm + xSize_));
uint64_t curRankXOffset = curXOffset + mteComm_.hcclContext_->rankId * xSliceSizeNums_;
uint64_t curRankScaleOffset = curScaleOffset + mteComm_.hcclContext_->rankId * scaleSliceNums_;
ReadDataBlockReduceSum(curRankXOffset, curRankScaleOffset);
}
uint32_t copyBlockNum = X_PRE_BLOCK_NUM;
if ((mteComm_.aivId_ == mteComm_.lastAivId_) && (curBlock == mteComm_.assignedBlockNums_ - 1)) {
copyBlockNum = tailXNums_;
}
mteComm_.CopyResultToOutput(curXOffset, sumTensor_, copyBlockNum);
}
}
template <TemplateTypeClass>
__aicore__ inline void QuantReduceScatterMte<TemplateType>::Process()
{
if ASCEND_IS_AIC {
return;
}
mteComm_.template CopyDataToWin<true>(xSliceSizeNums_, scaleSliceNums_);
mteComm_.WriteStatusToWin();
ExecuteReduceScatter();
}
}
#endif