本机推理延迟排查

September 16, 2026 · View on GitHub

2026-09-16。用户报告单题 MPS 耗时 12878 ms。本轮保持用户指定候选、通用提示和单 token 相对评分规则,不增加未知选项、不做专项训练、不缓存整题答案。

已验证的问题

  • 两个模型同时常驻:8765 为旧 CPU 模型,8766 为 4B FP16 MPS。检查时系统交换空间已用约 11.5 GB;累计交换量不等于该次请求的换页量,但表明存在明显内存压力。
  • 优化前八个固定请求,首个约 8007 ms,其余约 498–619 ms。
  • 释放旧模型后,同一组首个约 4311 ms,其余约 509–549 ms;逐项概率差为 0。旧地址现在是轻量重定向入口,不再常驻第二个模型。
  • 尝试合并 GPU 输出传输及 CPU 评分后,重启后的首个仍约 13540 ms。其中前向及输出传输约 13017 ms,预处理约 120 ms、评分约 26 ms;热请求约 533–681 ms。这个改动未解决慢请求,不能宣称单靠代码小优化已修好。

这些是同机不同时间的顺序观察,不是严格控制系统负载的因果实验。根因判断为大权重下的内存压力和运行时成本共同作用;没有证据把全部耗时归因于网页、排队或某一个算子。

MLX 8 位对照

使用 MLX LM 官方实现,在独立 .venv-mlx 环境,将同一 pinned Qwen3-4B-Instruct-2507 原始权重转成 affine int8、group size 64;非量化参数使用 float16。考虑量化元数据后转换器报告约 8.5 bits/weight,文件约 4 GB。原 FP16 权重保留。

脚本:scripts/convert_instruction_mlx.py;依赖:requirements-mlx.lock.txt;转换文件 SHA256 与源 revision:data/instruction-4b-mlx8-assets.json。没有联网推理或云端费用。

评分保持原问题、候选排序、聊天模板、长度上限、标签 token 及 softmax 规则;只投影最后位置,避免为所有输入 token 计算整词表 logits。MLX allocator cache 上限为 256 MiB,不降低模型上下文、不采用截断 KV。服务串行保护同一模型实例。

量化与更换执行引擎可能改变概率,不能声称数学/逐位等价。验证使用全部既有 236 条开发题和 128 条阅读子集,检查 token 数、逐题首选、概率偏差、分组准确率及 NLL/Brier。报告必须绑定转换权重 artifact hash,不能给新精度直接沿用 FP16 成绩。

复现

当前默认 bash scripts/run_instruction_demo.sh 使用经过固定评测的 MLX 8-bit 副本;启动脚本核对转换 artifact 与验证记录。当前服务仍在 8766,8765 只提供轻量跳转。没有持续后台预热。

# 原 PyTorch 路径仍可显式启动,用于对照。
DECISION_BACKEND=instruction bash scripts/run_instruction_demo.sh

# 八个不同请求,不复用答案。输出路径必须未存在。
.venv-mlx/bin/python scripts/benchmark_http_latency.py reports/my-latency.json

测量需区分首次请求、连续请求、空闲后请求以及较长资料;在服务空闲时跑延迟对照,不能把评测并发排队混入模型耗时。后台服务、系统负载和内存压力会影响观察值。绝不通过持续后台空转来隐藏空闲后的慢请求。

已完成的质量与速度对照

  • 全部 364 条输入的 token ID 序列与原模型完全一致;没有截断或替换问题、候选。
  • 236 条开发题首选全部一致,仍为 212/236;128 条阅读题首选全部一致,仍为 125/128。只能说明这些固定数据上的一致性,不能保证任意输入绝不变化。
  • MLX 观测峰值约 4.60 GB;原 FP16 MPS 约 8.35 GB,来自各自分配统计,不是同一工具测出的整机峰值。
  • MLX 的首次开发评测请求约 2068 ms,短题中位约 729 ms;完整评测后独立测八个 HTTP 请求为 485–683 ms,均未使用答案缓存。
  • 概率不是逐位一致:开发组最大单候选绝对偏差约 0.1854,NLL 由 1.7377 到 1.7505,Brier 由 0.1937 到 0.1964;阅读组 NLL 由 0.1456 到 0.1487,Brier 由 0.0460 到 0.0441。量化与引擎差异没有在这些数据上改变首选,但不能宣称完全无损。

原始记录:reports/latency-*.jsonreports/generalization-instruction-mlx8.jsonreports/reading-instruction-mlx8.jsonreports/mlx-tokenizer-parity.jsonreports/mlx-validation.json。36 项自动测试通过;原 PyTorch 环境与原始权重没有删除。

空闲后复测

服务日志确认 84.45 秒没有任何 POST /decide 请求后,首次 HTTP 请求约 657 ms,其余七次约 464–470 ms。无后台空转预热、无整题答案缓存。原始观察见 reports/mlx-idle-observation.jsonreports/latency-mlx8-after-idle.json;汇总见 reports/latency-summary.json。这支持本机当前负载下慢首请求已明显改善,不是对任意长输入、其他应用占满内存或长时间空闲的绝对保证。