Copy(L0C Buffer到Global Memory数据搬运)
说明
本接口为试验接口,在后续版本中可能会调整或改进,不保证后续兼容性。请开发者在使用过程中关注后续版本更新。
产品支持情况
- Ascend 950PR/Ascend 950DT:支持
- Atlas A3 训练系列产品/Atlas A3 推理系列产品:不支持
- Atlas A2 训练系列产品/Atlas A2 推理系列产品:不支持
- Atlas 200I/500 A2 推理产品:不支持
- Atlas 推理系列产品AI Core:不支持
- Atlas 推理系列产品Vector Core:不支持
- Atlas 训练系列产品:不支持
功能说明
头文件路径为:tensor_api/tensor.h。
Tensor API通过Copy接口统一执行不同通路数据搬运。该接口用于将L0C Buffer中的矩阵计算结果搬运到Global Memory。L0C Buffer中的数据通常为Mmad的输出,数据格式为NZ。搬运到Global Memory时,接口会根据目的张量布局自动选择NZ到ND、DN、NZ、NC1HWC0、NHWC或NCHW的随路格式转换。其中NC1HWC0、NHWC和NCHW用于卷积输出特征图。
L0C Buffer到Global Memory搬运支持不量化输出、float到half或bfloat16_t的直接转换输出,以及配合标量或张量量化参数的随路量化输出。随路Relu、通道拆分和量化舍入方式通过CopyL0C2GMTrait配置。Mmad与Fixpipe细粒度并行相关的unitFlag通过FixpipeParams配置。
接口支持batch模式。batch模式用于一次完成多块矩阵计算结果的搬运。Layout在原矩阵Layout最外层增加Batch维度。源张量为NZ格式,分形固定为16×16,可通过MakeFrameLayout<NZLayoutPtn>(batch, m, n)构造。目的张量可通过MakeFrameLayout<NDLayoutPtn>(batch, m, n)、MakeFrameLayout<DNLayoutPtn>(batch, m, n)、MakeFrameLayout<NDExtLayoutPtn>(batch, m, n)、MakeFrameLayout<DNExtLayoutPtn>(batch, m, n)或MakeFrameLayout<NZLayoutPtn, DstType>(batch, m, n)构造。NZ格式可通过模板参数DstType指定目的数据类型,C0表示NZ格式的列分形大小,默认为16。卷积输出通路当前仅支持N为1,不支持batch模式。
随路量化、随路Relu、随路格式转换、随路通道拆分以及随路通道合并的有效组合、中间数据类型和数据路径如下图所示。图中的F32到F16、F32到BF16为非量化模式,仅进行cast。其余路径为不量化模式、随路scalar量化模式或随路tensor量化模式。
针对Ascend 950PR/Ascend 950DT:
图1 L0C2GM流程图

函数原型
执行L0C Buffer到Global Memory的非量化搬运。
C++template <typename AtomType, typename DstTensor, typename SrcTensor> __aicore__ inline void Copy(const CopyAtom<AtomType>& atomCopy, const DstTensor& dst, const SrcTensor& src)执行L0C Buffer到Global Memory的量化搬运。
C++template <typename AtomType, typename DstTensor, typename SrcTensor, typename QuantParam, Std::enable_if_t<IsCopyQuantParamV<QuantParam>, int> Enable> __aicore__ inline void Copy(const CopyAtom<AtomType>& atomCopy, const DstTensor& dst, const SrcTensor& src, const QuantParam& quant)使用默认trait构造搬运原子对象。
C++template <typename CopyOperationType> __aicore__ inline constexpr auto MakeCopy(const CopyOperationType& copyOperation)使用指定trait构造搬运原子对象。
C++template <typename CopyOperationType, typename CopyTraitType> __aicore__ inline constexpr auto MakeCopy(const CopyOperationType& copyOperation, const CopyTraitType& copyTrait)
参数说明
表1 Copy接口参数说明
| 参数名 | 输入/输出 | 描述 |
|---|---|---|
| atomCopy | 输入 | 搬运原子对象,可由MakeCopy(CopyL0C2GM{})或MakeCopy(CopyL0C2GM{}, CopyL0C2GMTraitDefault{})构造。 |
| dst | 输出 | 目的张量,存储位置为Location::GM。支持ND、DN、NZ、NC1HWC0、NHWC和NCHW数据格式。 |
| src | 输入 | 源张量,存储位置为Location::L0C,数据格式为NZ,通常为Mmad的计算结果。 |
| quant | 输入 | 可选量化参数。传入uint64_t时表示scalar量化参数,传入张量时表示tensor量化参数,张量位于L1 Buffer,元素类型为uint64_t。 |
| fixpipeParams | 输入 | 可选搬运参数,类型为FixpipeParams,通过atomCopy的with接口绑定到搬运原子对象,未绑定时使用默认值。 |
表2 MakeCopy接口参数说明
| 参数名 | 输入/输出 | 描述 |
|---|---|---|
| copyOperation | 输入 | 搬运操作对象。L0C Buffer到Global Memory搬运采用CopyL0C2GM{}。 |
| copyTrait | 输入 | 搬运静态特性对象。L0C Buffer到Global Memory搬运默认采用CopyL0C2GMTraitDefault{}。 |
CopyL0C2GMTrait说明
CopyL0C2GMTrait用于配置L0C Buffer到Global Memory搬运的静态特性。
struct CopyL0C2GMTrait {
RoundMode roundMode = RoundMode::DEFAULT;
bool enableRelu = false;
bool enableChannelSplit = false;
};
表3 CopyL0C2GMTrait成员说明
| 成员 | 默认值 | 描述 |
|---|---|---|
| roundMode | RoundMode::DEFAULT | 舍入模式。RoundMode::HYBRID仅在源类型为float、目的类型为hifloat8_t的量化输出场景支持。 |
| enableRelu | false | 是否使能随路Relu。 |
| enableChannelSplit | false | 是否使能输出数据通道拆分。只支持NZ格式且源类型和目的类型均为float的场景。 |
使用自定义trait的示例:
constexpr CopyL0C2GMTrait l0c2gmTrait = {
RoundMode::DEFAULT,
false,
true
};
struct CopyL0C2GMTraitCustom {
using TraitType = CopyL0C2GMTrait;
static constexpr const TraitType value = l0c2gmTrait;
};
FixpipeParams说明
FixpipeParams用于配置运行时搬运参数。
struct FixpipeParams {
uint8_t unitFlag = 0;
bool subBlockId = false;
};
表4 FixpipeParams成员说明
| 成员 | 默认值 | 描述 |
|---|---|---|
| unitFlag | 0 | 控制Mmad指令和Fixpipe指令的细粒度并行。0表示不使能,2表示使能且执行后不复位单元标记位,3表示使能且执行后复位单元标记位。开启时,MmadParams和FixpipeParams中的unitFlag需要配套设置为2或3。 |
| subBlockId | false | 在启用单目标模式时指示目标UB的编号,L0C Buffer到Global Memory数据搬运时该参数无效。 |
数据类型
L0C Buffer到Global Memory搬运根据是否传入量化参数自动选择量化模式。
表5 数据类型说明
| 源张量类型(L0C Buffer) | 目的张量类型(Global Memory) | 调用形式 | 说明 |
|---|---|---|---|
int32_t | int8_t、uint8_t | Copy(atom, dst, src, quant) | scalar或tensor量化输出。 |
float | int8_t、uint8_t | Copy(atom, dst, src, quant) | scalar或tensor量化输出。 |
float | fp8_e4m3fn_t、hifloat8_t | Copy(atom, dst, src, quant) | scalar或tensor量化输出。hifloat8_t支持RoundMode::DEFAULT和RoundMode::HYBRID。 |
int32_t | half、bfloat16_t | Copy(atom, dst, src, quant) | scalar或tensor量化输出。 |
float | half | Copy(atom, dst, src) | 直接转换输出。 |
float | bfloat16_t | Copy(atom, dst, src) | 直接转换输出。 |
float | half、bfloat16_t | Copy(atom, dst, src, quant) | scalar或tensor量化输出。 |
int32_t | int32_t | Copy(atom, dst, src) | 不量化输出。 |
float | float | Copy(atom, dst, src) | 不量化输出。 |
float | float | Copy(atom, dst, src, quant) | scalar或tensor量化输出。 |
不传入quant时,接口选择不量化或直接转换模式,传入uint64_t时选择scalar量化模式,传入张量时选择tensor量化模式。
返回值说明
Copy无返回值。MakeCopy返回CopyAtom对象。
约束说明
- 源矩阵
NZ格式,地址要求64字节对齐。目的矩阵DN或ND格式时,地址要求1字节对齐,NZ格式时,地址要求32字节对齐。 - 目的矩阵为
NZ输出时,N方向大小需要为16的倍数;b8类型通道合并场景为32的倍数,float使能enableChannelSplit通道拆分场景为8的倍数。 - tensor量化参数张量应位于L1 Buffer,元素类型为
uint64_t,地址要求32字节对齐。详情参见随路量化。 - 使能
unitFlag时,需要配合Mmad同时使能。 - 使用
RoundMode::HYBRID时,源类型必须为float,目的类型必须为hifloat8_t。 enableChannelSplit仅在源类型和目的类型均为float,且目的格式为NZ时生效。详情参见F32 Channel Split。- 通道合并特性硬件自动使能,不能通过参数配置。详情参见Int8 Channel Merge。
NZ到NC1HWC0、NHWC或NCHW的卷积输出通路当前仅支持N为1。NZ到NHWC或NCHW仅支持不传入quant的调用形式。- 卷积输出通路中,源
NZ张量的逻辑Shape需要为(H * W, C)。目的张量为NC1HWC0时需要满足C = C1 * C0。
关键特性
L0C Buffer到Global Memory搬运涉及随路量化、随路Relu、F32 Channel Split、Int8 Channel Merge和batch搬运等关键特性。
调用示例
卷积输出
以下示例将L0C Buffer中Shape为(H * W, C)的NZ矩阵搬运到Global Memory,并转换为NHWC格式。将目的Layout替换为NCHWLayoutPtn或NC1HWC0LayoutPtn,可分别完成NCHW或NC1HWC0格式输出。
#include "tensor_api/tensor.h"
using namespace AscendC::Te;
constexpr uint32_t H = 8;
constexpr uint32_t W = 8;
constexpr uint32_t C = 16;
__aicore__ inline void CopyConvOutputL0CToGM(__gm__ float* gmAddr)
{
__cc__ float l0cBuf[H * W * C];
auto l0c = MakeTensor(
MakeMemPtr(l0cBuf),
MakeFrameLayout<NZLayoutPtn, 16>(H * W, C));
auto gm = MakeTensor(
MakeMemPtr(gmAddr), MakeFrameLayout<NHWCLayoutPtn>(1, H, W, C));
auto copyL0CToGM = MakeCopy(CopyL0C2GM{}, CopyL0C2GMTraitDefault{});
Copy(copyL0CToGM, gm, l0c);
}
不量化输出
#include "tensor_api/tensor.h"
using namespace AscendC::Te;
__aicore__ inline void CopyL0CToGM()
{
auto l0c = MakeTensor(MakeMemPtr(l0cAddr), MakeFrameLayout<NZLayoutPtn, 16>(m, n));
auto gm = MakeTensor(MakeMemPtr(gmAddr), MakeFrameLayout<NDExtLayoutPtn>(m, n));
FixpipeParams params;
auto atom = MakeCopy(CopyL0C2GM{}).with(params);
Copy(atom, gm, l0c);
}
scalar量化输出
#include "tensor_api/tensor.h"
using namespace AscendC::Te;
__aicore__ inline void CopyL0CToGM()
{
auto l0c = MakeTensor(MakeMemPtr(l0cAddr), MakeFrameLayout<NZLayoutPtn, 16>(m, n));
auto gm = MakeTensor(MakeMemPtr(gmAddr), MakeFrameLayout<NDExtLayoutPtn>(m, n));
uint64_t quant = 1;
auto atom = MakeCopy(CopyL0C2GM{}).with(FixpipeParams{});
Copy(atom, gm, l0c, quant);
}
tensor量化输出
#include "tensor_api/tensor.h"
using namespace AscendC::Te;
__aicore__ inline void CopyL0CToGM()
{
auto l0c = MakeTensor(MakeMemPtr(l0cAddr), MakeFrameLayout<NZLayoutPtn, 16>(m, n));
auto gm = MakeTensor(MakeMemPtr(gmAddr), MakeFrameLayout<NDExtLayoutPtn>(m, n));
auto quant = MakeTensor(MakeMemPtr(l1QuantAddr), MakeFrameLayout<NDExtLayoutPtn>(1, n));
auto atom = MakeCopy(CopyL0C2GM{}).with(FixpipeParams{});
Copy(atom, gm, l0c, quant);
}
batch模式输出
#include "tensor_api/tensor.h"
using namespace AscendC::Te;
__aicore__ inline void CopyBatchL0CToGM(__gm__ half* gmAddr)
{
constexpr uint32_t srcBatch = 3;
constexpr uint32_t dstBatch = 9;
constexpr uint32_t m = 32;
constexpr uint32_t n = 64;
__cc__ float l0cBuf[srcBatch * m * n];
auto l0c = MakeTensor(MakeMemPtr(l0cBuf), MakeFrameLayout<NZLayoutPtn>(srcBatch, m, n));
auto gm = MakeTensor(MakeMemPtr(gmAddr), MakeFrameLayout<NDExtLayoutPtn>(dstBatch, m, n));
auto atom = MakeCopy(CopyL0C2GM{}).with(FixpipeParams{});
for (uint32_t i = 0; i < dstBatch / srcBatch; ++i) {
auto gmSlice = gm.Slice(MakeCoord(i * srcBatch, MakeCoord(0, 0)), MakeShape(srcBatch, MakeShape(m, n)));
Copy(atom, gmSlice, l0c);
}
}