Skip to content

[Bug] MXFP4 L1 到 L0 展开生成了错误的非零 K 偏移和 scale stride【阻塞】 #1060

Description

@erhsh

Component

PTO Dialect / ODS (include/PTO/IR)

Description

问题描述

在将 MXFP4 L1→L0 wrapper 操作展开为 VPTO 底层操作时,存在两个控制参数无法正确表达的问题:

  1. packed FP4 数据加载的非零 start_col 被额外除以 2。例如,start_col = 4 最终被展开为 k_start = 2
  2. MX scale 加载的源 stride 和目标 stride 只能根据逻辑 tile shape 自动推导。对于需要 src_stride = 8dst_stride = 4 的合法 scale 布局,当前会展开为 4, 4,并且 wrapper 操作没有提供显式指定 stride 的方式。

这两个问题会导致第二个 K 子块与第一个 K 子块发生数据重叠,或者从错误的 L1 位置加载 scale metadata,最终产生静默数值错误。

影响范围

该问题会影响以下 MXFP4 kernel:

  • K 维被拆分为多个 L1→L0 子块;
  • MX scale 在 L1 中的物理 source stride 与自动推导值不同。

生成的 kernel 可以正常编译和运行,不会报告地址或类型错误,但可能读取重叠的数据或错误的 scale metadata,最终产生静默数值错误。

Reproduction (minimal)

## 完整最小复现

将以下内容保存为 `repro_mxfp4_l1_l0.pto`:


module attributes {
  pto.target_arch = "a5",
  pto.kernel_kind = #pto.kernel_kind<cube>
} {
  func.func @repro(
      %data: !pto.ptr<!pto.f4E2M1x2, l1>,
      %scale: !pto.ptr<!pto.f4E2M1x2, l1>,
      %dst: !pto.ptr<!pto.f4E2M1x2, l0a>)
      attributes {pto.kernel} {
    %c0 = arith.constant 0 : i64
    %c4 = arith.constant 4 : i64
    %c256 = arith.constant 256 : i64

    // 加载第二个逻辑 K=256 的 MXFP4 子块。
    pto.mte_l1_l0a
        %data, %dst, %c256, %c256, %c0, %c4
        : !pto.ptr<!pto.f4E2M1x2, l1>,
          !pto.ptr<!pto.f4E2M1x2, l0a>,
          i64, i64, i64, i64

    // scale 在 L1 中的 NZ 源 stride 为 8,
    // 在 L0 中的目标 stride 为 4。
    // 当前 wrapper 没有参数可以表达这两个物理布局 stride。
    pto.mte_l1_l0a_mx
        %scale, %dst, %c256, %c256, %c0, %c0
        : !pto.ptr<!pto.f4E2M1x2, l1>,
          !pto.ptr<!pto.f4E2M1x2, l0a>,
          i64, i64, i64, i64

    return
  }
}


执行以下命令:


ptoas \
  --pto-arch=a5 \
  --pto-backend=vpto \
  --emit-vpto \
  repro_mxfp4_l1_l0.pto \
  -o repro_mxfp4_l1_l0.vpto

grep -E "load_cbuf_to_ca_(s4|mx)" repro_mxfp4_l1_l0.vpto

Expected behavior

期望行为

生成的控制参数应等价于:

pto.load_cbuf_to_ca_s4 ..., 0, 4, 16, 4, 16, 16, 0
pto.load_cbuf_to_ca_mx ..., 0, 0, 16, 4, 8, 4

对于 packed FP4:

  • 表示加载长度的 k_step 可以根据 packed 数据宽度进行换算;
  • 已经由调用方提供的 k_start 控制坐标应保持为 4,不应再次除以 2。

MX scale wrapper 还应允许调用方显式提供 source stride 和 destination stride。当调用方没有提供时,可以继续使用现有的自动推导逻辑,以保持向后兼容。

Actual behavior / error logs

## 实际行为

生成的底层操作等价于:


// m_start, k_start, m_step, k_step,
// src_stride, dst_stride, transpose
pto.load_cbuf_to_ca_s4 ..., 0, 2, 16, 4, 16, 16, 0

// x_start, y_start, x_step, y_step,
// src_stride, dst_stride
pto.load_cbuf_to_ca_mx ..., 0, 0, 16, 4, 4, 4


存在以下问题:

- 数据加载中传入的 `start_col = 4` 被展开为 `k_start = 2`。
- scale 加载自动推导出 `src_stride = 4`,但实际布局要求为 `8`。
- 当前 wrapper 没有提供显式指定 scale source/destination stride 的参数。

Git commit

26212b2

Host platform

None

Target Ascend arch (if relevant)

None

PTOAS build level (if relevant)

None

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions