- 人工智能
- 编译器
- 模型编译
- 高性能计算
- 深度学习
- CANN
【免费下载链接】pypto
PyPTO(发音: pai p-t-o):Parallel Tensor/Tile Operation编程范式。
pypto_pro.language.move是 CANN PyPTO 编程范式中最核心的片上数据搬运动作,负责在 L1 Buffer、L0A/L0B Buffer、L0C Buffer、UB(Unified Buffer)等各级片上内存之间搬运 Tile 数据,并可在搬运过程中随路完成格式转换、量化(scale)与激活(ReLU)等融合操作。本文以该接口的官方文档为主体,结合 move 接口声明源码 与仓库中的测试用例,完整讲解其函数原型、参数语义、数据类型与分形约束、offset 子块搬运语义,以及三类量化参数传参方式与 phase 硬件握手机制,帮助开发者直接写出可运行、可对齐精度的搬运代码。
产品支持情况
该接口在不同硬件平台上支持情况不同,接口文档通过注释块明确标注(见 move.md):
- Ascend 950PR / Ascend 950DT:支持。
- Atlas A3 训练系列产品 / Atlas A3 推理系列产品:不支持。
- Atlas A2 训练系列产品 / Atlas A2 推理系列产品:不支持。
也就是说,当前move接口属于 Ascend 950 系列特有能力。配套的 AccToVecMode、ReluPreMode 以及 phase 机制(phase 使用约束)均只在 950 系列上可用。
功能说明
move用于片上 Tile 与 Tile 之间的数据搬运(tile↔tile),不涉及 GM(Global Memory)。从 move 接口源码注释 可以看到其支持的存储空间路径与对应硬件流水:
| 源(src) | 目的(dst) | 硬件流水 |
|---|---|---|
| Acc(L0C) | Vec(UB) | fix(Fixpipe) |
| Mat(L1) | Left(L0A) | mte1(MTE1) |
| Mat(L1) | Right(L0B) | mte1(MTE1) |
| Mat(L1) | Vec(UB) | v(Vector) |
| Vec(UB) | Mat(L1) | mte3(MTE3) |
| 其他组合 | — | v(Vector) |
同时,move支持三类随路融合操作(side operations):acc_to_vec_mode(L0C→UB 双目标搬运模式)、relu_pre_mode(随路 ReLU 激活)、scale(Fixpipe 量化比例,支持整块或按列粒度)。这些融合能力使move不只是"搬数据",而是"搬运即计算",减少中间步骤与流水同步开销。
函数原型
pypto_pro.language.move( dst_tile: Tile, src_tile: Tile, offset: Optional[Offset] = None, *, acc_to_vec_mode: Optional[AccToVecMode] = None, relu_pre_mode: Optional[ReluPreMode] = None, scale: Optional[Union[float, Scalar, Tile]] = None, phase: Optional[STPhase] = None, ) -> None函数返回None。offset之后的所有参数均为关键字参数(*分隔),且均带默认值,仅dst_tile、src_tile为必填。从 move 声明 可以确认,scale支持float、Scalar、Tile三种类型,这也决定了三种不同的量化粒度。
参数说明
| 参数 | 输入/输出 | 说明 |
|---|---|---|
dst_tile | 输出 | 目的操作数,Tile类型,支持的数据类型与分形详见约束说明。 |
src_tile | 输入 | 源操作数,Tile类型,支持的数据类型与分形详见约束说明。 |
offset | 输入 | 可选,小 Tile 在大 Tile 中的相对位置,格式为[offset_m, offset_n],单位为元素个数。见下方语义详解。 |
acc_to_vec_mode | 输入 | 可选,L0C Buffer→UB 搬运时是否开启双目标搬运模式,AccToVecMode 类型。 |
relu_pre_mode | 输入 | 可选,L0C Buffer→UB 搬运时是否开启随路 ReLU 操作,ReluPreMode 类型。 |
scale | 输入 | 可选,量化参数。数据搬出 L0C Buffer 时由 Fixpipe 乘以该比例并转换到目的数据类型。详见量化参数的使用。 |
phase | 输入 | 可选,phase 使用约束。 |
offset 的子块搬运语义
offset表示小 Tile 在大 Tile 中的相对位置,方向取决于源、目的 Tile 的 shape 大小关系:
- 当源操作数的 shape ≥ 目的操作数的 shape 时:表示从源操作数的第
offset_m行、offset_n列开始读,数据搬运量取目的操作数的valid_shape。典型场景是"大 Tile 取子块"。 - 当源操作数的 shape < 目的操作数的 shape 时:表示从目的操作数的第
offset_m行、offset_n列开始写,数据搬运量取源操作数的valid_shape。典型场景是"分块写入大 Tile"。
注意 move 源码注释 中 offset 被描述为"从更宽源 Tile 中提取子块"的[offset_m, offset_k],其本质含义与文档一致:以元素为单位的二维偏移。另外在 Acc→Vec 场景下,phase与offset不能同时使用(move 源码注释 明确 phase 仅用于 Acc→Vec 路径,且不可与 offset 组合)。
acc_to_vec_mode:双目标搬运模式
acc_to_vec_mode仅在 L0C Buffer→UB 场景生效,枚举定义见 AccToVecMode:
| 枚举值 | 说明 |
|---|---|
SingleModeVec0 | 单目标模式,将整个矩阵写入 Vec0 的目标 UB。 |
SingleModeVec1 | 单目标模式,将整个矩阵写入 Vec1 的目标 UB。 |
DualModeSplitM | 双目标模式,按 M 维度拆分,M/2×N 个元素写入每个 UB。尾块时框架自动将 valid_M 向上对齐到 2 的倍数得到 aligned_M;Vec0(sub_id=0)得到前 aligned_M/2 行,Vec1(sub_id=1)得到剩余 valid_M − aligned_M/2 行。注意:valid_M 为 1 时仅切分给 Vec0。 |
DualModeSplitN | 双目标模式,按 N 维度拆分,M×N/2 个元素写入每个 UB。尾块时框架自动将 valid_N 向上对齐到 32 的倍数得到 aligned_N;Vec0 得到前 aligned_N/2 列,Vec1 得到剩余 valid_N − aligned_N/2 列。注意:valid_N 不超过 16 时仅切分给 Vec0。 |
双目标模式的核心价值在于:将 L0C 中的矩阵结果一分为二写入两个 UB(对应两个 vector 核),提升后续 Vector 计算的并行度,这是 Flash Attention 等长序列注意力实现的重要手法。
DualModeSplitN 的卡死风险:接口文档特别指出,DualModeSplitN与phase同时使用时,若 N 未 32 对齐可能出现卡死现象。建议在矩阵乘运算前对 L0B Buffer 的 N 设置 valid shape,使其向上对齐到 32 的倍数。
relu_pre_mode:随路 ReLU
relu_pre_mode使能 L0C Buffer→UB 搬运过程中的随路 ReLU,枚举定义见 ReluPreMode:
PYPTO_DECLARE_ENUM(ReluPreMode, NormalRelu # 使能随路ReLU操作 )随路 ReLU 逐元素将负值置零、正值保持不变:
$$dst = \max(src, 0) = \begin{cases} src & src > 0 \ 0 & src \leq 0 \end{cases}$$
该操作由 Fixpipe 硬件在搬运数据离开 L0C 时完成,无需先将数据搬到 UB 再调用 Vector 的激活指令,省去一次数据往返和一次流水同步。
scale:量化参数
scale使能量化功能并设置量化模式下的量化参数,数据在搬出 L0C Buffer 时由 Fixpipe 乘以该比例并转换到目的数据类型。不支持与双目标搬运(DualModeSplitM/DualModeSplitN)同时使用。不同传入形式影响量化粒度,详见量化参数的使用一节。
phase:Fixpipe 硬件握手
phase参数(pypto_pro.language.STPhase类型,取Partial或Final)用于 L0C→UB 搬运与矩阵乘之间建立 unit_flag 硬件握手,详细机制见 phase 使用约束。在仓库的自动化测试中也有专门覆盖,例如 test_move_phase.py 与 test_scale_phase_atomic_order.py。
数据类型与分形约束
接口文档给出了完整的"源 → 目的"约束矩阵,覆盖分形(ND/NZ/ZN/ZZ/NN/DN)与数据类型两方面要求:
| 源 → 目的 | 分形要求 | 数据类型要求 |
|---|---|---|
| L1 Buffer → L0A Buffer | 源支持 ND、NZ、ZN、ZZ,目的固定为 NZ | 源与目的必须相同,支持 DT_INT8、DT_FP8E4M3FN、DT_FP8E5M2、DT_HF8、DT_FP16、DT_BF16、DT_FP32、DT_FP4E2M1、DT_FP4E1M2、DT_FP8E8M0 |
| L1 Buffer → L0B Buffer | 源支持 ND、NZ、ZN、ZZ,目的固定为 ZN | 源与目的必须相同,支持的数据类型同上 |
| UB → UB(目的 shape ≤ 源 shape) | 不校验分形 | 源与目的必须相同;非 ND → NZ 与 ND → NZ 支持集合略有差异(详见 move.md) |
| UB → UB(目的 shape > 源 shape) | ND → ND、NZ → NZ | 源与目的必须相同,支持 DT_INT8、DT_INT32、DT_FP16、DT_BF16、DT_FP32、DT_FP8E4M3FN、DT_FP8E5M2、DT_FP8E8M0、DT_HF8、DT_FP4E2M1、DT_FP4E1M2 |
| UB → L1 Buffer(目的 shape ≤ 源 shape) | 源支持 ND、NZ,目的不校验分形 | 源与目的必须相同,支持 DT_INT8、DT_FP8E4M3FN、DT_FP8E5M2、DT_HF8、DT_FP16、DT_BF16、DT_FP32、DT_FP4E2M1、DT_FP4E1M2、DT_FP8E8M0 |
| UB → L1 Buffer(目的 shape > 源 shape) | 源支持 ND、NZ,目的不校验分形 | 源与目的必须相同,在上一行基础上额外支持 DT_INT32 |
| L1 Buffer → BiasTable Buffer | 目的 layout 固定为 ND | 支持 DT_INT32 → DT_INT32、DT_FP32 → DT_FP32、DT_FP16 → DT_FP32、DT_BF16 → DT_FP32 |
| L1 Buffer → Fixpipe Buffer | 不校验分形 | 目的必须为 DT_INT64 或 DT_UINT64,源数据类型不做限制 |
| L1 Buffer → L0A_MX Buffer | 源与目的分形均为 ZZ | 源与目的必须相同,仅支持 DT_FP8E8M0 |
| L1 Buffer → L0B_MX Buffer | 源与目的分形均为 NN | 源与目的必须相同,仅支持 DT_FP8E8M0 |
| L0C Buffer → UB(不配置 scale) | NZ → ND、NZ → DN、NZ → NZ | 支持 DT_FP32 → DT_FP32/DT_FP16/DT_BF16,以及 DT_INT32 → DT_INT32 |
| L0C Buffer → UB(配置 scale) | NZ → ND、NZ → DN、NZ → NZ | 支持 DT_FP32 → DT_INT8/DT_UINT8/DT_HF8/DT_FP16/DT_BF16/DT_FP8E4M3FN/DT_FP32,以及 DT_INT32 → DT_INT8/DT_UINT8/DT_FP16/DT_BF16 |
| L0C Buffer → L1 Buffer(仅支持目的 shape > 源 shape) | NZ → NZ | 支持 DT_FP32 → DT_FP32/DT_FP16/DT_BF16,以及 DT_INT32 → DT_INT32 |
从源码可以印证这些存储单元与硬件流水的对应关系:codegen_common.h 中列出了各缓冲区类型的地址修饰符(如__cc__对应 L0C、__fbuf__对应 Fixpipe Buffer、__ca__/__cb__对应 L0A/L0B),codegen_common.h 中给出了各流水(PIPE_MTE1/PIPE_MTE3/PIPE_V/PIPE_FIX 等)的标识。L0C→UB 场景实际上由 Fixpipe(PIPE_FIX)承载,这正是scale、relu_pre_mode能在搬运过程中"随路"完成的硬件基础。
尾块与 L0A_MX/L0B_MX 的补充约束
- 尾块场景:需要搭配
pypto_pro.language.set_validshape与 TileType 中的compact参数使用,否则可能出现精度失败或卡死现象。 - L0A_MX / L0B_MX 地址约束:L1 Buffer → L0A_MX/L0B_MX 要求目的 Tile 必须满足
L0A_MX Buffer 地址 = L0A Buffer 地址 >> 4或L0B_MX Buffer 地址 = L0B Buffer 地址 >> 4,否则 MX 矩阵乘时会读取错误的量化系数。
调用示例
示例一:L1 → L0A / L0B 喂数给矩阵乘
这是最典型的矩阵乘(Matmul)前处理流程:先用pl.load把 GM 数据搬到 L1 Buffer,再用pl.move把 L1 数据分别送入 L0A(左矩阵,NZ)与 L0B(右矩阵,ZN),最后pl.matmul在 L0C 中完成计算:
import os import pypto_pro.language as pl import torch @pl.jit(auto_mutex=True) def kernel( a: pl.Tensor[[64, 128], pl.DT_FP16], b: pl.Tensor[[128, 32], pl.DT_FP16], out: pl.Tensor[[64, 32], pl.DT_FP32], ): a_l1 = pl.make_tile_group( type=pl.TileType(shape=[64, 128], dtype=pl.DT_FP16, target_memory=pl.MemorySpace.Mat, layout=pl.NZ), addrs=0x00000, mutex_ids=[0]) b_l1 = pl.make_tile_group( type=pl.TileType(shape=[128, 32], dtype=pl.DT_FP16, target_memory=pl.MemorySpace.Mat, layout=pl.NZ), addrs=0x10000, mutex_ids=[1]) a_l0a = pl.make_tile_group( type=pl.TileType(shape=[64, 128], dtype=pl.DT_FP16, target_memory=pl.MemorySpace.Left, layout=pl.NZ), addrs=0x0, mutex_ids=[2]) b_l0b = pl.make_tile_group( type=pl.TileType(shape=[128, 32], dtype=pl.DT_FP16, target_memory=pl.MemorySpace.Right, layout=pl.ZN), addrs=0x0, mutex_ids=[3]) c_l0c = pl.make_tile_group( type=pl.TileType(shape=[64, 32], dtype=pl.DT_FP32, target_memory=pl.MemorySpace.Acc, layout=pl.NZ), addrs=0x0, mutex_ids=[4]) with pl.section_cube(): cur_a = a_l1.current() cur_b = b_l1.current() al = a_l0a.current() br = b_l0b.current() ac = c_l0c.current() pl.load(cur_a, a, [0, 0]) pl.load(cur_b, b, [0, 0]) pl.move(al, cur_a) # L1 -> L0A pl.move(br, cur_b) # L1 -> L0B pl.matmul(ac, al, br) pl.store(out, ac, [0, 0]) if __name__ == "__main__": device = f"npu:{int(os.environ.get('TILE_FWK_DEVICE_ID', 0))}" torch.npu.set_device(device) torch.manual_seed(42) a = torch.randn([64, 128], device=device, dtype=torch.float16) b = torch.randn([128, 32], device=device, dtype=torch.float16) out = torch.zeros([64, 32], device=device, dtype=torch.float32) kernel(a, b, out) torch.npu.synchronize() ref = torch.matmul(a.float(), b.float()) torch.testing.assert_close(out, ref, rtol=2e-2, atol=2e-2) print(f"max diff = {(out - ref).abs().max().item()}")要点说明:
- L1 → L0A 时目的固定 NZ,L1 → L0B 时目的固定 ZN,与本例 TileType 中的 layout 一致。
- 矩阵乘对右矩阵采用 ZN 布局,示例中
b在 L1 中是 NZ(由 load 写入),move 到 L0B 时目的声明为 ZN。 - 使用
make_tile_group+current()在 cube section 内取当前 Tile,配合mutex_ids管理缓冲区互斥。
示例二:UB 数据转置写入 L1 Buffer
当左矩阵或右矩阵由 Vector 计算在 UB 中产生时,可先通过pl.move将 ND 转换为 NZ,再将结果写入 L1 Buffer:
- 不转置时,L1 Buffer Tile 使用 NZ,shape 与 UB 中的 NZ Tile 相同。
- 转置时,L1 Buffer Tile 使用 ZN,shape 的两个维度与 UB 中的 NZ Tile 互换。源 Tile 的 NZ [R, C] 与目的 Tile 的 ZN [C, R] 表示相同的物理分形,因此 ZN 写入本质是"零拷贝转置"。
| 矩阵 | 是否转置 | UB 中的 NZ Tile | L1 Buffer Tile |
|---|---|---|---|
| 左矩阵 A[M, K] | 否 | shape=[M, K] | shape=[M, K],NZ |
| 左矩阵 A[M, K] | 是 | shape=[K, M] | shape=[M, K],ZN |
| 右矩阵 B[K, N] | 否 | shape=[K, N] | shape=[K, N],NZ |
| 右矩阵 B[K, N] | 是 | shape=[N, K] | shape=[K, N],ZN |
分块写入 L1 Buffer 时可通过offset指定写入位置;源 Tile 的有效区域必须完整落入目的 Tile 范围内。以下示例中vector_result表示 Vector 计算产生的 [K, M] 数据:第一次 move 将其转换为 NZ,第二次 move 将其转置写入 L1 Buffer,得到供左矩阵使用的 [M, K]、ZN 数据:
import pypto_pro.language as pl M, K = 64, 128 # 前序Vector计算的输出:UB中的ND [K, M] vector_result = pl.make_tile( pl.TileType( shape=[K, M], dtype=pl.DT_FP16, target_memory=pl.MemorySpace.Vec, layout=pl.ND, ), addr=0x0000, ) # ND转换为NZ时使用的UB Tile vector_nz = pl.make_tile( pl.TileType( shape=[K, M], dtype=pl.DT_FP16, target_memory=pl.MemorySpace.Vec, layout=pl.NZ, ), addr=0x4000, ) # 转置后的数据写入L1 Buffer,逻辑shape为[M, K] lhs_l1 = pl.make_tile( pl.TileType( shape=[M, K], dtype=pl.DT_FP16, target_memory=pl.MemorySpace.Mat, layout=pl.ZN, ), addr=0x20000, ) with pl.section_vector(): pl.move(vector_nz, vector_result) # ND [K, M] → NZ [K, M] pl.move(lhs_l1, vector_nz) # NZ [K, M] → ZN [M, K]仓库中 test_move_nd_to_nz_vec.py 对该场景有直接覆盖:测试中dst与flat_view共享同一地址但属于不同 IR 值,auto_mutex无法识别该依赖,因此测试显式插入pl.system.sync_src(set_pipe=pl.PipeType.V, wait_pipe=pl.PipeType.MTE3, event_id=3)来保证 Vector 与 MTE3 之间的执行顺序——这提示我们在真实工程中,当搬运目的地址与源存在别名关系时,需要手动管理流水同步。
量化参数的使用
scale支持三种传参形式,对应三种量化粒度:
方式一:scale 为编译期常量(float)
# acc: L0C Buffer中的Tile, DT_FP32 # vec_tile: UB Tile, DT_INT8 pl.matmul(acc, q_left, k_right) pl.move(vec_tile, acc, scale=0.5) # L0C Buffer -> UB,随路按 0.5 量化为 INT8直接传固定值,适用于整块 Tile 使用同一比例。从 move 源码注释 可知,该路径走 deqScalar(per-tensor 量化)。
方式二:scale 为运行时标量(Scalar)
import struct @pl.jit() def kernel(..., scale_bits: pl.DT_INT32): # ... pl.move(vec_tile, acc, scale=scale_bits) scale_bits = struct.unpack("!I", struct.pack("!f", 0.5))[0] kernel(..., scale_bits=scale_bits)量化比例在运行时确定,需按数据类型传值:
- DT_FP32:直接传原始比例值(如
0.5)。源码注释说明运行时 FP32 标量会被自动按 IEEE-754 位模式重解释(codegen bitcast),因此传原始 float 数值即可。 - DT_INT32、DT_INT64:传预编码的 float32 位模式转成的整数,即
struct.pack("!f", 0.5)拆包后的整数。其他运行时标量 dtype(FP16/BF16/无符号/窄整数)会在解析期被拒绝。
方式三:scale 为 Tile 类型(逐列量化)
每列使用独立比例,适用于 per-channel 量化场景,前提条件较多:
- 目标存储区域必须为Fixpipe Buffer(
pl.MemorySpace.Scaling)。 - shape 为
[1, N](列量化),N 必须是 16 的倍数且 N ≤ 512;[N, 1]的行量化不支持(move 源码注释 明确说明硬件只支持每列缩放)。 - dtype 为 DT_INT64。
- 目的操作数的 Tile 数据类型为DT_INT8时,Fixpipe Buffer 中每个 DT_INT64 元素的bit46 需置 1,用于选择有符号量化;未置位时 L0C Buffer 中的负值会被按无符号解读。
- 用户需先把比例数据从 GM 搬到 L1 Buffer,再搬到 Fixpipe Buffer,并完成 MTE1→FIX 同步。框架不会自动分配缓冲或插入同步,数据流完全由用户负责(move 源码注释)。
# fp_mat: L1 Buffer中的Tile, shape [1, 64], DT_INT64 # fp_tile: Fixpipe Buffer中的Tile, shape [1, 64], DT_INT64 # acc: L0C Buffer中的Tile, DT_INT32 # vec_tile: UB Tile, DT_FP16 @pl.jit() def kernel(..., fp_params: pl.Tensor[[1, 64], pl.DT_INT64]): # ... pl.load(fp_mat, fp_params, [0, 0]) # GM -> L1 pl.move(fp_tile, fp_mat) # L1 Buffer -> Fixpipe Buffer pl.system.sync_src(set_pipe=pl.PipeType.MTE1, wait_pipe=pl.PipeType.FIX, event_id=1) pl.system.sync_dst(set_pipe=pl.PipeType.MTE1, wait_pipe=pl.PipeType.FIX, event_id=1) pl.matmul(acc, q_left, k_right) pl.move(vec_tile, acc, scale=fp_tile) # L0C Buffer -> UB,按列独立比例反量化为DT_FP16Host 侧如何准备量化比例张量,分两种情况:
# 情况一、Kernel需要DT_INT64,若使用float32的比例张量,需要先进行转换 import torch_npu scale_value = 2.0 scale_fp32 = torch.ones(1, 64, dtype=torch.float32, device=device) * scale_value fp_params = torch_npu.npu_trans_quant_param(scale_fp32) # 情况二、目的Tile数据类型为DT_INT8时,需要将Fixpipe Buffer中的Tile每个INT64元素的bit46需置1 def _make_scale_tensor(device: str, scale_values: list) -> torch.Tensor: scale_bits_list = [] for scale_value in scale_values: scale_bits = struct.unpack("!I", struct.pack("!f", scale_value))[0] scale_bits |= 1 << 46 # signed INT8 flag scale_bits_list.append(scale_bits) return torch.tensor(scale_bits_list, dtype=torch.int64, device=device).reshape(1, 64) scale_values = [2.0] * 64 fp_params = _make_scale_tensor(device, scale_values)仓库对量化参数有大量针对性测试,可作为实现参考:test_scale_param.py、test_scale_per_channel_advanced.py、test_scale_move_dtype.py、test_scale_dtype_validation.py、test_scale_value_range.py 以及 test_scale_relu_fusion.py(scale 与 ReLU 融合)。
phase 与双目标搬运的配合
phase(STPhase)与acc_to_vec_mode是 L0C→UB 场景下最常用的两个可选参数,二者配合可实现"双目标搬运 + 硬件握手"的高效流水。需要注意:
- DualModeSplitN 与 phase 同时使用时,若 N 未 32 对齐,可能出现卡死现象(详见参数说明),建议对 L0B 的 N 预先对齐到 32 的倍数。
- 尾块 + 双目标:框架自动对齐 valid_M/valid_N,UB 侧用户需自行计算两个 Vec 的 valid shape。完整示例见 AccToVecMode 文档:DualModeSplitM 下
aligned_M=34时v0=(valid_M+1)//2*2//2、v1=valid_M-v0;DualModeSplitN 下aligned_N=64时v0=(valid_N+31)//32*32//2、v1=valid_N-v0。 - 仓库测试 test_dual_mode_tail.py 专门验证尾块场景下的双目标搬运切分行为。
Flash Attention 的 QK matmul 是 phase + move 配合的经典模式:matmul 结果需要 vector 核做 softmax 后处理,store只能直接写 GM、无法在 UB 上继续计算,因此必须通过move(配合DualModeSplitN与STPhase.Final)将累加器数据搬到 UB。完整正确用法与三个错误案例(matmul 无 Final 导致卡死、store 未配 phase 导致精度问题、循环内 store(Final) 后 matmul 卡死)参见 phase 使用约束。
总结
pypto_pro.language.move是 Ascend 950 系列上连接 Cube(矩阵乘)与 Vector(UB 计算)两套流水、贯通 L1/L0A/L0B/L0C/UB 多级存储的核心动作。使用时需要重点关注四类信息:
- 路径合法性:根据约束说明确认源/目的存储空间组合及其数据类型、分形是否受支持,尤其注意 L0C→UB 的 Fixpipe 路径与 L1→L0A/L0B 的 MTE1 路径差异。
- offset 语义:根据源/目的 shape 大小关系确定是"从源读子块"还是"向目的写子块",并确保有效区域完整落入目的范围。
- 量化粒度:
scale的 float/Scalar/Tile 三种形式分别对应整块、运行时标量、逐列三种量化粒度,逐列量化时需自行完成 GM→L1→Fixpipe 的数据流与 MTE1→FIX 同步,INT8 场景还需置位 bit46。 - 同步与握手:尾块场景需配合
set_validshape与compact;需要省去软件同步时可配置phase走 unit_flag 硬件握手,但必须保证 matmul 与 move 的 phase 配对使用并以 Final 收尾。
- 人工智能
- 编译器
- 模型编译
- 高性能计算
- 深度学习
- CANN
【免费下载链接】pypto
PyPTO(发音: pai p-t-o):Parallel Tensor/Tile Operation编程范式。
相关推荐
PyPTO ReluPreMode 枚举详解:L0C Buffer 数据搬运中的随路 ReLU 融合编程
PyPTO ReluPreMode 枚举详解:L0C Buffer 数据搬运中的随路 ReLU 融合编程 导读 本文围绕 PyPTO(Parallel Tens
人工智能编译器模型编译高性能计算深度学习CANNCANN SHMEM SIMT RMA over UB Staging:以 simt_rma_ub2gm 为例解析 UB↔GM 数据搬运接口
CANN SHMEM SIMT RMA over UB Staging:以 simt_rma_ub2gm 为例解析 UB↔GM 数据搬运接口 本指南以 exam
通信高性能计算人工智能CANNAscendCANN pyasc 数据搬运接口 `asc.data_copy_pad` 详解:非对齐搬运与填充实战
CANN pyasc 数据搬运接口 asc.data_copy_pad 详解:非对齐搬运与填充实战 导读 asc.data_copy_pad 是 CANN py
编译器编程语言人工智能CANN
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考