Skip to content
cccskills
FreePublished on GitHub

quantization-dev

量化格式契约与位级对齐:从设备字节反推量化器的**编码公式、舍入模式、scale 粒度、退化块规则**, 并据此重实现/融合量化器(MXFP8 e8m0、int8 perblock、fp8 perchannel 等), 用「同进程同数据 + 独立参考实现 + 中点与退化输入全覆盖」做到**逐字节精确**。

当自研量化 kernel 与框架算子**对不上**、需要逆向某个量化器的数值契约、需要判断 「量化残差算不算可接受」、或要在融合内核里复现 aclnn 量化语义时使用此 skill。即使用户只说「量化结果和参考不一致」「这个 scale 怎么算出来的」「融合量化器精度对不上」 而未提"契约",也应触发。

**注意**:单纯选量化档位/配置(该不该开量化、开哪一档)走 dit-perf-opt;算子级性能调优与 DSL 选型走 operator-dev; 并行作用域导致的静默失效(DiT 侧「改了并行但不报错也没生效」的判定)走 dit-parallel-opt。

The English summary is being prepared. Showing the original description.

See how to install

Files included (5)

  • SKILL.md35.7 KB
  • evals/evals.json14.5 KB
  • references/contract-reverse-engineering.md10.5 KB
  • references/lora-merge-and-precision.md15.8 KB
  • references/online-quant-contract.md6.1 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

量化契约与位级对齐

0. ⚠️ 适用范围:本 skill 的结论硬绑定到具体环境,必须先复测再采信

本文档所有公式、常量、数字与"最优参数",都来自一次特定环境的实测(下表各维度的具体取值 见会话产物归档 {run_results_dir}/archive/,正文只留取数方式):

维度来源环境
芯片目标设备 —— 现场查 core 数 / UB 容量(设备属性 / 算子 UT)
软件栈特定版本的 CANN / triton-ascend / torch_npu / MindIE-SD
模型本案例模型(hidden / heads / head_dim 等几何见归档),少步蒸馏
形状每 rank (1, S, N/world, D) 符号形态(N = head 数,world = 并行度);S 的具体取值见归档

换任何一项,本文档的数字都不保证成立。 具体分四类:

  1. 硬规格(grid 上限、core 数、UB 容量)—— 可查文档确认,但要确认;
  2. 该版本的软件行为(round_mode 取值限制、支持的后端布局、triton 对 cast 的优化、量化算子的 tiling 边界、退化块规则)—— 换版本必须重跑;
  3. 性能与收益数字(加速比、耗时、占比)—— 随拓扑、并发、机器负载变化,不可移植;
  4. 阈值与容差(字节一致率门限、"多少差异算正常")—— 是该模型/该任务类型的属性,不可跨任务类型迁移。

特别提醒:"某方案快 / 某方案被证伪"同样依赖环境。 本 skill §七 的已证伪清单在新环境值得各复测一次 —— 证伪结论可能只在原形状/原版本下成立 (例如 kernel 形态、tile 大小、是否压 UB 上限,都会随硬件改变结论)。


0.1 默认动作:枚举多个方案、逐一实测、择优使用

不要照抄本文档的参数值(BLOCK_S、tile 形状、DSL 选择、是否用库算子…)。默认流程:

  1. 列出候选(≥2):包括本文档推荐的、以及本文档证伪的;
  2. 统一口径测量:同一进程内交错 / ABBA,避免热漂移(细则见 ../perf-gate/references/measurement-discipline.md §2);
  3. 先比正确性,再比性能:性能最快但数值错的配置必须淘汰 —— 来源环境真实出现过"看起来最快却数值错误(匹配率不足 100%)"的配置, 这是"很容易误采纳的改动";
  4. 记录两侧:落败方案的读数也要留档,才能说明"在本环境确实更差";
  5. 形成本环境自有基线,后续比较一律以此为参照;
  6. 只有在本环境复测过的结论才写进交付。

同理:本 skill 的契约本身也是"待验证的假设"而不是"标准答案"。 正确用法是照着 §五 的位级对拍 SOP 去验证,而不是假定成立 —— 这正是 §一/§二 标注证据等级的原因。

同理,契约与"为对齐它而生的技巧"也都是有寿命的:本 skill 记录的量化契约(scale 粒度、舍入模式、退化块规则) 与为匹配契约而必须做的动作(除数必须从内存载入、bf16 整数 RNE 技巧、大 tile + 64 行子块 amax、 补零对齐…),都是特定版本下逆向/试出来的 —— 下个版本可能把契约写进文档、暴露成原生 API, 或直接修掉逼出该技巧的工具链行为(例如常量除数的强度削减)。 因此套用本 skill 的任何绕行之前,先在本版本复测它是否仍然必需(一条探针 / 一个最小复现即可); 一旦不再需要就删除该条,不要留「以防万一」—— 否则会做无用绕行,甚至拒绝走已经可用的原生路径。

绕行的"存在方式"同样有纪律(单点在 ../README.md §7「禁止把一次性缺陷固化成结构」): 一次性缺陷的绕行一律走可一键关闭、可整体删除的开关,不长期分裂代码路径、不写兼容 shim, 以便确认修复后整块删掉——把绕行固化成结构,等于让"下个版本已修好"这条信息永远无法生效。


为什么需要单独一份契约

量化器是没有文档的二进制语义。它的三个自由度——scale 粒度、舍入模式、溢出行为——任何一个猜错, 结果都会"看起来差不多"(payload 99% 相符、PSNR 只掉一点),却在逐字节验收时全盘失败。

实践中猜错这三项的代价(示例):

猜错的东西后果
scale 粒度(每 tile 一个 vs 每 64-token 块一个)三种舍入模式一律 ~58% 字节不同 —— 让人误以为"舍入不是原因"
舍入模式(截断 vs RNE)差近一半的字节,不是小误差
除数用法(kernel 内重算 vs 从内存载入)常除数被强度削减成倒数乘法(~2 ulp)→ 静默污染千分之一以下的 payload 字节
溢出行为(假定饱和 vs 实际回绕)去钳位后产生静默回绕垃圾,而不是饱和值
bf16 舍入来源(x.to(bf16).to(fp32))triton-ascend 上被静默消除(no-op)→ 损失个位数百分比的 payload

一句话结论:契约必须从设备字节反推,不能猜、不能从"合理"推。


一、MXFP8(e8m0 scale)契约

证据等级:强。有独立逆向文档 + 独立推导 + 独立 numpy 参考实现逐字节完全相符(对拍规模见会话产物归档 {run_results_dir}/archive/)。

1.1 字节编码

byte = 127 + floor(log2(amax)) - 8 = 119 + floor(log2(amax))     clamped to [0, 254]
value(byte) = 2 ** (byte - 127)

语义:amax 被归一化进 [256, 512) —— 即选 scale 使最大元素至多需要 1.xxx * 2^8 表示。 因此一个值可以落在 (448, 512),必须饱和。

判别性测量(amax = 448 * 2**k 扫描):

amax0.43753.52244488967168458752
byte117121126127128131137

实现要点(承重):用 fp32 指数域取整,不要用 log2:

expf = (bits >> 23) & 0xFF
byte = clamp(expf - 8, 0, 254)

这是精确的(无 log2 舍入风险),且对 0 与 fp32 次正规数自然给出 byte 0(expf = 0 → -8 → clamp 0),与算子一致。

⚠️ 被证伪的公式:ceil(log2(amax/448)) 仅在约八成的组上相符, 在 amax = 450 / 1000 / 230 上失败。floor(log2(amax)) - 8 全部解释。

1.2 scale 布局

shape = [T, ceil(K/32/2), 2]      # 连续行主序
swizzle = 恒等映射                # group g 就在扁平偏移 g

用标记法实测(给 group g 一个唯一可识别的 2 的幂 amax,再查该字节的扁平位置):

group预期 byte实测扁平偏移(g//2, g%2)
01190(0,0)
11231(0,1)
21272(1,0)
8413384(42,0)
167135167(83,1)

结论:[T, ceil(c/2), 2] 只是形状标注,不是置换。 这一发现"removes a whole class of would-be bugs" —— 不要假设它需要 deswizzle。

1.3 payload 舍入 = RNE,饱和于 ±448

单块 amax = 440(scale = 1.0),设备原始 payload 字节:

value1.06251.18751.2520044051210001e30bf16 max-440
byte565858116126126126126126254
decoded1.01.251.25192448448448448448-448
  • 1.0625 是 1.0/1.125 的精确中点 → 1.0(偶数尾数)⇒ RNE,不是 round-half-away
  • 1.1875 是 1.125/1.25 的中点 → 1.25(偶数尾数)⇒ RNE
  • 有限溢出直接钳到 ±448(无 inf/NaN payload)
  • 由完整 e4m3 幅值表 + 全部 165 个中点及其负值构成的独立参考,在两个指数域下完全相符(100%)

1.4 退化块规则(逐条实测,容易漏)

块内容scale bytepayload
全零0全 0
amax < 2^-119(如 1e-38)0全 0
amax = 2^-110(byte 9)9正常 RNE
任意位置 ±inf255整块全 0
任意位置 nan255整块全 0

byte 0 的真实语义是 flush-to-zero(byte 0 要求 amax < 2^-119 ⇒ 块内每个值都是 bf16 次正规数)。

融合内核应采用:组 byte 为 0 或 255 ⇒ 该组 payload 全 0;byte 1..254 走 RNE(bf16_value / 2**(byte-127)) + ±448 饱和。

1.5 被量化的对象是 bf16 结果,不是 fp32 中间值(承重)

生产链路是 norm(...) -> bf16 tensor -> quant ⇒ amax 与 payload 都基于 bf16 舍入后的值。 改用 fp32 中间值会"在块 amax 跨越 2 的幂时改变指数 —— 随机数据约每 100 块 1 块"。这是设计承重点。


二、int8 契约

⚠️ 证据等级:弱(必须如实标注)。int8 没有同强度的逆向文档;结论只有零散来源(实验脚本与单句记录), 且其中一部分仍处于「待完成的阶段」。引用时必须带上这个不确定性。

项值证据等级
scale 粒度每 (head, 64-token block) 一个(每 scale 归约 64×128 = 8192 元素)源码 + reshape 机制,较强
舍入RNE(magic-number 手法 12582912.0 = 1.5*2^23)较弱:核心数字(truncate 差近一半)仅有单一来源的一句话记录、未经独立复现,原始日志不在手、无交叉验证
饱和±127脚本实现,中等
除数必须 LOADED(不得在内核内重算)强(有隔离实验,见 §3.1)
尾块S % 64 != 0(序列长不被块尺寸整除)时必然存在尾块 ⇒ 必须精确复现 F.pad-then-slice(本案例的余数见归档)未完成(尚无已验证的复现实现)

关键陷阱(值得单独记):粒度错误时三种舍入模式一律落到 ~58% 差异字节 ⇒ 若你在粒度还错的情况下比较舍入模式,会得到"舍入不是原因"的错误结论。先对粒度,再比舍入。

RNE 的整数实现手法(可迁移):

magic = tl.full((1,), 12582912.0, tl.float32)   # 1.5 * 2**23
q = tl.cast((v + magic) - magic, tl.int32)
q = tl.minimum(tl.maximum(q, -127), 127)        # ±127 饱和

三、三条实现普适规则(比具体公式更重要)

3.1 除(divide),不要乘倒数;除数必须从内存载入

在内核内计算 amax / 448.0 会被 triton-ascend 强度削减为倒数乘法(约 2 ulp 偏差), 而 2 ulp 的 scale 误差会翻转千分之一以下的 e4m3 payload 字节 —— 静默、且看起来只差一点点。

隔离实验(分母 2 097 152):

写法差异 fp8 字节
torch x / (amax/448)0
triton x / scale(scale 从内存加载)0
triton tl.fdiv(x, scale, ieee_rounding=True)0
triton x * (1/scale)零星(个位数)
torch x * (448/amax)成百上千量级
triton/torch (x / amax) * 448成百上千量级

(表中差异只保留量级;具体字节数与实验规模见会话产物归档 {run_results_dir}/archive/。)

结论:aclnn 的 payload 是 RNE(x / (amax/448)),使用正确舍入的 fp32 除法。

3.2 需要 bf16 舍入时,用整数 RNE 位技巧

b = modulated.to(tl.int32, bitcast=True)
m = ((b + 0x7FFF + ((b >> 16) & 1)) & -65536).to(tl.float32, bitcast=True)   # == 硬件 bf16 RNE
# 不要用 modulated.to(tl.bfloat16).to(tl.float32) —— 在 triton-ascend 上是 no-op(静默消除)

证据:用 262 144 个精确 bf16 中点证明 x.to(bf16).to(fp32) 与 torch 的 bf16 cast 完全不相符(0%),且原样返回输入。使用原始 cast 让某 kernel 损失个位数百分比的 payload 字节 (≈ 8-bit 尾数输入在 e4m3 上的 1/32 中点率)。

3.3 8-bit 转换通常是回绕(wrap-around),不是饱和

不要从"未钳位结果的 min=-128 / max=127"推断会饱和 —— 任何 int8 张量都是这个范围,该推断无价值。 真证据:强制 inv = 1e5 得到 256 个大致均匀分布的不同输出值(频次峰值与均匀期望同量级) —— 这是回绕签名。

实践后果:去掉钳位只因为归一化保证了范围(scale = amax/127 ⇒ |x/scale| ≤ 127 按构造成立)才安全, 不是因为 convert 会拦截溢出。必须把这个不变式写进注释 —— 任何破坏它的后续改动会产生静默回绕垃圾,而不是饱和值。


四、组尺度耦合:为什么融合量化器天生与字节精确为敌

一个组 scale 让 32(或 64)个元素共享命运:1 ULP 的激活差异若恰好命中该组最大值, 就会翻转整组的 e8m0 指数,从而改变该组全部 payload 字节。

实测(某融合量化器;模型几何、绝对计数与对拍规模见会话产物归档 {run_results_dir}/archive/,下列只保留量级):

groups with a DIFFERENT scale byte    : 千分之几量级(全部 delta = -1)
rows with >= 1 changed group          : 三成以上
bf16 bytes differing                  : 每元素 1 ULP(占全部字节的万分之几)
payload bytes differing               : 个位数百分比

即:输入侧万分之几量级的差异 → payload 侧个位数百分比的差异(放大数百倍)。

这是任何重实现的固有属性,不是某个内核的缺陷(纯 PyTorch 参考也显示同样残差)。

诊断价值(高):错误 scale 字节全部恰好低一个指数({-1: 4374})是 "amax 取到了低一个 binade" 的签名 —— 即量化器看到的是 fp32(x) 而非 bf16(x)。 这类"全部同向、幅度恰为一个 binade"的残差比随机分布更有诊断力,优先看它的分布形状。


四·B、量化前移:把量化放到集合通信之前(组尺度对齐条件)

动机:量化后的载荷是 8-bit,而集合通信(a2a / all-gather)默认传 bf16 ⇒ 把量化搬到通信 之前,通信字节直接减半。这是"减少通信量",不是"掩盖通信",两者可叠加;本节的判据回答 「前移之后还能不能保持逐字节等价」。

关键在于每个 scale 的归约域落在哪一侧——按归约域分三类,逐类判定:

scale 类型归约域前移是否字节精确判定/代价
分片局部(如沿序列的 per-block scale,块尺寸 b)单个 rank 的分片内可以,条件是块网格对齐S % (world × b) == 0:各 rank 等长且分片起点落在全局块网格上,块成员与前移前完全一致
跨分片全局(如 per-(head,channel) 的 amax,归约域 = 整条序列)全部分片不可以,除非先补齐归约量化前对 scale 张量做一次 all_reduce(MAX)(张量极小,但这是每层每块一次的新增集合通信,必须计入收益账)
由全量数据派生的元数据(如稀疏 mask 由池化后的全序列 Q/K 生成)全部分片不可以要么把派生计算也搬到通信前(代价常吃掉收益),要么用后移数据反解(pool 块跨两个 scale 时取加权平均 (Σs₁·a₁ + Σs₂·a₂)/N),要么为它单独走小张量侧信道(pool 后仅 1/b 的字节)。⚠️ 更正:侧信道可以做到位级(不是"放弃字节精确")—— 条件是 定序归约 + 尾块感知除数(见 §四·B.1);条件不满足时才退化为 L2 数值门

不能精确时的处置(强制):报漂移清单——payload 差异计数、端到端 md5 / 相对误差、 差异归因(边界块改组 / 全局 amax / mask)。不得把「数值接近」写成「无损」; 反过来,md5 恒等也不是"没生效"(见 §五.5 的反向陷阱)。

收益账必须三头算(逐张量算,别用「减半」口头禅):

省下的字节 = Σ(被量化张量: 原字节 − 量化字节 − scale 字节)   ← 未被量化的张量一分不省
新增成本   = 新增集合通信次数 × 单次固定开销(小张量集合是延迟主导,不是带宽主导)
             + 可能多出的一次全量/池化计算
有效时间   = t0 + 字节 ÷ B(字节)     ← B 随消息变小而下降,必须实测,不得线性外推
  • 只有被量化的张量减半:同一段通信里常夹着未量化的部分(注意力输出回传、残差/门控、 只量化了一侧的 KV…),它们保持原字节 ⇒ 期望降幅要按张量逐个算。本组合量级:一次 a2a 组含 4 张量(q/k/v 前向 + o 反向),只有 3 张可量化 ⇒ 期望降到 (3×0.5+1)/4 = 62.5%, 即减少约 3/8 而非 1/2。
  • scale 自身也要传,但先算比例再决定是否计入:per-block scale 是「每 64 token × 整条 head_dim」一个 fp32 ⇒ 约占量化载荷的 4 ÷ (64 × head_dim)(head_dim=128 时约为万分之几); per-channel scale(如 V 的 per-(head,channel) amax)更小。不要凭感觉给余量, 也不要因为它"要传"就否定整个方案——量级差三个数量级。
  • 带宽不是常数(承重):有效时间 ≈ 固定开销 t0 + 字节 ÷ B,且 B 随消息变小而下降 (大消息趋近峰值,小消息被启动/同步开销主导)。消息缩小后能否仍按原速率,必须用同 communicator、同拓扑的尺寸扫描实测(方法见 dit-parallel-opt/references/parallel-plan-attribution-method.md §6),不得线性外推; 最省事的同源证据 = 同一 A/B 里两臂的消息尺寸与耗时各自算一次隐含 B,直接读出「B 掉了多少」。

判定工作流:

  1. 列出被前移张量的每个 scale 及其归约域(哪一维、是否跨 rank);
  2. 对每个 scale 套上表判据,写出对齐式(S % (world × b))并用实际 shape 验算, 不要用「应该没问题」代替;
  3. 若只需补一次小 all_reduce(MAX),先实测这次集合的固定开销(延迟主导),再决定是否前移;
  4. 若涉及 mask 等元数据,优先选侧信道传池化小张量(字节少一个数量级)而不是把派生计算前移; 该侧信道位级可达,条件是定序归约 + 尾块感知除数(§四·B.1),不满足时按 L2 数值门声明;
  5. 落地后按 §五 位级对拍:精确就报 0 字节差,不精确就报漂移与归因,二者不许混说。

与 §四 的关系:§四 说明「1 ULP 的输入差异会被组尺度放大」,本节是它在通信顺序上的推论—— 前移改变了「谁参与同一个 scale 的归约」,因此放大的是改组后的整块 payload, 看起来"只差一点点输入"也会产生成片的字节差。

四·B.1 侧信道的位级可达性(旧判决"不可达"已作废:可达,但有两项条件)

⚠️ 更正(实测推翻,先读这条):本节曾写"部分和侧信道无法位级复现,因为归约结合顺序是 全局调用形状的函数"。该判决已作废 ✗ —— 它的依据(形状依赖表、"数十种候选结构无一匹配") 是在一个并不存在的"形状依赖结合顺序"里搜索出来的。位级一致是可达的。

推翻它的实测(单卡、无模型;口径 = 逐元素差异计数 / 总数):

测内容结果
S固定一个池化块的同样数值,把调用内块数 n 从 1 变到生产形状(数百档)0 / 128 不同 ⇒ 该均值算子与 n 完全无关("形状依赖"不成立 ✗)
D1逐 rank 部分和、统一步长 ÷ 块长128 处不同、全部落在 tail cell,最大相对误差 1 − 32/128 = 0.75(该 cell 整体偏约 4 倍量级)
D2逐 rank 部分和、尾块感知除数(tail 除以真实长度)0 差异 ⇒ 位级精确 ✓
D3部分和用 fp64 合成0 差异 ✓
D4在拼齐序列上取精确 fp64 块均值0 差异 ⇒ 库的结果就是正确舍入的块均值 ✓

⇒ 更正后的三条结论:

  1. 位级可达:分布式部分和分解 + 尾块感知除数即可逐位复现(D2/D3/D4 全 0);
  2. 真正的不一致来源是"我们自己的归约不确定",不是"库的结合顺序特殊" —— 同一输入重复调用同一归约就会得到成片的元素差异(规模见会话产物归档 {run_results_dir}/archive/)⇒ 换定序分段归约 (按 cell 排序后定序求和)是个工程任务,不是研究死局 ✓。 这也解释了"约 60 种候选结构一个都匹配不上":族搜错了 —— 正确姿势(先判形状相关性、再按 相邻配对 / 对折 / 跨步 / 分块逐族穷举)见 ../../operator-dev/references/triton-ascend-lowering-pitfalls.md §三。 另:放置类算子必须用「累加」语义 —— index_copy_ 对重复索引是覆盖(后者胜), 当两个来源合法地落到同一位置时会静默丢数据 ✗(本仓形态:同一 cell 内 k 与 k + L/2 会落到同一 (row, col));但累加类归约默认不确定,所以要用定序累加(同上), 不要用"重复调用结果不同"的算子做放置;
  3. 尾块是承重的:统一步长会把 tail cell 整体做偏(D1)⇒ 除数必须取 cell 的真实长度 (counts[-1] = used_len % POOL 那种形态),不能用常量。

⇒ 判决表最后一行"放弃字节精确"相应改为:可达,条件是 ① 归约确定(定序,不得用 "重复调用结果不同"的归约)、② 除数尾块感知、③ 若还要求与全局归约一致,amax 这类 归约域的边界块要显式补一次小集合通信。任一条不满足 ⇒ 退化为 L2 数值门(层级见下)。

不要过度声称(另一半仍成立):位级可达说的是侧信道这条链路;库自身仍可能不精确 —— 实测里用精确 fp64 参照在多 seed 多族上比,仍有一族以上与库不一致,且阈值比较的平局 (probs >= threshold 形态)会把极小的数值差放大成离散的选择差异 ⇒ "可达"≠"到处都逐位": 每换形状 / seed / 阈值口径都要重新对拍(这也是 §五 SOP 要求逐形状的原因)。

三条可迁移判据(更正后):

  1. 先问"是不是我自己的归约不确定":出现"只有少数元素不同"的差异时,第一件事是同一输入 重复调用自己的归约看是否自洽(本仓实测不自洽,计数如上)。把责任先推给"库的顺序特殊", 会把一次工程修复拖成一轮研究 ✗;
  2. "与现役实现一致" ≠ "与参考实现一致":现役(eager)与融合实现偏离参考的量级相同、 且互有胜负(各自的近/远与相等样本都在同一量级;读数见会话产物归档 {run_results_dir}/archive/)⇒ 验收目标只能是 参考实现(例:拼齐序列上的 fp64 精确均值),"和现役逐位相同"会把错误一起固化 ✗;
  3. 顺序敏感性要用对抗分布才看得见:真实量级激活下 fp32 求和确实随顺序变 (三种顺序给出 23 / 11 / 26 组不同;动态范围拉到 2²³ 量级升到数千组), 但最终 bf16 结果与库 0 / 8192 全同 —— 是末级 bf16 舍入把这点关联误差吸收掉了 ✓。 更正:此前写的"8+7+7 位 < 24 位 ⇒ 求和本身精确"是错的 ✗(fp32 求和并非精确); 结论仍成立,但理由是末级舍入吸收。⇒ 判断"顺序会不会影响产物"必须在最终 dtype 上比。

层级不得混用:位级可达是有条件的 —— 条件不满足时该侧信道只是 L2 数值门 ("数量级更小"≠"无损"),违反 ../accuracy-gate/SKILL.md 的铁律。


五、位级对拍 SOP

  1. 参考必须同进程、同数据运行生产链路 —— 跨进程/跨窗口比较会引入漂移。
  2. 分开计数:payload 用 view(torch.uint8)、scale 用 view(torch.int32), 报绝对计数(0 / 67 665 920)以及 max|Δscale|(期望 0.000e+00)。
  3. 独立参考实现(不复用被测代码路径),在完整张量上要求逐字节 100% 相符。
  4. 对抗性输入清单(缺一项就可能漏掉一整个 bug 类):
    • randn / uniform[-1,1] / all-equal
    • 全部 tie 中点(165 个 e4m3 中点 × 两个指数域)
    • amax 恰为 2^k / 略高于 2^k
    • 全零 / 全负 / big+small mix
    • bf16 次正规 / 1e-38 / inf / nan(退化块)
    • 饱和边界(>448 或 >127)
    • 尾块(S % 64 != 0)
  5. 端到端无损门:md5 恒等比任何 PSNR 阈值都强 —— 但前提是"管线本身逐位确定"已被单独验证。

    ⚠️ 反向陷阱:逐字节相同的 md5 不是"门控没生效",而正是字节精确优化所预测的结果。 实践中曾把它误读为失败信号。

  6. 诚实例外要写出来:唯一不精确的输入类别(如"整张 bf16 次正规",占比为千分之几量级、全是符号零; 读数见会话产物归档 {run_results_dir}/archive/) 应显式记录为"已刻画、不追",不要藏。
  7. 先证明仪器,再做对拍:参考实现自身也要过一遍「跨流依赖是否写全 / 顺序是否正确 / 快照是否与 被测动作同时刻」的检查(口径见 ../perf-gate/references/measurement-discipline.md §8)。 本仓实测:参考侧漏了一处跨流依赖,把正确的载荷报成上千条"污染记录" ✗ —— 这类假阳性的症状与真实缺陷形态高度相似,靠看形态分不出来。

六、工具链陷阱

陷阱现象处置
Tensor.to(torch.float8_e4m3fn)NPU 上抛异常(普通 dtype cast 到 fp8 未实现)用算子 API
torch_npu.npu_dtype_cast 到 fp8越界行为不同:449/512/1000 → byte 127 (NaN)它不等于量化器的饱和转换,不能当参考
torch.arange(dtype=torch.uint8, device='npu')aclnnArange ... code 107001用 torch.empty/zeros 分配
torch.frexpNPU 上静默回落 CPU参考实现中禁用
.view(torch.uint8) 传给 triton 做 fp8 输出triton 看到 uint8 指针 → 截断而非量化(match 不足 1%)用原生 fp8 dtype
w 与 w_scale 置换只换 w 不换 w_scale → 结果静默塌到接近 0必须同序置换
积分归约(amax/amin 两次读)两次读的基线耗时torch.linalg.vector_norm(v, inf, 2) 单次读快近一倍(绝对 µs 见归档),且 0/1792 精确
手写 Triton 融合归约最优值也输给两次 torch 读"手写融合归约是错误答案;正确是一个本身只读一次的现成库算子"

scale 公式实测:scale == amax/448.0 精确相等(max|scale - amax/448| = 0.0), 不是 2 的幂(max|scale - 2^ceil(log2(amax/448))| = 7.78e-3)。全零输入 → scale = 0.0。


七、已证伪清单(不要重复)

假设证伪它的实测
MXFP8 指数字节 = ceil(log2(amax/448))仅约八成相符;在 amax=450/1000/230 失败
npu_dtype_cast(x, fp8) 与量化器行为一致449/512/1000 → NaN,不是饱和转换
dtype cast 到 int8 会饱和是回绕:inv=1e5 得 256 个均匀值
除数可以在内核内重算常除数 → 倒数乘法(~2 ulp)→ 千分之一以下的 payload 差
用 x.to(bf16).to(fp32) 做 bf16 舍入在 triton-ascend 上被静默消除,完全不相符(0%)
用 split-tree 替代归约可绕过编译问题约 4 倍更慢(绝对值见归档)
量化器核心成本在 fp8 store / castA4(payload 存 bf16)与 A7(去 store)的读数都落在噪声内 ⇒ 免费;成本在归约及 scale-byte epilogue(占该核主要部分)
非 I/O 成本随归约调用数/ tile 形状缩放随"产生的 (row, group) 最大值个数"缩放(wide 对照耗时约为窄形态的一半)
把转置 view 交给库算子会被"吸收"五个捷径全部字节精确但只省几十 µs 量级 ⇒ view 是被计价的(costed, not absorbed)
手写融合归约比两次库读更快手写融合归约慢于两次库读;对单次读的 vector_norm 更差
y * 0.0 可保留 flush 的符号反方向错误:差异扩大若干数量级(读数见归档);字面 0.0 才正确
int8 粒度猜错时可以从舍入模式看差异粒度错时三种舍入一律 ~58%,无法区分
"它编译了" / "scale 是对的" 可作为正确性证据double-tl.reshape 形式编译通过但 payload 接近但不等于 100%
用逐 rank 部分和侧信道复现"组装后单张量归约"的位级结果已作废 ✗✗:曾记"归约顺序是全局调用形状的函数 ⇒ 侧信道不可达",实测推翻 —— 该均值算子与调用内块数 n 无关(n=1…生产形状逐位相同),且尾块感知除数下部分和信道逐位精确(0 差异)。真正的差异来源是我们自己的归约不确定(重复调用同一归约会得到成片差异,规模见归档);旧结论作废见 §四·B.1
在 randn 量级输入上判"归约顺序是否影响位级结果"真实量级下 fp32 求和确实随顺序变,但最终 bf16 结果与库 0 / 8192 全同 ⇒ 末级舍入吸收了这点关联误差(更正:旧记载"8+7+7 位 < 24 位 ⇒ 求和本身精确"是错的 ✗)⇒ 判断顺序敏感性必须在最终 dtype 上比
用"与现役实现逐位相同"当侧信道验收目标现役实现自身偏离参考(实测二者偏离量级相同)⇒ 该目标会把错误一起固化;验收目标只能是参考实现
把"数量级更小"的池化侧信道写成"无损"它是 L2 数值门,不是 L1 逐字节(层级不得混用,见 ../accuracy-gate/SKILL.md)

八、参考文件

  • 📐 references/contract-reverse-engineering.md —— 契约逆向六步法(判别性探针、标记法定布局、独立参考、退化覆盖、corrigendum)+ 完整探针数据与出处。要逆向一个新量化器时读它。
  • 🔎 references/online-quant-contract.md —— 在线量化契约(算法分派、被量化的范围:哪些层/是否含 FA、图节点形态与布局互通)——自 dummy-run 下沉;判断"某框架的 online scheme 实际量化了什么、和参考实现对不上在哪"时读它。
  • 🔗 references/lora-merge-and-precision.md —— 低秩适配器(LoRA)离线合并进权重的精度判据与形态选择(合并代数与"去冗余"定位、精度存活判据与三臂对拍、三形态选择决策、判据修正纪律、loader 与摆位契约)——何时读:任何"把运行时计算折进权重"的候选(适配器合并、把缩放/偏置折进相邻线性层、把量化残差折回权重)在定形态或下"合并后不等价 ⇒ 不可用"结论之前读它。

路由判据(何时读上面第三条):① 出现"把运行时的算子链换成权重里的一份预计算结果"的候选时——先按它的 §1 判"在 ckpt 里量化还是在 load 期量化",再进 §2/§3; ② 需要判"合并后增量还在不在"时——按它的 §2 三臂对拍取数,不要用自写模拟器; ③ 要因"数值上不等价"否掉一条合并路线时——按它的 §4:纯数值研究只能推翻等价性,可用性必须由服务端产物级 A/B 收口。

九、与既有 skill 的分工

  • operator-dev —— 算子开发/优化与 DSL 选型(CV→catlass / VV→triton);本 skill 是它的量化契约补充层。
    • 其 fusion-scope-analyze/references/fusion-unit-method.md 与 fusion-benefit-method.md 讲融合范围与收益(含 §3.1 的"移除流量 vs 移除延迟"判据);本 skill 讲数值契约。
  • dit-perf-opt —— 回答**"该不该开量化、开哪一档"(特性选型与质量门禁);本 skill 回答"这个量化器到底怎么算的"**。
    • accuracy-gate/references/quality-gate.md 是有损档位的阈值门禁;本 skill 的位级对拍是无损证明,两者不可互相替代。
  • dit-parallel-opt —— 并行作用域失效(静默降级)的判定(DiT 侧)与并行陷阱清单;其 dit-parallel-opt/references/ascend-parallel-traps.md §8 只保留了量化契约的指针,契约本体在本 skill; 测量与上报口径见 perf-gate。
  • dit-parallel-opt —— 并行选型、通信掩盖与归因;本 skill §四·B 只回答「量化前移能否字节精确」的数值契约,形态选择与收益判定在那侧。
  • pattern-dev —— 量化融合 pattern 的图命中与收益核验;本 skill 提供"数值上到底对不对"的判据。

十、维护与更新

  • §二 int8 一节的证据等级必须随新证据更新:目前"RNE / 误差差近一半"仅有单一来源的一句话记录、未经独立复现; 若能复现,改为强证据并补上分母与形状。
  • 当 CANN 量化算子行为变化(派发 kernel 名、tiling 边界、退化块规则)时,重跑 §五 SOP 并更新 §一/§二。
  • §七 已证伪清单应持续追加 —— 它比正面结论更省机时。
  • §四·B.1 的"位级可达"结论必须随版本复测:可达性依赖 ① 该均值算子与调用形状无关 (换 CANN / 算子实现后可能变成形状相关 ⇒ 那时尾块感知除数不再够用), ② 该归约在库里的语义仍是"正确舍入的块均值"。 复核方法:构造一个固定池化块,分别在 n = 1 / 中间档 / 生产形状 三次调用里求均值, 比较该块取值是否仍与 n 无关(当前实测 0 / 128 不同);再用"统一步长 vs 尾块感知步长" 各合成一次部分和,看前者是否只在 tail cell 出错、后者是否 0 差异。 另:用大指数跨度分布跑一次顺序敏感性对拍(最终 dtype 上比),否则会得到"任何顺序都相等"的假阴性。
  • "自己的归约是否确定"要作为常规前置检查:凡在侧信道/中间量里做归约,先重复调用两次比自身 (当前该归约不自洽,计数见 §四·B.1 结论 2);换成定序归约后本检查应为 0 差异。

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

**精度验收标准**:凡是"改动不应改变结果"的场合(等价替换、算子/子模块融合、并行切分、 编译与图下发、拷贝消减),都按本标准判"合格 / 不合格"——等价分层(L1 逐位 / L2 数值门 / L3 有损门)+ 三级验收序(① 同配置重跑逐位 → ② 跨配置数值门 + 产物 md5 不变 → ③ 质量门)+ 判据不达标时的排障入口。当用户说"这个算子能不能换个写法/换个 kernel/等价实现/ 无损替换""替换后结果会不会变""怎么证明逐位一致""结果不对""花屏""尾部塌了" "CPU 跑对 NPU 跑不对",或发现某个 hotspot 占了大头(例如某类算子在阶段里占 90% 以上)想动手时, 都应触发;即使用户只说"这样改有没有把结果改坏""能不能判它是无损的"也应触发。 覆盖:等价分层与判据、满足本标准的实现约定(per-shape 对拍写进实现,把索引/相位/顺序类重写 错误在首次调用抓住)、per-shape 条件性等价(同一改动在不同形状下结论可能不同)、 判据不达标 → `references/silent-failure-localization.md` 排障入口、否决案例的形态学 (换写法未换 kernel / 差异极小仍非逐位 / 等价但 OOM)、以及收益口径的归属(性能数字一律交 `perf-gate`)。 **近义分流**:选量化档 / 特性选档(要不要开量化、开哪一档)→ `dit-perf-opt`; 并行选型(USP / CP / TP 怎么切)→ `dit-parallel-opt`;本技能只判"结果是否被改变", 不负责选档与选型。

The English summary is being prepared. Showing the original description.

Ascend/MindIE-SD15Updated Oct 17, 2026

NPU 图批量下发能力(aclgraph / aclgraph_ex 家族)的开发与调优。覆盖 mindiesd 的 aclgraph_backend:NPUGraph 静态 capture、全局 graph pool、 lazy capture、专用 copy stream + event 管线、shape/dtype 校验、max_entries 驱逐。 当用户需要减少 host launch 开销、静态 shape 大 batch 场景加速、 或排查 NPUGraph replay 输入不匹配问题时使用此 skill。 即使用户只提"批量下发""graph capture""图捕获"而未说 aclgraph,也应触发; pattern/Inductor 融合(default 后端)见 pattern-dev,算子本体见 operator-dev, 本技能只覆盖图批量下发。由 dev-workflow 的编译开发阶段与 model-auto-optimization 的 图下发场景指引加载。

The English summary is being prepared. Showing the original description.

Ascend/MindIE-SD15Updated Oct 17, 2026

MindIE-SD 核心算子(FA/BSA/GMM/MM)性能基准工具链。使用:模型优化(model-auto-optimization 的 S1/S4 选型)中用 mindie_bench 对单算子做实现级实测,按 dtype/量化档/稀疏度/形态对比 选出最优配置(产物:选型证据;稀疏度-性能曲线供 S4 稀疏度选型);开发:benchmarks/ 工具链扩展与新算子接入测试(供 operator-dev / pattern-dev 调用)。 当用户需要对比算子实现选型、新增或修改 benchmark 代码、排查 benchmark 数据异常、 给基准加算子/指标时使用;即使用户只说"benchmark 数据不对""给基准加个算子" "对比下这几个 FA 实现哪个快"也应触发;特性级方案选档请走 dit-perf-opt (本 skill 只做实现级实测)。 由 model-auto-optimization 的 S1/S4 选型场景与 operator-dev 的算子接入验证场景调用, 亦由 dev-workflow 在基准开发时指引加载。

The English summary is being prepared. Showing the original description.

Ascend/MindIE-SD15Updated Oct 17, 2026

MindIE-SD Python 代码格式与 lint 规则。当编写、格式化、lint 检查或审查 MindIE-SD 项目的 Python 代码时使用此 skill。 即使用户只提到"提个MR"或"代码好像有 lint 问题"而未明确说格式化,也应触发;Markdown 格式问题见 markdown-lint,提交/PR 规范见 mindie-sd-community-governance。 通常由 dev-workflow 在编码阶段指引加载。

The English summary is being prepared. Showing the original description.

Ascend/MindIE-SD15Updated Oct 17, 2026

MindIE-SD 仓库开发总入口(侧轨)。当用户进行 MindIE-SD 的任何代码开发工作时使用此 skill—— 包括但不限于写 pattern、改测试、部署到昇腾、跑 benchmark、性能分析、多卡并行、复盘归档。 模型/三方框架自动优化类任务(非本仓代码改动)由 model-auto-optimization 入口承接, 本入口只在优化流程需要新增 pattern/算子/部署代码时承接其指向的开发子任务。 即使用户未明确提到"开发流程",只要涉及 MindIE-SD 代码改动都应触发。

The English summary is being prepared. Showing the original description.

Ascend/MindIE-SD15Updated Oct 17, 2026

分布式并行策略选型与实测(USP / CP 通信掩盖 / CFG / TP/RSP/PP 概览;含拓扑相关选型 (按实测拓扑分域条件化:域内 bulk vs 跨域 head-parallel 翻转)与 AlltoAllV 缺陷绕过)。在 model-auto-optimization 中承担 S3:优先 USP、结合拓扑带宽差异选 CP,少量 step + 多 rank 验证特性开启与掩盖(产物:并行方案 + 多 rank 证据)。当用户需要多卡并行 策略选择、**序列并行形态抉择**(纯 Ulysses vs 复合 AllGather-KV×Ulysses:按 GQA / 跨域带宽 / 形态 plumbing 条件化定胜负)、**并行 × 稀疏叠加**(seam 契约:先汇聚后稀疏、 窗口偏移、块对齐、per-head 掩码;含「稀疏看似生效实则未生效」判定)、通信掩盖调优 (含**掩盖率上限**:1-1/n 何时成立、c/f 决定的真实上限、没生效的排查)、**并行方案 差异归因**(阶段 Δ 分解 / 集合通信按 communicator 归属 / 4→8 卡线性度),或排查多卡 跑不动 / 通信暴露大 / 换卡组 / 端口 bind / HCCL 带宽验证问题时使用;**并收编原并行作用域诊断**: 改了 SP/CP/Ulysses/AllGather-KV 后**不报错但结果没变/性能没变**、或小规模能跑大规模崩 (如 Ascend EE1003 coreDim 超限)时,用本技能证明"改动到底有没有生效"(判别量逐层收窄 + 两侧对照 + 日志≠生效,见 `references/scope-effectiveness-check.md`); 即使用户只说 "多卡跑不动""通信暴露大""为什么没达到 6/7 的掩盖率""CP 和 USP 该选哪个""CP 叠稀疏 怎么不生效"而未说并行,也应触发。特性档位/接口事实见 `docs/zh/features/parallelism.md` /`usp.md`(仓内真源),框架侧开启见 framework-integration; 本技能承载选型决策、monkey-patch 掩盖与多卡诊断实测。 由 dev-workflow 多卡场景触发,亦由 model-auto-optimization 的 S3 阶段触发。

The English summary is being prepared. Showing the original description.

Ascend/MindIE-SD15Updated Oct 17, 2026

See all skills by Ascend

Report a problem with this skill