Files
calculet-npu-research-archive/reports/Calculet-NPU-性能压测故障注入与验收规范-20260802.md

13 KiB
Raw Permalink Blame History

Calculet NPU 性能压测、故障注入与验收规范

日期:2026-08-02
适用:当前 batch=1 基线、异步执行器、后续 batch calbin/新模型

1. 为什么必须重建基线

历史 CSV 有 163 行,可保留作趋势参考,但不能作为正式结论:脚本把 model 固定写为 deepseekTTFT 又被算成 predicted_ms + prompt_ms,不是客户端收到首 token 的真实时间。

新基线必须从客户端单调时钟采集首字节/首 token,同时由服务和 Runtime 用 request/job id 对齐队列、H2D、infer、D2H、后处理。任何无法对齐的时间单独标 unattributed,不得塞进 TTFT。

2. 时钟和事件定义

2.1 客户端事件

t0 request_start        客户端准备发请求前
t1 request_headers_sent HTTP headers/body 已写完
t2 response_headers     收到响应 headers
t3 first_event          收到第一个有效 SSE/JSON event
t4 first_token          收到第一个非空生成 token
t5 last_token           收到最后生成 token
t6 response_end         流/连接正常结束

所有本进程间隔用 CLOCK_MONOTONIC/steady clock。UTC wall clock 只用于跨进程关联,需记录 NTP offset,不用于精确 duration。

2.2 指标公式

TTFH = t2 - t0                         # time to response headers
TTFE = t3 - t0                         # time to first stream event
TTFT = t4 - t0                         # 真实 time to first generated token
E2E  = t6 - t0
decode_duration = t5 - t4              # output_tokens > 1
TPOT = decode_duration/(output_tokens-1)
output_tokens_per_s = (output_tokens-1)/decode_duration

若接口在第一个 event 同时返回多个 token,要记录 chunk token count,不能用 event 数当 token 数。output_tokens<=1 时 TPOT 为 null。

2.3 服务事件

accepted -> slot_assigned -> admitted -> job_prepared -> submit_start
-> submit_ok -> wait_done -> logits_ready -> sampled -> token_flushed

Prefill/decode 分开,每 token step 有 step_index。Runtime 时长:input_transfer_mswait_msoutput_transfer_ms;服务还要测 input prepare、BF16 conversion、sampling。

3. 原始请求 schema

每个请求一行 JSONL,不直接把复杂数组塞 CSV:

{
  "schema":"calculet-perf-request/v1",
  "run_id":"...",
  "request_id":"...",
  "model_alias":"qwen3",
  "model_generation":42,
  "calbin_sha256":"...",
  "software":{"server_commit":"...","image_digest":"...","calrt":"0.7.6","driver":"...","firmware":"..."},
  "hardware":{"board_serial_hash":"...","chips":2,"power_mode":"..."},
  "workload":{"prompt_tokens":128,"requested_output_tokens":256,"actual_output_tokens":256,"concurrency":4,"stream":true,"seed":1234},
  "client_ns":{"request_start":0,"headers_sent":0,"response_headers":0,"first_event":0,"first_token":0,"last_token":0,"response_end":0},
  "durations_ms":{"ttfh":0,"ttfe":0,"ttft":0,"tpot":0,"e2e":0},
  "server_ms":{"queue":0,"prefill":0,"decode_total":0,"postprocess":0,"sampling":0},
  "runtime_ms":{"h2d_prefill":0,"infer_prefill":0,"d2h_prefill":0,"h2d_decode":0,"infer_decode":0,"d2h_decode":0},
  "result":{"http_status":200,"finish_reason":"stop","token_hash":"...","error_code":null},
  "quality":{"clock_complete":true,"server_trace_joined":true,"warmup":false,"throttled":false}
}

原始 prompt 内容默认不落性能日志;记录 corpus sample id 和 token hash,避免隐私泄露。

4. step 和设备 schema

高粒度数据单独写 steps.jsonl

{"request_id":"...","job_id":123,"seq_id":7,"kind":"decode","step":12,
 "queue_ms":0.2,"prepare_ms":0.1,"h2d_ms":0.1,"device_wait_ms":15.4,
 "d2h_ms":0.3,"bf16_ms":0.2,"sampling_ms":0.1,"engine":"auto",
 "kv_before":139,"kv_after":140,"output_status":"done"}

设备采样 device.jsonlwall timestamp、monotonic offset、per-chip temperature/power/frequency/memory、pending/finished/left jobs、reset counter。每项带单位;取不到的字段为 null,不用 0 代替。

5. run manifest

schema: calculet-perf-run/v1
run_id: 20260802-qwen3-baseline-001
purpose: baseline
model:
  alias: qwen3
  generation: 42
  calbin_sha256: REQUIRED
software:
  server_commit: REQUIRED
  image_digest: REQUIRED
  calrt: 0.7.6
  driver: REQUIRED
  firmware: REQUIRED
hardware:
  board: REQUIRED
  chips: 2
  power_mode: REQUIRED
environment:
  ambient_c: REQUIRED
  vpn_in_path: false
client:
  host: REQUIRED
  transport: http-sse
matrix: configs/baseline.yaml
warmup_requests: 10
measured_requests: 100
timeout_s: 900

NPU 性能客户端应与服务处在稳定低抖动 LAN;VPN 只用于管理,不应位于性能数据路径。若无法避免,记录 RTT/jitter 并把 Runtime 设备指标与客户端指标分开解释。

6. 基线矩阵

6.1 单请求

维度
prompt tokens 1, 16, 17, 128, 512, 1024, 2048, 4096, 8192, 16384, 32768, 40959
output tokens 1, 32, 256
concurrency 1
sampling greedy(数值基线),固定 seed 的业务 sampling
stream true/false

prompt=40959, output>1 是边界拒绝/截断策略测试,不是成功生成 256 token 的性能 case。

6.2 并发

concurrency arrival 目的
1 closed-loop 单请求下界
2,4,8,16 closed-loop 饱和吞吐/排队
目标 QPS 0.25/0.5/1/2... open-loop Poisson 真实排队和 overload
burst 2/4/8/16 同时到达 admission/backpressure

closed-loop 每个 worker 收到结果后再发请求,会隐藏 overload;容量和 P99 必须用 open-loop 复测。

6.3 混合流量

  • 70% 短 prompt(128)/短 output(32)20% 中(2K/128)10% 长(16K/256)。
  • decode-heavy:已有 KV 的长生成。
  • prefill-heavy:长 prompt/短输出。
  • 长 prefill 与短 decode 同时到达,观察 head-of-line blocking。

7. batch calbin 矩阵

对 B4/B8/B16 每个产物分别测 active lanes 1..B,不满 lane 的 mask/填充策略必须由厂商说明。

fill_ratio = active_lanes / compiled_batch
effective_tokens_s = successful_generated_tokens / wall_time
lane_waste = 1 - useful_lane_steps / total_lane_steps

同时报告单请求 TPOT P99 和 aggregate tokens/s。若 B16 aggregate 更高但低负载 TPOT/P99 不满足 SLA,可采用多 profile 或调度阈值,不能笼统宣称“B16 最优”。

8. 测量执行顺序

  1. 校验 release manifest、hash 和设备版本。
  2. 空闲采样 5 分钟,确认温度/功耗/频率稳定。
  3. 跑固定 golden,失败立即终止性能测试。
  4. 每个新模型/shape 10 次 warmup,不计入测量。
  5. case 顺序随机化或 baseline/candidate 交错,降低温漂偏差。
  6. 每 case 至少 30 次;短 case 100 次。
  7. 每轮记录 idle gap、温度和 throttle;触发 throttle 的结果分层报告。
  8. 测后再跑 golden,并检查资源回落。

9. 统计和比较

每个 cell 输出 count、success/error、P50/P90/P95/P99/max、mean/std、MAD、95% bootstrap CI。吞吐使用整个稳态窗口而非逐请求 tokens/s 的简单平均。

baseline/candidate 同一 case 计算配对差值:

delta_abs = candidate - baseline
delta_pct = (candidate/baseline - 1)*100

延迟负值改善,吞吐正值改善。报告应明确方向,避免表格误读。

异常值不随意删除。只有客户端 clock 缺失、进程启动 warmup、明确网络断链等预注册条件可排除,并报告排除数量/理由。

10. 正式指标面板

10.1 请求

  • request rate、success、4xx/5xx/timeout/cancel。
  • TTFT、TPOT、E2E 按 model/prompt/output/concurrency 分桶。
  • generated tokens/s、prompt tokens/s、active sequences。
  • queue time、admission wait、slot wait。

10.2 Runtime

  • jobs in-flight、pending/finished/left。
  • H2D/infer/D2H、OutputBuf status。
  • buffer pool total/free/leased/quarantine/wait。
  • KV allocated/free/wait/reject、sequence length histogram。
  • CCU exception、timeout、busy、reset、generation change。

10.3 系统/设备

  • process RSS/CPU/thread count/open FDs。
  • device DRAM/SRAM usage(单位经确认后)。
  • per-chip temp/power/frequency/throttle。
  • D2D/DDR/PCIe bytes/cycles(厂商 trace)。

11. 故障注入架构

不要通过真的破坏样机文件或任意写寄存器做日常注入。优先在我方 wrapper 注入返回码/延迟/状态;设备级 reset 只在维护窗口和厂商契约下测试。

struct CalrtFaultInjector {
    virtual CalrtError_e before_submit(const JobContext &) = 0;
    virtual std::optional<CalrtError_e> override_wait(const JobContext &) = 0;
    virtual std::optional<OutputStatus> override_status(const JobContext &) = 0;
    virtual void corrupt_output(JobContext &) = 0;
};

生产编译默认注入器 disabled;启用需要 test build 或受控 admin flag,普通请求不能设置。

12. 故障场景清单

12.1 请求/资源

场景 注入 预期
非法长度/溢出 0、max+1、uint 边界 提交前 400,不影响设备
KV 满 canAllocate=false 有界等待后 429/503CPU 不忙等
buffer pool 满 占满 lease 排队/timeout,无共享复用
cancel waiting 等待队列中取消 立即移除并释放 reservation
cancel submitted infer 后取消 仍 drain Wait,不交付结果

12.2 Runtime

场景 注入 预期
submit DeviceBusy wrapper rc=17 有界 backoff/失败,不 reset
submit DeviceUnavailable rc=18 停 admission,进入恢复
Wait Timeout rc=13 buffer/KV quarantine
CCU exception output status 不交付 logitsgeneration 恢复
invalid shape/dtype rc=21/22 隔离 artifact,不反复 reset
stale completion 延迟旧 job 到 reset 后 generation check 阻断写入
output NaN/Inf corrupt hook 数值检查失败、golden 复测

12.3 生命周期

场景 操作 预期
shutdown with queue queued+submitted queued 取消,submitted drain
load while ready 新 generation 先 drain,原子切换
configure failure 错 calbin 旧 generation 保持或可回滚
reset failure mock soft reset fail 实例 Failed,由 supervisor 重启
repeated fault 连续 timeout/crash 指数退避和 reset 限频

12.4 硬件维护窗口

可在明确授权下测试 PCIe/driver/device reset,但不清理审计日志掩盖实验。每次记录操作者、时间、在途 job、前后版本/health、影响用户和恢复结果。

13. 稳定性阶段

阶段 时长 负载 通过条件
smoke 10 min C1、短请求 golden、零错误
dev soak 1 h 70% 目标负载 无 leak/hang/abort
candidate 8 h 混合+burst SLA、恢复、资源稳定
release 24 h 目标稳态+周期 burst 零未恢复 device fault
endurance 72 h 可选 生产模拟 观察热/长期碎片

资源泄漏判定:warmup 后对 RSS、device memory、leased buffer、KV allocated、FD/thread 做 Theil-Sen slope 或至少起止/周期趋势;不能仅看最终值。每个 sequence 完成后 KV 和 lease 最终回到预期基线。

14. 验收阈值

14.1 正确性和可靠性是硬门槛

  • 固定 golden 100% 通过;无请求间 logits/KV 串扰。
  • 24h 无 abort()、无限等待、use-after-free、未处理 exception。
  • 所有 fault scenario 状态转换符合设计,恢复后 golden 通过。
  • success response 中 NaN/Inf=0;错误响应不含未初始化输出。

14.2 性能门槛

基线重构(in-flight=1):TTFT/TPOT P50 退化 <=3%P99 <=5%。

优化候选:目标 cell 至少改善 8% 或端到端关键指标改善 5%;非目标 workload P99 退化 <=5%;功耗/温度不突破设备/产品上限。

ping/pongaggregate tokens/s 提升 >=10%,单请求 TPOT P99 退化 <=5%24h 稳定。

batch calbin:在目标并发下 aggregate tokens/s 相对 B1 提升必须给出明确目标;在数据到位前不预设倍数。低填充率必须仍满足交互 SLA。

14.3 容量门槛

在目标 arrival rate 下,P99 queue time、reject rate 和利用率同时满足 SLA。稳定最大 QPS 定义为 30 分钟窗口内错误率/延迟合格且队列不持续增长的最高点,不是短时峰值。

15. 自动化 pass/fail

validate manifests/hashes
  -> golden before
  -> warmup
  -> execute randomized matrix
  -> join client/server/device records
  -> quality filters
  -> summarize + confidence intervals
  -> fault matrix
  -> golden after
  -> resource leak analysis
  -> acceptance rules
  -> signed report

程序退出码:0 pass1 correctness/reliability fail2 artifact/config invalid3 infrastructure invalid(例如客户端时钟或网络断链);4 performance regression。基础设施失败不算产品 pass 或 fail,需重跑。

16. 报告必须呈现的反例

  • 最慢的 20 个请求及其 queue/device/postprocess 分解。
  • 发生过的所有 Runtime 非 success,即使最终请求重试成功。
  • 每次 reset/reconfigure 和恢复时长。
  • 被排除样本及理由。
  • candidate 赢/输的 workload,不只展示最佳 case。
  • 长 context TPOT 曲线;当前历史趋势约在 33K/40K 明显下降,必须用新 harness 重测。

17. 厂商数据接口要求

正式归因仍需要:per-op/per-chip cycles、D2D/DDR/PCIe bytes、队列 counters 语义、温度/功耗/频率 API、trace schema/时钟/开销。没有这些字段时仍可完成端到端 A/B,但结论只到图/服务级,不虚构 kernel 瓶颈。