# Calculet NPU 逐算子优化实验手册 日期:2026-08-02 对象:当前 Qwen3-30B-A3B 双芯粒 prefill/decode 整图及后续新模型 ## 1. 先说明能力边界 当前生产是预编译整图,不是 GGML 逐算子 NPU backend。我们可以离线分析 op、设计实验、修改 host adapter,并对厂商编译的不同 calbin 做 A/B;没有 calcc/pass/kernel/oplib 时,不能自行替换 NPU kernel。因此: - C0:当前图和算子分布、现有整图运行。 - C2:harness、数据集、统计、host-side 搬运/后处理改造。 - C3:fusion、layout、quant、kernel、partition、新 calbin。 ## 2. 当前图的优化对象 | op family | 每图数量 | 主要阶段 | 首要成本假设 | 优先级 | | --- | ---: | --- | --- | --- | | fused matmul/add | 193 | prefill+decode | 权重/activation 带宽、量化解码、GEMM 利用率 | P0 | | fused RMSNorm | 193 | 两者 | 小归约和 kernel launch/sync | P1 | | sync CPU/CCU D2D | 146 | 两者 | 芯粒同步和 barrier | P0 | | gather | 145 | 两者 | TP 重组/通信 | P0 | | grouped MoE dense | 144 | 两者 | expert 稀疏 GEMM、token 分桶、负载不均 | P0 | | RoPE | 96 | 两者 | layout/表访问 | P2 | | KV scatter | 96 | 两者 | KV 写带宽和不连续访问 | P0 decode | | residual/add | 96 | 两者 | memory-bound、融合机会 | P1 | | Flash Attention | 48 | 两者 | attention 主体、长 context | P0 prefill/长 decode | | MoE gate pre/post | 48+48 | 两者 | top-k、dispatch/gather | P0 MoE | | dynamic D2D | 96 | prefill only | 双芯粒 activation 交换 | P0 prefill | 数量是结构化 YAML 顶层实例统计,不等于调用次数或耗时占比。优化排序必须在 trace/per-op cycle 到位后更新。 ## 3. 实验资产和命名 每个候选生成一组不可变资产: ```text experiment// hypothesis.yaml baseline/manifest.json candidate/manifest.json compile/baseline.log compile/candidate.log golden/input-manifest.jsonl accuracy/result.json performance/raw-requests.jsonl performance/raw-device-trace.* performance/summary.json stability/faults.jsonl decision.md ``` `EXP_ID` 规则:`OP--`,例如 `OP-MOE-0001`。一次实验只改变一个主要因素;若 compiler 被迫同时改变 layout 与 quant,必须拆成 factorial 设计或明确不可归因。 ## 4. `hypothesis.yaml` 模板 ```yaml schema: calculet-op-experiment/v1 experiment_id: OP-FA-0001 operator_family: flash_attention status: planned capability: C3 hypothesis: larger sequence tile reduces DDR traffic without harming latency tails baseline: calbin_sha256: REQUIRED compiler_oci_digest: REQUIRED compiler_flags: {} candidate: calbin_sha256: REQUIRED compiler_oci_digest: REQUIRED changed_flags: attention_seq_tile: 256 controlled: model_hash: REQUIRED tokenizer_hash: REQUIRED quant_config_hash: REQUIRED runtime: 0.7.6 driver: REQUIRED firmware: REQUIRED power_mode: REQUIRED matrix: prompt_tokens: [1, 16, 128, 512, 2048, 8192, 32768, 40959] output_tokens: [1, 32, 256] concurrency: [1] metrics: - numerical - ttft_ms - tpot_ms - per_op_cycles - ddr_bytes - d2d_bytes - power_w acceptance: top1_match_min: 0.999 p99_regression_max_pct: 5 target_metric_improvement_min_pct: 8 rollback: deploy previous calbin generation ``` 数字阈值是第一版工程门槛,可按产品 SLA 收紧;不能用平均吞吐覆盖 P99 或正确性失败。 ## 5. 统一输入矩阵 ### 5.1 shape 边界 Prefill token 数:`1,2,15,16,17,31,32,33,127,128,129,511,512,513,1024,2048,4096,8192,16384,32768,40959`。 Decode past length:`0,1,15,16,17,127,128,1023,1024,4095,4096,8191,16383,32767,40959`。总长超过 40960 的 case 是拒绝用例,不提交设备。 选择 15/16/17 是为了暴露当前 D0=16 相关 layout 边界;127/128/129 暴露 head/tile 边界。 ### 5.2 内容分布 | 数据集 | 目的 | 最低样本 | | --- | --- | ---: | | 固定自然语言 prompt | 端到端可重复 | 100 | | 随机合法 token | shape/数值覆盖 | 每长度 20 | | 重复 token/低熵 prompt | attention/KV 极端 | 每长度 10 | | 多语种、代码、数字 | tokenizer/量化敏感 | 各 50 | | MoE expert 覆盖集 | router/expert 分布 | 每个 expert 至少被命中,需 trace 证明 | | near-tie logits | top-k/quant 敏感 | 1000 token step | ## 6. 数值比较规范 对每个可 dump 的 tensor 记录:shape、dtype、element count、SHA-256、min/max/mean/std、NaN/Inf、零比例。BF16/量化图不能仅使用 byte hash。 ```text max_abs = max(|candidate-reference|) max_rel = max(|candidate-reference| / max(|reference|, eps)) cosine = dot(c,r) / (||c||*||r||) top1_match, top5_overlap token_sequence_exact_match under greedy decoding task-level metric (perplexity/accuracy as applicable) ``` 建议分层门槛: | 层级 | 首轮门槛 | | --- | --- | | kernel golden | shape 完全一致;NaN/Inf 不新增;容差由 dtype/op 明确 | | layer output | cosine >= 0.999(初筛,不是通用最终标准) | | final logits | top1 >= 99.9%,top5 overlap >= 99.9%,报告 max_abs/max_rel | | greedy tokens | 固定 100 prompt 完全一致;若业务接受差异需专项审批 | | 量化模型任务集 | 相对基线退化不超过已约定模型门槛 | 对于 near-tie logits,top1 翻转可能是合法浮点敏感,也可能放大成长序列差异,因此同时看 logit margin 和 token divergence point。 ## 7. 性能统计规范 每个 case:10 次 warmup,至少 30 次 measured run;短 case 建议 100 次。报告 median、P90、P99、MAD/标准差、95% bootstrap CI。温度/频率未稳定的样本不得与稳态混合。 至少分解: ```text client queue -> service queue -> input prepare -> H2D -> NPU wait -> D2H -> logits conversion -> sampling -> stream flush ``` 设备侧要求 per-chip、per-op cycles,DDR/SRAM/D2D/PCIe bytes,stall 分类,频率/功耗/温度。若厂商只能给整图时间,实验结论只能写“整图候选更快”,不能归因到某个 kernel。 ## 8. 实验卡:fused matmul/add ### 8.1 当前形态 当前 YAML 示例包含 BF16 activation、U8 权重以及 BF16 scale/辅助张量,对应 W8A8/W4AF16 混合策略的编译结果。具体每层哪个矩阵使用 W8/W4 必须由 quant manifest 补齐。 ### 8.2 候选变量 | 变量 | 候选 | 固定项 | 目标 | | --- | --- | --- | --- | | weight quant | W8 vs W4 分层 | activation、layout | 降权重带宽/容量 | | activation quant | A8 vs BF16 | weight、tile | 降计算/带宽,关注 outlier | | M/N/K tile | compiler 候选 2-4 档 | quant、频率 | 提升 core 利用率 | | bias/residual fusion | on/off | math 等价 | 减少中间写回 | | weight packing | 两种 layout | 数值相同 | 减少 unpack/stall | ### 8.3 必测 shape 分开统计 Q/K/V/O projection、gate/up/down、expert GEMM、lm_head;prefill M 随 token 数变化,decode M 近似 1。不能用大 M prefill 结果推断 decode。 ### 8.4 通过条件 - candidate 的目标 GEMM cycles/有效 FLOP/s 至少改善 8%。 - 相关整图阶段至少改善 3%,否则认为局部收益被同步/搬运吞没。 - 无新 overflow/NaN,logits/token 门槛通过。 - 权重包大小、load time、DRAM reservation 都入报告。 ## 9. 实验卡:Flash Attention 变量:sequence tile、head packing、Q/K/V dtype、causal mask、online softmax 精度、double buffering、prefill/decode 专用 kernel。矩阵必须覆盖 1 到 40959 的 context,特别是 tile 前后边界。 需要采集:attention cycles、DDR read/write、KV read bytes、softmax reduction stalls、D2D、峰值 workspace。验证 causal mask,确保未来 token 不影响过去输出;用单点扰动输入做 metamorphic test。 候选失败回退:关闭对应 compiler flag,恢复已知好 FA calbin。CPU fallback 只能用于诊断,不能静默进入生产。 ## 10. 实验卡:KV scatter 与 KV layout 变量:BF16 vs S8 V-cache、写合并粒度、batch lane layout、K/V 分开策略、连续/分块地址、RoPE 前后写入。当前 BF16 KV 3.750 GiB 是容量基线。 测试: - token position 0、15、16、17、最后位置。 - 两 sequence 交替写,验证绝不串 lane。 - remove tail 后重写相同位置。 - reset/timeout 后旧 KV 不被新 generation 使用。 - context 逐步增大时每 token KV write/read 与 TPOT 曲线。 S8 candidate 报告真实节省量、K/V 哪部分压缩、scale 粒度、dequant 位置、任务精度、长上下文 token divergence。没有新 calbin 和 golden 不能把 header 枚举当成能力。 ## 11. 实验卡:MoE gate pre/post 核心指标不是 gate kernel 平均时延,而是: ```text expert hit histogram per layer tokens per selected expert top-8 probability mass and margin empty/small bucket count max/mean expert load ratio dispatch bytes, cross-chip bytes, padding slots ``` 候选:top-k selection 融合、router logits 精度 BF16/FP32、排序/稳定 tie-break、dispatch compact、post-gather + weighted sum fusion。 正确性:top-8 expert id/order、权重误差、重复 expert 禁止、概率归一、tie case、NaN router input。改变 routing 的 candidate 必须做任务级评估,不能只比较最终一个 token。 ## 12. 实验卡:grouped MoE dense 变量:expert token bucket 阈值、small-M kernel、合并多个 expert 的 grouped launch、W4/W8 分层、expert 权重预取、chip partition。 实验分桶:0、1、2-4、5-8、9-16、17-32、>32 token/expert。分别报告每个 bucket 的 cycles/token;整体平均会掩盖大量 small-M expert 的低利用率。 TP/EP A/B 只有 compiler 生成不同 partition calbin 才成立。当前两芯粒都含全部 128 experts 的分片,不是 EP。EP candidate 额外报告跨芯粒 all-to-all bytes、hot expert imbalance 和故障域。 ## 13. 实验卡:sync/gather/dynamic D2D ### 13.1 问题拆分 - sync 146 次/图:区分真实数据依赖、保守 barrier、host/CCU handoff。 - gather 145 次/图:区分 TP partial result gather、reduce 和 layout convert。 - prefill dynamic D2D 96 次:区分实际有效长度数据和 40960 静态上限描述。 ### 13.2 候选 1. 合并相邻 D2D,减少小 command。 2. 将 barrier 下沉到真正 consumer 前。 3. D2D 与本芯粒独立计算 overlap。 4. 按有效 token 动态缩小传输。 5. 改 TP split 维度,减少每层 gather。 每个候选必须提供 dependency DAG 或 compiler proof。移除 barrier 后只跑一次正确不够;需要 24h 并发、随机延迟注入和跨芯粒结果 hash。 指标:command count、size histogram、D2D bytes/time、barrier wait cycles、overlap ratio、per-chip idle。静态 `dataSize` 总和只作为候选之间的结构比较,不当实测流量。 ## 14. 实验卡:RMSNorm、RoPE、residual 这些算子单个小但次数高,优先测试 producer/consumer fusion: | 候选 | 风险 | 数值重点 | | --- | --- | --- | | residual+RMSNorm | 改变 rounding/reduction 顺序 | epsilon、variance、长序列漂移 | | RMSNorm+QKV matmul | fusion 复杂、复用 norm output | layer-level cosine | | RoPE+KV scatter | position/layout 耦合 | 位置边界、shift、theta | | activation+residual | inplace alias | race/覆盖、buffer live interval | 要求 compiler 同时输出未融合/fused graph、op count diff、内存 live interval 和逐层 golden。收益门槛可低至整图 2%,但不能增加不可恢复的 alias 风险。 ## 15. 实验卡:logits、top-k 和 sampling 当前每 token D2H `303,872 B` BF16 logits,再在 CPU 转 151,936 个 FP32。分三步: 1. C2:只转换最终需要的 vocab 范围,直接写目标 FP32,无临时 vector。 2. C2:CPU SIMD BF16 conversion/top-k A/B,保持 llama sampling 语义。 3. C3:NPU 输出 top-k values+indices 或完整 NPU sampling。 NPU top-k 需要 k 覆盖所有 sampling 策略:temperature、top-k、top-p、min-p、penalties、logprobs。固定小 k 可能破坏 top-p/penalties;不能仅凭 greedy 一致就开放。随机采样还需要 RNG seed/state、可复现性和流式 logprob 契约。 ## 16. 量化实验设计 ### 16.1 校准集 manifest ```json {"sample_id":"...","sha256":"...","domain":"code","tokens":2048, "tokenizer_sha256":"...","license":"...","pii_review":"passed"} ``` 至少分 domain 报告 activation range/outlier,不只给混合平均。校准过程记录 percentile/algorithm、per-tensor/per-channel/group size、excluded layers、seed、工具版本。 ### 16.2 分层敏感度 先对 embedding、attention QKV/O、router、experts、lm_head 单组回退 BF16/W8,计算质量恢复量与容量/性能代价。由 Pareto frontier 选 mixed precision,而不是全图一次从 W8 改 W4。 ## 17. 自动决策规则 ```text if correctness fails -> reject else if any P99 SLA fails -> reject or keep experiment-only else if target op improves but phase/graph does not -> investigate bottleneck migration else if graph improves >= threshold and power/thermal stable -> 24h soak else -> no-merge ``` 报告必须同时给 absolute 和 relative 数值。例如从 2 ms 到 1 ms 是 -50%,但若整图只从 100 ms 到 99 ms,业务收益是 1%。 ## 18. 厂商每个候选的最小交付 1. baseline/candidate calbin 和 SHA-256。 2. 完整 compile command、flags diff、compiler OCI digest、commits。 3. graph/op count、partition、memory plan diff。 4. 逐 op/layer golden、输入 manifest、容差说明。 5. per-op/per-chip trace 和解析器。 6. 支持的 shape/dtype/quant 边界与 fallback。 7. 错误路径和 reset 后复测。 8. 性能原始数据,不只汇总 PPT。 ## 19. 首批建议实验顺序 | 顺序 | EXP | 原因 | 所需依赖 | | ---: | --- | --- | --- | | 1 | HOST-LOGITS-0001 | C2 可独立完成,风险低 | 本地源码 | | 2 | OP-D2D-0001 | 当前双芯粒重复通信显著 | 厂商 trace+compiler | | 3 | OP-MOE-0001 | 144 grouped GEMM,MoE 核心 | expert trace+kernel | | 4 | OP-KV-0001 | 长 context TPOT 主线 | KV trace+新 calbin | | 5 | OP-FA-0001 | prefill/长 context 主线 | FA flags+trace | | 6 | OP-GEMM-0001 | 权重/计算大头 | quant manifest+kernel | | 7 | OP-FUSION-0001 | 高频小 op/写回 | pass 控制 | | 8 | OP-TOPK-0001 | 降 D2H/CPU | NPU top-k contract | 每完成一个实验就更新 operator evidence matrix:原假设、观测、结论、适用 shape、回滚版本和剩余不确定性。