[Edge][CPU] Predictor fast-path modes: torch.ao int8 (default), torchao weight-only + compiled step, fp32 control; parity metrics

torchao's dynamic-activation int8 is numerically wrong under torch.compile on
CPU (cosine 0.02 vs fp32; caused runaway generations), so it is not offered;
weight-only + compile is faithful but slower (78 ms vs 36 ms per frame for the
15 sub-steps), so torch.ao dynamic int8 stays the default. Parity mode now also
records top-5 overlap and KL vs the bf16 model; compiled-step equivalence test.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
tzhouamandClaude Fable 5.1 committed 2026-09-10 02:44:29 +08:00
1 parent 6ce8de1b28
commit 94485152d2
2 files changed
+79 -12

No files matched your search

@@ -77,3 +77,23 @@ def test_forward_static_step_matches_full_prefix():
mask = (torch.arange(max_seq) <= step).view(1, 1, 1, max_seq).expand(bsz, 1, 1, max_seq)
out = model.forward_static_step(x[:, step : step + 1], pos[:, step : step + 1], caches, pos_t, mask)
assert torch.allclose(out[:, 0], full[:, step], atol=1e-4, rtol=1e-4), step
@torch.inference_mode()
def test_compiled_static_step_matches_eager():
torch.manual_seed(2)
model = CodePredictorBaseModel(_tiny_config()).eval()
for p in model.parameters():
p.normal_(0, 0.2)
bsz, max_seq = 1, 17
x = torch.randn(bsz, max_seq, 64)
pos = torch.arange(max_seq).unsqueeze(0).expand(bsz, -1)
full = model(x, pos)
step_fn = torch.compile(model.forward_static_step, dynamic=False)
caches = model.new_kv_caches(bsz, max_seq, x.device, x.dtype)
model.forward_cached(x[:, :2], pos[:, :2], caches, 0)
for step in range(2, max_seq):
pos_t = torch.tensor([step])
mask = (torch.arange(max_seq) <= step).view(1, 1, 1, max_seq).expand(bsz, 1, 1, max_seq)
out = step_fn(x[:, step : step + 1], pos[:, step : step + 1], caches, pos_t, mask)
assert torch.allclose(out[:, 0], full[:, step], atol=1e-4, rtol=1e-4), step