Contiguous Non-aligned Data Move-out
Applicability
Product |
Supported |
|---|---|
Atlas 350 Accelerator Card |
√ |
x |
|
x |
|
x |
|
x |
|
x |
|
x |
Function Usage
Indicates the Reg vector computation data movement interface, and is used to move non-contiguous aligned data from RegTensor to UB.
Prototype
// Scenario 1: Use uint32_t as the storage offset and use the post mode for data movement. The address of the destination operand in the UB is updated each time the API is called. template <typename T = DefaultType, PostLiteral postMode = PostLiteral::POST_MODE_UPDATE, typename U> __simd_callee__ inline void StoreUnAlign(__ubuf__ T*& dstAddr, U& srcReg, UnalignRegForStore& ureg, uint32_t postUpdateStride); // Process the tail block of non-aligned data movement. This is applicable to scenario 1. template <typename T, PostLiteral postMode = PostLiteral::POST_MODE_UPDATE> __simd_callee__ inline void StoreUnAlignPost(__ubuf__ T*& dstAddr, UnalignRegForStore& ureg, int32_t postUpdateStride); // Scenario 2: Use AddrReg to store the offset for data movement and use the post mode for data movement. The address of the destination operand in the UB is updated each time the API is called. template <typename T = DefaultType, PostLiteral postMode = PostLiteral::POST_MODE_UPDATE, typename U> __simd_callee__ inline void StoreUnAlign(__ubuf__ T*& dstAddr, U& srcReg, UnalignRegForStore& ureg, AddrReg& areg); // Process the tail block of non-aligned data movement. This is applicable to scenario 2. template <typename T> __simd_callee__ inline void StoreUnAlignPost(__ubuf__ T*& dstAddr, UnalignRegForStore& ureg, AddrReg& areg); // Scenario 3: Use this API together with Squeeze for contiguous non-aligned move-out. The SqueezeReg vector computation API stores the total number of bytes of valid elements to the AR special register. When this API is used, the number of valid elements in the AR register is used as the storage offset. template <typename T = DefaultType, PostLiteral postMode = PostLiteral::POST_MODE_UPDATE, typename U> __simd_callee__ inline void StoreUnAlign(__ubuf__ T* dstAddr, U& srcReg, UnalignRegForStore& ureg); // Process the tail block of non-aligned data movement. This is applicable to scenario 3. template <typename T> __simd_callee__ inline void StoreUnAlignPost(__ubuf__ T* dstAddr, UnalignRegForStore& ureg);
Parameters
Parameter |
Input/Output |
Description |
|---|---|---|
T |
Input |
Template parameter. The supported data types are b8, b16, b32, and b64. |
postMode |
Input |
This parameter controls whether to enable post update. The value is of the PostLiteral type. |
U |
Input |
Template parameter. The corresponding RegTensor type for the data types supported by template parameter T. |
ureg |
Input/Output |
UnalignRegForStore: non-aligned register, which is used to store non-aligned data. The length is 32 bytes. It is used as an input/output in the StoreUnAlign function and as an input in the StoreUnAlignPost function. |
srcReg |
Input |
Source operand, which is of the RegTensor type. |
dstAddr |
Input/Output |
Start address of the destination operand in the UB. |
postUpdateStride |
Input |
The meaning of postUpdateStride is different under the POST_MODE_NORMAL and POST_MODE_UPDATE scenarios.
|
Parameter |
Input/Output |
Description |
|---|---|---|
ureg |
Input/Output |
UnalignRegForStore: non-aligned register, which is used to store non-aligned data. The length is 32 bytes. It is used as an input/output in the StoreUnAlign function and as an input in the StoreUnAlignPost function. |
srcReg |
Input |
Source operand, which is of the RegTensor type. |
dstAddr |
Input/Output |
Start address of the destination operand in the UB. |
areg |
Input |
The actual UB start address for data movement is of the AddrReg data type, which stores the address offset. The actual UB start address for the movement is computed as: srcAddr + offset. |
Parameter |
Input/Output |
Description |
|---|---|---|
dstAddr |
Input/Output |
Start address of the destination operand in the UB. |
ureg |
Input/Output |
UnalignRegForStore: non-aligned register, which is used to store non-aligned data. The length is 32 bytes. It is used as an input/output in the StoreUnAlign function and as an input in the StoreUnAlignPost function. |
srcReg |
Input |
Source operand, which is of the RegTensor type. |
Restrictions
- The dstAddr parameter in this API does not need to be 32-byte aligned.
- The StoreUnAlign and StoreUnAlignPost interfaces must be used together.
Examples
// Use uint32_t to store the offset in the contiguous non-aligned data move-out mode.
template <typename T>
__simd_vf__ inline void StoreUnAlignVF(__ubuf__ T* dstAddr, __ubuf__ T* srcAddr, uint32_t postUpdateStride, uint16_t repeatTimes)
{
AscendC::Reg::RegTensor<T> srcReg;
AscendC::Reg::UnalignRegForLoad ureg0;
AscendC::Reg::UnalignRegForStore ureg1;
for (uint16_t i = 0; i < repeatTimes; ++i) {
AscendC::Reg::LoadUnAlignPre(ureg0, srcAddr + i * postUpdateStride);
AscendC::Reg::LoadUnAlign(srcReg, ureg0, srcAddr + i * postUpdateStride);
AscendC::Reg::StoreUnAlign(dstAddr, srcReg, ureg1, postUpdateStride);
}
AscendC::Reg::StoreUnAlignPost(dstAddr, ureg1, 0);
}
// Use AddrReg to store the offset in the contiguous non-aligned data move-out mode.
template <typename T>
__simd_vf__ inline void StoreUnAlignVF(__ubuf__ T* dstAddr, __ubuf__ T* srcAddr, uint32_t oneRepeatSize, uint16_t repeatTimes)
{
AscendC::Reg::RegTensor<T> srcReg;
AscendC::Reg::UnalignRegForLoad ureg0;
AscendC::Reg::UnalignRegForStore ureg1;
AscendC::Reg::AddrReg aReg;
for (uint16_t i = 0; i < (uint16_t)repeatTimes; ++i) {
aReg = AscendC::Reg::CreateAddrReg<T>(i, oneRepeatSize);
AscendC::Reg::LoadUnAlignPre(ureg0, srcAddr, aReg);
AscendC::Reg::LoadUnAlign(srcReg, ureg0, srcAddr, aReg, 0);
AscendC::Reg::StoreUnAlign(dstAddr, srcReg, ureg1, aReg);
}
AscendC::Reg::StoreUnAlignPost(dstAddr, ureg1, aReg);
}
// Used with Squeeze. For contiguous non-aligned move-out, the SqueezeReg vector computation API stores the total number of bytes of valid elements to the AR register, and uses the number of valid elements in the AR register as the storage offset.
template <typename T>
__aicore__ inline void SqueezeVF(__ubuf__ T* dstAddr, __ubuf__ T* srcAddr, uint32_t oneRepeatSize, uint16_t repeatTimes)
{
AscendC::Reg::RegTensor<T> srcReg0;
AscendC::Reg::RegTensor<T> srcReg1;
AscendC::Reg::UnalignRegForStore ureg;
AscendC::Reg::MaskReg mask = AscendC::Reg::CreateMask<T, AscendC::Reg::MaskPattern::H>();
for (uint16_t i = 0; i < repeatTimes; ++i) {
AscendC::Reg::LoadAlign<T, AscendC::Reg::PostLiteral::POST_MODE_UPDATE>(srcReg0, srcAddr, oneRepeatSize);
AscendC::Reg::Squeeze<T, AscendC::Reg::GatherMaskMode::STORE_REG>(srcReg1, srcReg0, mask);
AscendC::Reg::StoreUnAlign<T, AscendC::Reg::PostLiteral::POST_MODE_UPDATE>(dstAddr, srcReg1, ureg);
}
AscendC::Reg::StoreUnAlignPost(dstAddr, ureg);
}