Gather
产品支持情况
功能说明
给定输入的张量和一个地址偏移张量,本接口根据偏移地址将输入张量按元素收集到结果张量中。
函数原型
-
tensor前n个数据计算
template <typename T> __aicore__ inline void Gather(const LocalTensor<T>& dst, const LocalTensor<T>& src, const LocalTensor<uint32_t>& srcOffset, const uint32_t srcBaseAddr, const uint32_t count) -
tensor高维切分计算
-
mask逐bit模式
template <typename T> __aicore__ inline void Gather(const LocalTensor<T>& dst, const LocalTensor<T>& src, const LocalTensor<uint32_t>& srcOffset, const uint32_t srcBaseAddr, const uint64_t mask[], const uint8_t repeatTime, const uint16_t dstRepStride) -
mask连续模式
template <typename T> __aicore__ inline void Gather(const LocalTensor<T>& dst, const LocalTensor<T>& src, const LocalTensor<uint32_t>& srcOffset, const uint32_t srcBaseAddr, const uint64_t mask, const uint8_t repeatTime, const uint16_t dstRepStride)
-
参数说明
表 1 模板参数说明
表 2 参数说明
|
类型为LocalTensor,支持的TPosition为VECIN/VECCALC/VECOUT。 |
||
|
类型为LocalTensor,支持的TPosition为VECIN/VECCALC/VECOUT。 |
||
|
类型为LocalTensor,支持的TPosition为VECIN/VECCALC/VECOUT。 该偏移量相对于src的起始基地址而言。单位为Bytes。取值要求如下: |
||
src的起始基地址,用于指定Gather操作中源操作数的起始位置,单位为Bytes。取值应保证src元素类型位宽对齐,否则会导致非预期行为。 |
||
|
||
指令迭代次数,每次迭代完成8个datablock(32Bytes)的数据收集,数据范围:repeatTime∈[0,255]。 |
||
约束说明
-
操作数地址对齐要求请参见通用地址对齐约束。
-
操作数地址重叠约束请参考通用地址重叠约束。
-
针对Ascend 950PR/Ascend 950DT,uint8_t/int8_t数据类型仅支持tensor前n个数据计算接口。
调用示例
#include "kernel_operator.h"
template <typename T>
class GatherTest {
public:
__aicore__ inline GatherTest() {}
__aicore__ inline void Init(__gm__ uint8_t* dstGm, __gm__ uint8_t* srcGm,
__gm__ uint8_t* srcOffsetGm, const uint32_t count)
{
m_elementCount = count;
m_dstGlobal.SetGlobalBuffer((__gm__ T*)dstGm);
m_srcGlobal.SetGlobalBuffer((__gm__ T*)srcGm);
m_srcOffsetGlobal.SetGlobalBuffer((__gm__ uint32_t*)srcOffsetGm);
m_pipe.InitBuffer(m_queIn, 2, m_elementCount * sizeof(uint32_t));
m_pipe.InitBuffer(m_queOut, 2, m_elementCount * sizeof(uint32_t));
}
__aicore__ inline void Process()
{
CopyIn();
Compute();
CopyOut();
}
private:
__aicore__ inline void CopyIn()
{
AscendC::LocalTensor<T> srcLocal = m_queIn.AllocTensor<T>();
AscendC::DataCopy(srcLocal, m_srcGlobal, m_elementCount);
m_queIn.EnQue(srcLocal);
AscendC::LocalTensor<uint32_t> srcOffsetLocal = m_queIn.AllocTensor<uint32_t>();
AscendC::DataCopy(srcOffsetLocal, m_srcOffsetGlobal, m_elementCount);
m_queIn.EnQue(srcOffsetLocal);
}
__aicore__ inline void Compute()
{
AscendC::LocalTensor<T> srcLocal = m_queIn.DeQue<T>();
AscendC::LocalTensor<uint32_t> srcOffsetLocal = m_queIn.DeQue<uint32_t>();
AscendC::LocalTensor<T> dstLocal = m_queOut.AllocTensor<T>();
srcLocal.SetSize(m_elementCount);
AscendC::Gather(dstLocal, srcLocal, srcOffsetLocal, (uint32_t)0, m_elementCount);
m_queIn.FreeTensor(srcLocal);
m_queIn.FreeTensor(srcOffsetLocal);
m_queOut.EnQue(dstLocal);
}
__aicore__ inline void CopyOut()
{
AscendC::LocalTensor<T> dstLocal = m_queOut.DeQue<T>();
AscendC::DataCopy(m_dstGlobal, dstLocal, m_elementCount);
m_queOut.FreeTensor(dstLocal);
}
private:
AscendC::TPipe m_pipe;
AscendC::TQue<AscendC::TPosition::VECIN, 1> m_queCalc;
AscendC::GlobalTensor<T> m_valueGlobal;
uint32_t m_concatRepeatTimes;
uint32_t m_sortRepeatTimes;
uint32_t m_extractRepeatTimes;
uint32_t m_elementCount;
AscendC::GlobalTensor<uint32_t> m_srcOffsetGlobal;
AscendC::GlobalTensor<T> m_srcGlobal;
AscendC::GlobalTensor<T> m_dstGlobal;
AscendC::TQue<AscendC::TPosition::VECIN, 2> m_queIn;
AscendC::TQue<AscendC::TPosition::VECOUT, 2> m_queOut;
}; // class GatherTest
extern "C" __global__ __aicore__ void kernel_gather(GM_ADDR dstGm, GM_ADDR srcGm, GM_ADDR srcOffsetGm)
{
GatherTest<half> op;
op.Init(dstGm, srcGm, srcOffsetGm, 128);
op.Process();
}
结果示例:
输入数据srcOffsetLocal:
[254 252 250 ... 4 2 0]
输入数据srcLocal(128个half类型数据):
[0 1 2 ... 125 126 127]
输出数据dstGlobal:
[127 126 125 ... 2 1 0]