| @@ -0,0 +1,1008 @@ |
| + |
| + * Copyright (c) 2026 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 MhcPreGradKernel.h |
| + * \brief |
| + */ |
| +#ifndef MHC_PRE_SINKHORN_BACKWARD_OP_KERNEL_MHC_PRE_GRAD_KERNEL_H |
| +#define MHC_PRE_SINKHORN_BACKWARD_OP_KERNEL_MHC_PRE_GRAD_KERNEL_H |
| + |
| +#include "kernel_operator.h" |
| +#include "lib/matmul_intf.h" |
| + |
| +using namespace AscendC; |
| + |
| +namespace { |
| +constexpr int32_t BYTE_SIZE_PER_BLOCK = 32; |
| +constexpr int32_t ELEMENTS_SIZE_PER_BLOCK = BYTE_SIZE_PER_BLOCK / sizeof(float); |
| +constexpr int32_t BYTE_SIZE_PER_REPEAT = 256; |
| +constexpr int32_t ELEMENTS_SIZE_PER_REPEAT = 256 / sizeof(float); |
| +constexpr int32_t REPEAT_LENTH = ELEMENTS_SIZE_PER_REPEAT; |
| +constexpr int32_t BLOCK_PER_REPEAT = 8; |
| +constexpr uint64_t MASK_PRE[] = {0b0000111100001111000011110000111100001111000011110000111100001111}; |
| +constexpr uint64_t MASK_POST[] = {0b1111000011110000111100001111000011110000111100001111000011110000}; |
| +constexpr uint64_t MASK_POST_SCALE[] = {0b0000000000000000000000000000000000000000000000000000000011110000}; |
| +constexpr int32_t PING_PONG_NUM = 2; |
| +constexpr int32_t PRE_POST_NUM = 2; |
| +constexpr int32_t DOUBLE_RATIO = 2; |
| + |
| +constexpr int32_t INNER_SPILT_NUM = 8; |
| + |
| +constexpr MatmulConfig MHC_PRE_GRAD_MM1_CFG = GetMDLConfig(false, false, 0, false, false, false, true); |
| +constexpr MatmulConfig MHC_PRE_GRAD_MM2_CFG = GetMDLConfig(false, false, 0, false, false, false, true); |
| +} |
| + |
| +template <typename TYPE_X, typename T> |
| +class MhcPreGradKernel { |
| +public: |
| + using A0Type = matmul::MatmulType<TPosition::GM, CubeFormat::ND, T>; |
| + using A1Type = matmul::MatmulType<TPosition::GM, CubeFormat::ND, T, true>; |
| + using BType = matmul::MatmulType<TPosition::GM, CubeFormat::ND, T>; |
| + using CType = matmul::MatmulType<TPosition::GM, CubeFormat::ND, T>; |
| + |
| + matmul::MatmulImpl<A0Type, BType, CType, CType, MHC_PRE_GRAD_MM1_CFG> mm1_; |
| + matmul::MatmulImpl<A1Type, BType, CType, CType, MHC_PRE_GRAD_MM2_CFG> mm2_; |
| + |
| + __aicore__ inline MhcPreGradKernel() = default; |
| + |
| + __aicore__ inline void Init(GM_ADDR x, GM_ADDR hc_fn, GM_ADDR pre, GM_ADDR grad_y, GM_ADDR grad_post, |
| + GM_ADDR grad_comb, GM_ADDR hc_scale, GM_ADDR hc_base, GM_ADDR h_hat2, GM_ADDR rsqrt, |
| + GM_ADDR sum_out, GM_ADDR norm_out, GM_ADDR grad_x, GM_ADDR grad_hc_fn, |
| + GM_ADDR grad_hc_scale, GM_ADDR grad_hc_base, GM_ADDR workspace, |
| + const MhcPreSinkhornBackwardTilingData *tilingData, TPipe *pipe) |
| + { |
| + pipe_ = pipe; |
| + blkIdx_ = GetBlockIdx(); |
| + |
| + InitTiling(tilingData); |
| + InitGM(x, hc_fn, pre, grad_y, grad_post, grad_comb, hc_scale, hc_base, h_hat2, rsqrt, sum_out, norm_out, grad_x, |
| + grad_hc_fn, grad_hc_scale, grad_hc_base, workspace); |
| + InitGradPreStageBuffer(); |
| + } |
| + __aicore__ inline void Process(); |
| + |
| +protected: |
| + int64_t blkIdx_, aivNum_, aicNum_; |
| + TPipe *pipe_; |
| + int64_t batchSize_, seqLength_, totalTasks_, totalTasksAligned_, BSNN, BSN; |
| + int64_t c_, n_, c0_, c1_, cTail_, c0RepeatTime_, cTailAlign_, cTailBlockStride_, c1Align_; |
| + int64_t tileCoreBS_; |
| + int64_t skIterCount_; |
| + int64_t ubSize_; |
| + int64_t mm1K_, mm1M_, mm1N_; |
| + int64_t mm2K_, mm2M_, mm2N_; |
| + int64_t tileRepeatTimes_; |
| + float eps_; |
| + event_t eventIdVToMTE3XCast; |
| + |
| + T hcScalePre_, hcScalePost_, hcScaleRes_; |
| + |
| + TQue<QuePosition::VECIN, 1> inputXInQueue; |
| + TQue<QuePosition::VECIN, 1> inputGradQueue; |
| + |
| + TQue<QuePosition::VECIN, 1> SKInQueue; |
| + |
| + TQue<QuePosition::VECOUT, 1> OutQueue; |
| + |
| + TBuf<TPosition::VECCALC> fusedGradHPre2AndGradHPost2Buf_, gradRsqrtBuf_, gradBiasBuf_, onesBuf_, ScaleBuf_, |
| + hcBaseBuf_, tempBuf_; |
| + |
| + LocalTensor<T> dBiasLocal_, gradRsqrtLocal_, dPrePostTempLocal_; |
| + LocalTensor<T> xCastLocal_, gradYCastLocal_, gradXCastLocal_; |
| + LocalTensor<T> scaleLocal_, dScaleLocal_; |
| + int32_t onceTask_; |
| + LocalTensor<T> gradHResLocal_; |
| + LocalTensor<T> hcBaseLocal_; |
| + LocalTensor<T> preBrcbLocal_, dRsqrtBrcbLocal_, rsqrtbrcbLocal_, tmpLocal_, hat2Scale, dhatBeforeNormLocal, |
| + gradHResTempLocal_, gradHResTempLocal2_, dhatLocal_, rsqrtTempLocal_, gradXCubeLocal_; |
| + |
| + LocalTensor<T> hatLocal; |
| + LocalTensor<T> onesLocal_; |
| + |
| + GlobalTensor<TYPE_X> xGlobal_, gradYGlobal_; |
| + GlobalTensor<T> preGlobal_; |
| + GlobalTensor<TYPE_X> gradXGlobal_; |
| + GlobalTensor<T> gradPreGlobal_, gradPostGlobal_; |
| + GlobalTensor<T> hcScaleGlobal_, hcBaseGlobal_; |
| + GlobalTensor<T> rsqrtGlobal_; |
| + GlobalTensor<T> gradHcScaleGlobal_, gradHcBaseGlobal_; |
| + GlobalTensor<T> h2Global_; |
| + GlobalTensor<T> skNormGlobal_, skSumGlobal_; |
| + GlobalTensor<T> gradHResGlobal_; |
| + GlobalTensor<T> gradH2Global_; |
| + GlobalTensor<T> gradWeightGlobal_; |
| + GlobalTensor<T> weightGlobal_; |
| + GlobalTensor<T> gradHcBaseWSGlobal_; |
| + GlobalTensor<T> gradHcScaleWSGlobal_; |
| + GlobalTensor<T> xWorkspaceGlobal_; |
| + GlobalTensor<T> gradXCubeGlobal_; |
| + |
| +private: |
| + __aicore__ inline void InitTiling(const MhcPreSinkhornBackwardTilingData *tilingData) |
| + { |
| + batchSize_ = tilingData->batchSize; |
| + seqLength_ = tilingData->seqLength; |
| + aivNum_ = tilingData->aivNum; |
| + aicNum_ = tilingData->aivNum / DOUBLE_RATIO; |
| + c_ = tilingData->c; |
| + n_ = tilingData->n; |
| + c0_ = tilingData->c0; |
| + c1_ = tilingData->c1; |
| + BSNN = batchSize_ * seqLength_ * n_ * n_; |
| + BSN = batchSize_ * seqLength_ * n_; |
| + c1Align_ = CeilDiv(c_, c0_); |
| + cTail_ = max((c_ - (c1Align_ - 1) * c0_), static_cast<int64_t>(0)); |
| + |
| + cTailAlign_ = AlignUp(cTail_, ELEMENTS_SIZE_PER_BLOCK); |
| + cTailBlockStride_ = c0_ / ELEMENTS_SIZE_PER_BLOCK - cTailAlign_ / ELEMENTS_SIZE_PER_BLOCK; |
| + skIterCount_ = tilingData->skIterCount; |
| + ubSize_ = tilingData->ubSize; |
| + eps_ = tilingData->eps; |
| + tileCoreBS_ = tilingData->tileSize; |
| + |
| + c0RepeatTime_ = c0_ / ELEMENTS_SIZE_PER_REPEAT; |
| + totalTasks_ = batchSize_ * seqLength_; |
| + totalTasksAligned_ = AlignUp(totalTasks_, aivNum_ * tileCoreBS_); |
| + if ASCEND_IS_AIC { |
| + mm1K_ = n_ * n_ + PRE_POST_NUM * n_; |
| + mm1M_ = tileCoreBS_ * 2; |
| + mm1N_ = n_ * c_; |
| + |
| + mm2K_ = batchSize_ * seqLength_; |
| + mm2M_ = n_ * n_ + PRE_POST_NUM * n_; |
| + mm2N_ = n_ * c_; |
| + } |
| + } |
| + |
| + __aicore__ inline void InitGM(GM_ADDR x, GM_ADDR hc_fn, GM_ADDR pre, GM_ADDR grad_y, GM_ADDR grad_post, |
| + GM_ADDR grad_comb, GM_ADDR hc_scale, GM_ADDR hc_base, GM_ADDR h_hat2, GM_ADDR rsqrt, |
| + GM_ADDR sum_out, GM_ADDR norm_out, GM_ADDR grad_x, GM_ADDR grad_hc_fn, |
| + GM_ADDR grad_hc_scale, GM_ADDR grad_hc_base, GM_ADDR workspace) |
| + { |
| + |
| + xGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ TYPE_X *>(x)); |
| + gradWeightGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(grad_hc_fn)); |
| + int64_t workspaceOffset = 0; |
| + gradH2Global_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(workspace) + workspaceOffset); |
| + workspaceOffset += batchSize_ * seqLength_ * (n_ * PRE_POST_NUM + n_ * n_); |
| + xWorkspaceGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(workspace) + workspaceOffset); |
| + workspaceOffset += batchSize_ * seqLength_ * (n_ * c_); |
| + gradXCubeGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(workspace) + workspaceOffset); |
| + |
| + workspaceOffset += batchSize_ * seqLength_ * (n_ * c_); |
| + weightGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(hc_fn)); |
| + gradXGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ TYPE_X *>(grad_x)); |
| + |
| + if ASCEND_IS_AIV { |
| + preGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(pre)); |
| + gradYGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ TYPE_X *>(grad_y)); |
| + |
| + gradPostGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(grad_post)); |
| + |
| + hcScaleGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(hc_scale)); |
| + hcBaseGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(hc_base)); |
| + |
| + rsqrtGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(rsqrt)); |
| + gradHcScaleGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(grad_hc_scale)); |
| + gradHcBaseGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(grad_hc_base)); |
| + gradHcScaleWSGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(workspace) + workspaceOffset); |
| + workspaceOffset += aivNum_ * (n_ * 2 + n_ * n_); |
| + gradHcBaseWSGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(workspace) + workspaceOffset); |
| + workspaceOffset += aivNum_ * (n_ * 2 + n_ * n_); |
| + |
| + h2Global_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(h_hat2)); |
| + |
| + skNormGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(norm_out)); |
| + skSumGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(sum_out)); |
| + |
| + gradHResGlobal_.SetGlobalBuffer(reinterpret_cast<__gm__ T *>(grad_comb)); |
| + if (blkIdx_ == aivNum_ - 1) { |
| + InitOutput<T>(gradHcBaseGlobal_, (n_ * n_ + PRE_POST_NUM * n_), 0); |
| + InitOutput<T>(gradHcScaleGlobal_, 3, 0); |
| + } |
| + for (int64_t taskOffset = blkIdx_ * tileCoreBS_; taskOffset < n_ * c_; |
| + taskOffset += aivNum_ * tileCoreBS_) { |
| + int32_t tileTaskCount = |
| + min(static_cast<int32_t>(tileCoreBS_), static_cast<int32_t>(n_ * c_ - taskOffset)); |
| + InitOutput<T>(gradWeightGlobal_[taskOffset * (n_ * n_ + PRE_POST_NUM * n_)], |
| + (n_ * n_ + PRE_POST_NUM * n_) * tileTaskCount, 0); |
| + } |
| + SyncAll<true>(); |
| + } |
| + } |
| + |
| + __aicore__ inline void InitGradPreStageBuffer() |
| + { |
| + if ASCEND_IS_AIV { |
| + pipe_->InitBuffer(fusedGradHPre2AndGradHPost2Buf_, tileCoreBS_ * n_ * 2 * sizeof(float)); |
| + pipe_->InitBuffer(gradRsqrtBuf_, tileCoreBS_ * (n_ * n_ + 2 * n_) * sizeof(float) * 2); |
| + pipe_->InitBuffer(gradBiasBuf_, 2 * tileCoreBS_ * (n_ * n_ + 2 * n_) * sizeof(float)); |
| + pipe_->InitBuffer(onesBuf_, tileCoreBS_ * n_ * 2 * sizeof(float)); |
| + pipe_->InitBuffer(hcBaseBuf_, (n_ * n_ + 2 * n_) * sizeof(float)); |
| + pipe_->InitBuffer(ScaleBuf_, BYTE_SIZE_PER_BLOCK * 2); |
| + pipe_->InitBuffer(inputXInQueue, 2, tileCoreBS_ * n_ * c0_ * sizeof(float) / 4); |
| + pipe_->InitBuffer(inputGradQueue, 1, tileCoreBS_ * n_ * ELEMENTS_SIZE_PER_BLOCK * sizeof(float)); |
| + pipe_->InitBuffer(SKInQueue, 2, |
| + tileCoreBS_ * (n_ * ELEMENTS_SIZE_PER_BLOCK + ELEMENTS_SIZE_PER_BLOCK * 2) * |
| + sizeof(float)); |
| + pipe_->InitBuffer(OutQueue, 2, tileCoreBS_ * n_ * c0_ * sizeof(float) / 8); |
| + auto ubSizeRemain = |
| + CeilDiv(tileCoreBS_, ELEMENTS_SIZE_PER_BLOCK) * ELEMENTS_SIZE_PER_REPEAT * sizeof(float) + |
| + CeilDiv(tileCoreBS_ * n_, ELEMENTS_SIZE_PER_BLOCK) * ELEMENTS_SIZE_PER_REPEAT * sizeof(float) + |
| + onceTask_ * n_ * c0_ * sizeof(float) * 2 + onceTask_ * c0_ * sizeof(float); |
| + |
| + pipe_->InitBuffer(tempBuf_, ubSizeRemain); |
| + |
| + eventIdVToMTE3XCast = static_cast<event_t>(GetTPipePtr()->AllocEventID<HardEvent::V_MTE3>()); |
| + dPrePostTempLocal_ = fusedGradHPre2AndGradHPost2Buf_.Get<T>(); |
| + hcBaseLocal_ = hcBaseBuf_.Get<T>(); |
| + onesLocal_ = onesBuf_.Get<T>(); |
| + scaleLocal_ = ScaleBuf_.Get<T>(); |
| + gradRsqrtLocal_ = gradRsqrtBuf_.Get<T>(); |
| + dBiasLocal_ = gradBiasBuf_.Get<T>(); |
| + dScaleLocal_ = dBiasLocal_[tileCoreBS_ * (n_ * n_ + PRE_POST_NUM * n_)]; |
| + |
| + onceTask_ = tileCoreBS_ / INNER_SPILT_NUM; |
| + |
| + int32_t offset = 0; |
| + int32_t brcbAlign = CeilDiv(tileCoreBS_ * n_, ELEMENTS_SIZE_PER_BLOCK); |
| + preBrcbLocal_ = tempBuf_.GetWithOffset<T>(brcbAlign * ELEMENTS_SIZE_PER_REPEAT, offset); |
| + offset += brcbAlign * ELEMENTS_SIZE_PER_REPEAT * sizeof(float); |
| + brcbAlign = CeilDiv(tileCoreBS_, ELEMENTS_SIZE_PER_BLOCK); |
| + dRsqrtBrcbLocal_ = tempBuf_.GetWithOffset<T>(brcbAlign * ELEMENTS_SIZE_PER_REPEAT, offset); |
| + offset += brcbAlign * ELEMENTS_SIZE_PER_REPEAT * sizeof(float); |
| + gradYCastLocal_ = tempBuf_.GetWithOffset<T>(onceTask_ * c0_, offset); |
| + offset += onceTask_ * c0_ * sizeof(float); |
| + gradXCastLocal_ = tempBuf_.GetWithOffset<T>(onceTask_ * n_ * c0_, offset); |
| + offset += onceTask_ * n_ * c0_ * sizeof(float); |
| + xCastLocal_ = tempBuf_.GetWithOffset<T>(onceTask_ * n_ * c0_, offset); |
| + offset = 0; |
| + |
| + tmpLocal_ = gradXCastLocal_; |
| + |
| + |
| + gradHResTempLocal_ = |
| + tempBuf_.GetWithOffset<T>(tileCoreBS_ * n_ * ELEMENTS_SIZE_PER_BLOCK * 2, offset); |
| + offset += tileCoreBS_ * n_ * ELEMENTS_SIZE_PER_BLOCK * 2 * sizeof(float); |
| + gradHResTempLocal2_ = tempBuf_.GetWithOffset<T>(tileCoreBS_ * n_ * ELEMENTS_SIZE_PER_BLOCK, offset); |
| + offset = 0; |
| + |
| + dhatLocal_ = tempBuf_.GetWithOffset<T>(tileCoreBS_ * (n_ * n_ + PRE_POST_NUM * n_), offset); |
| + offset += tileCoreBS_ * (n_ * n_ + PRE_POST_NUM * n_) * sizeof(float); |
| + brcbAlign = CeilDiv(tileCoreBS_, ELEMENTS_SIZE_PER_BLOCK); |
| + rsqrtbrcbLocal_ = |
| + tempBuf_.GetWithOffset<T>(brcbAlign * ELEMENTS_SIZE_PER_BLOCK * (n_ * n_ + PRE_POST_NUM * n_), offset); |
| + offset += brcbAlign * ELEMENTS_SIZE_PER_BLOCK * (n_ * n_ + PRE_POST_NUM * n_) * sizeof(float); |
| + hat2Scale = tempBuf_.GetWithOffset<T>(tileCoreBS_ * (n_ * n_ + PRE_POST_NUM * n_), offset); |
| + offset += tileCoreBS_ * (n_ * n_ + PRE_POST_NUM * n_) * sizeof(float); |
| + dhatBeforeNormLocal = tempBuf_.GetWithOffset<T>(tileCoreBS_ * (2 * n_), offset); |
| + offset += tileCoreBS_ * (n_ * n_ + PRE_POST_NUM * n_) * sizeof(float); |
| + hatLocal = tempBuf_.GetWithOffset<T>(tileCoreBS_ * (n_ * n_ + PRE_POST_NUM * n_), offset); |
| + offset += tileCoreBS_ * (n_ * n_ + PRE_POST_NUM * n_) * sizeof(float); |
| + rsqrtTempLocal_ = tempBuf_.GetWithOffset<T>(tileCoreBS_ * (n_ * n_ + PRE_POST_NUM * n_), offset); |
| + |
| + Duplicate(onesLocal_, 1.f, tileCoreBS_ * n_ * 2); |
| + Duplicate(dScaleLocal_, 0.f, tileCoreBS_ * (2 * n_ + n_ * n_)); |
| + Duplicate(dBiasLocal_, 0.f, tileCoreBS_ * (2 * n_ + n_ * n_)); |
| + } |
| + } |
| + |
| + __aicore__ inline void ComputeGradPre(const int32_t taskOffset, const int32_t tileTaskCount, const int32_t innerId); |
| + |
| + __aicore__ inline void ComputeGradHHat2(const int32_t taskOffset, const int32_t tileTaskCount); |
| + __aicore__ inline void SinkhornGrad(const int32_t taskOffset, const int32_t tileTaskCount); |
| + |
| + __aicore__ inline void ComputeGradX1(const int32_t taskOffset, const int32_t tileTaskCount, const int32_t innerId); |
| + __aicore__ inline void GetHcScaleAndHcBase(); |
| + __aicore__ inline void ProcessMatmul1(const int32_t taskOffset, const int32_t mm1M); |
| + __aicore__ inline void ProcessMatmul2(const int32_t taskOffset, const int32_t mm2K); |
| + __aicore__ inline void ComputeScaleBias(); |
| +}; |
| + |
| +template <typename TYPE_X, typename T> |
| +__aicore__ inline void MhcPreGradKernel<TYPE_X, T>::GetHcScaleAndHcBase() |
| +{ |
| + |
| + hcScalePre_ = hcScaleGlobal_.GetValue(0); |
| + hcScalePost_ = hcScaleGlobal_.GetValue(1); |
| + hcScaleRes_ = hcScaleGlobal_.GetValue(2); |
| + event_t eventIDSToV = static_cast<event_t>(GetTPipePtr()->FetchEventID(HardEvent::S_V)); |
| + SetFlag<HardEvent::S_V>(eventIDSToV); |
| + WaitFlag<HardEvent::S_V>(eventIDSToV); |
| + Duplicate(scaleLocal_[8], hcScaleRes_, 8); |
| + Duplicate(scaleLocal_, hcScalePost_, 8); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Duplicate(scaleLocal_, hcScalePre_, 4); |
| + |
| + DataCopyPad(hcBaseLocal_, hcBaseGlobal_, |
| + {static_cast<uint16_t>(1), static_cast<uint32_t>((n_ * n_ + PRE_POST_NUM * n_) * sizeof(T)), 0, 0, 0}, |
| + {false, 0, 0, 0}); |
| +} |
| + |
| +template <typename TYPE_X, typename T> |
| +__aicore__ inline void MhcPreGradKernel<TYPE_X, T>::SinkhornGrad(const int32_t taskOffset, const int32_t tileTaskCount) |
| +{ |
| + gradHResLocal_ = inputGradQueue.AllocTensor<T>(); |
| + |
| + DataCopyPad(gradHResLocal_, gradHResGlobal_[taskOffset * n_ * n_], |
| + {static_cast<uint16_t>(tileTaskCount * n_), static_cast<uint32_t>(n_ * sizeof(T)), 0, 0, 0}, |
| + {true, 0, static_cast<uint8_t>(ELEMENTS_SIZE_PER_BLOCK - n_), 0}); |
| + inputGradQueue.EnQue(gradHResLocal_); |
| + inputGradQueue.DeQue(); |
| + |
| + int64_t iterRowNormOffset = (skIterCount_ - 1) * 2 * BSNN + taskOffset * n_ * n_; |
| + int64_t iterColNormOffset = ((skIterCount_ - 1) * 2 + 1) * BSNN + taskOffset * n_ * n_; |
| + |
| + int64_t iterRowSumOffset = (skIterCount_ - 1) * 2 * BSN + taskOffset * n_; |
| + int64_t iterColSumOffset = ((skIterCount_ - 1) * 2 + 1) * BSN + taskOffset * n_; |
| + int32_t brcbAlign = CeilDiv(tileTaskCount * n_, ELEMENTS_SIZE_PER_BLOCK); |
| + for (int32_t iter = skIterCount_ - 1; iter > 0; iter--) { |
| + auto skRowNormLocal_ = SKInQueue.AllocTensor<T>(); |
| + auto skRowSumLocal_ = skRowNormLocal_[tileCoreBS_ * n_ * ELEMENTS_SIZE_PER_BLOCK]; |
| + auto skColSumLocal_ = |
| + skRowNormLocal_[tileCoreBS_ * n_ * ELEMENTS_SIZE_PER_BLOCK + tileCoreBS_ * ELEMENTS_SIZE_PER_BLOCK]; |
| + |
| + DataCopyPad(skRowNormLocal_, skNormGlobal_[iterRowNormOffset], |
| + {static_cast<uint16_t>(tileTaskCount * n_), static_cast<uint32_t>(n_ * sizeof(T)), 0, 0, 0}, |
| + {true, 0, static_cast<uint8_t>(ELEMENTS_SIZE_PER_BLOCK - n_), 0}); |
| + DataCopyPad(skColSumLocal_, skSumGlobal_[iterColSumOffset], |
| + {static_cast<uint16_t>(tileTaskCount), static_cast<uint32_t>(n_ * sizeof(T)), 0, 0, 0}, |
| + {true, 0, static_cast<uint8_t>(ELEMENTS_SIZE_PER_BLOCK - n_), 0}); |
| + DataCopyPad(skRowSumLocal_, skSumGlobal_[iterRowSumOffset], |
| + {static_cast<uint16_t>(1), static_cast<uint32_t>(tileTaskCount * n_ * sizeof(T)), 0, 0, 0}, |
| + {false, 0, static_cast<uint8_t>(ELEMENTS_SIZE_PER_BLOCK - n_), 0}); |
| + SKInQueue.EnQue(skRowNormLocal_); |
| + SKInQueue.DeQue(); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Adds(skColSumLocal_, skColSumLocal_, eps_, tileTaskCount * ELEMENTS_SIZE_PER_BLOCK); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + |
| + for (int32_t loopIdN = 0; loopIdN < n_; loopIdN += 1) { |
| + Div(gradHResTempLocal_[loopIdN * ELEMENTS_SIZE_PER_BLOCK], |
| + gradHResLocal_[loopIdN * ELEMENTS_SIZE_PER_BLOCK], skColSumLocal_, ELEMENTS_SIZE_PER_REPEAT, |
| + tileRepeatTimes_, |
| + {static_cast<uint8_t>(n_), static_cast<uint8_t>(n_), 1, static_cast<uint8_t>(n_ * 8), |
| + static_cast<uint8_t>(n_ * 8), 8}); |
| + } |
| + |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Mul(gradHResTempLocal2_, gradHResLocal_, skRowNormLocal_, tileTaskCount * n_ * ELEMENTS_SIZE_PER_BLOCK); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Mul(skColSumLocal_, skColSumLocal_, skColSumLocal_, tileTaskCount * ELEMENTS_SIZE_PER_BLOCK); |
| + |
| + |
| + |
| + for (int32_t loopIdN = 1; loopIdN < n_; loopIdN += 1) { |
| + Add(gradHResTempLocal2_, gradHResTempLocal2_, gradHResTempLocal2_[loopIdN * ELEMENTS_SIZE_PER_BLOCK], |
| + ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, |
| + {static_cast<uint8_t>(n_), static_cast<uint8_t>(n_), static_cast<uint8_t>(n_), |
| + static_cast<uint8_t>(n_ * 8), static_cast<uint8_t>(n_ * 8), static_cast<uint8_t>(n_ * 8)}); |
| + PipeBarrier<PIPE_V>(); |
| + } |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Div(gradHResTempLocal2_, gradHResTempLocal2_, skColSumLocal_, ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, |
| + {static_cast<uint8_t>(n_), static_cast<uint8_t>(n_), 1, static_cast<uint8_t>(n_ * 8), |
| + static_cast<uint8_t>(n_ * 8), 8}); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + for (int32_t loopIdN = 0; loopIdN < n_; loopIdN += 1) { |
| + Sub(gradHResLocal_[loopIdN * ELEMENTS_SIZE_PER_BLOCK], |
| + gradHResTempLocal_[loopIdN * ELEMENTS_SIZE_PER_BLOCK], gradHResTempLocal2_, ELEMENTS_SIZE_PER_REPEAT, |
| + tileRepeatTimes_, |
| + {static_cast<uint8_t>(n_), static_cast<uint8_t>(n_), static_cast<uint8_t>(n_), |
| + static_cast<uint8_t>(n_ * 8), static_cast<uint8_t>(n_ * 8), static_cast<uint8_t>(n_ * 8)}); |
| + } |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Adds(skRowSumLocal_, skRowSumLocal_, eps_, tileTaskCount * n_); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Brcb(gradHResTempLocal2_, skRowSumLocal_, brcbAlign, {1, 8}); |
| + |
| + PipeBarrier<PIPE_V>(); |
| + Div(gradHResTempLocal_, gradHResLocal_, gradHResTempLocal2_, tileTaskCount * n_ * ELEMENTS_SIZE_PER_BLOCK); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Mul(skRowNormLocal_, skRowNormLocal_, gradHResTempLocal_, tileTaskCount * n_ * ELEMENTS_SIZE_PER_BLOCK); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + AscendC::BlockReduceSum(skRowNormLocal_, skRowNormLocal_, |
| + static_cast<int32_t>(static_cast<int64_t>(tileRepeatTimes_) * n_), MASK_PRE, 1, 1, 8); |
| + |
| + PipeBarrier<PIPE_V>(); |
| + Brcb(gradHResTempLocal2_, skRowNormLocal_, brcbAlign, {1, 8}); |
| + SKInQueue.FreeTensor(skRowNormLocal_); |
| + |
| + PipeBarrier<PIPE_V>(); |
| + Sub(gradHResLocal_, gradHResTempLocal_, gradHResTempLocal2_, tileTaskCount * n_ * ELEMENTS_SIZE_PER_BLOCK); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + iterRowNormOffset = iterRowNormOffset - 2 * BSNN; |
| + iterRowSumOffset = iterRowSumOffset - 2 * BSN; |
| + iterColSumOffset = iterColSumOffset - 2 * BSN; |
| + } |
| + auto skRowNormLocal_ = SKInQueue.AllocTensor<T>(); |
| + auto skColSumLocal_ = skRowNormLocal_[tileCoreBS_ * n_ * ELEMENTS_SIZE_PER_BLOCK]; |
| + DataCopyPad(skRowNormLocal_, skNormGlobal_[iterRowNormOffset], |
| + {static_cast<uint16_t>(tileTaskCount * n_), static_cast<uint32_t>(n_ * sizeof(T)), 0, 0, 0}, |
| + {true, 0, static_cast<uint8_t>(ELEMENTS_SIZE_PER_BLOCK - n_), 0}); |
| + DataCopyPad(skColSumLocal_, skSumGlobal_[iterColSumOffset], |
| + {static_cast<uint16_t>(tileTaskCount), static_cast<uint32_t>(n_ * sizeof(T)), 0, 0, 0}, |
| + {true, 0, static_cast<uint8_t>(ELEMENTS_SIZE_PER_BLOCK - n_), 0}); |
| + PipeBarrier<PIPE_V>(); |
| + SKInQueue.EnQue(skRowNormLocal_); |
| + |
| + SKInQueue.DeQue(); |
| + Adds(skColSumLocal_, skColSumLocal_, eps_, tileTaskCount * ELEMENTS_SIZE_PER_BLOCK); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + for (int32_t loopIdN = 0; loopIdN < n_; loopIdN += 1) { |
| + Div(gradHResTempLocal_[loopIdN * ELEMENTS_SIZE_PER_BLOCK], gradHResLocal_[loopIdN * ELEMENTS_SIZE_PER_BLOCK], |
| + skColSumLocal_, ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, |
| + {static_cast<uint8_t>(n_), static_cast<uint8_t>(n_), 1, static_cast<uint8_t>(n_ * 8), |
| + static_cast<uint8_t>(n_ * 8), 8}); |
| + } |
| + |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Mul(gradHResTempLocal2_, gradHResLocal_, skRowNormLocal_, tileTaskCount * n_ * ELEMENTS_SIZE_PER_BLOCK); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Mul(skColSumLocal_, skColSumLocal_, skColSumLocal_, tileTaskCount * ELEMENTS_SIZE_PER_BLOCK); |
| + |
| + |
| + for (int32_t loopIdN = 1; loopIdN < n_; loopIdN += 1) { |
| + Add(gradHResTempLocal2_, gradHResTempLocal2_, gradHResTempLocal2_[loopIdN * ELEMENTS_SIZE_PER_BLOCK], |
| + ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, |
| + {static_cast<uint8_t>(n_), static_cast<uint8_t>(n_), static_cast<uint8_t>(n_), static_cast<uint8_t>(n_ * 8), |
| + static_cast<uint8_t>(n_ * 8), static_cast<uint8_t>(n_ * 8)}); |
| + PipeBarrier<PIPE_V>(); |
| + } |
| + |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Div(gradHResTempLocal2_, gradHResTempLocal2_, skColSumLocal_, ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, |
| + {static_cast<uint8_t>(n_), static_cast<uint8_t>(n_), 1, static_cast<uint8_t>(n_ * 8), |
| + static_cast<uint8_t>(n_ * 8), 8}); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + for (int32_t loopIdN = 0; loopIdN < n_; loopIdN += 1) { |
| + Sub(gradHResLocal_[loopIdN * ELEMENTS_SIZE_PER_BLOCK], gradHResTempLocal_[loopIdN * ELEMENTS_SIZE_PER_BLOCK], |
| + gradHResTempLocal2_, ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, |
| + {static_cast<uint8_t>(n_), static_cast<uint8_t>(n_), static_cast<uint8_t>(n_), static_cast<uint8_t>(n_ * 8), |
| + static_cast<uint8_t>(n_ * 8), static_cast<uint8_t>(n_ * 8)}); |
| + } |
| + |
| + PipeBarrier<PIPE_V>(); |
| + Mul(gradHResTempLocal_, gradHResLocal_, skRowNormLocal_, tileTaskCount * n_ * ELEMENTS_SIZE_PER_BLOCK); |
| + SKInQueue.FreeTensor(skRowNormLocal_); |
| + |
| + PipeBarrier<PIPE_V>(); |
| + AscendC::BlockReduceSum(gradHResTempLocal_, gradHResTempLocal_, |
| + static_cast<int32_t>(static_cast<int64_t>(tileRepeatTimes_) * n_), MASK_PRE, 1, 1, 8); |
| + PipeBarrier<PIPE_V>(); |
| + Brcb(gradHResTempLocal2_, gradHResTempLocal_, brcbAlign, {1, 8}); |
| + PipeBarrier<PIPE_V>(); |
| + Sub(gradHResLocal_, gradHResLocal_, gradHResTempLocal2_, tileTaskCount * n_ * ELEMENTS_SIZE_PER_BLOCK); |
| + PipeBarrier<PIPE_V>(); |
| + Mul(gradHResLocal_, gradHResLocal_, skRowNormLocal_, tileTaskCount * n_ * ELEMENTS_SIZE_PER_BLOCK); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Cast(gradHResTempLocal_.template ReinterpretCast<int64_t>(), gradHResLocal_.template ReinterpretCast<int32_t>(), |
| + RoundMode::CAST_NONE, tileTaskCount * n_ * ELEMENTS_SIZE_PER_BLOCK); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Copy(gradHResLocal_, gradHResTempLocal_, ELEMENTS_SIZE_PER_REPEAT, n_ * tileRepeatTimes_, {1, 2, 8, 16}); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Cast(gradHResLocal_.template ReinterpretCast<int32_t>(), gradHResLocal_.template ReinterpretCast<int64_t>(), |
| + RoundMode::CAST_NONE, tileTaskCount * n_ * n_); |
| + |
| + PipeBarrier<PIPE_V>(); |
| +} |
| + |
| +template <typename TYPE_X, typename T> |
| +__aicore__ inline void MhcPreGradKernel<TYPE_X, T>::ComputeGradHHat2(const int32_t taskOffset, |
| + const int32_t tileTaskCount) |
| +{ |
| + SinkhornGrad(taskOffset, tileTaskCount); |
| + for (int32_t loopIdN = 0; loopIdN < 2; loopIdN += 1) { |
| + Copy(dhatLocal_[ELEMENTS_SIZE_PER_BLOCK + loopIdN * ELEMENTS_SIZE_PER_BLOCK], |
| + gradHResLocal_[loopIdN * ELEMENTS_SIZE_PER_BLOCK], ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, |
| + {static_cast<uint16_t>(3), static_cast<uint16_t>(2), static_cast<uint16_t>((2 + 1) * 8), |
| + static_cast<uint16_t>(2 * 8)}); |
| + } |
| + |
| + inputGradQueue.FreeTensor(gradHResLocal_); |
| + |
| + auto gradHPostLocal_ = inputXInQueue.AllocTensor<T>(); |
| + auto hat2LocalTemp = gradHPostLocal_[tileCoreBS_ * ELEMENTS_SIZE_PER_BLOCK]; |
| + auto rsqrtLocal_ = |
| + gradHPostLocal_[tileCoreBS_ * ELEMENTS_SIZE_PER_BLOCK + tileCoreBS_ * (n_ * n_ + PRE_POST_NUM * n_)]; |
| + |
| + DataCopyPad(gradHPostLocal_, gradPostGlobal_[taskOffset * n_], |
| + {static_cast<uint16_t>(tileTaskCount), static_cast<uint32_t>(n_ * sizeof(T)), 0, 0, 0}, |
| + {true, static_cast<uint8_t>(ELEMENTS_SIZE_PER_BLOCK - n_), 0, 0}); |
| + |
| + DataCopyPad(hat2LocalTemp, h2Global_[taskOffset * (n_ * n_ + PRE_POST_NUM * n_)], |
| + {static_cast<uint16_t>(tileTaskCount), static_cast<uint32_t>((n_ * n_ + PRE_POST_NUM * n_) * sizeof(T)), |
| + 0, 0, 0}, |
| + {false, 0, 0, 0}); |
| + DataCopyPad(rsqrtLocal_, rsqrtGlobal_[taskOffset], |
| + {static_cast<uint16_t>(1), static_cast<uint32_t>(tileTaskCount * sizeof(T)), 0, 0, 0}, |
| + {false, 0, 0, 0}); |
| + inputXInQueue.EnQue(gradHPostLocal_); |
| + inputXInQueue.DeQue(); |
| + |
| + PipeBarrier<PIPE_V>(); |
| + |
| + |
| + Axpy(dPrePostTempLocal_, gradHPostLocal_, float(2), tileTaskCount * 2 * n_); |
| + |
| + const uint32_t srcShape[2] = {static_cast<uint32_t>(tileTaskCount * n_), 1}; |
| + const uint32_t dstShape[2] = {static_cast<uint32_t>(tileTaskCount * n_), |
| + static_cast<uint32_t>(n_ * n_ + PRE_POST_NUM * n_)}; |
| + PipeBarrier<PIPE_V>(); |
| + |
| + AscendC::Broadcast<float, 2, 1>(rsqrtbrcbLocal_, rsqrtLocal_, dstShape, srcShape); |
| + |
| + PipeBarrier<PIPE_V>(); |
| + |
| + |
| + Mul(hat2Scale, scaleLocal_, hat2LocalTemp, ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, {3, 0, 3, 24, 0, 24}); |
| + Mul(hat2Scale[8], scaleLocal_[8], hat2LocalTemp[8], ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, |
| + {3, 0, 3, 24, 0, 24}); |
| + Mul(hat2Scale[16], scaleLocal_[8], hat2LocalTemp[16], ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, |
| + {3, 0, 3, 24, 0, 24}); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Add(hatLocal, hcBaseLocal_, hat2Scale, ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, {3, 0, 3, 24, 0, 24}); |
| + Add(hatLocal[8], hcBaseLocal_[8], hat2Scale[8], ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, {3, 0, 3, 24, 0, 24}); |
| + Add(hatLocal[16], hcBaseLocal_[16], hat2Scale[16], ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, |
| + {3, 0, 3, 24, 0, 24}); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Mul(hatLocal, hatLocal, rsqrtbrcbLocal_, (n_ * n_ + PRE_POST_NUM * n_) * tileTaskCount); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + auto hatLocalTemp = dhatBeforeNormLocal; |
| + |
| + |
| + Muls(hatLocalTemp, hatLocal, float(-1), ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, {1, 3, 8, 24}); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Exp(hatLocal, hatLocalTemp, (2 * n_) * tileTaskCount); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Adds(hatLocal, hatLocal, float(1), (2 * n_) * tileTaskCount); |
| + PipeBarrier<PIPE_V>(); |
| + Div(hatLocal, onesLocal_, hatLocal, ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, {1, 0, 1, 8, 0, 8}); |
| + |
| + |
| + PipeBarrier<PIPE_V>(); |
| + Mul(hatLocalTemp, hatLocal, hatLocal, ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, {1, 1, 1, 8, 8, 8}); |
| + PipeBarrier<PIPE_V>(); |
| + Sub(hatLocalTemp, hatLocal, hatLocalTemp, ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, {1, 1, 1, 8, 8, 8}); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Mul(dhatLocal_, dPrePostTempLocal_, hatLocalTemp, ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, {3, 1, 1, 24, 8, 8}); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + |
| + PipeBarrier<PIPE_V>(); |
| + Add(dBiasLocal_, dhatLocal_, dBiasLocal_, (n_ * n_ + PRE_POST_NUM * n_) * tileTaskCount); |
| + |
| + Mul(gradRsqrtLocal_, dhatLocal_, hat2Scale, (n_ * n_ + PRE_POST_NUM * n_) * tileTaskCount); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + WholeReduceSum(rsqrtTempLocal_, gradRsqrtLocal_, (n_ * n_ + PRE_POST_NUM * n_), tileTaskCount, 1, 1, |
| + 3); |
| + PipeBarrier<PIPE_V>(); |
| + Mul(rsqrtTempLocal_, rsqrtTempLocal_, rsqrtLocal_, tileTaskCount); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Mul(rsqrtLocal_, rsqrtLocal_, rsqrtLocal_, tileTaskCount); |
| + PipeBarrier<PIPE_V>(); |
| + Mul(rsqrtTempLocal_, rsqrtTempLocal_, rsqrtLocal_, tileTaskCount); |
| + inputXInQueue.FreeTensor(gradHPostLocal_); |
| + |
| + PipeBarrier<PIPE_V>(); |
| + |
| + PipeBarrier<PIPE_V>(); |
| + Muls(gradRsqrtLocal_, rsqrtTempLocal_, float(-1) / (n_ * c_), tileTaskCount); |
| + |
| + |
| + |
| + Mul(dhatBeforeNormLocal, rsqrtbrcbLocal_, dhatLocal_, (n_ * n_ + PRE_POST_NUM * n_) * tileTaskCount); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + MulAddDst(dScaleLocal_, hat2LocalTemp, dhatBeforeNormLocal, (n_ * n_ + PRE_POST_NUM * n_) * tileTaskCount); |
| + auto dhat2Local = OutQueue.AllocTensor<float>(); |
| + |
| + Mul(dhat2Local, scaleLocal_, dhatBeforeNormLocal, ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, {3, 0, 3, 24, 0, 24}); |
| + Mul(dhat2Local[8], scaleLocal_[8], dhatBeforeNormLocal[8], ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, |
| + {3, 0, 3, 24, 0, 24}); |
| + Mul(dhat2Local[16], scaleLocal_[8], dhatBeforeNormLocal[16], ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, |
| + {3, 0, 3, 24, 0, 24}); |
| + OutQueue.EnQue(dhat2Local); |
| + dhat2Local = OutQueue.DeQue<T>(); |
| + DataCopyPad(gradH2Global_[taskOffset * (n_ * n_ + PRE_POST_NUM * n_)], dhat2Local, |
| + {static_cast<uint16_t>(1), |
| + static_cast<uint32_t>(tileTaskCount * (n_ * n_ + PRE_POST_NUM * n_) * sizeof(float)), 0, 0, 0}); |
| + OutQueue.FreeTensor(dhat2Local); |
| +} |
| + |
| +template <typename TYPE_X, typename T> |
| +__aicore__ inline void MhcPreGradKernel<TYPE_X, T>::ComputeGradX1(const int32_t taskOffset, const int32_t tileTaskCount, |
| + const int32_t innerId) |
| +{ |
| + PipeBarrier<PIPE_V>(); |
| + |
| + for (int32_t loopIdC = 0; loopIdC < c1Align_; loopIdC += 1) { |
| + int64_t copyLen = c0_; |
| + bool isPad = false; |
| + uint8_t padLen = 0; |
| + int64_t ubAlignC = c0_; |
| + if (loopIdC == c1_) { |
| + isPad = true; |
| + copyLen = cTail_; |
| + ubAlignC = cTailAlign_; |
| + padLen = static_cast<uint8_t>(cTailAlign_ - cTail_); |
| + } |
| + auto xLocal_ = inputXInQueue.AllocTensor<TYPE_X>(); |
| + auto gradXCubeLocal_ = xLocal_.template ReinterpretCast<float>()[onceTask_ * n_ * c0_ / 2]; |
| + auto gradYLocal_ = xLocal_[onceTask_ * n_ * c0_ * 3]; |
| + |
| + DataCopyPad(gradYLocal_, gradYGlobal_[taskOffset * c_ + c0_ * loopIdC], |
| + {static_cast<uint16_t>(tileTaskCount), static_cast<uint32_t>(copyLen * sizeof(TYPE_X)), |
| + static_cast<uint32_t>((c_ - copyLen) * sizeof(TYPE_X)), 0, 0}, |
| + {isPad, 0, padLen, 0}); |
| + DataCopyPad(xLocal_, xGlobal_[taskOffset * n_ * c_ + c0_ * loopIdC], |
| + {static_cast<uint16_t>(n_ * tileTaskCount), static_cast<uint32_t>(copyLen * sizeof(TYPE_X)), |
| + static_cast<uint32_t>((c_ - copyLen) * sizeof(TYPE_X)), 0, 0}, |
| + {isPad, 0, padLen, 0}); |
| + DataCopyPad(gradXCubeLocal_, gradXCubeGlobal_[taskOffset * n_ * c_ + c0_ * loopIdC], |
| + {static_cast<uint16_t>(n_ * tileTaskCount), static_cast<uint32_t>(copyLen * sizeof(T)), |
| + static_cast<uint32_t>((c_ - copyLen) * sizeof(T)), 0, 0}, |
| + {isPad, 0, padLen, 0}); |
| + |
| + inputXInQueue.EnQue(xLocal_); |
| + inputXInQueue.DeQue(); |
| + PipeBarrier<PIPE_V>(); |
| + Cast(gradYCastLocal_, gradYLocal_, RoundMode::CAST_NONE, ubAlignC * tileTaskCount); |
| + |
| + Cast(xCastLocal_, xLocal_, RoundMode::CAST_NONE, ubAlignC * n_ * tileTaskCount); |
| + |
| + PipeBarrier<PIPE_V>(); |
| + uint8_t blkStride1 = static_cast<uint8_t>(ubAlignC / ELEMENTS_SIZE_PER_BLOCK); |
| + uint8_t blkStride2 = static_cast<uint8_t>(n_ * ubAlignC / ELEMENTS_SIZE_PER_BLOCK); |
| + |
| + for (int32_t loopIdN = 0; loopIdN < n_; loopIdN += 1) { |
| + for (int32_t loopOffsetC0 = 0; loopOffsetC0 < copyLen; loopOffsetC0 += ELEMENTS_SIZE_PER_REPEAT) { |
| + uint64_t mask = |
| + min(static_cast<uint64_t>(ELEMENTS_SIZE_PER_REPEAT), static_cast<uint64_t>(copyLen - loopOffsetC0)); |
| + Mul(gradXCastLocal_[loopIdN * ubAlignC + loopOffsetC0], gradYCastLocal_[loopOffsetC0], |
| + preBrcbLocal_[loopIdN * ELEMENTS_SIZE_PER_BLOCK + innerId * n_ * ELEMENTS_SIZE_PER_BLOCK], mask, |
| + tileTaskCount, {1, 1, 0, blkStride2, blkStride1, static_cast<uint8_t>(n_)}); |
| + } |
| + } |
| + |
| + PipeBarrier<PIPE_V>(); |
| + for (int32_t loopIdN = 0; loopIdN < n_; loopIdN += 1) { |
| + for (int32_t loopOffsetC0 = 0; loopOffsetC0 < copyLen; loopOffsetC0 += ELEMENTS_SIZE_PER_REPEAT) { |
| + uint64_t mask = |
| + min(static_cast<uint64_t>(ELEMENTS_SIZE_PER_REPEAT), static_cast<uint64_t>(copyLen - loopOffsetC0)); |
| + MulAddDst(gradXCastLocal_[loopIdN * ubAlignC + loopOffsetC0], |
| + xCastLocal_[loopIdN * ubAlignC + loopOffsetC0], |
| + dRsqrtBrcbLocal_[innerId * ELEMENTS_SIZE_PER_BLOCK], mask, tileTaskCount, |
| + {1, 1, 0, blkStride2, blkStride2, 1}); |
| + } |
| + } |
| + |
| + Add(gradXCastLocal_, gradXCubeLocal_, gradXCastLocal_, ubAlignC * n_ * tileTaskCount); |
| + PipeBarrier<PIPE_V>(); |
| + inputXInQueue.FreeTensor(xLocal_); |
| + |
| + auto gradXLocalOut = OutQueue.AllocTensor<TYPE_X>(); |
| + |
| + Cast(gradXLocalOut, gradXCastLocal_, RoundMode::CAST_RINT, ubAlignC * n_ * tileTaskCount); |
| + OutQueue.EnQue(gradXLocalOut); |
| + gradXLocalOut = OutQueue.DeQue<TYPE_X>(); |
| + |
| + DataCopyPad(gradXGlobal_[taskOffset * n_ * c_ + c0_ * loopIdC], gradXLocalOut, |
| + {static_cast<uint16_t>(n_ * tileTaskCount), static_cast<uint32_t>(copyLen * sizeof(TYPE_X)), 0, |
| + static_cast<uint32_t>((c_ - copyLen) * sizeof(TYPE_X)), 0}); |
| + OutQueue.FreeTensor(gradXLocalOut); |
| + |
| + PipeBarrier<PIPE_V>(); |
| + } |
| +} |
| +template <typename TYPE_X, typename T> |
| +__aicore__ inline void MhcPreGradKernel<TYPE_X, T>::ComputeGradPre(const int32_t taskOffset, |
| + const int32_t tileTaskCount, const int32_t innerId) |
| +{ |
| + Duplicate(tmpLocal_, 0.f, tileTaskCount * n_ * ELEMENTS_SIZE_PER_REPEAT); |
| + for (int32_t loopIdC = 0; loopIdC < c1Align_; loopIdC += 1) { |
| + int64_t copyLen = c0_; |
| + bool isPad = false; |
| + uint8_t padLen = 0; |
| + int64_t ubAlignC = c0_; |
| + if (loopIdC == c1_) { |
| + isPad = false; |
| + copyLen = cTail_; |
| + ubAlignC = cTailAlign_; |
| + padLen = static_cast<uint8_t>(cTailAlign_ - cTail_); |
| + } |
| + auto xLocal_ = inputXInQueue.AllocTensor<TYPE_X>(); |
| + |
| + auto gradYLocal_ = xLocal_[onceTask_ * n_ * c0_]; |
| + |
| + DataCopyPad(gradYLocal_, gradYGlobal_[taskOffset * c_ + c0_ * loopIdC], |
| + {static_cast<uint16_t>(tileTaskCount), static_cast<uint32_t>(copyLen * sizeof(TYPE_X)), |
| + static_cast<uint32_t>((c_ - copyLen) * sizeof(TYPE_X)), 0, 0}, |
| + {isPad, 0, padLen, 0}); |
| + |
| + DataCopyPad(xLocal_, xGlobal_[taskOffset * n_ * c_ + c0_ * loopIdC], |
| + {static_cast<uint16_t>(n_ * tileTaskCount), static_cast<uint32_t>(copyLen * sizeof(TYPE_X)), |
| + static_cast<uint32_t>((c_ - copyLen) * sizeof(TYPE_X)), 0, 0}, |
| + {isPad, 0, padLen, 0}); |
| + |
| + inputXInQueue.EnQue(xLocal_); |
| + inputXInQueue.DeQue(); |
| + PipeBarrier<PIPE_V>(); |
| + auto xCastOutLocal = OutQueue.AllocTensor<float>(); |
| + |
| + Cast(xCastOutLocal, xLocal_, RoundMode::CAST_NONE, ubAlignC * n_ * tileTaskCount); |
| + |
| + Cast(gradYCastLocal_, gradYLocal_, RoundMode::CAST_NONE, ubAlignC * tileTaskCount); |
| + inputXInQueue.FreeTensor(xLocal_); |
| + |
| + PipeBarrier<PIPE_V>(); |
| + uint8_t blkStride = static_cast<uint8_t>(ubAlignC / ELEMENTS_SIZE_PER_BLOCK); |
| + |
| + uint8_t blkStride3 = static_cast<uint8_t>(n_ * ubAlignC / ELEMENTS_SIZE_PER_BLOCK); |
| + for (int32_t loopIdN = 0; loopIdN < n_; loopIdN += 1) { |
| + for (int32_t loopOffsetC0 = 0; loopOffsetC0 < copyLen; loopOffsetC0 += ELEMENTS_SIZE_PER_REPEAT) { |
| + uint64_t mask = |
| + min(static_cast<uint64_t>(ELEMENTS_SIZE_PER_REPEAT), static_cast<uint64_t>(copyLen - loopOffsetC0)); |
| + Mul(xCastLocal_[loopIdN * ubAlignC + loopOffsetC0], xCastOutLocal[loopIdN * ubAlignC + loopOffsetC0], |
| + gradYCastLocal_[loopOffsetC0], mask, tileTaskCount, {1, 1, 1, blkStride3, blkStride3, blkStride}); |
| + } |
| + } |
| + OutQueue.EnQue(xCastOutLocal); |
| + xCastOutLocal = OutQueue.DeQue<T>(); |
| + |
| + DataCopyPad(xWorkspaceGlobal_[taskOffset * n_ * c_ + c0_ * loopIdC], xCastOutLocal, |
| + {static_cast<uint16_t>(n_ * tileTaskCount), static_cast<uint32_t>(copyLen * sizeof(float)), 0, |
| + static_cast<uint32_t>((c_ - copyLen) * sizeof(float)), 0}); |
| + OutQueue.FreeTensor(xCastOutLocal); |
| + |
| + PipeBarrier<PIPE_V>(); |
| + |
| + int64_t reduceLen = ubAlignC; |
| + if (ubAlignC != c0_) { |
| + Add(xCastLocal_[64], xCastLocal_[64], xCastLocal_[128 + 64], ELEMENTS_SIZE_PER_REPEAT, tileTaskCount * n_, |
| + {1, 1, 1, blkStride, blkStride, blkStride}); |
| + Add(xCastLocal_, xCastLocal_, xCastLocal_[128], ELEMENTS_SIZE_PER_REPEAT, tileTaskCount * n_, |
| + {1, 1, 1, blkStride, blkStride, blkStride}); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Add(xCastLocal_, xCastLocal_, xCastLocal_[64], ELEMENTS_SIZE_PER_REPEAT, tileTaskCount * n_, |
| + {1, 1, 1, blkStride, blkStride, blkStride}); |
| + } else { |
| + if (cTail_ - (128 + 64) > 0) { |
| + uint64_t mask = min(static_cast<uint64_t>(cTail_ - (128 + 64)), static_cast<uint64_t>(REPEAT_LENTH)); |
| + Add(xCastLocal_[64], xCastLocal_[64], xCastLocal_[128 + 64], mask, tileTaskCount * n_, |
| + {1, 1, 1, blkStride, blkStride, blkStride}); |
| + } |
| + if (cTail_ - (128) > 0) { |
| + uint64_t mask = min(static_cast<uint64_t>(cTail_ - (128)), static_cast<uint64_t>(REPEAT_LENTH)); |
| + Add(xCastLocal_, xCastLocal_, xCastLocal_[128], mask, tileTaskCount * n_, |
| + {1, 1, 1, blkStride, blkStride, blkStride}); |
| + } |
| + PipeBarrier<PIPE_V>(); |
| + if (cTail_ - (64) > 0) { |
| + uint64_t mask = min(static_cast<uint64_t>(cTail_ - (64)), static_cast<uint64_t>(REPEAT_LENTH)); |
| + Add(xCastLocal_, xCastLocal_, xCastLocal_[64], mask, tileTaskCount * n_, |
| + {1, 1, 1, blkStride, blkStride, blkStride}); |
| + } |
| + } |
| + PipeBarrier<PIPE_V>(); |
| + |
| + uint64_t mask = min(static_cast<uint64_t>(cTail_), static_cast<uint64_t>(REPEAT_LENTH)); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + Add(tmpLocal_, tmpLocal_, xCastLocal_, mask, tileTaskCount * n_, {1, 1, 1, 8, 8, blkStride}); |
| + PipeBarrier<PIPE_V>(); |
| + } |
| + PipeBarrier<PIPE_V>(); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + for (int32_t loopIdN = 0; loopIdN < n_; loopIdN += 1) { |
| + WholeReduceSum(dPrePostTempLocal_[loopIdN + innerId * n_ * 2], tmpLocal_[loopIdN * REPEAT_LENTH], REPEAT_LENTH, |
| + tileTaskCount, n_ * 2, 1, n_ * 8); |
| + |
| + } |
| +} |
| + |
| +template <typename TYPE_X, typename T> |
| +__aicore__ inline void MhcPreGradKernel<TYPE_X, T>::ComputeScaleBias() |
| +{ |
| + |
| + Add(dScaleLocal_[8], dScaleLocal_[8], dScaleLocal_[16], ELEMENTS_SIZE_PER_REPEAT, tileRepeatTimes_, |
| + {3, 3, 3, 24, 24, 24}); |
| + |
| + |
| + PipeBarrier<PIPE_V>(); |
| + |
| + for (int32_t bsCount = tileCoreBS_ / 2; bsCount > 0; bsCount = bsCount / 2) { |
| + Add(dBiasLocal_, dBiasLocal_, dBiasLocal_[bsCount * (n_ * n_ + PRE_POST_NUM * n_)], |
| + bsCount * (n_ * n_ + PRE_POST_NUM * n_)); |
| + Add(dScaleLocal_, dScaleLocal_, dScaleLocal_[bsCount * (n_ * n_ + PRE_POST_NUM * n_)], |
| + bsCount * (n_ * n_ + PRE_POST_NUM * n_)); |
| + PipeBarrier<PIPE_V>(); |
| + } |
| + SetFlag<HardEvent::V_MTE3>(eventIdVToMTE3XCast); |
| + WaitFlag<HardEvent::V_MTE3>(eventIdVToMTE3XCast); |
| + |
| + SetAtomicAdd<T>(); |
| + |
| + LocalTensor<T> dscaleOut = tempBuf_.GetWithOffset<T>(ELEMENTS_SIZE_PER_BLOCK, 0); |
| + |
| + DataCopyPad(gradHcBaseGlobal_, dBiasLocal_, |
| + {static_cast<uint16_t>(1), static_cast<uint32_t>((n_ * n_ + PRE_POST_NUM * n_) * sizeof(T)), 0, 0, 0}); |
| + PipeBarrier<PIPE_V>(); |
| + |
| + WholeReduceSum(dscaleOut, dScaleLocal_, 4, 1, 1, 3, 8); |
| + WholeReduceSum(dscaleOut[1], dScaleLocal_, MASK_POST_SCALE, 1, 1, 3, |
| + 8); |
| + WholeReduceSum(dscaleOut[2], dScaleLocal_[8], 8, 1, 1, 3, 8); |
| + WholeReduceSum(dscaleOut[3], dScaleLocal_, 8, 1, 1, 3, 8); |
| + |
| + SetFlag<HardEvent::V_MTE3>(eventIdVToMTE3XCast); |
| + WaitFlag<HardEvent::V_MTE3>(eventIdVToMTE3XCast); |
| + DataCopyPad(gradHcScaleGlobal_, dscaleOut, |
| + {static_cast<uint16_t>(1), static_cast<uint32_t>((3) * sizeof(T)), 0, 0, 0}); |
| + SetAtomicNone(); |
| +} |
| + |
| + 约束: |
| + c: c >= 64 && c % 64 == 0 |
| + n: n == 4 |
| +*/ |
| + |
| +template <typename TYPE_X, typename T> |
| +__aicore__ inline void MhcPreGradKernel<TYPE_X, T>::Process() |
| +{ |
| + if ASCEND_IS_AIV { |
| + GetHcScaleAndHcBase(); |
| + |
| + int8_t ping = 0; |
| + |
| + for (int32_t taskOffset = blkIdx_ * tileCoreBS_; taskOffset < totalTasksAligned_; |
| + taskOffset += aivNum_ * tileCoreBS_) { |
| + int32_t tileTaskCount = |
| + min(static_cast<int32_t>(tileCoreBS_), static_cast<int32_t>(totalTasks_ - taskOffset)); |
| + tileRepeatTimes_ = CeilDiv(tileTaskCount * 2 * n_, ELEMENTS_SIZE_PER_REPEAT); |
| + if (tileTaskCount > 0) { |
| + int32_t innerId = 0; |
| + Duplicate(dPrePostTempLocal_, 0.f, tileCoreBS_ * n_ * 2); |
| + for (int32_t taskOffsetInner = 0; taskOffsetInner < tileTaskCount; taskOffsetInner += onceTask_) { |
| + int32_t tileTaskCountInner = |
| + min(static_cast<int32_t>(onceTask_), static_cast<int32_t>(tileTaskCount - taskOffsetInner)); |
| + |
| + ComputeGradPre(taskOffset + taskOffsetInner, tileTaskCountInner, taskOffsetInner); |
| + innerId++; |
| + } |
| + ComputeGradHHat2(taskOffset, tileTaskCount); |
| + } |
| + CrossCoreSetFlag<0x2, PIPE_MTE3>(0); |
| + CrossCoreWaitFlag<0x2>(1); |
| + ping = (ping + 1) % 10; |
| + if (tileTaskCount > 0) { |
| + int32_t innerId = 0; |
| + for (int32_t taskOffsetInner = 0; taskOffsetInner < tileTaskCount; taskOffsetInner += onceTask_) { |
| + int32_t tileTaskCountInner = |
| + min(static_cast<int32_t>(onceTask_), static_cast<int32_t>(tileTaskCount - taskOffsetInner)); |
| + int32_t brcbAlign = CeilDiv(tileTaskCount * n_, ELEMENTS_SIZE_PER_BLOCK); |
| + int32_t offset = 0; |
| + auto preLocal_ = inputGradQueue.AllocTensor<T>(); |
| + DataCopyPad( |
| + preLocal_, preGlobal_[taskOffset * n_], |
| + {static_cast<uint16_t>(1), static_cast<uint32_t>(tileTaskCount * n_ * sizeof(T)), 0, 0, 0}, |
| + {false, 0, 0, 0}); |
| + inputGradQueue.EnQue(preLocal_); |
| + inputGradQueue.DeQue(); |
| + |
| + const uint32_t srcShape[2] = {static_cast<uint32_t>(tileTaskCount * n_), 1}; |
| + const uint32_t dstShape[2] = {static_cast<uint32_t>(tileTaskCount * n_), |
| + ELEMENTS_SIZE_PER_BLOCK}; |
| + preBrcbLocal_ = tempBuf_.GetWithOffset<T>(brcbAlign * 8, offset); |
| + Brcb(preBrcbLocal_, preLocal_, brcbAlign, {static_cast<uint8_t>(1), static_cast<uint8_t>(8)}); |
| + inputGradQueue.FreeTensor(preLocal_); |
| + |
| + offset += brcbAlign * 8 * sizeof(float); |
| + brcbAlign = CeilDiv(tileTaskCount, ELEMENTS_SIZE_PER_BLOCK); |
| + |
| + offset += brcbAlign * 8 * sizeof(float); |
| + |
| + const uint32_t srcRsqrtShape[2] = {static_cast<uint32_t>(tileTaskCount), 1}; |
| + const uint32_t dstRsqrtShape[2] = {static_cast<uint32_t>(tileTaskCount), |
| + ELEMENTS_SIZE_PER_BLOCK}; |
| + Brcb(dRsqrtBrcbLocal_, gradRsqrtLocal_, brcbAlign, |
| + {static_cast<uint8_t>(1), static_cast<uint8_t>(8)}); |
| + ComputeGradX1(taskOffset + taskOffsetInner, tileTaskCountInner, taskOffsetInner); |
| + innerId++; |
| + } |
| + } |
| + } |
| + |
| + tileRepeatTimes_ = CeilDiv(tileCoreBS_ * 2 * n_, ELEMENTS_SIZE_PER_REPEAT); |
| + ComputeScaleBias(); |
| + GetTPipePtr()->ReleaseEventID<HardEvent::V_MTE3>(eventIdVToMTE3XCast); |
| + } |
| + |
| + if ASCEND_IS_AIC { |
| + int8_t ping = 0; |
| + for (int32_t taskOffset = blkIdx_ * 2 * tileCoreBS_; taskOffset < totalTasksAligned_; |
| + taskOffset += aicNum_ * 2 * tileCoreBS_) { |
| + int32_t tileTaskCount = |
| + min(static_cast<int32_t>(2 * tileCoreBS_), static_cast<int32_t>(totalTasks_ - taskOffset)); |
| + CrossCoreWaitFlag<0x2>(0); |
| + |
| + if (tileTaskCount > 0) { |
| + ProcessMatmul1(taskOffset, tileTaskCount); |
| + ProcessMatmul2(taskOffset, tileTaskCount); |
| + } |
| + AscendC::CrossCoreSetFlag<0x2, PIPE_FIX>(1); |
| + |
| + ping = (ping + 1) % 10; |
| + } |
| + } |
| +} |
| + |
| +template <typename TYPE_X, typename T> |
| +__aicore__ inline void MhcPreGradKernel<TYPE_X, T>::ProcessMatmul1(const int32_t taskOffset, const int32_t mm1M) |
| +{ |
| + if (mm1M <= 0) |
| + return; |
| + |
| + mm1_.SetTensorA(gradH2Global_[taskOffset * mm1K_]); |
| + mm1_.SetTensorB(weightGlobal_); |
| + mm1_.SetHF32(true, 1); |
| + mm1_.SetOrgShape(mm1M, mm1N_, mm1K_); |
| + mm1_.SetSingleShape(mm1M, mm1N_, mm1K_); |
| + mm1_.template IterateAll<false>(gradXCubeGlobal_[taskOffset * (n_ * c_)]); |
| + mm1_.End(); |
| +} |
| + |
| +template <typename TYPE_X, typename T> |
| +__aicore__ inline void MhcPreGradKernel<TYPE_X, T>::ProcessMatmul2(const int32_t taskOffset, const int32_t mm2K) |
| +{ |
| + if (mm2K <= 0) |
| + return; |
| + |
| + mm2_.SetTensorA(gradH2Global_[taskOffset * mm2M_], true); |
| + mm2_.SetTensorB(xWorkspaceGlobal_[taskOffset * mm2N_]); |
| + mm2_.SetHF32(true, 1); |
| + mm2_.SetOrgShape(mm2M_, mm2N_, mm2K); |
| + mm2_.SetSingleShape(mm2M_, mm2N_, mm2K); |
| + mm2_.template IterateAll<false>(gradWeightGlobal_, 1); |
| + mm2_.End(); |
| +} |
| + |
| +#endif |