* 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 dequant_swiglu_quant.h
* \brief
*/
#ifndef DEQUANT_SWIGLU_QUANT_H
#define DEQUANT_SWIGLU_QUANT_H
#include "kernel_tiling/kernel_tiling.h"
#if ASC_DEVKIT_MAJOR >= 9
#include "basic_api/kernel_vec_intf.h"
#else
#include "kernel_operator.h"
#endif
#include "dequant_swiglu_quant_common.h"
namespace DequantSwigluQuantV35Ops {
using namespace AscendC;
template <typename TActScale, typename TQuantScale, typename TGroup, typename TBias, typename TXtype, typename TYtype>
class DequantSwigluQuantBase {
public:
static constexpr bool hasActScale_ = IsSameType<TActScale, float>::value;
static constexpr bool hasQuantScale_ = IsSameType<TQuantScale, float>::value;
static constexpr bool hasGroupIndex_ = IsSameType<TGroup, int64_t>::value || IsSameType<TGroup, int32_t>::value;
static constexpr bool hasBiasIndex_ = IsSameType<TBias, float>::value || IsSameType<TBias, half>::value ||
IsSameType<TBias, bfloat16_t>::value || IsSameType<TBias, int32_t>::value;
static constexpr bool ifBiasIntIndex_ = IsSameType<TBias, int32_t>::value;
static constexpr bool ifBiasFloatIndex_ = IsSameType<TBias, float>::value;
static constexpr bool ifBiasFloat16Index_ = IsSameType<TBias, half>::value;
static constexpr bool ifBiasBfloat16Index_ = IsSameType<TBias, bfloat16_t>::value;
static constexpr bool ifXIntIndex_ = IsSameType<TXtype, int32_t>::value;
static constexpr bool ifXBf16Index_ = IsSameType<TXtype, bfloat16_t>::value;
static constexpr bool ifXFloat16Index_ = IsSameType<TXtype, half>::value;
static constexpr bool ifYInt8Index_ = IsSameType<TYtype, int8_t>::value;
static constexpr bool ifYFloat8e4m3Index_ = IsSameType<TYtype, fp8_e4m3fn_t>::value;
static constexpr bool ifYFloat8e5m2Index_ = IsSameType<TYtype, fp8_e5m2_t>::value;
static constexpr bool ifYFloat4e2m1Index_ = IsSameType<TYtype, fp4x2_e2m1_t>::value;
static constexpr bool ifYFloat4e1m2Index_ = IsSameType<TYtype, fp4x2_e1m2_t>::value;
static constexpr bool ifYHiFloat8Index_ = IsSameType<TYtype, hifloat8_t>::value;
__aicore__ inline DequantSwigluQuantBase(TPipe* pipe) { pipe_ = pipe; };
__aicore__ inline void Init(GM_ADDR x, GM_ADDR weightScale, GM_ADDR activationScale, GM_ADDR bias,
GM_ADDR quantScale, GM_ADDR quantOffset, GM_ADDR groupIndex, GM_ADDR y, GM_ADDR scale,
const DequantSwigluQuantV35BaseTilingData* tilingData);
__aicore__ inline void Process();
private:
__aicore__ inline void ComputeReduceMax(const LocalTensor<float>& tempRes, int32_t calCount, float& maxValue);
__aicore__ inline void ProcessSingleGroup(int64_t groupIndex, int64_t realDimx, int64_t groupOffset);
__aicore__ inline void ProcessSingleGroupPerCore(int64_t groupIdx, int64_t xDimPerCore, int64_t coreDimxOffset);
protected:
GlobalTensor<TXtype> xGm_;
GlobalTensor<float> weightScaleGm_;
GlobalTensor<TActScale> activationScaleGm_;
GlobalTensor<TBias> biasGm_;
GlobalTensor<TQuantScale> quantScaleGm_;
GlobalTensor<float> quantOffsetGm_;
GlobalTensor<int32_t> groupIndexGm_;
GlobalTensor<TYtype> yGm_;
GlobalTensor<float> scaleGm_;
LocalTensor<TBias> biasLocal;
__local_mem__ TBias* bias1Ptr;
__local_mem__ TBias* bias2Ptr;
__local_mem__ float* wScale1Ptr;
__local_mem__ float* wScale2Ptr;
__local_mem__ float* wScale1Addr;
__local_mem__ float* wScale2Addr;
TPipe* pipe_ = nullptr;
TQue<QuePosition::VECIN, 1> xActQueue_;
TQue<QuePosition::VECIN, 1> inScaleQueue_;
TQue<QuePosition::VECIN, 1> biasQueue_;
TQue<QuePosition::VECOUT, 1> yQueue_;
TQue<QuePosition::VECOUT, 1> scaleQueue_;
TBuf<> tmpBuffer;
uint32_t blockIdx_ = GetBlockIdx();
uint32_t realCoreDim_ = 0;
int64_t realDimx_ = 0;
int64_t groupOffset_ = 0;
uint32_t xUbAlignB32_ = 0;
uint32_t xUbAlignB32FullRow_ = 0;
uint32_t xTypeUbAlignB32_ = 0;
uint32_t xTypeUbAlignB32FullRow_ = 0;
uint32_t yUbAlignB8_ = 0;
uint32_t yUbAlignB4_ = 0;
uint32_t aScaleUbAlignB32_ = 0;
uint32_t biasUbAlign_ = 0;
int64_t roundMode_ = 0;
float scalarMaxNum_ = 127.0;
const DequantSwigluQuantV35BaseTilingData* tl_ = nullptr;
};
template <typename TActScale, typename TQuantScale, typename TGroup, typename TBias, typename TXtype, typename TYtype>
__aicore__ inline void DequantSwigluQuantBase<TActScale, TQuantScale, TGroup, TBias, TXtype, TYtype>::Init(
GM_ADDR x, GM_ADDR weightScale, GM_ADDR activationScale, GM_ADDR bias, GM_ADDR quantScale, GM_ADDR quantOffset,
GM_ADDR groupIndex, GM_ADDR y, GM_ADDR scale, const DequantSwigluQuantV35BaseTilingData* tilingData)
{
tl_ = tilingData;
if constexpr (ifXBf16Index_ || ifXFloat16Index_) {
uint32_t BLOCK_ELEM_B32_BF = BLOCK_SIZE / sizeof(TXtype);
xTypeUbAlignB32_ = CeilDivision(tl_->UbFactorDimy, BLOCK_ELEM_B32_BF) * BLOCK_ELEM_B32_BF;
xTypeUbAlignB32FullRow_ = CeilDivision(tl_->UbFactorDimy * 2, BLOCK_ELEM_B32_BF) * BLOCK_ELEM_B32_BF;
} else {
xTypeUbAlignB32_ = CeilDivision(tl_->UbFactorDimy, BLOCK_ELEM_B32) * BLOCK_ELEM_B32;
xTypeUbAlignB32FullRow_ = CeilDivision(tl_->UbFactorDimy * 2, BLOCK_ELEM_B32) * BLOCK_ELEM_B32;
}
xUbAlignB32_ = CeilDivision(tl_->UbFactorDimy, BLOCK_ELEM_B32) * BLOCK_ELEM_B32;
xUbAlignB32FullRow_ = CeilDivision(tl_->UbFactorDimy * 2, BLOCK_ELEM_B32) * BLOCK_ELEM_B32;
yUbAlignB8_ = CeilDivision(tl_->UbFactorDimy, BLOCK_ELEM_B8) * BLOCK_ELEM_B8;
yUbAlignB4_ = CeilDivision(tl_->UbFactorDimy / 2, BLOCK_ELEM_B8) * BLOCK_ELEM_B8;
aScaleUbAlignB32_ = BLOCK_ELEM_B32;
uint32_t blockElem = BLOCK_SIZE / sizeof(TBias);
biasUbAlign_ = CeilDivision(tl_->UbFactorDimy, blockElem) * blockElem;
roundMode_ = tl_->roundMode;
if constexpr (ifYFloat8e4m3Index_) {
scalarMaxNum_ = 448.0;
}
if constexpr (ifYFloat8e5m2Index_) {
scalarMaxNum_ = 57344.0;
}
if constexpr (ifYFloat4e2m1Index_) {
scalarMaxNum_ = 6.0;
}
if constexpr (ifYFloat4e1m2Index_) {
scalarMaxNum_ = 1.75;
}
if constexpr (ifYHiFloat8Index_) {
scalarMaxNum_ = 32768.0;
}
xGm_.SetGlobalBuffer((__gm__ TXtype*)x);
weightScaleGm_.SetGlobalBuffer((__gm__ float*)weightScale);
activationScaleGm_.SetGlobalBuffer((__gm__ TActScale*)activationScale);
quantScaleGm_.SetGlobalBuffer((__gm__ TQuantScale*)quantScale);
if constexpr (hasGroupIndex_) {
groupIndexGm_.SetGlobalBuffer((__gm__ int32_t*)groupIndex);
}
yGm_.SetGlobalBuffer((__gm__ TYtype*)y);
scaleGm_.SetGlobalBuffer((__gm__ float*)scale);
uint32_t tailSupply = CeilDivision(tl_->inDimy, BLOCK_SIZE * 4) * BLOCK_SIZE * 4 - tl_->inDimy;
if (tl_->swiGluMode == 0) {
pipe_->InitBuffer(xActQueue_, DOUBLE_BUFFER,
(tl_->UbFactorDimx * xTypeUbAlignB32_ * 2) * sizeof(TXtype) +
(tl_->UbFactorDimx * aScaleUbAlignB32_) * sizeof(float));
} else {
pipe_->InitBuffer(xActQueue_, DOUBLE_BUFFER,
(tl_->UbFactorDimx * xTypeUbAlignB32_ * 2) * sizeof(TXtype) + tailSupply * sizeof(TXtype) +
(tl_->UbFactorDimx * aScaleUbAlignB32_) * sizeof(float));
}
if (tl_->swiGluMode == 0) {
pipe_->InitBuffer(inScaleQueue_, 1, (xUbAlignB32_ * 2 + xUbAlignB32_) * sizeof(float));
} else {
pipe_->InitBuffer(inScaleQueue_, 1, (xUbAlignB32_ * 2 + xUbAlignB32_ + tailSupply) * sizeof(float));
}
pipe_->InitBuffer(yQueue_, DOUBLE_BUFFER, tl_->UbFactorDimx * yUbAlignB8_ * sizeof(TYtype));
pipe_->InitBuffer(scaleQueue_, 1, tl_->UbFactorDimx * aScaleUbAlignB32_ * sizeof(float));
pipe_->InitBuffer(tmpBuffer, tl_->UbFactorDimx * xUbAlignB32_ * sizeof(float));
if constexpr (hasBiasIndex_) {
biasGm_.SetGlobalBuffer((__gm__ TBias*)bias);
if (tl_->swiGluMode == 0) {
pipe_->InitBuffer(biasQueue_, 1, (biasUbAlign_ * 2) * sizeof(TBias));
} else {
uint32_t biasTailSupply = CeilDivision(tl_->inDimy, BLOCK_SIZE * 4) * BLOCK_SIZE * 4 - tl_->inDimy;
pipe_->InitBuffer(biasQueue_, 1, (biasUbAlign_ * 2) * sizeof(TBias) + biasTailSupply * sizeof(TBias));
}
}
SetFloatOverflowModeForRegbase<TYtype>();
}
template <typename TActScale, typename TQuantScale, typename TGroup, typename TBias, typename TXtype, typename TYtype>
__aicore__ inline void DequantSwigluQuantBase<TActScale, TQuantScale, TGroup, TBias, TXtype, TYtype>::Process()
{
if constexpr (!hasGroupIndex_) {
realDimx_ = tl_->inDimx;
if (realDimx_ < 0) {
realDimx_ = 0;
}
ProcessSingleGroup(0, realDimx_, 0);
return;
}
groupOffset_ = 0;
if (tl_->isSpecialCoreCut == 0) {
for (int64_t groupIndex = 0; groupIndex < tl_->inGroupNum; groupIndex++) {
int64_t realGroupIndex = 0;
if (tl_->speGroupType == 1) {
if (tl_->groupIndexMode == 1) {
realDimx_ = static_cast<int64_t>(groupIndexGm_(groupIndex * 2 + 1));
realGroupIndex = static_cast<int64_t>(groupIndexGm_(groupIndex * 2));
} else {
realDimx_ = groupIndexGm_.template ReinterpretCast<int64_t>()(groupIndex * 2 + 1);
realGroupIndex = groupIndexGm_.template ReinterpretCast<int64_t>()(groupIndex * 2);
}
} else {
realGroupIndex = groupIndex;
if (tl_->groupIndexMode == 1) {
realDimx_ = static_cast<int64_t>(groupIndexGm_(groupIndex));
} else {
realDimx_ = groupIndexGm_.template ReinterpretCast<int64_t>()(groupIndex);
}
}
if (realDimx_ <= 0) {
continue;
}
if (groupOffset_ < tl_->inDimx) {
ProcessSingleGroup(realGroupIndex, realDimx_, groupOffset_);
groupOffset_ += realDimx_;
}
}
return;
} else {
int64_t cuGroupIdx = blockIdx_;
for (int64_t groupIndex = 0; groupIndex < tl_->inGroupNum; groupIndex++) {
int64_t realGroupIndex = 0;
if (tl_->speGroupType == 1) {
if (tl_->groupIndexMode == 1) {
realDimx_ = static_cast<int64_t>(groupIndexGm_(groupIndex * 2 + 1));
realGroupIndex = static_cast<int64_t>(groupIndexGm_(groupIndex * 2));
} else {
realDimx_ = groupIndexGm_.template ReinterpretCast<int64_t>()(groupIndex * 2 + 1);
realGroupIndex = groupIndexGm_.template ReinterpretCast<int64_t>()(groupIndex * 2);
}
} else {
realGroupIndex = groupIndex;
if (tl_->groupIndexMode == 1) {
realDimx_ = static_cast<int64_t>(groupIndexGm_(groupIndex));
} else {
realDimx_ = groupIndexGm_.template ReinterpretCast<int64_t>()(groupIndex);
}
}
if (groupIndex == cuGroupIdx) {
if (realDimx_ > 0) {
ProcessSingleGroupPerCore(realGroupIndex, realDimx_, groupOffset_);
}
cuGroupIdx += tl_->maxCoreNum;
}
groupOffset_ += realDimx_;
}
return;
}
}
template <typename TActScale, typename TQuantScale, typename TGroup, typename TBias, typename TXtype, typename TYtype>
__aicore__ inline void DequantSwigluQuantBase<TActScale, TQuantScale, TGroup, TBias, TXtype,
TYtype>::ProcessSingleGroupPerCore(int64_t groupIdx, int64_t xDimPerCore,
int64_t coreDimxOffset)
{
DataCopyPadParams padParams{false, 0, 0, 0};
int64_t actOffset = tl_->actRight * tl_->UbFactorDimy;
int64_t gateOffset = tl_->UbFactorDimy - actOffset;
LocalTensor<float> inScaleLocal = inScaleQueue_.AllocTensor<float>();
if constexpr (ifXIntIndex_) {
if (tl_->swiGluMode == 0) {
DataCopyParams dataCopyWeightScaleParams;
dataCopyWeightScaleParams.blockCount = 1;
dataCopyWeightScaleParams.blockLen = tl_->UbFactorDimy * sizeof(float);
dataCopyWeightScaleParams.srcStride = 0;
dataCopyWeightScaleParams.dstStride = 0;
DataCopyPad(inScaleLocal[0], weightScaleGm_[groupIdx * tl_->inDimy + actOffset], dataCopyWeightScaleParams,
padParams);
DataCopyPad(inScaleLocal[xUbAlignB32_], weightScaleGm_[groupIdx * tl_->inDimy + gateOffset],
dataCopyWeightScaleParams, padParams);
} else {
DataCopyParams dataCopyWeightScaleParams;
dataCopyWeightScaleParams.blockCount = 1;
dataCopyWeightScaleParams.blockLen = tl_->UbFactorDimy * 2 * sizeof(float);
dataCopyWeightScaleParams.srcStride = 0;
dataCopyWeightScaleParams.dstStride = 0;
DataCopyPad(inScaleLocal[0], weightScaleGm_[groupIdx * tl_->inDimy], dataCopyWeightScaleParams, padParams);
}
}
if constexpr (hasQuantScale_) {
DataCopyParams dataCopyQuantScaleParams;
dataCopyQuantScaleParams.blockCount = 1;
dataCopyQuantScaleParams.blockLen = tl_->UbFactorDimy * sizeof(TQuantScale);
dataCopyQuantScaleParams.srcStride = 0;
dataCopyQuantScaleParams.dstStride = 0;
DataCopyPad(inScaleLocal[xUbAlignB32_ * 2], quantScaleGm_[groupIdx * tl_->UbFactorDimy],
dataCopyQuantScaleParams, padParams);
}
inScaleQueue_.EnQue(inScaleLocal);
inScaleLocal = inScaleQueue_.DeQue<float>();
if constexpr (hasBiasIndex_) {
if (tl_->swiGluMode == 0) {
biasLocal = biasQueue_.AllocTensor<TBias>();
DataCopyParams dataCopyBiasParams;
dataCopyBiasParams.blockCount = 1;
dataCopyBiasParams.blockLen = tl_->UbFactorDimy * sizeof(TBias);
dataCopyBiasParams.srcStride = 0;
dataCopyBiasParams.dstStride = 0;
DataCopyPad(biasLocal[0], biasGm_[groupIdx * tl_->inDimy + actOffset], dataCopyBiasParams, padParams);
DataCopyPad(biasLocal[biasUbAlign_], biasGm_[groupIdx * tl_->inDimy + gateOffset], dataCopyBiasParams,
padParams);
} else {
biasLocal = biasQueue_.AllocTensor<TBias>();
DataCopyParams dataCopyBiasParams;
dataCopyBiasParams.blockCount = 1;
dataCopyBiasParams.blockLen = tl_->UbFactorDimy * 2 * sizeof(TBias);
dataCopyBiasParams.srcStride = 0;
dataCopyBiasParams.dstStride = 0;
DataCopyPad(biasLocal[0], biasGm_[groupIdx * tl_->inDimy], dataCopyBiasParams, padParams);
}
biasQueue_.EnQue(biasLocal);
biasLocal = biasQueue_.DeQue<TBias>();
}
int64_t ubDimxLoop = (xDimPerCore + tl_->UbFactorDimx - 1) / tl_->UbFactorDimx;
int64_t ubDimxTailFactor = xDimPerCore - tl_->UbFactorDimx * (ubDimxLoop - 1);
for (uint64_t i = 0; i < ubDimxLoop; i++) {
int64_t xDimOffsetPerLoop = coreDimxOffset + i * tl_->UbFactorDimx;
int64_t xDimPerLoop = tl_->UbFactorDimx;
if (i == ubDimxLoop - 1) {
xDimPerLoop = ubDimxTailFactor;
}
LocalTensor<TXtype> xActLocal = xActQueue_.AllocTensor<TXtype>();
if (tl_->swiGluMode == 0) {
DataCopyParams dataCopyXParams;
dataCopyXParams.blockCount = xDimPerLoop;
dataCopyXParams.blockLen = tl_->UbFactorDimy * sizeof(TXtype);
dataCopyXParams.srcStride = tl_->UbFactorDimy * sizeof(TXtype);
dataCopyXParams.dstStride = 0;
DataCopyPad(xActLocal[0], xGm_[xDimOffsetPerLoop * tl_->inDimy + actOffset], dataCopyXParams, padParams);
DataCopyPad(xActLocal[xTypeUbAlignB32_ * xDimPerLoop], xGm_[xDimOffsetPerLoop * tl_->inDimy + gateOffset],
dataCopyXParams, padParams);
} else {
DataCopyParams dataCopyXParams;
dataCopyXParams.blockCount = xDimPerLoop;
dataCopyXParams.blockLen = tl_->UbFactorDimy * 2 * sizeof(TXtype);
dataCopyXParams.srcStride = 0;
dataCopyXParams.dstStride = 0;
DataCopyPad(xActLocal[0], xGm_[xDimOffsetPerLoop * tl_->inDimy], dataCopyXParams, padParams);
}
LocalTensor<float> xActLocalFp32 = xActLocal.template ReinterpretCast<float>();
if constexpr (hasActScale_) {
DataCopyParams dataCopyActScaleParams;
dataCopyActScaleParams.blockCount = xDimPerLoop;
dataCopyActScaleParams.blockLen = sizeof(float);
dataCopyActScaleParams.srcStride = 0;
dataCopyActScaleParams.dstStride = 0;
DataCopyPad(xActLocalFp32[xTypeUbAlignB32_ * xDimPerLoop * 2], activationScaleGm_[xDimOffsetPerLoop],
dataCopyActScaleParams, padParams);
}
xActQueue_.EnQue(xActLocal);
xActLocal = xActQueue_.DeQue<TXtype>();
LocalTensor<TYtype> yLocal = yQueue_.AllocTensor<TYtype>();
LocalTensor<uint8_t> yFp4Local = yLocal.template ReinterpretCast<uint8_t>();
LocalTensor<float> scaleLocal = scaleQueue_.AllocTensor<float>();
LocalTensor<float> tmpXLocal = tmpBuffer.Get<float>();
__local_mem__ float* tmpXPtr = (__local_mem__ float*)tmpXLocal.GetPhyAddr();
__local_mem__ TYtype* yPtr = (__local_mem__ TYtype*)yLocal.GetPhyAddr();
__local_mem__ uint8_t* yFp4Ptr = (__local_mem__ uint8_t*)yFp4Local.GetPhyAddr();
__local_mem__ float* scalePtr = (__local_mem__ float*)scaleLocal.GetPhyAddr();
__local_mem__ TXtype* x1Ptr = (__local_mem__ TXtype*)xActLocal.GetPhyAddr(0);
__local_mem__ TXtype* x2Ptr = (__local_mem__ TXtype*)xActLocal.GetPhyAddr(xTypeUbAlignB32_ * xDimPerLoop);
__local_mem__ float* aScalePtr = (__local_mem__ float*)xActLocalFp32.GetPhyAddr(xTypeUbAlignB32_ * xDimPerLoop *
2);
if constexpr (ifXIntIndex_) {
wScale1Ptr = (__local_mem__ float*)inScaleLocal.GetPhyAddr(0);
wScale2Ptr = (__local_mem__ float*)inScaleLocal.GetPhyAddr(xUbAlignB32_);
}
if constexpr (hasBiasIndex_) {
bias1Ptr = (__local_mem__ TBias*)biasLocal.GetPhyAddr(0);
bias2Ptr = (__local_mem__ TBias*)biasLocal.GetPhyAddr(biasUbAlign_);
}
if (tl_->swiGluMode == 0) {
__VEC_SCOPE__
{
AscendC::MicroAPI::RegTensor<TXtype> vreg0, vreg10;
AscendC::MicroAPI::RegTensor<float> vreg1, vreg2, vreg3, vreg4, vreg5, vreg6;
AscendC::MicroAPI::RegTensor<float> vreg7, vreg8, vreg9, vreg11, vreg12;
AscendC::MicroAPI::RegTensor<float> vreg13, vreg14, vreg15;
AscendC::MicroAPI::RegTensor<int32_t> vreg16, vreg17, verg18, vreg19;
AscendC::MicroAPI::RegTensor<float> vreg20, vreg21;
AscendC::MicroAPI::RegTensor<half> vreg24, vreg25;
AscendC::MicroAPI::RegTensor<bfloat16_t> vreg26, vreg27;
AscendC::MicroAPI::MaskReg mask;
constexpr uint16_t sizePerRepeat = AscendC::GetVecLen() / sizeof(float);
uint32_t width = tl_->UbFactorDimy;
uint16_t repeatTimes = CeilDivision(tl_->UbFactorDimy, sizePerRepeat);
const float scalarOne = 1.0;
for (uint16_t j = 0; j < repeatTimes; j++) {
mask = AscendC::MicroAPI::UpdateMask<uint32_t>(width);
if constexpr (ifXIntIndex_) {
wScale1Addr = wScale1Ptr + j * sizePerRepeat;
wScale2Addr = wScale2Ptr + j * sizePerRepeat;
AscendC::MicroAPI::DataCopy(vreg2, wScale1Addr);
AscendC::MicroAPI::DataCopy(vreg12, wScale2Addr);
}
for (uint16_t i = 0; i < static_cast<uint16_t>(xDimPerLoop); i++) {
auto x1Addr = x1Ptr + i * xTypeUbAlignB32_ + j * sizePerRepeat;
auto x2Addr = x2Ptr + i * xTypeUbAlignB32_ + j * sizePerRepeat;
auto dstAddr = tmpXPtr + i * xTypeUbAlignB32_ + j * sizePerRepeat;
if constexpr (ifXFloat16Index_) {
AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(vreg0,
x1Addr);
AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(vreg10,
x2Addr);
}
if constexpr (ifXBf16Index_) {
AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
vreg0, x1Addr);
AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
vreg10, x2Addr);
}
if constexpr (ifXIntIndex_) {
AscendC::MicroAPI::DataCopy(vreg0, x1Addr);
AscendC::MicroAPI::DataCopy(vreg10, x2Addr);
}
if constexpr (hasBiasIndex_) {
if constexpr (ifXIntIndex_ && ifBiasIntIndex_) {
auto bias1Addr = bias1Ptr + j * sizePerRepeat;
auto bias2Addr = bias2Ptr + j * sizePerRepeat;
AscendC::MicroAPI::DataCopy(vreg16, bias1Addr);
AscendC::MicroAPI::DataCopy(vreg17, bias2Addr);
AscendC::MicroAPI::Add(vreg0, vreg0, vreg16, mask);
AscendC::MicroAPI::Add(vreg10, vreg10, vreg17, mask);
}
}
if constexpr (ifXIntIndex_) {
AscendC::MicroAPI::Cast<float, TXtype, CAST_INT32_TO_FP32>(vreg1, vreg0, mask);
AscendC::MicroAPI::Cast<float, TXtype, CAST_INT32_TO_FP32>(vreg11, vreg10, mask);
AscendC::MicroAPI::Mul(vreg3, vreg1, vreg2, mask);
AscendC::MicroAPI::Mul(vreg13, vreg11, vreg12, mask);
}
if constexpr (ifXBf16Index_ || ifXFloat16Index_) {
AscendC::MicroAPI::Cast<float, TXtype, CAST_BF16_FP16_TO_FP32>(vreg3, vreg0, mask);
AscendC::MicroAPI::Cast<float, TXtype, CAST_BF16_FP16_TO_FP32>(vreg13, vreg10, mask);
}
if constexpr (hasActScale_) {
auto aScaleAddr = aScalePtr + i * aScaleUbAlignB32_;
AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::LoadDist::DIST_BRC_B32>(vreg4,
aScaleAddr);
AscendC::MicroAPI::Mul(vreg3, vreg3, vreg4, mask);
AscendC::MicroAPI::Mul(vreg13, vreg13, vreg4, mask);
}
if constexpr (ifBiasFloatIndex_ || ifBiasFloat16Index_ || ifBiasBfloat16Index_) {
auto bias1Addr = bias1Ptr + j * sizePerRepeat;
auto bias2Addr = bias2Ptr + j * sizePerRepeat;
if constexpr (ifBiasFloatIndex_) {
AscendC::MicroAPI::DataCopy(vreg20, bias1Addr);
AscendC::MicroAPI::DataCopy(vreg21, bias2Addr);
}
if constexpr (ifBiasFloat16Index_) {
AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
vreg24, bias1Addr);
AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
vreg25, bias2Addr);
AscendC::MicroAPI::Cast<float, half, CAST_BF16_FP16_TO_FP32>(vreg20, vreg24, mask);
AscendC::MicroAPI::Cast<float, half, CAST_BF16_FP16_TO_FP32>(vreg21, vreg25, mask);
}
if constexpr (ifBiasBfloat16Index_) {
AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
vreg26, bias1Addr);
AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
vreg27, bias2Addr);
AscendC::MicroAPI::Cast<float, bfloat16_t, CAST_BF16_FP16_TO_FP32>(vreg20, vreg26,
mask);
AscendC::MicroAPI::Cast<float, bfloat16_t, CAST_BF16_FP16_TO_FP32>(vreg21, vreg27,
mask);
}
AscendC::MicroAPI::Add(vreg3, vreg3, vreg20, mask);
AscendC::MicroAPI::Add(vreg13, vreg13, vreg21, mask);
}
AscendC::MicroAPI::Muls(vreg6, vreg3, -(scalarOne), mask);
AscendC::MicroAPI::Exp(vreg7, vreg6, mask);
AscendC::MicroAPI::Adds(vreg8, vreg7, scalarOne, mask);
AscendC::MicroAPI::Div<float, &DIV_MODE>(vreg9, vreg3, vreg8, mask);
AscendC::MicroAPI::Mul(vreg15, vreg9, vreg13, mask);
AscendC::MicroAPI::DataCopy(dstAddr, vreg15, mask);
}
}
}
} else {
constexpr uint16_t sizePerRepeat = AscendC::GetVecLen() / sizeof(float);
uint32_t width = tl_->UbFactorDimy;
uint32_t widthFullRow = tl_->UbFactorDimy * 2;
uint16_t repeatTimes = CeilDivision(tl_->UbFactorDimy, sizePerRepeat);
uint16_t repeatTimesFullRow = CeilDivision(widthFullRow, sizePerRepeat);
VF_CALL<DequantSwigluV2<TXtype, TBias, ifXIntIndex_, ifXFloat16Index_, ifXBf16Index_, hasBiasIndex_,
hasActScale_, ifBiasIntIndex_, ifBiasFloatIndex_, ifBiasFloat16Index_,
ifBiasBfloat16Index_>>(
x1Ptr, tmpXPtr, wScale1Ptr, aScalePtr, bias1Ptr, xDimPerLoop, widthFullRow, repeatTimesFullRow,
sizePerRepeat, xTypeUbAlignB32FullRow_, xTypeUbAlignB32_, xTypeUbAlignB32_, aScaleUbAlignB32_, 0,
tl_->clampLimit, tl_->gluAlpha, tl_->gluBias);
}
xActQueue_.FreeTensor(xActLocal);
if constexpr (hasBiasIndex_) {
biasQueue_.FreeTensor(biasLocal);
}
__local_mem__ float* qScalePtr = (__local_mem__ float*)inScaleLocal.GetPhyAddr(xUbAlignB32_ * 2);
__VEC_SCOPE__
{
AscendC::MicroAPI::RegTensor<float> vreg0, vreg1, vreg2, vreg3, vreg4, vreg5, vreg6, vreg7, vreg8, vregDiv;
AscendC::MicroAPI::RegTensor<float> vregTmpX;
AscendC::MicroAPI::RegTensor<float> vreg16;
AscendC::MicroAPI::RegTensor<int16_t> vreg17;
AscendC::MicroAPI::RegTensor<half> vreg18;
AscendC::MicroAPI::RegTensor<int8_t> vreg19;
AscendC::MicroAPI::MaskReg mask, maskTail, maskOne;
constexpr uint16_t sizePerRepeat = AscendC::GetVecLen() / sizeof(float);
uint16_t repeatTimes = CeilDivision(tl_->UbFactorDimy, sizePerRepeat);
uint32_t block = static_cast<uint32_t>(sizePerRepeat);
uint32_t tailBlock = tl_->UbFactorDimy - sizePerRepeat * (repeatTimes - 1);
uint32_t numOne = 1;
mask = AscendC::MicroAPI::UpdateMask<uint32_t>(block);
maskTail = AscendC::MicroAPI::UpdateMask<uint32_t>(tailBlock);
maskOne = AscendC::MicroAPI::UpdateMask<uint32_t>(numOne);
float scalarOne = 1.0;
float scalarZero = 0;
float scalarMaxNum = scalarMaxNum_;
AscendC::MicroAPI::Duplicate(vregDiv, scalarMaxNum);
for (uint16_t i = 0; i < static_cast<uint16_t>(xDimPerLoop); i++) {
auto scaleAddr = scalePtr + i * aScaleUbAlignB32_;
AscendC::MicroAPI::Duplicate(vregTmpX, scalarZero);
uint16_t j = repeatTimes - 1;
auto tmpXAddr = tmpXPtr + i * xTypeUbAlignB32_ + j * sizePerRepeat;
AscendC::MicroAPI::DataCopy(vreg0, tmpXAddr);
if constexpr (hasQuantScale_) {
auto qScaleAddr = qScalePtr + j * sizePerRepeat;
AscendC::MicroAPI::DataCopy(vreg1, qScaleAddr);
AscendC::MicroAPI::Mul(vreg0, vreg0, vreg1, maskTail);
AscendC::MicroAPI::DataCopy(tmpXAddr, vreg0, maskTail);
}
AscendC::MicroAPI::Abs(vreg3, vreg0, maskTail);
AscendC::MicroAPI::Max(vregTmpX, vregTmpX, vreg3, maskTail);
for (uint16_t j = 0; j < static_cast<uint16_t>(repeatTimes - 1); j++) {
auto tmpXAddr = tmpXPtr + i * xTypeUbAlignB32_ + j * sizePerRepeat;
AscendC::MicroAPI::DataCopy(vreg0, tmpXAddr);
if constexpr (hasQuantScale_) {
auto qScaleAddr = qScalePtr + j * sizePerRepeat;
AscendC::MicroAPI::DataCopy(vreg1, qScaleAddr);
AscendC::MicroAPI::Mul(vreg0, vreg0, vreg1, mask);
AscendC::MicroAPI::DataCopy(tmpXAddr, vreg0, mask);
}
AscendC::MicroAPI::Abs(vreg3, vreg0, mask);
AscendC::MicroAPI::Max(vregTmpX, vregTmpX, vreg3, mask);
}
AscendC::MicroAPI::ReduceMax(vreg4, vregTmpX, mask);
AscendC::MicroAPI::Div(vreg5, vreg4, vregDiv, mask);
AscendC::MicroAPI::DataCopy(scaleAddr, vreg5, maskOne);
}
}
scaleQueue_.EnQue<float>(scaleLocal);
scaleLocal = scaleQueue_.DeQue<float>();
DataCopyParams dataCopyScaleParams;
dataCopyScaleParams.blockCount = xDimPerLoop;
dataCopyScaleParams.blockLen = sizeof(float);
dataCopyScaleParams.srcStride = 0;
dataCopyScaleParams.dstStride = 0;
DataCopyPad(scaleGm_[xDimOffsetPerLoop], scaleLocal[0], dataCopyScaleParams);
__VEC_SCOPE__
{
constexpr uint16_t sizePerRepeat = AscendC::GetVecLen() / sizeof(float);
uint16_t repeatTimes = CeilDivision(tl_->UbFactorDimy, sizePerRepeat);
AscendC::MicroAPI::RegTensor<float> vreg6, vreg7, vreg8;
AscendC::MicroAPI::RegTensor<int16_t> vreg9;
AscendC::MicroAPI::RegTensor<half> vreg10;
AscendC::MicroAPI::RegTensor<int8_t> vreg11;
AscendC::MicroAPI::RegTensor<fp8_e4m3fn_t> vreg12;
AscendC::MicroAPI::RegTensor<fp8_e5m2_t> vreg13;
AscendC::MicroAPI::RegTensor<bfloat16_t> vreg14, vreg15;
AscendC::MicroAPI::RegTensor<fp4x2_e2m1_t> vreg16;
AscendC::MicroAPI::RegTensor<fp4x2_e1m2_t> vreg17;
AscendC::MicroAPI::RegTensor<hifloat8_t> vreg18;
AscendC::MicroAPI::RegTensor<uint16_t> yRegTensor;
AscendC::MicroAPI::RegTensor<uint8_t> out;
AscendC::MicroAPI::MaskReg maskFull8;
AscendC::MicroAPI::MaskReg mask;
uint32_t fp4Width = 32;
maskFull8 = AscendC::MicroAPI::UpdateMask<uint32_t>(fp4Width);
for (uint16_t i = 0; i < static_cast<uint16_t>(xDimPerLoop); i++) {
auto scaleAddr = scalePtr + i * aScaleUbAlignB32_;
AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::LoadDist::DIST_BRC_B32>(vreg6, scaleAddr);
uint32_t width = static_cast<uint32_t>(tl_->UbFactorDimy);
for (uint16_t j = 0; j < repeatTimes; j++) {
mask = AscendC::MicroAPI::UpdateMask<uint32_t>(width);
auto tmpXAddr = tmpXPtr + i * xTypeUbAlignB32_ + j * sizePerRepeat;
auto yAddr = yPtr + i * yUbAlignB8_ + j * sizePerRepeat;
auto yFp4Addr = yFp4Ptr + i * yUbAlignB4_ + (j * sizePerRepeat / 2);
AscendC::MicroAPI::DataCopy(vreg7, tmpXAddr);
AscendC::MicroAPI::Div(vreg8, vreg7, vreg6, mask);
if constexpr (ifYFloat8e4m3Index_) {
AscendC::MicroAPI::Cast<fp8_e4m3fn_t, float, CAST_FP32_TO_FP8>(vreg12, vreg8, mask);
AscendC::MicroAPI::DataCopy<fp8_e4m3fn_t, AscendC::MicroAPI::StoreDist::DIST_PACK4_B32>(
yAddr, vreg12, mask);
} else if constexpr (ifYFloat8e5m2Index_) {
AscendC::MicroAPI::Cast<fp8_e5m2_t, float, CAST_FP32_TO_FP8>(vreg13, vreg8, mask);
AscendC::MicroAPI::DataCopy<fp8_e5m2_t, AscendC::MicroAPI::StoreDist::DIST_PACK4_B32>(
yAddr, vreg13, mask);
} else if constexpr (ifYFloat4e2m1Index_) {
AscendC::MicroAPI::Cast<bfloat16_t, float, CAST_FP32_TO_BF16>(vreg14, vreg8, mask);
AscendC::MicroAPI::Pack((AscendC::MicroAPI::RegTensor<uint16_t>&)vreg14,
(AscendC::MicroAPI::RegTensor<uint32_t>&)vreg14);
if (roundMode_ == 1) {
AscendC::MicroAPI::Cast<fp4x2_e2m1_t, bfloat16_t, CAST_BF16_TO_FP4_ROUND>(vreg16, vreg14,
mask);
} else if (roundMode_ == 2) {
AscendC::MicroAPI::Cast<fp4x2_e2m1_t, bfloat16_t, CAST_BF16_TO_FP4_FLOOR>(vreg16, vreg14,
mask);
} else if (roundMode_ == 3) {
AscendC::MicroAPI::Cast<fp4x2_e2m1_t, bfloat16_t, CAST_BF16_TO_FP4_CEIL>(vreg16, vreg14,
mask);
} else if (roundMode_ == 4) {
AscendC::MicroAPI::Cast<fp4x2_e2m1_t, bfloat16_t, CAST_BF16_TO_FP4_TRUNC>(vreg16, vreg14,
mask);
} else {
AscendC::MicroAPI::Cast<fp4x2_e2m1_t, bfloat16_t, CAST_BF16_TO_FP4_RINT>(vreg16, vreg14,
mask);
}
AscendC::MicroAPI::DataCopy<uint8_t, AscendC::MicroAPI::StoreDist::DIST_PACK4_B32>(
yFp4Addr, (AscendC::MicroAPI::RegTensor<uint8_t>&)vreg16, maskFull8);
} else if constexpr (ifYFloat4e1m2Index_) {
AscendC::MicroAPI::Cast<bfloat16_t, float, CAST_FP32_TO_BF16>(vreg15, vreg8, mask);
AscendC::MicroAPI::Pack((AscendC::MicroAPI::RegTensor<uint16_t>&)vreg15,
(AscendC::MicroAPI::RegTensor<uint32_t>&)vreg15);
if (roundMode_ == 1) {
AscendC::MicroAPI::Cast<fp4x2_e1m2_t, bfloat16_t, CAST_BF16_TO_FP4_ROUND>(vreg17, vreg15,
mask);
} else if (roundMode_ == 2) {
AscendC::MicroAPI::Cast<fp4x2_e1m2_t, bfloat16_t, CAST_BF16_TO_FP4_FLOOR>(vreg17, vreg15,
mask);
} else if (roundMode_ == 3) {
AscendC::MicroAPI::Cast<fp4x2_e1m2_t, bfloat16_t, CAST_BF16_TO_FP4_CEIL>(vreg17, vreg15,
mask);
} else if (roundMode_ == 4) {
AscendC::MicroAPI::Cast<fp4x2_e1m2_t, bfloat16_t, CAST_BF16_TO_FP4_TRUNC>(vreg17, vreg15,
mask);
} else {
AscendC::MicroAPI::Cast<fp4x2_e1m2_t, bfloat16_t, CAST_BF16_TO_FP4_RINT>(vreg17, vreg15,
mask);
}
AscendC::MicroAPI::DataCopy<uint8_t, AscendC::MicroAPI::StoreDist::DIST_PACK4_B32>(
yFp4Addr, (AscendC::MicroAPI::RegTensor<uint8_t>&)vreg17, maskFull8);
} else if constexpr (ifYHiFloat8Index_) {
AscendC::MicroAPI::Cast<hifloat8_t, float, CAST_FP32_TO_HI8>(vreg18, vreg8, mask);
AscendC::MicroAPI::DataCopy<hifloat8_t, AscendC::MicroAPI::StoreDist::DIST_PACK4_B32>(
yAddr, vreg18, mask);
} else {
AscendC::MicroAPI::Cast<int16_t, float, CAST_FP32_TO_INT16>(vreg9, vreg8, mask);
AscendC::MicroAPI::Cast<half, int16_t, CAST_INT16_TO_FP16>(vreg10, vreg9, mask);
AscendC::MicroAPI::Cast<int8_t, half, CAST_FP16_TO_INT8>(vreg11, vreg10, mask);
AscendC::MicroAPI::DataCopy<int8_t, AscendC::MicroAPI::StoreDist::DIST_PACK4_B32>(yAddr, vreg11,
mask);
}
}
}
}
inScaleQueue_.FreeTensor(inScaleLocal);
scaleQueue_.FreeTensor(scaleLocal);
yQueue_.EnQue<TYtype>(yLocal);
yLocal = yQueue_.DeQue<TYtype>();
if constexpr (ifYFloat4e2m1Index_ || ifYFloat4e1m2Index_) {
DataCopyParams dataCopyYParams;
dataCopyYParams.blockCount = xDimPerLoop;
dataCopyYParams.blockLen = tl_->outDimy * sizeof(TYtype) / 2;
dataCopyYParams.srcStride = 0;
dataCopyYParams.dstStride = 0;
DataCopyPad(yGm_.template ReinterpretCast<uint8_t>()[xDimOffsetPerLoop * tl_->outDimy / 2], yFp4Local[0],
dataCopyYParams);
yQueue_.FreeTensor(yLocal);
} else {
DataCopyParams dataCopyYParams;
dataCopyYParams.blockCount = xDimPerLoop;
dataCopyYParams.blockLen = tl_->outDimy * sizeof(TYtype);
dataCopyYParams.srcStride = 0;
dataCopyYParams.dstStride = 0;
DataCopyPad(yGm_[xDimOffsetPerLoop * tl_->outDimy], yLocal[0], dataCopyYParams);
yQueue_.FreeTensor(yLocal);
}
}
}
template <typename TActScale, typename TQuantScale, typename TGroup, typename TBias, typename TXtype, typename TYtype>
__aicore__ inline void
DequantSwigluQuantBase<TActScale, TQuantScale, TGroup, TBias, TXtype, TYtype>::ProcessSingleGroup(int64_t groupIdx,
int64_t realDimx,
int64_t groupOffset)
{
int64_t blockDimxFactor = (realDimx + tl_->maxCoreNum - 1) / tl_->maxCoreNum;
realCoreDim_ = (realDimx + blockDimxFactor - 1) / blockDimxFactor;
if (blockIdx_ < realCoreDim_) {
int64_t blockDimxTailFactor = realDimx - blockDimxFactor * (realCoreDim_ - 1);
int64_t xDimPerCore = blockDimxFactor;
if (blockIdx_ == (realCoreDim_ - 1)) {
xDimPerCore = blockDimxTailFactor;
}
int64_t coreDimxOffset = blockDimxFactor * blockIdx_ + groupOffset;
ProcessSingleGroupPerCore(groupIdx, xDimPerCore, coreDimxOffset);
}
}
}
#endif