From 56d90565e16a6d4ae37af6324a3f85d3bdeb5d39 Mon Sep 17 00:00:00 2001 From: gspark Date: Fri, 23 Oct 2026 15:27:46 +0900 Subject: [PATCH 1/6] feat: add experimental Qwen3 RNGD prefill validation --- opt_prime/examples/pd/qwen3_rngd/README.md | 63 +++++ .../examples/pd/qwen3_rngd/check_atom.py | 111 ++++++++ opt_prime/examples/pd/qwen3_rngd/prefill.py | 196 ++++++++++++++ .../examples/pd/qwen3_rngd/run_prefill.py | 47 ++++ opt_prime/examples/pd/qwen3_rngd/spec.py | 33 +++ opt_prime/examples/pd/qwen3_rngd/test_spec.py | 43 ++++ .../examples/pd/qwen3_rngd/validation.json | 239 ++++++++++++++++++ 7 files changed, 732 insertions(+) create mode 100644 opt_prime/examples/pd/qwen3_rngd/README.md create mode 100644 opt_prime/examples/pd/qwen3_rngd/check_atom.py create mode 100644 opt_prime/examples/pd/qwen3_rngd/prefill.py create mode 100644 opt_prime/examples/pd/qwen3_rngd/run_prefill.py create mode 100644 opt_prime/examples/pd/qwen3_rngd/spec.py create mode 100644 opt_prime/examples/pd/qwen3_rngd/test_spec.py create mode 100644 opt_prime/examples/pd/qwen3_rngd/validation.json diff --git a/opt_prime/examples/pd/qwen3_rngd/README.md b/opt_prime/examples/pd/qwen3_rngd/README.md new file mode 100644 index 00000000..4f98ba0d --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/README.md @@ -0,0 +1,63 @@ +# Experimental Qwen3 RNGD prefill → ATOM validation (#197) + +Qwen3-0.6B requires Q/K normalization, unbiased projections, and a2048-wide query +projection despite hidden_size1024. This separate graph implements those semantics; +it does not loosen the existing Qwen2-only DenseModel contract or register a new +production serving backend. Quantized weights, scaled RoPE, sliding attention and +non-Qwen3 configs are rejected. Only Qwen3-0.6B has been hardware-validated here. + +## Reproduce + +Use the isolated single-card device-plugin Pod setup from PR195's +`ATOM_CONTAINER_EXPERIMENT.md`, including validated Python environments, HOME, +offline model cache, device leases, and the fusion4/Mesh2 Furiosa launcher. Requires +existing `rngd_pd` and optimus-rm modules on PYTHONPATH, plus PR195's +`atom_stream_upload.py` and `check_atom_container.py`. Do not install into or mutate +another workload's environment. Work from a writable scratch directory containing +these files. Use only the allocated devices. + +```bash +python3 test_spec.py +# Export FURIOSA_PYTHON to the validated Furiosa2026.4 interpreter. +./furiosa_prefill_python.sh -m run_prefill +"$ATOM_PYTHON" check_atom_container.py check_atom.py +``` + +`run_prefill.py` writes trusted tensor data to qwen3_197_kv.pt. `check_atom.py` +compiles/loads its own B1/context512/3KV-block artifact under qwen3-197-atom, compares +CPU FP32 prefill, native ATOM prefill and imported RNGD KV, and writes +qwen3_197_atom.json. It uses both the existing and portable importers and reads back +every imported slot. These scripts run a finite fixture, not an HTTP service. + +## Hardware evidence (2026-10-23) + +RNGD: Furiosa2026.4,fusion4/Mesh2,width128,28layers,8KV heads,head_dim128. +ATOM: rebel-compiler0.11.0,optimum-rbln0.11.0.post1,torch2.11.0+cpu, +B1/context512/3KV blocks. Checkpoint Qwen/Qwen3-0.6B; three chat prompts with thinking +disabled. Exact records in validation.json; compilation provenance in the local +research experiment2026-10-23-gemma-fix-qwen3-koni.md. + +-3/3first tokens match CPU FP32 and native ATOM. +-3/3fixed16-token PD outputs match native ATOM. +-3/3full decode-logit sequences match between original and portable importers. +-336/336slot readbacks exact:3prompts ×2importers ×56slots. +-RNGD-vs-CPU relative RMS:K0.470–0.491%,V1.757–1.911%,last logits1.164–1.604%. +-Prefill wall time including host KV/logits:1.321s first,0.723/0.714s subsequent. + This is a correctness bring-up, not vendor-native performance parity. + +Fixed-length diagnostic generation continues beyondEOS; service termination semantics +are not tested. The Korean-capital answer is incorrectlyIncheon on both CPU/ATOM in +this fixture; matching tokens does not establish factual quality. No DMA, zero-copy, +streamed source export or overlap claim. Host transfer occurs after complete prefill. + +The initial compile failed because epsilon/exponent inputs wereBF16 while rms_dsl +requiresFP32. They now remainFP32; weights/activation carriers remainBF16. Failed +compile log is retained with the experiment. CPU contract tests reject unsupported +semantics; hardware records are essential evidence beyond those tests. + +## Limits + +Other sizes, longer prompts, concurrent requests, prefix reuse, cancellation and +production recovery/lifetime behavior are unvalidated. The handoff has not been +wired into npu_pd_bench/serve_batched. Keep model-specific math in this prefiller; +the portable56-slot import succeeded without communication-library changes. diff --git a/opt_prime/examples/pd/qwen3_rngd/check_atom.py b/opt_prime/examples/pd/qwen3_rngd/check_atom.py new file mode 100644 index 00000000..61edc38d --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/check_atom.py @@ -0,0 +1,111 @@ +import json +from pathlib import Path + +import numpy as np +import torch +from atom_stream_upload import import_atom_span +from opt_prime.accel.platforms.atom.engine import AtomRblnEngine +from transformers import AutoModelForCausalLM, AutoTokenizer + +mid = "Qwen/Qwen3-0.6B" +physical = int(next(Path("/dev").glob("rbln[0-9]*")).name[4:]) +e = AtomRblnEngine( + devices=[physical], + max_seq_len=512, + batch_size=1, + kv_blocks=3, + cache_dir=str(Path("qwen3-197-atom").resolve()), +) +e.start(mid) +records = torch.load("qwen3_197_kv.pt", weights_only=True) +ref = AutoModelForCausalLM.from_pretrained(mid, dtype=torch.float32).eval() +tok = AutoTokenizer.from_pretrained(mid) +b = e.batcher(prefix_cache=False) +rows = [] + + +def decode(first, n): + out = [first] + vectors = [] + for j in range(15): + z = ( + b.decoder( + input_ids=torch.tensor([[out[-1]]]), + cache_position=torch.tensor([[n + j]], dtype=torch.int32), + block_tables=b.blocks.table([0]), + ) + .logits[0, -1] + .float() + ) + assert torch.isfinite(z).all() + vectors.append(z.clone()) + out.append(int(z.argmax())) + return out, torch.stack(vectors) + + +with torch.inference_mode(): + for r in records: + ids = r["ids"] + n = len(ids) + b.blocks.admit(0, ids) + block = b.blocks.lane_block[0] + nl = b._prefill(0, ids).logits[0, -1].float() + native, _ = decode(int(nl.argmax()), n) + hf = ref(torch.tensor([ids]), use_cache=True) + hl = hf.logits[0, -1].float() + ll = r["logits"].float() + ck = torch.stack([l.keys[0] for l in hf.past_key_values.layers]) + cv = torch.stack([l.values[0] for l in hf.past_key_values.layers]) + kr = float( + (r["keys"].float() - ck).square().mean().sqrt() / ck.square().mean().sqrt() + ) + vr = float( + (r["values"].float() - cv).square().mean().sqrt() + / cv.square().mean().sqrt() + ) + variants = {} + saved = [] + for name in ["original", "portable"]: + if name == "original": + b.blocks.import_span(0, 0, r["keys"], r["values"]) + else: + import_atom_span(b.blocks, 0, 0, r["keys"], r["values"]) + exact = 0 + for meta, buf in zip(b.blocks.metas, b.blocks._staging()): + expected = buf[block, :, :n].copy() + buf.fill(0) + b.blocks.io_rt.get_kv_cache_for_layer(meta["name"], block, 0, n, buf) + assert np.array_equal(expected, buf[block, :, :n]) + exact += 1 + tokens, vectors = decode(int(ll.argmax()), n) + saved.append(vectors) + variants[name] = { + "tokens": tokens, + "text": tok.decode(tokens), + "readback_exact_slots": exact, + "native_equal": tokens == native, + } + row = { + "prompt": r["prompt"], + "prompt_tokens": n, + "first_cpu": int(hl.argmax()), + "first_rngd": int(ll.argmax()), + "first_atom": int(nl.argmax()), + "key_relative_rms": kr, + "value_relative_rms": vr, + "logits_relative_rms": float( + (ll - hl).square().mean().sqrt() / hl.square().mean().sqrt() + ), + "prefill_s": r["prefill_s"], + "native_tokens": native, + "native_text": tok.decode(native), + "variants": variants, + "importer_logits_exact": bool(torch.equal(*saved)), + } + rows.append(row) + print(json.dumps(row, ensure_ascii=False), flush=True) + b.blocks.release(0, None) +Path("qwen3_197_atom.json").write_text( + json.dumps(rows, ensure_ascii=False, indent=2) + "\n" +) +e.close() diff --git a/opt_prime/examples/pd/qwen3_rngd/prefill.py b/opt_prime/examples/pd/qwen3_rngd/prefill.py new file mode 100644 index 00000000..ad45b85f --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/prefill.py @@ -0,0 +1,196 @@ +"""Experimental Qwen3 full-prefix graph; requires validated Furiosa environment.""" + +import math + +import torch +from rngd_pd.engines.fsdk import ( + CompileModule, + FCConfig, + TacticKernelModule, + dev_str, + hint, + sync, +) +from rngd_pd.kernels.prefill_chunk import rms_dsl, softmax_dsl, swiglu_dsl, zipadd_dsl +from spec import validate + +BF = torch.bfloat16 + + +class Layer(torch.nn.Module): + def __init__(self, s, width): + super().__init__() + self.s = s + self.width = width + h = s["hidden_size"] + d = s["head_dim"] + nh = s["num_attention_heads"] + nk = s["num_key_value_heads"] + self.norm = TacticKernelModule(rms_dsl(width, h)) + self.add = TacticKernelModule(zipadd_dsl(width, h)) + self.qnorm = TacticKernelModule(rms_dsl(width * nh, d)) + self.knorm = TacticKernelModule(rms_dsl(width * nk, d)) + self.act = TacticKernelModule(swiglu_dsl(width, s["intermediate_size"])) + self.softmax = TacticKernelModule( + softmax_dsl(nk, (nh // nk) * width, width).replace("/bf16", "/f32") + ) + + def forward( + self, + x, + eps, + exponent, + qeps, + qexp, + keps, + kexp, + n1, + n2, + qn, + kn, + wq, + wk, + wv, + wo, + wg, + wu, + wd, + rotation, + mask, + ): + s = self.s + c = self.width + d = s["head_dim"] + nh = s["num_attention_heads"] + nk = s["num_key_value_heads"] + g = nh // nk + h = self.norm(x, n1, eps, exponent)[0] + q = self.qnorm((h @ wq).reshape(c * nh, d), qn, qeps, qexp)[0].reshape(c, nh, d) + k = self.knorm((h @ wk).reshape(c * nk, d), kn, keps, kexp)[0].reshape(c, nk, d) + q = torch.matmul(q, rotation).to(BF) + k = torch.matmul(k, rotation).to(BF) + keys = k.permute(1, 2, 0) + values = (h @ wv).reshape(c, nk, d).permute(1, 0, 2) + query = q.reshape(c, nk, g, d).permute(1, 2, 0, 3).reshape(nk, g * c, d) + probs = self.softmax((query.float() @ keys.float()) * (d**-0.5) + mask.float())[ + 0 + ].to(BF) + att = ( + (probs @ values).reshape(nk, g, c, d).permute(2, 0, 1, 3).reshape(c, nh * d) + ) + res = self.add(att @ wo, x)[0] + h = self.norm(res, n2, eps, exponent)[0] + out = self.add(self.act(h @ wg, h @ wu)[0] @ wd, res)[0] + return out, torch.stack((keys, values.transpose(-1, -2))) + + +class Prefill: + def __init__(self, config, weights, width=128, chip=0): + s = self.s = validate(config) + self.width = width + self.chip = chip + if width <= 0 or width > 512 or width % 32: + raise ValueError("width must be a multiple of32 within512") + device = dev_str(chip) + self.device = device + + def put(x): + return x.contiguous().to(BF).to(device) + + self.embedding = weights["model.embed_tokens.weight"] + h = s["hidden_size"] + d = s["head_dim"] + nh = s["num_attention_heads"] + nk = s["num_key_value_heads"] + eps = s["rms_norm_eps"] + c = width + self.fixed = [ + torch.full((r, col), v, dtype=torch.float32).to(device) + for r, col, v in [ + (c, h, eps * h), + (c, h, -0.5), + (c * nh, d, eps * d), + (c * nh, d, -0.5), + (c * nk, d, eps * d), + (c * nk, d, -0.5), + ] + ] + self.layers = [] + for i in range(s["num_hidden_layers"]): + + def w(k, i=i): + return weights[f"model.layers.{i}." + k] + + norms = [ + put(w(k).repeat(n, 1) * math.sqrt(dim)) + for k, n, dim in [ + ("input_layernorm.weight", c, h), + ("post_attention_layernorm.weight", c, h), + ("self_attn.q_norm.weight", c * nh, d), + ("self_attn.k_norm.weight", c * nk, d), + ] + ] + mats = [ + put(w(k).T) + for k in [ + "self_attn.q_proj.weight", + "self_attn.k_proj.weight", + "self_attn.v_proj.weight", + "self_attn.o_proj.weight", + "mlp.gate_proj.weight", + "mlp.up_proj.weight", + "mlp.down_proj.weight", + ] + ] + self.layers.append(norms + mats) + inv = 1 / (s["rope_theta"] ** (torch.arange(0, d, 2).float() / d)) + angle = torch.arange(c)[:, None] * inv[None] + rot = torch.zeros(c, d, d) + idx = torch.arange(d // 2) + rot[:, idx, idx] = angle.cos() + rot[:, idx + d // 2, idx + d // 2] = angle.cos() + rot[:, idx, idx + d // 2] = angle.sin() + rot[:, idx + d // 2, idx] = -angle.sin() + self.rotation = put(rot) + self.mask = put( + torch.triu(torch.full((c, c), -1e4), 1).repeat(nh // nk, 1)[None] + ) + tensors = [ + torch.zeros(c, h, dtype=BF), + *self.fixed, + *self.layers[0], + self.rotation, + self.mask, + ] + sample = tuple(torch.zeros(tuple(t.shape), dtype=t.dtype) for t in tensors) + self.module = CompileModule.from_module( + Layer(s, c), + sample, + compiler_config=FCConfig(tactic_hint=hint("ForLlmModelPrefill")), + ) + self.module.to(device) + sync(chip) + self.norm = weights["model.norm.weight"].float() + self.head = weights.get("lm_head.weight", self.embedding).float() + + def prefill(self, tokens): + if not 0 < len(tokens) <= self.width: + raise ValueError("prompt exceeds compiled capacity") + x = ( + self.embedding[tokens + [tokens[-1]] * (self.width - len(tokens))] + .to(BF) + .to(self.device) + ) + keys = [] + values = [] + for w in self.layers: + x, kv = self.module(x, *self.fixed, *w, self.rotation, self.mask) + keys.append(kv[0]) + values.append(kv[1].transpose(-1, -2)) + sync(self.chip) + n = len(tokens) + k = torch.stack(keys).cpu()[:, :, :, :n].transpose(-1, -2) + v = torch.stack(values).cpu()[:, :, :n] + z = x.cpu()[n - 1].float() + z = z * torch.rsqrt(z.square().mean() + self.s["rms_norm_eps"]) * self.norm + return k, v, z @ self.head.T diff --git a/opt_prime/examples/pd/qwen3_rngd/run_prefill.py b/opt_prime/examples/pd/qwen3_rngd/run_prefill.py new file mode 100644 index 00000000..337fd4ed --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/run_prefill.py @@ -0,0 +1,47 @@ +import json +import time +from pathlib import Path + +import torch +from huggingface_hub import snapshot_download +from prefill import Prefill +from safetensors import safe_open +from transformers import AutoTokenizer + +mid = "Qwen/Qwen3-0.6B" +path = Path(snapshot_download(mid, local_files_only=True)) +c = json.loads((path / "config.json").read_text()) +w = {} +for shard in sorted(path.glob("*.safetensors")): + with safe_open(shard, framework="pt") as f: + for key in f: + w[key] = f.get_tensor(key).float() +e = Prefill(c, w, width=128, chip=0) +print("READY", flush=True) +tok = AutoTokenizer.from_pretrained(mid) +records = [] +for prompt in [ + "What is the capital of France?", + "Compute 2 + 3.", + "한국의 수도는 어디인가요?", +]: + ids = tok.apply_chat_template( + [{"role": "user", "content": prompt}], + tokenize=True, + add_generation_prompt=True, + return_dict=False, + enable_thinking=False, + ) + t = time.perf_counter() + k, v, l = e.prefill(ids) + row = { + "prompt": prompt, + "ids": ids, + "keys": k, + "values": v, + "logits": l, + "prefill_s": time.perf_counter() - t, + } + records.append(row) + print(prompt, "first", int(l.argmax()), "seconds", row["prefill_s"], flush=True) +torch.save(records, "qwen3_197_kv.pt") diff --git a/opt_prime/examples/pd/qwen3_rngd/spec.py b/opt_prime/examples/pd/qwen3_rngd/spec.py new file mode 100644 index 00000000..903c30fe --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/spec.py @@ -0,0 +1,33 @@ +"""Strict semantics for the experimental dense Qwen3 graph, SDK independent.""" + + +def validate(config): + c = dict(config) + if ( + c.get("model_type") != "qwen3" + or c.get("hidden_act") != "silu" + or c.get("attention_bias", False) + ): + raise ValueError("requires unbiased dense Qwen3/SwiGLU") + if ( + c.get("quantization_config") + or c.get("rope_scaling") + or c.get("use_sliding_window", False) + ): + raise ValueError( + "quantization, scaled RoPE and sliding attention need separate validation" + ) + for k in [ + "hidden_size", + "num_attention_heads", + "num_key_value_heads", + "num_hidden_layers", + "head_dim", + ]: + if type(c.get(k)) is not int or c[k] <= 0: + raise ValueError("invalid " + k) + if c["head_dim"] != 128 or c["num_attention_heads"] % c["num_key_value_heads"]: + raise ValueError("unsupported head geometry") + c["query_width"] = c["num_attention_heads"] * c["head_dim"] + c["slots"] = 2 * c["num_hidden_layers"] + return c diff --git a/opt_prime/examples/pd/qwen3_rngd/test_spec.py b/opt_prime/examples/pd/qwen3_rngd/test_spec.py new file mode 100644 index 00000000..93ba1be9 --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/test_spec.py @@ -0,0 +1,43 @@ +import unittest + +from spec import validate + + +class SpecTests(unittest.TestCase): + def config(self, **kw): + c = { + "model_type": "qwen3", + "hidden_size": 1024, + "num_attention_heads": 16, + "num_key_value_heads": 8, + "head_dim": 128, + "num_hidden_layers": 28, + "hidden_act": "silu", + "attention_bias": False, + "rope_theta": 1e6, + } + c.update(kw) + return c + + def test_query_width_is_independent(self): + s = validate(self.config()) + self.assertEqual(s["query_width"], 2048) + self.assertEqual(s["hidden_size"], 1024) + self.assertEqual(s["slots"], 56) + + def test_rejects_other_semantics(self): + for kw in [ + {"model_type": "qwen2"}, + {"quantization_config": {"quant_method": "fp8"}}, + {"use_sliding_window": True}, + {"rope_scaling": {"rope_type": "linear"}}, + {"attention_bias": True}, + {"num_key_value_heads": 3}, + {"head_dim": 64}, + ]: + with self.subTest(kw=kw), self.assertRaises(ValueError): + validate(self.config(**kw)) + + +if __name__ == "__main__": + unittest.main() diff --git a/opt_prime/examples/pd/qwen3_rngd/validation.json b/opt_prime/examples/pd/qwen3_rngd/validation.json new file mode 100644 index 00000000..3211a05c --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/validation.json @@ -0,0 +1,239 @@ +[ + { + "prompt": "What is the capital of France?", + "prompt_tokens": 19, + "first_cpu": 785, + "first_rngd": 785, + "first_atom": 785, + "key_relative_rms": 0.004695013631135225, + "value_relative_rms": 0.01862264797091484, + "logits_relative_rms": 0.011644327081739902, + "prefill_s": 1.3208831560332328, + "native_tokens": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "native_text": "The capital of France is **Paris**.<|im_end|>\n<|endoftext|>Human: What is", + "variants": { + "original": { + "tokens": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "text": "The capital of France is **Paris**.<|im_end|>\n<|endoftext|>Human: What is", + "readback_exact_slots": 56, + "native_equal": true + }, + "portable": { + "tokens": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "text": "The capital of France is **Paris**.<|im_end|>\n<|endoftext|>Human: What is", + "readback_exact_slots": 56, + "native_equal": true + } + }, + "importer_logits_exact": true + }, + { + "prompt": "Compute 2 + 3.", + "prompt_tokens": 19, + "first_cpu": 17, + "first_rngd": 17, + "first_atom": 17, + "key_relative_rms": 0.004911903291940689, + "value_relative_rms": 0.01911376416683197, + "logits_relative_rms": 0.01556027214974165, + "prefill_s": 0.723041116958484, + "native_tokens": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "native_text": "2 + 3 = 5.<|im_end|>\n<|endoftext|>In the context of the", + "variants": { + "original": { + "tokens": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "text": "2 + 3 = 5.<|im_end|>\n<|endoftext|>In the context of the", + "readback_exact_slots": 56, + "native_equal": true + }, + "portable": { + "tokens": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "text": "2 + 3 = 5.<|im_end|>\n<|endoftext|>In the context of the", + "readback_exact_slots": 56, + "native_equal": true + } + }, + "importer_logits_exact": true + }, + { + "prompt": "한국의 수도는 어디인가요?", + "prompt_tokens": 22, + "first_cpu": 23573, + "first_rngd": 23573, + "first_atom": 23573, + "key_relative_rms": 0.004876873455941677, + "value_relative_rms": 0.01756548509001732, + "logits_relative_rms": 0.016039395704865456, + "prefill_s": 0.7141205350635573, + "native_tokens": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "native_text": "한국의 수도는 **인천**입니다.<|im_end|>\n<|endoftext|>Human:", + "variants": { + "original": { + "tokens": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "text": "한국의 수도는 **인천**입니다.<|im_end|>\n<|endoftext|>Human:", + "readback_exact_slots": 56, + "native_equal": true + }, + "portable": { + "tokens": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "text": "한국의 수도는 **인천**입니다.<|im_end|>\n<|endoftext|>Human:", + "readback_exact_slots": 56, + "native_equal": true + } + }, + "importer_logits_exact": true + } +] From d4b6fe6ba764a43ec66538e448cff5eb98220965 Mon Sep 17 00:00:00 2001 From: gspark Date: Fri, 23 Oct 2026 16:02:29 +0900 Subject: [PATCH 2/6] perf: remove Qwen3 device-stack bottleneck and validate HTTP PD (#199) --- opt_prime/examples/pd/qwen3_rngd/README.md | 53 +- .../pd/qwen3_rngd/SERVING_EXPERIMENT.md | 61 ++ .../examples/pd/qwen3_rngd/bench_export.py | 52 ++ .../examples/pd/qwen3_rngd/bench_http.py | 68 ++ .../examples/pd/qwen3_rngd/bench_stream.py | 74 ++ opt_prime/examples/pd/qwen3_rngd/prefill.py | 5 +- .../examples/pd/qwen3_rngd/run_prefill.py | 2 +- opt_prime/examples/pd/qwen3_rngd/serve.py | 100 +++ .../qwen3_197_export_profile.json | 155 ++++ .../serving_results/qwen3_197_profile.json | 614 ++++++++++++++++ .../serving_results/qwen3_199_export_ab.json | 170 +++++ .../serving_results/qwen3_199_http_atom.json | 665 ++++++++++++++++++ .../qwen3_199_http_baseline.json | 665 ++++++++++++++++++ .../serving_results/qwen3_199_http_pd.json | 665 ++++++++++++++++++ .../qwen3_199_stream_atom.json | 97 +++ .../qwen3_199_stream_baseline.json | 97 +++ .../serving_results/qwen3_199_stream_pd.json | 97 +++ .../examples/pd/qwen3_rngd/test_worker.py | 48 ++ opt_prime/examples/pd/qwen3_rngd/worker.py | 121 ++++ .../examples/pd/qwen3_rngd/worker_python.sh | 9 + 20 files changed, 3812 insertions(+), 6 deletions(-) create mode 100644 opt_prime/examples/pd/qwen3_rngd/SERVING_EXPERIMENT.md create mode 100644 opt_prime/examples/pd/qwen3_rngd/bench_export.py create mode 100644 opt_prime/examples/pd/qwen3_rngd/bench_http.py create mode 100644 opt_prime/examples/pd/qwen3_rngd/bench_stream.py create mode 100644 opt_prime/examples/pd/qwen3_rngd/serve.py create mode 100644 opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_197_export_profile.json create mode 100644 opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_197_profile.json create mode 100644 opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_export_ab.json create mode 100644 opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_http_atom.json create mode 100644 opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_http_baseline.json create mode 100644 opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_http_pd.json create mode 100644 opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_stream_atom.json create mode 100644 opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_stream_baseline.json create mode 100644 opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_stream_pd.json create mode 100644 opt_prime/examples/pd/qwen3_rngd/test_worker.py create mode 100644 opt_prime/examples/pd/qwen3_rngd/worker.py create mode 100755 opt_prime/examples/pd/qwen3_rngd/worker_python.sh diff --git a/opt_prime/examples/pd/qwen3_rngd/README.md b/opt_prime/examples/pd/qwen3_rngd/README.md index 4f98ba0d..6c6c8f4e 100644 --- a/opt_prime/examples/pd/qwen3_rngd/README.md +++ b/opt_prime/examples/pd/qwen3_rngd/README.md @@ -27,7 +27,7 @@ python3 test_spec.py compiles/loads its own B1/context512/3KV-block artifact under qwen3-197-atom, compares CPU FP32 prefill, native ATOM prefill and imported RNGD KV, and writes qwen3_197_atom.json. It uses both the existing and portable importers and reads back -every imported slot. These scripts run a finite fixture, not an HTTP service. +every imported slot. These two scripts run a finite fixture; the experimental HTTP adapter is described below. ## Hardware evidence (2026-10-23) @@ -58,6 +58,53 @@ semantics; hardware records are essential evidence beyond those tests. ## Limits Other sizes, longer prompts, concurrent requests, prefix reuse, cancellation and -production recovery/lifetime behavior are unvalidated. The handoff has not been -wired into npu_pd_bench/serve_batched. Keep model-specific math in this prefiller; +production recovery/lifetime behavior are unvalidated. The handoff is exposed by the explicit experimental `serve.py` adapter below; +it is not automatically registered in npu_pd_bench/serve_batched. Keep model-specific math in this prefiller; the portable56-slot import succeeded without communication-library changes. + + +## Experimental HTTP adapter and export improvement (#199) + +`serve.py` reuses the existing optimus-rm `SubprocessPrefillWorker`, ATOM batcher, +`BatchedService` and `BatchedOwner`. `worker_python.sh` redirects only the expected +prefill worker module launch to `worker.py`; model-specific math stays in +`prefill.py`. This is an explicit experiment requiring the existing optimus-rm +runtime on PYTHONPATH, not a new production backend in this checkout. + +Place PR195's `furiosa_prefill_python.sh` alongside `worker_python.sh` and use its +single-card allocation/bootstrap instructions. Keep the task's own compiled +artifact cache and validated interpreters. The HTTP listener binds only loopback. +The service is fixed to Qwen3-0.6B, B1/context512/3KV blocks, no prefix caching. +Prompts above `--width` (default128) are rejected before worker submission. Decode +requests may queue; only one lane executes. SIGTERM drains queued work before +closing the worker and slab. Disconnect cancellation and fault recovery have not +been hardware-validated in this experiment. + +```bash +python3 -m unittest discover -s . -p 'test_*.py' +# In the writable scratch directory with the validated fixture/artifacts: +"$ATOM_PYTHON" check_atom_container.py serve.py --cache-dir "$PWD/qwen3-197-atom" +# Another process in the same allocated Pod: +"$ATOM_PYTHON" bench_http.py --name pd +"$ATOM_PYTHON" bench_stream.py --name pd +# Stop/drain the service, then restart with --local-prefill for the same ATOM-only baseline. +``` + +The export fix replaces device-side `torch.stack(...).cpu()` with per-layer +`.cpu()` followed by CPU stacking. The device graph and width remain unchanged. +To reproduce the alternating A/B, save the old implementation in the scratch +working directory (not over the new prefiller): + +```bash +git show 353d15090aa7908e0bb2ea5422f047e59ea9273d:opt_prime/examples/pd/qwen3_rngd/prefill.py > prefill_baseline.py +./furiosa_prefill_python.sh -m bench_export +``` + +Measured warm prefill: 728.435→55.823ms mean (nine pairs); all twelve paired K,V +and full-logit comparisons exact. Detailed serving results and limitations are +in `SERVING_EXPERIMENT.md` and `serving_results/`. The old roughly719ms measurement +above is historical, before this export fix. Width32/64 were also measured but +changed numerical values, so the verified improvement retains width128. + +`safe_open` must be iterated through `.keys()` in this SDK environment; the +specific lint exemption preserves that behavior. diff --git a/opt_prime/examples/pd/qwen3_rngd/SERVING_EXPERIMENT.md b/opt_prime/examples/pd/qwen3_rngd/SERVING_EXPERIMENT.md new file mode 100644 index 00000000..dbfb3bf0 --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/SERVING_EXPERIMENT.md @@ -0,0 +1,61 @@ +# Qwen3 RNGD → ATOM: host stacking and experimental HTTP serving + +- **Date**: 2026-10-23 +- **Task**: Qwen3 serving and export profiling (aicomp #199) +- **Host / device**: RNGD+ATOM host, dedicated single-card device-plugin Pod; Furiosa 2026.4 fusion4/Mesh2; ATOM rebel-compiler 0.11.0, optimum-rbln 0.11.0.post1, torch 2.11.0+cpu +- **Commit**: baseline 353d15090aa7908e0bb2ea5422f047e59ea9273d; experiment branch exp/199-qwen3-serving (56d9056 plus working changes before final commit) + +## Question + +Is the roughly 719 ms Qwen3 research prefill dominated by model computation or KV materialization, and does its improvement survive the existing batched HTTP service? + +## Setup + +Checkpoint Qwen/Qwen3-0.6B revision c1899de289a04d12100db370d81485cdf75e47ca. Three fixed chat prompts, thinking disabled, 19/19/22 tokens, fixed 16 output tokens for parity diagnostics. RNGD width128, 28 layers, 8 KV heads, dimension128. ATOM own B1/context512/3KV-block artifact from the previous experiment. Prefix caching disabled; B1 serializes three concurrent requests through the existing queue. + +Baseline stacks each K/V tensor on RNGD before copying. Improvement copies each layer to CPU and stacks there; model math, widths and sampler unchanged. Existing SubprocessPrefillWorker, AtomRblnEngine, BatchedOwner and HTTP handlers are reused through an explicit experimental launcher. No shared SDK files or other workloads changed. Host-mediated KV, no DMA or producer overlap. + +## Command + +Use PR195 isolated-container environment and bootstrap; working directory contains the Qwen3 example files and the previous trusted fixture. Set HOME to the SDK owner's home, offline HF cache, OMP_NUM_THREADS=4, MKL_NUM_THREADS=4, RBLN_DEVICES=0, RBLN_NPUS_PER_DEVICE=1, and PYTHONPATH to the existing optimus-rm, rngd_pd and hetero_p2p sources. FURIOSA_PYTHON and ATOM_PYTHON select the previously validated interpreters. + +```bash +# From the checkout, save the exact pre-change implementation into the scratch directory: +git show 353d15090aa7908e0bb2ea5422f047e59ea9273d:opt_prime/examples/pd/qwen3_rngd/prefill.py > prefill_baseline.py +./furiosa_prefill_python.sh -m bench_export +# Service on a dedicated Pod, loopback only. Baseline adds --local-prefill. +"$ATOM_PYTHON" check_atom_container.py serve.py --cache-dir "$PWD/qwen3-197-atom" +"$ATOM_PYTHON" bench_http.py --name pd +"$ATOM_PYTHON" bench_stream.py --name pd +``` + +A/B export alternates baseline/optimized order over four rounds and three prompts; round0 excluded from latency means. Whole K,V,logits are compared bit-for-bit each pair. HTTP harness performs twelve sequential requests, three concurrent requests, an over-capacity HTTP400 check and a successful follow-up. Streaming harness performs nine requests plus EOS termination; first round excluded from warm means. + +## Results + +- Alternating A/B: baseline 728.435 ms mean (688.581–829.348), host stacking 55.823 ms (44.516–67.473), nine warm pairs; 12/12 complete K,V,logit comparisons exact including first round. +- Phase diagnostic: device stack/export roughly 650 ms versus per-layer CPU export/host stack roughly 11 ms. Layer execution plus final hidden materialization roughly 5 ms; CPU output head roughly 26–40 ms. These are diagnostic wall times with fences, not isolated DMA bandwidth. +- Width32/64 reduced the original stack cost but changed KV/logits numerically; not adopted. Width128 stays unchanged. +- Optimized PD HTTP: 16/16 full output sequences equal ATOM-only; 16 remote prefills, zero local fallback. Warm sequential nonstream mean201.439 ms vs ATOM121.831 ms. +- Warm streaming (six requests): optimized PD TTFT69.567 ms/E2E167.535 ms; ATOM TTFT15.883 ms/E2E128.254 ms. +- Oversize129-token prompt rejectedHTTP400 before device work; next request succeeds. EOS termination passes both routes. Fixed-length diagnostics intentionally ignoreEOS and are not quality tests. + +Failures retained: first profiling script attempted to iterate safe_open directly (TypeError); changed to .keys(), with targeted SIM118 exemption. Initial experimental worker launch used a relative executable path and failed before worker startup; changed to an absolute sibling path. Parent resource_tracker cleaned the abandoned slab. No shared package modified. + +Raw logs/results: analysis/local_prefill/native_dma/general/serving199/. Exact local launch scripts retained with this experiment's artifacts; public reproduction uses role/environment variable names. + +### Pre-change HTTP baseline and final comparison + +| Route | Warm streaming TTFT (ms) | Warm streaming E2E,16 outputs (ms) | Warm nonstream E2E (ms) | +|---|---:|---:|---:| +| PD, device-stack baseline |755.042|905.176|887.234| +| PD, host-stack improvement |69.567|167.535|201.439| +| ATOM-only |15.883|128.254|121.831| + +Streaming means use six requests after excluding the first round; nonstream means use nine requests after excluding the first round. Routes ran sequentially (optimized PD, ATOM, old PD), not a randomized serving trial. No quiet-host guarantee or confidence intervals; the alternating in-process A/B supports the export mechanism independently. All16 nonstream token sequences match across all three routes. All three pass oversized-request rejection/recovery and EOS termination. The pre-change service uses exactly the old prefiller file in the same task-owned scratch directory, restored to the improved file afterwards. + +The improved PD first-token gap to ATOM is53.684ms; E2E gap39.281ms in this small streaming sample. Source export and CPU LM head now merit optimization; no producer-side overlap was added. Server drains were successful and the dedicated validation namespace was deleted; other workloads untouched. + +## Conclusion + +The largest original delay was device-side KV stacking/materialization, not inherent PD disaggregation or transformer-layer compute. Moving the stack to CPU yields about13× prefill speedup without numerical changes and enables the existing HTTP service. ATOM-only remains faster for these short B1 requests; this does not establish native Furiosa parity, throughput at high concurrency, or an advantage for PD. Remaining work: output-head cost, ATOM import/IPC and longer prompts; source-streaming overlap and KONI HTTP integration remain separate validations. diff --git a/opt_prime/examples/pd/qwen3_rngd/bench_export.py b/opt_prime/examples/pd/qwen3_rngd/bench_export.py new file mode 100644 index 00000000..1eeedf81 --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/bench_export.py @@ -0,0 +1,52 @@ +import json +import time +from pathlib import Path + +import torch +from huggingface_hub import snapshot_download +from prefill import Prefill +from safetensors import safe_open + +path = Path(snapshot_download("Qwen/Qwen3-0.6B", local_files_only=True)) +c = json.loads((path / "config.json").read_text()) +w = {} +for shard in path.glob("*.safetensors"): + with safe_open(shard, framework="pt") as f: + for k in f.keys(): # noqa: SIM118 - safe_open is not iterable + w[k] = f.get_tensor(k).float() +records = torch.load("qwen3_197_kv.pt", weights_only=True) +from prefill_baseline import Prefill as Baseline + +rows = [] +e = Prefill(c, w, width=128, chip=0) +for repeat in range(4): + for i, r in enumerate(records): + outputs = {} + times = {} + for name in ( + ["baseline", "host_stack"] + if repeat % 2 == 0 + else ["host_stack", "baseline"] + ): + t = time.perf_counter() + outputs[name] = ( + Baseline.prefill(e, r["ids"]) + if name == "baseline" + else e.prefill(r["ids"]) + ) + times[name] = time.perf_counter() - t + exact = [ + torch.equal(a, b) + for a, b in zip(outputs["baseline"], outputs["host_stack"]) + ] + assert all(exact), exact + row = { + "repeat": repeat, + "prompt": i, + "n": len(r["ids"]), + "seconds": times, + "kv_logits_exact": exact, + } + rows.append(row) + print(json.dumps(row), flush=True) +Path("qwen3_199_export_ab.json").write_text(json.dumps(rows, indent=2) + "\n") diff --git a/opt_prime/examples/pd/qwen3_rngd/bench_http.py b/opt_prime/examples/pd/qwen3_rngd/bench_http.py new file mode 100644 index 00000000..5d28d1fb --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/bench_http.py @@ -0,0 +1,68 @@ +import argparse +import concurrent.futures +import json +import time +import urllib.error +import urllib.request +from pathlib import Path + +import torch + +ap = argparse.ArgumentParser() +ap.add_argument("--name", required=True) +a = ap.parse_args() +base = "http://127.0.0.1:18197" +records = torch.load("qwen3_197_kv.pt", weights_only=True) +rows = [] + + +def request(i, repeat, extra=None): + body = { + "model": "Qwen/Qwen3-0.6B", + "prompt": records[i]["ids"], + "temperature": 0, + "max_tokens": 16, + "ignore_eos": True, + } + body.update(extra or {}) + req = urllib.request.Request( + base + "/v1/completions", + json.dumps(body).encode(), + headers={ + "Content-Type": "application/json", + "x-request-id": f"{a.name}-{repeat}-{i}", + }, + ) + t = time.perf_counter() + with urllib.request.urlopen(req, timeout=120) as r: + out = json.load(r) + row = { + "repeat": repeat, + "prompt": i, + "seconds": time.perf_counter() - t, + "response": out, + } + print(json.dumps(row), flush=True) + return row + + +for repeat in range(4): + for i in range(3): + rows.append(request(i, repeat)) +with concurrent.futures.ThreadPoolExecutor(max_workers=3) as pool: + rows.extend(pool.map(lambda i: request(i, 4), range(3))) +# Capacity must be rejected before submitting to the worker, then service must remain usable. +try: + request(0, 5, {"prompt": [1] * 129}) + raise AssertionError("oversize request unexpectedly accepted") +except urllib.error.HTTPError as e: + assert e.code == 400, e.code + rejected = json.loads(e.read()) +rows.append(request(0, 6)) +with urllib.request.urlopen(base + "/metrics") as r: + metrics = r.read().decode() +Path(f"qwen3_199_http_{a.name}.json").write_text( + json.dumps({"rows": rows, "oversize": rejected, "metrics": metrics}, indent=2) + + "\n" +) +print(metrics, flush=True) diff --git a/opt_prime/examples/pd/qwen3_rngd/bench_stream.py b/opt_prime/examples/pd/qwen3_rngd/bench_stream.py new file mode 100644 index 00000000..56818743 --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/bench_stream.py @@ -0,0 +1,74 @@ +import argparse +import json +import time +import urllib.request +from pathlib import Path + +import torch + +ap = argparse.ArgumentParser() +ap.add_argument("--name", required=True) +a = ap.parse_args() +records = torch.load("qwen3_197_kv.pt", weights_only=True) +rows = [] +for repeat in range(3): + for i, r in enumerate(records): + payload = { + "model": "Qwen/Qwen3-0.6B", + "prompt": r["ids"], + "max_tokens": 16, + "temperature": 0, + "ignore_eos": True, + "stream": True, + } + req = urllib.request.Request( + "http://127.0.0.1:18197/v1/completions", + json.dumps(payload).encode(), + headers={ + "Content-Type": "application/json", + "x-request-id": f"{a.name}-stream-{repeat}-{i}", + }, + ) + t = time.perf_counter() + first = None + done = False + chunks = [] + with urllib.request.urlopen(req, timeout=120) as f: + for line in f: + if not line.startswith(b"data: "): + continue + if line.strip() == b"data: [DONE]": + done = True + break + chunk = json.loads(line[6:]) + chunks.append(chunk) + if ( + chunk.get("choices") + and chunk["choices"][0].get("text") + and first is None + ): + first = time.perf_counter() - t + assert done and first is not None + row = { + "repeat": repeat, + "prompt": i, + "ttft_s": first, + "e2e_s": time.perf_counter() - t, + "text": "".join( + c["choices"][0].get("text", "") for c in chunks if c.get("choices") + ), + } + rows.append(row) + print(json.dumps(row), flush=True) +payload.update(stream=False, ignore_eos=False, prompt=records[0]["ids"]) +req = urllib.request.Request( + "http://127.0.0.1:18197/v1/completions", + json.dumps(payload).encode(), + headers={"Content-Type": "application/json", "x-request-id": a.name + "-eos"}, +) +with urllib.request.urlopen(req, timeout=120) as f: + eos = json.load(f) +assert eos["choices"][0]["finish_reason"] == "stop", eos +Path(f"qwen3_199_stream_{a.name}.json").write_text( + json.dumps({"rows": rows, "eos": eos}, indent=2) + "\n" +) diff --git a/opt_prime/examples/pd/qwen3_rngd/prefill.py b/opt_prime/examples/pd/qwen3_rngd/prefill.py index ad45b85f..0fc527d1 100644 --- a/opt_prime/examples/pd/qwen3_rngd/prefill.py +++ b/opt_prime/examples/pd/qwen3_rngd/prefill.py @@ -189,8 +189,9 @@ def prefill(self, tokens): values.append(kv[1].transpose(-1, -2)) sync(self.chip) n = len(tokens) - k = torch.stack(keys).cpu()[:, :, :, :n].transpose(-1, -2) - v = torch.stack(values).cpu()[:, :, :n] + # Host stacking avoids the expensive device-side concatenation path. + k = torch.stack([key.cpu() for key in keys])[:, :, :, :n].transpose(-1, -2) + v = torch.stack([value.cpu() for value in values])[:, :, :n] z = x.cpu()[n - 1].float() z = z * torch.rsqrt(z.square().mean() + self.s["rms_norm_eps"]) * self.norm return k, v, z @ self.head.T diff --git a/opt_prime/examples/pd/qwen3_rngd/run_prefill.py b/opt_prime/examples/pd/qwen3_rngd/run_prefill.py index 337fd4ed..90b53efe 100644 --- a/opt_prime/examples/pd/qwen3_rngd/run_prefill.py +++ b/opt_prime/examples/pd/qwen3_rngd/run_prefill.py @@ -14,7 +14,7 @@ w = {} for shard in sorted(path.glob("*.safetensors")): with safe_open(shard, framework="pt") as f: - for key in f: + for key in f.keys(): # noqa: SIM118 - safe_open is not iterable w[key] = f.get_tensor(key).float() e = Prefill(c, w, width=128, chip=0) print("READY", flush=True) diff --git a/opt_prime/examples/pd/qwen3_rngd/serve.py b/opt_prime/examples/pd/qwen3_rngd/serve.py new file mode 100644 index 00000000..f6ba6738 --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/serve.py @@ -0,0 +1,100 @@ +"""Experimental B1 Qwen3 HTTP service using existing optimus-rm ownership and batching.""" + +import argparse +import os +import signal +from pathlib import Path + +from opt_prime.accel.pd.pd_batching import SubprocessPrefillWorker +from opt_prime.accel.platforms.atom.engine import AtomRblnEngine +from opt_prime.accel.serve.batched import BatchedOwner, BatchedService +from opt_prime.accel.serve.llmd import StageError, serve_stage +from transformers import AutoTokenizer + + +class BoundedService(BatchedService): + def __init__(self, *args, prompt_capacity, **kwargs): + self.prompt_capacity = prompt_capacity + super().__init__(*args, **kwargs) + + def _request(self, rid, body, chat=False): + request, stops = super()._request(rid, body, chat) + if len(request.input_ids) > self.prompt_capacity: + raise StageError(400, "prompt exceeds compiled Qwen3 prefill width") + return request, stops + + +def main(): + ap = argparse.ArgumentParser(description=__doc__) + ap.add_argument("--port", type=int, default=18197) + ap.add_argument("--width", type=int, default=128) + ap.add_argument("--cache-dir", required=True) + ap.add_argument( + "--local-prefill", + action="store_true", + help="ATOM-only baseline using the same service", + ) + a = ap.parse_args() + devices = list(Path("/dev").glob("rbln[0-9]*")) + if len(devices) != 1: + raise ValueError("requires an isolated single-ATOM allocation") + mid = "Qwen/Qwen3-0.6B" + tok = AutoTokenizer.from_pretrained(mid) + engine = AtomRblnEngine( + devices=[int(devices[0].name[4:])], + max_seq_len=512, + batch_size=1, + kv_blocks=3, + cache_dir=a.cache_dir, + ) + worker = server = None + try: + engine.start(mid) + c = engine.model.config.get_text_config() + if not a.local_prefill: + worker = SubprocessPrefillWorker( + str(Path(__file__).resolve().with_name("worker_python.sh")), + ["--model", mid, "--width", str(a.width)], + slots=1, + layers=c.num_hidden_layers, + kv_heads=c.num_key_value_heads, + head_dim=c.head_dim, + max_context=512, + env=dict(os.environ), + ) + b = engine.batcher( + prefix_cache=False, prefill_worker=worker, local_prefill=a.local_prefill + ) + eos = engine.model.generation_config.eos_token_id + svc = BoundedService( + b, + prompt_capacity=a.width, + model=mid, + vocab_size=c.vocab_size, + max_output=128, + render=lambda t: tok.decode(t, skip_special_tokens=True), + tokenizer=tok, + eos_token_ids=tuple(eos) if isinstance(eos, (tuple, list)) else (eos,), + ) + owner = BatchedOwner(svc) + + # Drain in-flight requests before releasing the shared-memory slab and devices. + def stop(*_): + owner.submit_async("stop") + + signal.signal(signal.SIGTERM, stop) + signal.signal(signal.SIGINT, stop) + server, _ = serve_stage(owner, "decode", a.port) + print("HTTP_READY", flush=True) + owner.run() + finally: + if server is not None: + server.shutdown() + server.server_close() + if worker is not None: + worker.close() + engine.close() + + +if __name__ == "__main__": + main() diff --git a/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_197_export_profile.json b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_197_export_profile.json new file mode 100644 index 00000000..209ee0fc --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_197_export_profile.json @@ -0,0 +1,155 @@ +[ + { + "width": 128, + "repeat": 0, + "prompt": 0, + "n": 19, + "input_s": 0.0006219040369614959, + "layers_and_hidden_s": 0.004504419979639351, + "kv_export_s": 0.01061674696393311, + "hidden_export_s": 0.0002370449947193265, + "head_s": 0.030969161074608564, + "total_s": 0.04694927704986185, + "first": 785, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 0, + "prompt": 1, + "n": 19, + "input_s": 0.000629443908110261, + "layers_and_hidden_s": 0.00464651407673955, + "kv_export_s": 0.010553185013122857, + "hidden_export_s": 0.00026791589334607124, + "head_s": 0.03083170810714364, + "total_s": 0.04692876699846238, + "first": 17, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 0, + "prompt": 2, + "n": 22, + "input_s": 0.0005821130471304059, + "layers_and_hidden_s": 0.004609663039445877, + "kv_export_s": 0.011402474017813802, + "hidden_export_s": 0.0002546359319239855, + "head_s": 0.030859099002555013, + "total_s": 0.04770798503886908, + "first": 23573, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 1, + "prompt": 0, + "n": 19, + "input_s": 0.0006276339991018176, + "layers_and_hidden_s": 0.004648193949833512, + "kv_export_s": 0.010822981013916433, + "hidden_export_s": 0.00021584494970738888, + "head_s": 0.03149873309303075, + "total_s": 0.0478133870055899, + "first": 785, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 1, + "prompt": 1, + "n": 19, + "input_s": 0.0008148879278451204, + "layers_and_hidden_s": 0.004738376010209322, + "kv_export_s": 0.011202770052477717, + "hidden_export_s": 0.0002653059782460332, + "head_s": 0.031153884949162602, + "total_s": 0.048175224917940795, + "first": 17, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 1, + "prompt": 2, + "n": 22, + "input_s": 0.0005853730253875256, + "layers_and_hidden_s": 0.0046637540217489, + "kv_export_s": 0.011821603984571993, + "hidden_export_s": 0.00026384496595710516, + "head_s": 0.030933211091905832, + "total_s": 0.04826778708957136, + "first": 23573, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 2, + "prompt": 0, + "n": 19, + "input_s": 0.0007110660662874579, + "layers_and_hidden_s": 0.0046412929659709334, + "kv_export_s": 0.011320922989398241, + "hidden_export_s": 0.00027665600646287203, + "head_s": 0.03126502805389464, + "total_s": 0.04821496608201414, + "first": 785, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 2, + "prompt": 1, + "n": 19, + "input_s": 0.0008229190716519952, + "layers_and_hidden_s": 0.004791516927070916, + "kv_export_s": 0.011187429074198008, + "hidden_export_s": 0.00023271492682397366, + "head_s": 0.03093738097231835, + "total_s": 0.04797196097206324, + "first": 17, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 2, + "prompt": 2, + "n": 22, + "input_s": 0.0006468149367719889, + "layers_and_hidden_s": 0.00464962306432426, + "kv_export_s": 0.011294952011667192, + "hidden_export_s": 0.00025847600772976875, + "head_s": 0.031100824009627104, + "total_s": 0.04795069003012031, + "first": 23573, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + } +] diff --git a/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_197_profile.json b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_197_profile.json new file mode 100644 index 00000000..a07b921b --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_197_profile.json @@ -0,0 +1,614 @@ +[ + { + "width": 128, + "repeat": 0, + "prompt": 0, + "n": 19, + "input_s": 0.0008347210241481662, + "layers_s": 0.004783479031175375, + "kv_export_s": 0.6512959250248969, + "hidden_export_s": 0.0005497429519891739, + "head_s": 0.37443894799798727, + "total_s": 1.0319028160301968, + "first": 785, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 0, + "prompt": 1, + "n": 19, + "input_s": 0.0008467710576951504, + "layers_s": 0.004424049984663725, + "kv_export_s": 0.6519521150039509, + "hidden_export_s": 0.0005255630239844322, + "head_s": 0.03527562797535211, + "total_s": 0.6930241270456463, + "first": 17, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 0, + "prompt": 2, + "n": 22, + "input_s": 0.001019895076751709, + "layers_s": 0.00468721694778651, + "kv_export_s": 0.6547371220076457, + "hidden_export_s": 0.0005087120225653052, + "head_s": 0.03990906197577715, + "total_s": 0.7008620080305263, + "first": 23573, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 1, + "prompt": 0, + "n": 19, + "input_s": 0.0009103730553761125, + "layers_s": 0.004774917964823544, + "kv_export_s": 0.6529824699973688, + "hidden_export_s": 0.0004310410004109144, + "head_s": 0.035557662951759994, + "total_s": 0.6946564649697393, + "first": 785, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 1, + "prompt": 1, + "n": 19, + "input_s": 0.0008877119980752468, + "layers_s": 0.004763347911648452, + "kv_export_s": 0.6488819480873644, + "hidden_export_s": 0.00042821094393730164, + "head_s": 0.03430014196783304, + "total_s": 0.6892613609088585, + "first": 17, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 1, + "prompt": 2, + "n": 22, + "input_s": 0.0010040350025519729, + "layers_s": 0.006587793934158981, + "kv_export_s": 0.6493192040361464, + "hidden_export_s": 0.00040609994903206825, + "head_s": 0.0340559349860996, + "total_s": 0.691373067907989, + "first": 23573, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 2, + "prompt": 0, + "n": 19, + "input_s": 0.0008531209314242005, + "layers_s": 0.004732787027023733, + "kv_export_s": 0.6505081260111183, + "hidden_export_s": 0.000438411021605134, + "head_s": 0.036465034005232155, + "total_s": 0.6929974789964035, + "first": 785, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 2, + "prompt": 1, + "n": 19, + "input_s": 0.0008169809589162469, + "layers_s": 0.004747227067127824, + "kv_export_s": 0.6521612888900563, + "hidden_export_s": 0.0004985620034858584, + "head_s": 0.038552755024284124, + "total_s": 0.6967768139438704, + "first": 17, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 2, + "prompt": 2, + "n": 22, + "input_s": 0.0008278510067611933, + "layers_s": 0.004681735998019576, + "kv_export_s": 0.6527199470438063, + "hidden_export_s": 0.00040916004218161106, + "head_s": 0.03571245400235057, + "total_s": 0.6943511480931193, + "first": 23573, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 3, + "prompt": 0, + "n": 19, + "input_s": 0.0008854119805619121, + "layers_s": 0.004704165970906615, + "kv_export_s": 0.6515327190281823, + "hidden_export_s": 0.0003407580079510808, + "head_s": 0.03277586097829044, + "total_s": 0.6902389159658924, + "first": 785, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 3, + "prompt": 1, + "n": 19, + "input_s": 0.0007401379989460111, + "layers_s": 0.004589613992720842, + "kv_export_s": 0.6485086249886081, + "hidden_export_s": 0.0007659790571779013, + "head_s": 0.03104247699957341, + "total_s": 0.6856468330370262, + "first": 17, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 128, + "repeat": 3, + "prompt": 2, + "n": 22, + "input_s": 0.0006058050785213709, + "layers_s": 0.005066694924607873, + "kv_export_s": 0.6487668190384284, + "hidden_export_s": 0.0004536010092124343, + "head_s": 0.05140661005862057, + "total_s": 0.7062995301093906, + "first": 23573, + "first_equal": true, + "k_exact": true, + "v_exact": true, + "logits_exact": true + }, + { + "width": 32, + "repeat": 0, + "prompt": 0, + "n": 19, + "input_s": 0.0005263829370960593, + "layers_s": 0.004423127043992281, + "kv_export_s": 0.16992694593500346, + "hidden_export_s": 0.00036647904198616743, + "head_s": 0.03533839003648609, + "total_s": 0.21058132499456406, + "first": 785, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 32, + "repeat": 0, + "prompt": 1, + "n": 19, + "input_s": 0.0007607080042362213, + "layers_s": 0.004749885993078351, + "kv_export_s": 0.16571163292974234, + "hidden_export_s": 0.00021845509763807058, + "head_s": 0.026356630958616734, + "total_s": 0.1977973129833117, + "first": 17, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 32, + "repeat": 0, + "prompt": 2, + "n": 22, + "input_s": 0.0006349849281832576, + "layers_s": 0.0031692180782556534, + "kv_export_s": 0.1671277869027108, + "hidden_export_s": 0.0004335810663178563, + "head_s": 0.03523491695523262, + "total_s": 0.20660048793070018, + "first": 23573, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 32, + "repeat": 1, + "prompt": 0, + "n": 19, + "input_s": 0.0007785089546814561, + "layers_s": 0.0048694879515096545, + "kv_export_s": 0.16958659701049328, + "hidden_export_s": 0.0004529510624706745, + "head_s": 0.03535957098938525, + "total_s": 0.2110471159685403, + "first": 785, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 32, + "repeat": 1, + "prompt": 1, + "n": 19, + "input_s": 0.0008163589518517256, + "layers_s": 0.004844957962632179, + "kv_export_s": 0.1666239449987188, + "hidden_export_s": 0.0002609359798952937, + "head_s": 0.026306050014682114, + "total_s": 0.1988522479077801, + "first": 17, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 32, + "repeat": 1, + "prompt": 2, + "n": 22, + "input_s": 0.0006441060686483979, + "layers_s": 0.0036030180053785443, + "kv_export_s": 0.17069922992959619, + "hidden_export_s": 0.00020756502635776997, + "head_s": 0.026094004977494478, + "total_s": 0.20124792400747538, + "first": 23573, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 32, + "repeat": 2, + "prompt": 0, + "n": 19, + "input_s": 0.000636775977909565, + "layers_s": 0.003132786019705236, + "kv_export_s": 0.16562453703954816, + "hidden_export_s": 0.00031911791302263737, + "head_s": 0.026435062056407332, + "total_s": 0.19614827900659293, + "first": 785, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 32, + "repeat": 2, + "prompt": 1, + "n": 19, + "input_s": 0.00066114601213485, + "layers_s": 0.0031617670319974422, + "kv_export_s": 0.16564765700604767, + "hidden_export_s": 0.0002888169838115573, + "head_s": 0.02611203503329307, + "total_s": 0.19587142206728458, + "first": 17, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 32, + "repeat": 2, + "prompt": 2, + "n": 22, + "input_s": 0.0006788169266656041, + "layers_s": 0.003140106098726392, + "kv_export_s": 0.16600926697719842, + "hidden_export_s": 0.0002662360202521086, + "head_s": 0.025786506943404675, + "total_s": 0.1958809329662472, + "first": 23573, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 32, + "repeat": 3, + "prompt": 0, + "n": 19, + "input_s": 0.000706756953150034, + "layers_s": 0.0031706970185041428, + "kv_export_s": 0.1659600349375978, + "hidden_export_s": 0.0002899870742112398, + "head_s": 0.02585060801357031, + "total_s": 0.19597808399703354, + "first": 785, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 32, + "repeat": 3, + "prompt": 1, + "n": 19, + "input_s": 0.0006827970501035452, + "layers_s": 0.0031336660031229258, + "kv_export_s": 0.16570535500068218, + "hidden_export_s": 0.000291517935693264, + "head_s": 0.026122514042071998, + "total_s": 0.1959358500316739, + "first": 17, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 32, + "repeat": 3, + "prompt": 2, + "n": 22, + "input_s": 0.000790458987466991, + "layers_s": 0.0031246660510078073, + "kv_export_s": 0.16592418996151537, + "hidden_export_s": 0.0003598789917305112, + "head_s": 0.02591610001400113, + "total_s": 0.1961152940057218, + "first": 23573, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 64, + "repeat": 0, + "prompt": 0, + "n": 19, + "input_s": 0.0006128239911049604, + "layers_s": 0.0042561020236462355, + "kv_export_s": 0.3358758300310001, + "hidden_export_s": 0.0003723789704963565, + "head_s": 0.03500391496345401, + "total_s": 0.37612104997970164, + "first": 785, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 64, + "repeat": 0, + "prompt": 1, + "n": 19, + "input_s": 0.0006625560345128179, + "layers_s": 0.004000125918537378, + "kv_export_s": 0.3294087910326198, + "hidden_export_s": 0.00036420905962586403, + "head_s": 0.03649088891688734, + "total_s": 0.3709265709621832, + "first": 17, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 64, + "repeat": 0, + "prompt": 2, + "n": 22, + "input_s": 0.0008460700046271086, + "layers_s": 0.004636150086298585, + "kv_export_s": 0.33325277094263583, + "hidden_export_s": 0.0006204149685800076, + "head_s": 0.041220832034014165, + "total_s": 0.3805762380361557, + "first": 23573, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 64, + "repeat": 1, + "prompt": 0, + "n": 19, + "input_s": 0.0008103089639917016, + "layers_s": 0.00492568698246032, + "kv_export_s": 0.33192863909062, + "hidden_export_s": 0.0005238029407337308, + "head_s": 0.039801607956178486, + "total_s": 0.3779900459339842, + "first": 785, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 64, + "repeat": 1, + "prompt": 1, + "n": 19, + "input_s": 0.0009044409962370992, + "layers_s": 0.0047244729939848185, + "kv_export_s": 0.33201387303415686, + "hidden_export_s": 0.0004423409700393677, + "head_s": 0.03943839902058244, + "total_s": 0.3775235270150006, + "first": 17, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 64, + "repeat": 1, + "prompt": 2, + "n": 22, + "input_s": 0.0008868309669196606, + "layers_s": 0.004680142039433122, + "kv_export_s": 0.33221081795636564, + "hidden_export_s": 0.0004603910492733121, + "head_s": 0.03923906502313912, + "total_s": 0.37747724703513086, + "first": 23573, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 64, + "repeat": 2, + "prompt": 0, + "n": 19, + "input_s": 0.0009344520512968302, + "layers_s": 0.004740903037600219, + "kv_export_s": 0.33104831899981946, + "hidden_export_s": 0.0005142219597473741, + "head_s": 0.03856701694894582, + "total_s": 0.3758049129974097, + "first": 785, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 64, + "repeat": 2, + "prompt": 1, + "n": 19, + "input_s": 0.0009566129883751273, + "layers_s": 0.004750523017719388, + "kv_export_s": 0.33074570598546416, + "hidden_export_s": 0.00037297909148037434, + "head_s": 0.038764331955462694, + "total_s": 0.37559015303850174, + "first": 17, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 64, + "repeat": 2, + "prompt": 2, + "n": 22, + "input_s": 0.0009333220077678561, + "layers_s": 0.006150125991553068, + "kv_export_s": 0.33139683201443404, + "hidden_export_s": 0.00043998996261507273, + "head_s": 0.03648957808036357, + "total_s": 0.3754098480567336, + "first": 23573, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 64, + "repeat": 3, + "prompt": 0, + "n": 19, + "input_s": 0.000947442022152245, + "layers_s": 0.0057815080508589745, + "kv_export_s": 0.3326019949745387, + "hidden_export_s": 0.00048702198546379805, + "head_s": 0.039825235959142447, + "total_s": 0.37964320299215615, + "first": 785, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 64, + "repeat": 3, + "prompt": 1, + "n": 19, + "input_s": 0.0008422699756920338, + "layers_s": 0.006085054948925972, + "kv_export_s": 0.3279253620421514, + "hidden_export_s": 0.00024803599808365107, + "head_s": 0.02587737503927201, + "total_s": 0.36097809800412506, + "first": 17, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + }, + { + "width": 64, + "repeat": 3, + "prompt": 2, + "n": 22, + "input_s": 0.000702137011103332, + "layers_s": 0.003383349976502359, + "kv_export_s": 0.3301020449725911, + "hidden_export_s": 0.000433659995906055, + "head_s": 0.039141769986599684, + "total_s": 0.37376296194270253, + "first": 23573, + "first_equal": true, + "k_exact": false, + "v_exact": false, + "logits_exact": false + } +] diff --git a/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_export_ab.json b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_export_ab.json new file mode 100644 index 00000000..a80f26f4 --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_export_ab.json @@ -0,0 +1,170 @@ +[ + { + "repeat": 0, + "prompt": 0, + "n": 19, + "seconds": { + "baseline": 0.6998434429988265, + "host_stack": 0.051616474986076355 + }, + "kv_logits_exact": [ + true, + true, + true + ] + }, + { + "repeat": 0, + "prompt": 1, + "n": 19, + "seconds": { + "baseline": 0.706331770052202, + "host_stack": 0.05393066303804517 + }, + "kv_logits_exact": [ + true, + true, + true + ] + }, + { + "repeat": 0, + "prompt": 2, + "n": 22, + "seconds": { + "baseline": 0.6959986350266263, + "host_stack": 0.055388121982105076 + }, + "kv_logits_exact": [ + true, + true, + true + ] + }, + { + "repeat": 1, + "prompt": 0, + "n": 19, + "seconds": { + "host_stack": 0.05561624700203538, + "baseline": 0.7183967599412426 + }, + "kv_logits_exact": [ + true, + true, + true + ] + }, + { + "repeat": 1, + "prompt": 1, + "n": 19, + "seconds": { + "host_stack": 0.05398259300272912, + "baseline": 0.6937722340226173 + }, + "kv_logits_exact": [ + true, + true, + true + ] + }, + { + "repeat": 1, + "prompt": 2, + "n": 22, + "seconds": { + "host_stack": 0.05680075008422136, + "baseline": 0.6885809010127559 + }, + "kv_logits_exact": [ + true, + true, + true + ] + }, + { + "repeat": 2, + "prompt": 0, + "n": 19, + "seconds": { + "baseline": 0.7037170620169491, + "host_stack": 0.0628558739554137 + }, + "kv_logits_exact": [ + true, + true, + true + ] + }, + { + "repeat": 2, + "prompt": 1, + "n": 19, + "seconds": { + "baseline": 0.7075157429790124, + "host_stack": 0.06747303693555295 + }, + "kv_logits_exact": [ + true, + true, + true + ] + }, + { + "repeat": 2, + "prompt": 2, + "n": 22, + "seconds": { + "baseline": 0.8293483580928296, + "host_stack": 0.04779647197574377 + }, + "kv_logits_exact": [ + true, + true, + true + ] + }, + { + "repeat": 3, + "prompt": 0, + "n": 19, + "seconds": { + "host_stack": 0.0541782429208979, + "baseline": 0.6991903349990025 + }, + "kv_logits_exact": [ + true, + true, + true + ] + }, + { + "repeat": 3, + "prompt": 1, + "n": 19, + "seconds": { + "host_stack": 0.059191674925386906, + "baseline": 0.8156559279887006 + }, + "kv_logits_exact": [ + true, + true, + true + ] + }, + { + "repeat": 3, + "prompt": 2, + "n": 22, + "seconds": { + "host_stack": 0.04451628401875496, + "baseline": 0.6997385469730943 + }, + "kv_logits_exact": [ + true, + true, + true + ] + } +] diff --git a/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_http_atom.json b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_http_atom.json new file mode 100644 index 00000000..8b6a7d87 --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_http_atom.json @@ -0,0 +1,665 @@ +{ + "rows": [ + { + "repeat": 0, + "prompt": 0, + "seconds": 0.22145032801199704, + "response": { + "id": "atom-0-0", + "object": "text_completion", + "created": 1792738562, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 0, + "prompt": 1, + "seconds": 0.12278760096523911, + "response": { + "id": "atom-0-1", + "object": "text_completion", + "created": 1792738563, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 0, + "prompt": 2, + "seconds": 0.11882712109945714, + "response": { + "id": "atom-0-2", + "object": "text_completion", + "created": 1792738563, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 1, + "prompt": 0, + "seconds": 0.11997814103960991, + "response": { + "id": "atom-1-0", + "object": "text_completion", + "created": 1792738563, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 1, + "prompt": 1, + "seconds": 0.1597187090665102, + "response": { + "id": "atom-1-1", + "object": "text_completion", + "created": 1792738563, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 1, + "prompt": 2, + "seconds": 0.11627412505913526, + "response": { + "id": "atom-1-2", + "object": "text_completion", + "created": 1792738563, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 2, + "prompt": 0, + "seconds": 0.11632456595543772, + "response": { + "id": "atom-2-0", + "object": "text_completion", + "created": 1792738563, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 2, + "prompt": 1, + "seconds": 0.11670319305267185, + "response": { + "id": "atom-2-1", + "object": "text_completion", + "created": 1792738563, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 2, + "prompt": 2, + "seconds": 0.11645854904782027, + "response": { + "id": "atom-2-2", + "object": "text_completion", + "created": 1792738563, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 3, + "prompt": 0, + "seconds": 0.11751408805139363, + "response": { + "id": "atom-3-0", + "object": "text_completion", + "created": 1792738564, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 3, + "prompt": 1, + "seconds": 0.11955268203746527, + "response": { + "id": "atom-3-1", + "object": "text_completion", + "created": 1792738564, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 3, + "prompt": 2, + "seconds": 0.11395426304079592, + "response": { + "id": "atom-3-2", + "object": "text_completion", + "created": 1792738564, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 4, + "prompt": 0, + "seconds": 0.11710813897661865, + "response": { + "id": "atom-4-0", + "object": "text_completion", + "created": 1792738564, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 4, + "prompt": 1, + "seconds": 0.230754796997644, + "response": { + "id": "atom-4-1", + "object": "text_completion", + "created": 1792738564, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 4, + "prompt": 2, + "seconds": 0.34350392897613347, + "response": { + "id": "atom-4-2", + "object": "text_completion", + "created": 1792738564, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 6, + "prompt": 0, + "seconds": 0.1139481239952147, + "response": { + "id": "atom-6-0", + "object": "text_completion", + "created": 1792738564, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + } + ], + "oversize": { + "error": "prompt exceeds compiled Qwen3 prefill width", + "retryable": false + }, + "metrics": "# HELP vllm:num_requests_running Requests executing on the stage.\n# TYPE vllm:num_requests_running gauge\nvllm:num_requests_running{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:num_requests_waiting Requests queued for the stage owner.\n# TYPE vllm:num_requests_waiting gauge\nvllm:num_requests_waiting{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:kv_cache_usage_perc Occupied fraction of the stage's KV lanes (1 = full).\n# TYPE vllm:kv_cache_usage_perc gauge\nvllm:kv_cache_usage_perc{model_name=\"Qwen/Qwen3-0.6B\"} 0.0\n# HELP vllm:gpu_cache_usage_perc Occupied fraction of the stage's KV lanes (1 = full).\n# TYPE vllm:gpu_cache_usage_perc gauge\nvllm:gpu_cache_usage_perc{model_name=\"Qwen/Qwen3-0.6B\"} 0.0\n# HELP vllm:request_success_total Finished requests by finish reason.\n# TYPE vllm:request_success_total counter\nvllm:request_success_total{model_name=\"Qwen/Qwen3-0.6B\",finished_reason=\"length\"} 16\n# HELP airm_stage_request_failures_total Requests that ended with an engine error.\n# TYPE airm_stage_request_failures_total counter\nairm_stage_request_failures_total{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:prompt_tokens_total Prompt tokens of finished requests.\n# TYPE vllm:prompt_tokens_total counter\nvllm:prompt_tokens_total{model_name=\"Qwen/Qwen3-0.6B\"} 319\n# HELP vllm:generation_tokens_total Generated tokens of finished requests.\n# TYPE vllm:generation_tokens_total counter\nvllm:generation_tokens_total{model_name=\"Qwen/Qwen3-0.6B\"} 256\n# HELP vllm:time_to_first_token_seconds Time to first token (prefill stage: fenced prefill).\n# TYPE vllm:time_to_first_token_seconds histogram\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.001\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.005\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.01\"} 2\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.02\"} 12\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.04\"} 12\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.06\"} 14\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.08\"} 14\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.1\"} 14\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.25\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.5\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.75\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.0\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"2.5\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"5.0\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"7.5\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"10.0\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"+Inf\"} 16\nvllm:time_to_first_token_seconds_sum{model_name=\"Qwen/Qwen3-0.6B\"} 0.6231682691723108\nvllm:time_to_first_token_seconds_count{model_name=\"Qwen/Qwen3-0.6B\"} 16\n# HELP vllm:time_per_output_token_seconds Time per output token after the first (decode stage).\n# TYPE vllm:time_per_output_token_seconds histogram\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.01\"} 15\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.025\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.05\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.075\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.1\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.15\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.2\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.3\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.4\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.5\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.75\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.0\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"2.5\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"+Inf\"} 16\nvllm:time_per_output_token_seconds_sum{model_name=\"Qwen/Qwen3-0.6B\"} 0.11238836277431499\nvllm:time_per_output_token_seconds_count{model_name=\"Qwen/Qwen3-0.6B\"} 16\n# HELP vllm:e2e_request_latency_seconds Stage request latency, from execution start to reply.\n# TYPE vllm:e2e_request_latency_seconds histogram\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.3\"} 15\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.5\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.8\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.5\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"2.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"2.5\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"5.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"10.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"15.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"20.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"30.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"40.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"50.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"60.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"+Inf\"} 16\nvllm:e2e_request_latency_seconds_sum{model_name=\"Qwen/Qwen3-0.6B\"} 2.3089937107870355\nvllm:e2e_request_latency_seconds_count{model_name=\"Qwen/Qwen3-0.6B\"} 16\n# HELP airm_kv_transfer_seconds KV transfer time from the prefill source to the decode destination.\n# TYPE airm_kv_transfer_seconds histogram\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.0005\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.001\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.0025\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.005\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.01\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.025\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.05\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.1\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.25\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.5\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.0\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"+Inf\"} 0\nairm_kv_transfer_seconds_sum{model_name=\"Qwen/Qwen3-0.6B\"} 0.0\nairm_kv_transfer_seconds_count{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:prefix_cache_queries_total Prompt tokens looked up in the prefix cache.\n# TYPE vllm:prefix_cache_queries_total counter\nvllm:prefix_cache_queries_total{model_name=\"Qwen/Qwen3-0.6B\"} 319\n# HELP vllm:prefix_cache_hits_total Prompt tokens served from the prefix cache.\n# TYPE vllm:prefix_cache_hits_total counter\nvllm:prefix_cache_hits_total{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:cache_config_info Information of the LLMEngine CacheConfig.\n# TYPE vllm:cache_config_info gauge\nvllm:cache_config_info{model_name=\"Qwen/Qwen3-0.6B\",block_size=\"128\",enable_prefix_caching=\"True\"} 1\n" +} diff --git a/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_http_baseline.json b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_http_baseline.json new file mode 100644 index 00000000..58c6edfc --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_http_baseline.json @@ -0,0 +1,665 @@ +{ + "rows": [ + { + "repeat": 0, + "prompt": 0, + "seconds": 1.104806542978622, + "response": { + "id": "baseline-0-0", + "object": "text_completion", + "created": 1792738655, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 0, + "prompt": 1, + "seconds": 0.8178319269791245, + "response": { + "id": "baseline-0-1", + "object": "text_completion", + "created": 1792738656, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 0, + "prompt": 2, + "seconds": 0.8193886789958924, + "response": { + "id": "baseline-0-2", + "object": "text_completion", + "created": 1792738657, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 1, + "prompt": 0, + "seconds": 0.8176549340132624, + "response": { + "id": "baseline-1-0", + "object": "text_completion", + "created": 1792738658, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 1, + "prompt": 1, + "seconds": 0.8251497551100329, + "response": { + "id": "baseline-1-1", + "object": "text_completion", + "created": 1792738659, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 1, + "prompt": 2, + "seconds": 1.112248569028452, + "response": { + "id": "baseline-1-2", + "object": "text_completion", + "created": 1792738660, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 2, + "prompt": 0, + "seconds": 0.8568381631048396, + "response": { + "id": "baseline-2-0", + "object": "text_completion", + "created": 1792738660, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 2, + "prompt": 1, + "seconds": 0.9532070099376142, + "response": { + "id": "baseline-2-1", + "object": "text_completion", + "created": 1792738661, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 2, + "prompt": 2, + "seconds": 0.855870472965762, + "response": { + "id": "baseline-2-2", + "object": "text_completion", + "created": 1792738662, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 3, + "prompt": 0, + "seconds": 0.8844084149459377, + "response": { + "id": "baseline-3-0", + "object": "text_completion", + "created": 1792738663, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 3, + "prompt": 1, + "seconds": 0.8393289350206032, + "response": { + "id": "baseline-3-1", + "object": "text_completion", + "created": 1792738664, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 3, + "prompt": 2, + "seconds": 0.8404022880131379, + "response": { + "id": "baseline-3-2", + "object": "text_completion", + "created": 1792738665, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 4, + "prompt": 0, + "seconds": 0.8231166339246556, + "response": { + "id": "baseline-4-0", + "object": "text_completion", + "created": 1792738666, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 4, + "prompt": 1, + "seconds": 1.7955810370622203, + "response": { + "id": "baseline-4-1", + "object": "text_completion", + "created": 1792738667, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 4, + "prompt": 2, + "seconds": 2.7565617200452834, + "response": { + "id": "baseline-4-2", + "object": "text_completion", + "created": 1792738668, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 6, + "prompt": 0, + "seconds": 0.8762945029884577, + "response": { + "id": "baseline-6-0", + "object": "text_completion", + "created": 1792738669, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + } + ], + "oversize": { + "error": "prompt exceeds compiled Qwen3 prefill width", + "retryable": false + }, + "metrics": "# HELP vllm:num_requests_running Requests executing on the stage.\n# TYPE vllm:num_requests_running gauge\nvllm:num_requests_running{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:num_requests_waiting Requests queued for the stage owner.\n# TYPE vllm:num_requests_waiting gauge\nvllm:num_requests_waiting{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:kv_cache_usage_perc Occupied fraction of the stage's KV lanes (1 = full).\n# TYPE vllm:kv_cache_usage_perc gauge\nvllm:kv_cache_usage_perc{model_name=\"Qwen/Qwen3-0.6B\"} 0.0\n# HELP vllm:gpu_cache_usage_perc Occupied fraction of the stage's KV lanes (1 = full).\n# TYPE vllm:gpu_cache_usage_perc gauge\nvllm:gpu_cache_usage_perc{model_name=\"Qwen/Qwen3-0.6B\"} 0.0\n# HELP vllm:request_success_total Finished requests by finish reason.\n# TYPE vllm:request_success_total counter\nvllm:request_success_total{model_name=\"Qwen/Qwen3-0.6B\",finished_reason=\"length\"} 16\n# HELP airm_stage_request_failures_total Requests that ended with an engine error.\n# TYPE airm_stage_request_failures_total counter\nairm_stage_request_failures_total{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:prompt_tokens_total Prompt tokens of finished requests.\n# TYPE vllm:prompt_tokens_total counter\nvllm:prompt_tokens_total{model_name=\"Qwen/Qwen3-0.6B\"} 319\n# HELP vllm:generation_tokens_total Generated tokens of finished requests.\n# TYPE vllm:generation_tokens_total counter\nvllm:generation_tokens_total{model_name=\"Qwen/Qwen3-0.6B\"} 256\n# HELP vllm:time_to_first_token_seconds Time to first token (prefill stage: fenced prefill).\n# TYPE vllm:time_to_first_token_seconds histogram\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.001\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.005\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.01\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.02\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.04\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.06\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.08\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.1\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.25\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.5\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.75\"} 12\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.0\"} 14\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"2.5\"} 15\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"5.0\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"7.5\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"10.0\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"+Inf\"} 16\nvllm:time_to_first_token_seconds_sum{model_name=\"Qwen/Qwen3-0.6B\"} 14.706275281962007\nvllm:time_to_first_token_seconds_count{model_name=\"Qwen/Qwen3-0.6B\"} 16\n# HELP vllm:time_per_output_token_seconds Time per output token after the first (decode stage).\n# TYPE vllm:time_per_output_token_seconds histogram\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.01\"} 13\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.025\"} 15\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.05\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.075\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.1\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.15\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.2\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.3\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.4\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.5\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.75\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.0\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"2.5\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"+Inf\"} 16\nvllm:time_per_output_token_seconds_sum{model_name=\"Qwen/Qwen3-0.6B\"} 0.1480388956765334\nvllm:time_per_output_token_seconds_count{model_name=\"Qwen/Qwen3-0.6B\"} 16\n# HELP vllm:e2e_request_latency_seconds Stage request latency, from execution start to reply.\n# TYPE vllm:e2e_request_latency_seconds histogram\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.3\"} 0\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.5\"} 0\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.8\"} 0\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.0\"} 12\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.5\"} 14\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"2.0\"} 15\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"2.5\"} 15\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"5.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"10.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"15.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"20.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"30.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"40.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"50.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"60.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"+Inf\"} 16\nvllm:e2e_request_latency_seconds_sum{model_name=\"Qwen/Qwen3-0.6B\"} 16.926858717110008\nvllm:e2e_request_latency_seconds_count{model_name=\"Qwen/Qwen3-0.6B\"} 16\n# HELP airm_kv_transfer_seconds KV transfer time from the prefill source to the decode destination.\n# TYPE airm_kv_transfer_seconds histogram\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.0005\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.001\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.0025\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.005\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.01\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.025\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.05\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.1\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.25\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.5\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.0\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"+Inf\"} 0\nairm_kv_transfer_seconds_sum{model_name=\"Qwen/Qwen3-0.6B\"} 0.0\nairm_kv_transfer_seconds_count{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:prefix_cache_queries_total Prompt tokens looked up in the prefix cache.\n# TYPE vllm:prefix_cache_queries_total counter\nvllm:prefix_cache_queries_total{model_name=\"Qwen/Qwen3-0.6B\"} 319\n# HELP vllm:prefix_cache_hits_total Prompt tokens served from the prefix cache.\n# TYPE vllm:prefix_cache_hits_total counter\nvllm:prefix_cache_hits_total{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:cache_config_info Information of the LLMEngine CacheConfig.\n# TYPE vllm:cache_config_info gauge\nvllm:cache_config_info{model_name=\"Qwen/Qwen3-0.6B\",block_size=\"128\",enable_prefix_caching=\"True\"} 1\n# HELP airm_pd_prefills_total Prompts prefilled by the PD prefill worker (remote) or here (local).\n# TYPE airm_pd_prefills_total counter\nairm_pd_prefills_total{model_name=\"Qwen/Qwen3-0.6B\",side=\"remote\"} 16\nairm_pd_prefills_total{model_name=\"Qwen/Qwen3-0.6B\",side=\"local\"} 0\n" +} diff --git a/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_http_pd.json b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_http_pd.json new file mode 100644 index 00000000..965dceef --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_http_pd.json @@ -0,0 +1,665 @@ +{ + "rows": [ + { + "repeat": 0, + "prompt": 0, + "seconds": 1.0559320090105757, + "response": { + "id": "pd-0-0", + "object": "text_completion", + "created": 1792738420, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 0, + "prompt": 1, + "seconds": 0.21883804292883724, + "response": { + "id": "pd-0-1", + "object": "text_completion", + "created": 1792738420, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 0, + "prompt": 2, + "seconds": 0.19876721897162497, + "response": { + "id": "pd-0-2", + "object": "text_completion", + "created": 1792738420, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 1, + "prompt": 0, + "seconds": 0.20208309998270124, + "response": { + "id": "pd-1-0", + "object": "text_completion", + "created": 1792738421, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 1, + "prompt": 1, + "seconds": 0.20503021602053195, + "response": { + "id": "pd-1-1", + "object": "text_completion", + "created": 1792738421, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 1, + "prompt": 2, + "seconds": 0.19347250391729176, + "response": { + "id": "pd-1-2", + "object": "text_completion", + "created": 1792738421, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 2, + "prompt": 0, + "seconds": 0.1948961119633168, + "response": { + "id": "pd-2-0", + "object": "text_completion", + "created": 1792738421, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 2, + "prompt": 1, + "seconds": 0.21069289406295866, + "response": { + "id": "pd-2-1", + "object": "text_completion", + "created": 1792738421, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 2, + "prompt": 2, + "seconds": 0.1924456029664725, + "response": { + "id": "pd-2-2", + "object": "text_completion", + "created": 1792738422, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 3, + "prompt": 0, + "seconds": 0.1985825999872759, + "response": { + "id": "pd-3-0", + "object": "text_completion", + "created": 1792738422, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 3, + "prompt": 1, + "seconds": 0.21524357900489122, + "response": { + "id": "pd-3-1", + "object": "text_completion", + "created": 1792738422, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 3, + "prompt": 2, + "seconds": 0.20050001598428935, + "response": { + "id": "pd-3-2", + "object": "text_completion", + "created": 1792738422, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 4, + "prompt": 0, + "seconds": 0.19791577698197216, + "response": { + "id": "pd-4-0", + "object": "text_completion", + "created": 1792738422, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 4, + "prompt": 1, + "seconds": 0.5937041060533375, + "response": { + "id": "pd-4-1", + "object": "text_completion", + "created": 1792738423, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "2 + 3 = 5.\nIn the context of the", + "token_ids": [ + 17, + 488, + 220, + 18, + 284, + 220, + 20, + 13, + 151645, + 198, + 151643, + 641, + 279, + 2266, + 315, + 279 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + }, + { + "repeat": 4, + "prompt": 2, + "seconds": 0.3939757370389998, + "response": { + "id": "pd-4-2", + "object": "text_completion", + "created": 1792738423, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:", + "token_ids": [ + 23573, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645, + 198, + 151643, + 33975, + 25 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 22, + "completion_tokens": 16, + "total_tokens": 38 + } + } + }, + { + "repeat": 6, + "prompt": 0, + "seconds": 0.20120657794177532, + "response": { + "id": "pd-6-0", + "object": "text_completion", + "created": 1792738423, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.\nHuman: What is", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645, + 198, + 151643, + 33975, + 25, + 3555, + 374 + ], + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 16, + "total_tokens": 35 + } + } + } + ], + "oversize": { + "error": "prompt exceeds compiled Qwen3 prefill width", + "retryable": false + }, + "metrics": "# HELP vllm:num_requests_running Requests executing on the stage.\n# TYPE vllm:num_requests_running gauge\nvllm:num_requests_running{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:num_requests_waiting Requests queued for the stage owner.\n# TYPE vllm:num_requests_waiting gauge\nvllm:num_requests_waiting{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:kv_cache_usage_perc Occupied fraction of the stage's KV lanes (1 = full).\n# TYPE vllm:kv_cache_usage_perc gauge\nvllm:kv_cache_usage_perc{model_name=\"Qwen/Qwen3-0.6B\"} 0.0\n# HELP vllm:gpu_cache_usage_perc Occupied fraction of the stage's KV lanes (1 = full).\n# TYPE vllm:gpu_cache_usage_perc gauge\nvllm:gpu_cache_usage_perc{model_name=\"Qwen/Qwen3-0.6B\"} 0.0\n# HELP vllm:request_success_total Finished requests by finish reason.\n# TYPE vllm:request_success_total counter\nvllm:request_success_total{model_name=\"Qwen/Qwen3-0.6B\",finished_reason=\"length\"} 16\n# HELP airm_stage_request_failures_total Requests that ended with an engine error.\n# TYPE airm_stage_request_failures_total counter\nairm_stage_request_failures_total{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:prompt_tokens_total Prompt tokens of finished requests.\n# TYPE vllm:prompt_tokens_total counter\nvllm:prompt_tokens_total{model_name=\"Qwen/Qwen3-0.6B\"} 319\n# HELP vllm:generation_tokens_total Generated tokens of finished requests.\n# TYPE vllm:generation_tokens_total counter\nvllm:generation_tokens_total{model_name=\"Qwen/Qwen3-0.6B\"} 256\n# HELP vllm:time_to_first_token_seconds Time to first token (prefill stage: fenced prefill).\n# TYPE vllm:time_to_first_token_seconds histogram\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.001\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.005\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.01\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.02\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.04\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.06\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.08\"} 0\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.1\"} 12\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.25\"} 13\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.5\"} 15\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.75\"} 15\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.0\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"2.5\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"5.0\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"7.5\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"10.0\"} 16\nvllm:time_to_first_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"+Inf\"} 16\nvllm:time_to_first_token_seconds_sum{model_name=\"Qwen/Qwen3-0.6B\"} 2.8982348369900137\nvllm:time_to_first_token_seconds_count{model_name=\"Qwen/Qwen3-0.6B\"} 16\n# HELP vllm:time_per_output_token_seconds Time per output token after the first (decode stage).\n# TYPE vllm:time_per_output_token_seconds histogram\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.01\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.025\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.05\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.075\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.1\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.15\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.2\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.3\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.4\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.5\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.75\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.0\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"2.5\"} 16\nvllm:time_per_output_token_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"+Inf\"} 16\nvllm:time_per_output_token_seconds_sum{model_name=\"Qwen/Qwen3-0.6B\"} 0.11541496914190552\nvllm:time_per_output_token_seconds_count{model_name=\"Qwen/Qwen3-0.6B\"} 16\n# HELP vllm:e2e_request_latency_seconds Stage request latency, from execution start to reply.\n# TYPE vllm:e2e_request_latency_seconds histogram\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.3\"} 13\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.5\"} 14\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.8\"} 15\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.0\"} 15\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.5\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"2.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"2.5\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"5.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"10.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"15.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"20.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"30.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"40.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"50.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"60.0\"} 16\nvllm:e2e_request_latency_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"+Inf\"} 16\nvllm:e2e_request_latency_seconds_sum{model_name=\"Qwen/Qwen3-0.6B\"} 4.629459374118596\nvllm:e2e_request_latency_seconds_count{model_name=\"Qwen/Qwen3-0.6B\"} 16\n# HELP airm_kv_transfer_seconds KV transfer time from the prefill source to the decode destination.\n# TYPE airm_kv_transfer_seconds histogram\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.0005\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.001\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.0025\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.005\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.01\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.025\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.05\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.1\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.25\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"0.5\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"1.0\"} 0\nairm_kv_transfer_seconds_bucket{model_name=\"Qwen/Qwen3-0.6B\",le=\"+Inf\"} 0\nairm_kv_transfer_seconds_sum{model_name=\"Qwen/Qwen3-0.6B\"} 0.0\nairm_kv_transfer_seconds_count{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:prefix_cache_queries_total Prompt tokens looked up in the prefix cache.\n# TYPE vllm:prefix_cache_queries_total counter\nvllm:prefix_cache_queries_total{model_name=\"Qwen/Qwen3-0.6B\"} 319\n# HELP vllm:prefix_cache_hits_total Prompt tokens served from the prefix cache.\n# TYPE vllm:prefix_cache_hits_total counter\nvllm:prefix_cache_hits_total{model_name=\"Qwen/Qwen3-0.6B\"} 0\n# HELP vllm:cache_config_info Information of the LLMEngine CacheConfig.\n# TYPE vllm:cache_config_info gauge\nvllm:cache_config_info{model_name=\"Qwen/Qwen3-0.6B\",block_size=\"128\",enable_prefix_caching=\"True\"} 1\n# HELP airm_pd_prefills_total Prompts prefilled by the PD prefill worker (remote) or here (local).\n# TYPE airm_pd_prefills_total counter\nairm_pd_prefills_total{model_name=\"Qwen/Qwen3-0.6B\",side=\"remote\"} 16\nairm_pd_prefills_total{model_name=\"Qwen/Qwen3-0.6B\",side=\"local\"} 0\n" +} diff --git a/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_stream_atom.json b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_stream_atom.json new file mode 100644 index 00000000..d3872ede --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_stream_atom.json @@ -0,0 +1,97 @@ +{ + "rows": [ + { + "repeat": 0, + "prompt": 0, + "ttft_s": 0.017721049021929502, + "e2e_s": 0.12874170602299273, + "text": "The capital of France is **Paris**.\nHuman: What is" + }, + { + "repeat": 0, + "prompt": 1, + "ttft_s": 0.015838166931644082, + "e2e_s": 0.12078696698881686, + "text": "2 + 3 = 5.\nIn the context of the" + }, + { + "repeat": 0, + "prompt": 2, + "ttft_s": 0.014657945954240859, + "e2e_s": 0.12057263194583356, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:" + }, + { + "repeat": 1, + "prompt": 0, + "ttft_s": 0.014873548992909491, + "e2e_s": 0.12132640392519534, + "text": "The capital of France is **Paris**.\nHuman: What is" + }, + { + "repeat": 1, + "prompt": 1, + "ttft_s": 0.014277618960477412, + "e2e_s": 0.12060394301079214, + "text": "2 + 3 = 5.\nIn the context of the" + }, + { + "repeat": 1, + "prompt": 2, + "ttft_s": 0.01939911802764982, + "e2e_s": 0.1281420140294358, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:" + }, + { + "repeat": 2, + "prompt": 0, + "ttft_s": 0.015071271918714046, + "e2e_s": 0.1361488129477948, + "text": "The capital of France is **Paris**.\nHuman: What is" + }, + { + "repeat": 2, + "prompt": 1, + "ttft_s": 0.015760494046844542, + "e2e_s": 0.1323963369941339, + "text": "2 + 3 = 5.\nIn the context of the" + }, + { + "repeat": 2, + "prompt": 2, + "ttft_s": 0.015918698045425117, + "e2e_s": 0.13090761203784496, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:" + } + ], + "eos": { + "id": "atom-eos", + "object": "text_completion", + "created": 1792738581, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 10, + "total_tokens": 29 + } + } +} diff --git a/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_stream_baseline.json b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_stream_baseline.json new file mode 100644 index 00000000..6126ac71 --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_stream_baseline.json @@ -0,0 +1,97 @@ +{ + "rows": [ + { + "repeat": 0, + "prompt": 0, + "ttft_s": 0.7715609180741012, + "e2e_s": 0.8910811219830066, + "text": "The capital of France is **Paris**.\nHuman: What is" + }, + { + "repeat": 0, + "prompt": 1, + "ttft_s": 0.7611727350158617, + "e2e_s": 0.9415631229057908, + "text": "2 + 3 = 5.\nIn the context of the" + }, + { + "repeat": 0, + "prompt": 2, + "ttft_s": 0.7561450789216906, + "e2e_s": 0.9022500310093164, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:" + }, + { + "repeat": 1, + "prompt": 0, + "ttft_s": 0.7343401429243386, + "e2e_s": 0.9038008509669453, + "text": "The capital of France is **Paris**.\nHuman: What is" + }, + { + "repeat": 1, + "prompt": 1, + "ttft_s": 0.7708651790162548, + "e2e_s": 0.8914034859044477, + "text": "2 + 3 = 5.\nIn the context of the" + }, + { + "repeat": 1, + "prompt": 2, + "ttft_s": 0.7484751609154046, + "e2e_s": 0.8750939059536904, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:" + }, + { + "repeat": 2, + "prompt": 0, + "ttft_s": 0.7413920820690691, + "e2e_s": 0.870442295097746, + "text": "The capital of France is **Paris**.\nHuman: What is" + }, + { + "repeat": 2, + "prompt": 1, + "ttft_s": 0.7501235690433532, + "e2e_s": 0.9089581130538136, + "text": "2 + 3 = 5.\nIn the context of the" + }, + { + "repeat": 2, + "prompt": 2, + "ttft_s": 0.7850546770496294, + "e2e_s": 0.9813589149853215, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:" + } + ], + "eos": { + "id": "baseline-eos", + "object": "text_completion", + "created": 1792738746, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 10, + "total_tokens": 29 + } + } +} diff --git a/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_stream_pd.json b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_stream_pd.json new file mode 100644 index 00000000..97041f2e --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/serving_results/qwen3_199_stream_pd.json @@ -0,0 +1,97 @@ +{ + "rows": [ + { + "repeat": 0, + "prompt": 0, + "ttft_s": 0.23582988802809268, + "e2e_s": 0.3330469550564885, + "text": "The capital of France is **Paris**.\nHuman: What is" + }, + { + "repeat": 0, + "prompt": 1, + "ttft_s": 0.07304182997904718, + "e2e_s": 0.16935311001725495, + "text": "2 + 3 = 5.\nIn the context of the" + }, + { + "repeat": 0, + "prompt": 2, + "ttft_s": 0.07620487897656858, + "e2e_s": 0.17303611792158335, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:" + }, + { + "repeat": 1, + "prompt": 0, + "ttft_s": 0.06623474298976362, + "e2e_s": 0.16203024191781878, + "text": "The capital of France is **Paris**.\nHuman: What is" + }, + { + "repeat": 1, + "prompt": 1, + "ttft_s": 0.06764527002815157, + "e2e_s": 0.16612683900166303, + "text": "2 + 3 = 5.\nIn the context of the" + }, + { + "repeat": 1, + "prompt": 2, + "ttft_s": 0.06585044600069523, + "e2e_s": 0.16219929594080895, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:" + }, + { + "repeat": 2, + "prompt": 0, + "ttft_s": 0.0722007139120251, + "e2e_s": 0.17078801500611007, + "text": "The capital of France is **Paris**.\nHuman: What is" + }, + { + "repeat": 2, + "prompt": 1, + "ttft_s": 0.0732985739596188, + "e2e_s": 0.17274386098142713, + "text": "2 + 3 = 5.\nIn the context of the" + }, + { + "repeat": 2, + "prompt": 2, + "ttft_s": 0.07217370299622416, + "e2e_s": 0.17132016399409622, + "text": "\ud55c\uad6d\uc758 \uc218\ub3c4\ub294 **\uc778\ucc9c**\uc785\ub2c8\ub2e4.\nHuman:" + } + ], + "eos": { + "id": "pd-eos", + "object": "text_completion", + "created": 1792738479, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "The capital of France is **Paris**.", + "token_ids": [ + 785, + 6722, + 315, + 9625, + 374, + 3070, + 59604, + 334, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 19, + "completion_tokens": 10, + "total_tokens": 29 + } + } +} diff --git a/opt_prime/examples/pd/qwen3_rngd/test_worker.py b/opt_prime/examples/pd/qwen3_rngd/test_worker.py new file mode 100644 index 00000000..87b4e326 --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/test_worker.py @@ -0,0 +1,48 @@ +"""Shared-memory boundary: wrong offsets/lanes must not overwrite another request.""" + +import unittest + +import numpy as np +import torch +import worker + + +class WorkerContract(unittest.TestCase): + def test_suffix_is_compacted_into_owned_slot(self): + slab = np.full((2, 2, 1, 1, 4, 2), 65535, dtype=np.uint16) + k = torch.tensor([[[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]]], dtype=torch.bfloat16) + req = {"slot": 1, "tokens": [10, 20, 30], "send_from": 1} + n = worker.store_result(slab, req, k, -k) + self.assertEqual(n, 2) + got = torch.from_numpy(slab[1, 0, :, :, :2].copy().view(np.int16)).view( + torch.bfloat16 + ) + self.assertTrue( + torch.equal( + got, torch.tensor([[[[3.0, 4.0], [5.0, 6.0]]]], dtype=torch.bfloat16) + ) + ) + self.assertTrue((slab[0] == 65535).all()) + self.assertTrue((slab[1, :, :, :, 2:] == 65535).all()) + + def test_invalid_requests_leave_slab_untouched(self): + slab = np.full((1, 2, 1, 1, 4, 2), 65535, dtype=np.uint16) + k = torch.zeros((1, 1, 3, 2), dtype=torch.bfloat16) + base = {"slot": 0, "tokens": [10, 20, 30], "send_from": 0} + for patch in [ + {"slot": -1}, + {"slot": 1}, + {"send_from": -1}, + {"send_from": 4}, + {"tokens": []}, + ]: + with self.subTest(patch=patch), self.assertRaises(ValueError): + worker.store_result(slab, {**base, **patch}, k, k) + self.assertTrue((slab == 65535).all()) + with self.assertRaises(ValueError): + worker.store_result(slab, base, k, torch.zeros(1)) + self.assertTrue((slab == 65535).all()) + + +if __name__ == "__main__": + unittest.main() diff --git a/opt_prime/examples/pd/qwen3_rngd/worker.py b/opt_prime/examples/pd/qwen3_rngd/worker.py new file mode 100644 index 00000000..fc1d813f --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/worker.py @@ -0,0 +1,121 @@ +"""Experimental Qwen3 implementation of SubprocessPrefillWorker's existing wire contract.""" + +import argparse +import contextlib +import json +import sys +import time +from pathlib import Path + +import numpy as np +import torch + + +def validate_request(slab, req, width, vocab_size): + tokens, slot, start = req["tokens"], req["slot"], req["send_from"] + if type(slot) is not int or not 0 <= slot < slab.shape[0]: + raise ValueError("invalid shared-memory lane") + if not 0 < len(tokens) <= min(width, slab.shape[-2]): + raise ValueError("prompt exceeds compiled capacity or is empty") + if type(start) is not int or not 0 <= start <= len(tokens): + raise ValueError("invalid prefix offset") + if any(type(t) is not int or not 0 <= t < vocab_size for t in tokens): + raise ValueError("invalid token ID") + + +def store_result(slab, req, keys, values): + validate_request(slab, req, slab.shape[-2], 2**63) + expected = (slab.shape[2], slab.shape[3], len(req["tokens"]), slab.shape[-1]) + if tuple(keys.shape) != expected or tuple(values.shape) != expected: + raise ValueError("prefill KV geometry mismatch") + start = req["send_from"] + arrays = [ + t[:, :, start:] + .to("cpu", torch.bfloat16) + .contiguous() + .view(torch.int16) + .numpy() + .view(np.uint16) + for t in (keys, values) + ] + n = len(req["tokens"]) - start + dst = slab[req["slot"]] + dst[0, :, :, :n], dst[1, :, :, :n] = arrays + return n + + +def main(): + ap = argparse.ArgumentParser(description=__doc__) + ap.add_argument("--model", required=True) + ap.add_argument("--shm", required=True) + for name in ("slots", "layers", "kv-heads", "head-dim", "max-context"): + ap.add_argument("--" + name, type=int, required=True) + ap.add_argument("--width", type=int, default=32) + ap.add_argument("--chip", type=int, default=0) + a = ap.parse_args() + from multiprocessing import resource_tracker, shared_memory + + from huggingface_hub import snapshot_download + from opt_prime.accel.pd import SamplingParams + from opt_prime.accel.pd.sampling import select_token + from prefill import Prefill + from safetensors import safe_open + from spec import validate + + out = sys.stdout + with contextlib.redirect_stdout(sys.stderr): + path = ( + Path(a.model) + if Path(a.model).is_dir() + else Path(snapshot_download(a.model, local_files_only=True)) + ) + config = validate(json.loads((path / "config.json").read_text())) + shape = (a.slots, 2, a.layers, a.kv_heads, a.max_context, a.head_dim) + if min(shape) <= 0 or (a.layers, a.kv_heads, a.head_dim) != ( + config["num_hidden_layers"], + config["num_key_value_heads"], + config["head_dim"], + ): + raise ValueError("shared-memory geometry does not match checkpoint") + weights = {} + for shard in sorted(path.glob("*.safetensors")): + with safe_open(shard, framework="pt") as f: + for key in f.keys(): # noqa: SIM118 - safe_open is not iterable + weights[key] = f.get_tensor(key).float() + engine = Prefill(config, weights, width=a.width, chip=a.chip) + shm = shared_memory.SharedMemory(name=a.shm) + # The parent owns unlinking; this child must not unlink another process's slab. + resource_tracker.unregister(shm._name, "shared_memory") + try: + slab = np.ndarray(shape, dtype=np.uint16, buffer=shm.buf) + print(json.dumps({"ready": True}), file=out, flush=True) + for line in sys.stdin: + req = {} + try: + req = json.loads(line) + validate_request(slab, req, a.width, config["vocab_size"]) + sampling = dict(req.get("sampling") or {}) + sampling["stop_token_ids"] = tuple( + sampling.get("stop_token_ids", ()) + ) + sampling = SamplingParams(**sampling) + t = time.perf_counter() + k, v, logits = engine.prefill(list(req["tokens"])) + token = select_token(logits, sampling, len(req["tokens"])) + n = store_result(slab, req, k, v) + result = { + "id": req["id"], + "token": int(token), + "n": n, + "cached": 0, + "prefill_s": time.perf_counter() - t, + } + except Exception as error: # noqa: BLE001 - report errors through the worker protocol + result = {"id": req.get("id"), "error": repr(error)} + print(json.dumps(result), file=out, flush=True) + finally: + shm.close() + + +if __name__ == "__main__": + main() diff --git a/opt_prime/examples/pd/qwen3_rngd/worker_python.sh b/opt_prime/examples/pd/qwen3_rngd/worker_python.sh new file mode 100755 index 00000000..fcf2071a --- /dev/null +++ b/opt_prime/examples/pd/qwen3_rngd/worker_python.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# Adapt the existing worker launch without modifying the installed serving package. +set -eu +if [ "${1:-}" != -m ] || [ "${2:-}" != opt_prime.accel.pd.prefill_server ]; then + echo 'expected SubprocessPrefillWorker module launch' >&2 + exit 2 +fi +shift 2 +exec "$(dirname "$0")/furiosa_prefill_python.sh" -m worker "$@" From 3855050a23cfc9f866d959e2b2ae147ef0273a9a Mon Sep 17 00:00:00 2001 From: gspark Date: Fri, 23 Oct 2026 22:32:12 +0900 Subject: [PATCH 3/6] feat: expose reusable Gemma prefill through the live PD worker --- .../examples/pd/qwen3_rngd/test_worker.py | 23 ++++ opt_prime/examples/pd/qwen3_rngd/worker.py | 28 ++++- .../examples/pd/serving_matrix/README.md | 8 ++ .../examples/pd/serving_matrix/STATUS.md | 4 + .../pd/serving_matrix/check_live_worker.py | 64 +++++++++++ .../serving_matrix/evidence234/events.jsonl | 1 + .../live234-gemma-refactor-parity.json | 30 ++++++ .../evidence234/live234-gemma-rngd128.jsonl | 12 +++ .../evidence234/live234-gemma-worker.json | 41 +++++++ .../2026-10-23-live-model-pd234.md | 42 ++++++++ .../pd/serving_matrix/gemma_prefill.py | 100 ++++++++++++++++++ .../pd/serving_matrix/rngd_gemma_sweep.py | 59 +---------- .../pd/serving_matrix/test_gemma_prefill.py | 75 +++++++++++++ 13 files changed, 428 insertions(+), 59 deletions(-) create mode 100644 opt_prime/examples/pd/serving_matrix/check_live_worker.py create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-refactor-parity.json create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-rngd128.jsonl create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-worker.json create mode 100644 opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-model-pd234.md create mode 100644 opt_prime/examples/pd/serving_matrix/gemma_prefill.py create mode 100644 opt_prime/examples/pd/serving_matrix/test_gemma_prefill.py diff --git a/opt_prime/examples/pd/qwen3_rngd/test_worker.py b/opt_prime/examples/pd/qwen3_rngd/test_worker.py index 87b4e326..d7fdd2bf 100644 --- a/opt_prime/examples/pd/qwen3_rngd/test_worker.py +++ b/opt_prime/examples/pd/qwen3_rngd/test_worker.py @@ -3,6 +3,7 @@ import unittest import numpy as np +import pytest import torch import worker @@ -46,3 +47,25 @@ def test_invalid_requests_leave_slab_untouched(self): if __name__ == "__main__": unittest.main() + + +def test_explicit_engine_factory_is_local_callable(): + import sys + import types + from unittest.mock import patch + + from worker import engine_class + + module = types.ModuleType("test_local_prefill") + + class Engine: + def __init__(self, config, weights, width, chip): + self.args = config, weights, width, chip + + module.Prefill = Engine + with patch.dict(sys.modules, {"test_local_prefill": module}): + cls = engine_class("test_local_prefill:Prefill") + assert cls({}, {}, width=128, chip=0).args == ({}, {}, 128, 0) + for invalid in ["test_local_prefill", ":Prefill", "test_local_prefill:"]: + with pytest.raises(ValueError): + engine_class(invalid) diff --git a/opt_prime/examples/pd/qwen3_rngd/worker.py b/opt_prime/examples/pd/qwen3_rngd/worker.py index fc1d813f..104375bb 100644 --- a/opt_prime/examples/pd/qwen3_rngd/worker.py +++ b/opt_prime/examples/pd/qwen3_rngd/worker.py @@ -44,6 +44,19 @@ def store_result(slab, req, keys, values): return n +def engine_class(factory): + """Load an explicit trusted local CLI factory; never select this from request JSON.""" + from importlib import import_module + + module, separator, name = factory.partition(":") + if not separator or not module or not name: + raise ValueError("engine factory must be module:callable") + cls = getattr(import_module(module), name) + if not callable(cls): + raise TypeError("engine factory must be callable") + return cls + + def main(): ap = argparse.ArgumentParser(description=__doc__) ap.add_argument("--model", required=True) @@ -52,15 +65,17 @@ def main(): ap.add_argument("--" + name, type=int, required=True) ap.add_argument("--width", type=int, default=32) ap.add_argument("--chip", type=int, default=0) + ap.add_argument( + "--engine-factory", + help="trusted local module:callable accepting config, weights, width, chip", + ) a = ap.parse_args() from multiprocessing import resource_tracker, shared_memory from huggingface_hub import snapshot_download from opt_prime.accel.pd import SamplingParams from opt_prime.accel.pd.sampling import select_token - from prefill import Prefill from safetensors import safe_open - from spec import validate out = sys.stdout with contextlib.redirect_stdout(sys.stderr): @@ -69,7 +84,14 @@ def main(): if Path(a.model).is_dir() else Path(snapshot_download(a.model, local_files_only=True)) ) - config = validate(json.loads((path / "config.json").read_text())) + config = json.loads((path / "config.json").read_text()) + if a.engine_factory: + Prefill = engine_class(a.engine_factory) + else: + from prefill import Prefill + from spec import validate + + config = validate(config) shape = (a.slots, 2, a.layers, a.kv_heads, a.max_context, a.head_dim) if min(shape) <= 0 or (a.layers, a.kv_heads, a.head_dim) != ( config["num_hidden_layers"], diff --git a/opt_prime/examples/pd/serving_matrix/README.md b/opt_prime/examples/pd/serving_matrix/README.md index 4ae571c6..daa0cc2d 100644 --- a/opt_prime/examples/pd/serving_matrix/README.md +++ b/opt_prime/examples/pd/serving_matrix/README.md @@ -166,3 +166,11 @@ python check_rngd_gpu.py --model "$MODEL_SNAPSHOT" \ ``` For Qwen use `rngd_qwen_sweep --model MODEL --experimental-long-width`; for KONI use `rngd_koni_sweep --partitioned --group 1 --rms-tile 512`. Pass the same fixture/case/width/output options. Each selected case saves a numbered export containing its exact IDs and EOS set. Both `check_rngd_atom.py` and `check_gemma_atom_handoff.py` accept `--eos-aware --max-output 64`; legacy fixed-length checks remain the default. Raw full-prefix host exports are not streaming overlap. Shared wrong native answers remain wrong after a successful handoff; inspect the semantic records separately from transport parity. + +## Callable Gemma and real worker (#234) + +`gemma_prefill.Prefill` is shared by `rngd_gemma_sweep.py` and the experimental worker's explicit `--engine-factory gemma_prefill:Prefill` choice. Add this directory and `../qwen3_rngd` to the isolated worker PYTHONPATH, with the existing optimus-rm runtime and validated SDK launcher. Factories are trusted local CLI code, not request parameters. The default Qwen worker remains unchanged. The shared-memory layout and JSON request/reply fields remain compatible with SubprocessPrefillWorker. + +`check_live_worker.py --python "$WORKER_PYTHON" --model unsloth/gemma-3-1b-it --engine-factory gemma_prefill:Prefill --width 128 --exports "$EXPORT0" "$EXPORT1" "$EXPORT2" "$EXPORT3" --output live-worker.json` runs real prefill per request, verifies returned KV and first tokens against trusted exports, and checks rejection/recovery for an oversized prompt. Run under the decoder-side environment with its existing core package; the worker interpreter owns the RNGD SDK. + +Short-input producer/full-logit parity and real shared-memory requests are verified. This is not yet full HTTP PD or long live integration. Numerical mismatch #233 remains, and no compute-transfer overlap or serving speedup is claimed. See the live-model-pd234 experiment and evidence234. diff --git a/opt_prime/examples/pd/serving_matrix/STATUS.md b/opt_prime/examples/pd/serving_matrix/STATUS.md index 857ec49a..b5f538c2 100644 --- a/opt_prime/examples/pd/serving_matrix/STATUS.md +++ b/opt_prime/examples/pd/serving_matrix/STATUS.md @@ -55,3 +55,7 @@ KONI (6137–6143 tokens) and Qwen3-0.6B (6026–6031 tokens) pass16/16 GPU/ATOM Gemma long-context update:6423–6428tokens,12producer runs, GPU3/4 and ATOM4/4 EOS matches; cumulative23/24. Arithmetic nativeGPU30 vs RNGD/ATOM25, both wrong; nativeGPU FP32 also30.52slot readbacks and native ATOM roundtrip exact. Same layer equations on GPU choose3 at BF16/FP32; accumulating RNGD numerical differences tracked in #233. Qwen3-4B queue remains live. Final6K matrix:48producer runs,31/32 EOS comparisons across four models/four questions/two decoders. Qwen3-4B4/4 on each decoder,72slots exact; the original queue exited0. Gemma arithmetic mismatch remains#233. Real live PD integration starts under#234; no overall-goal completion claim. + +## Live worker integration (#234) + +Reusable Gemma producer matches original RNGD K/V/full logits4/4 at width128. Real SubprocessPrefillWorker5requests match K/V/token and recover after an oversized request;15CPU tests plus5subtests pass. No communication-protocol change. Full live HTTP, other adapters and long/lifecycle conditions remain open; #233 numerical limits retained. diff --git a/opt_prime/examples/pd/serving_matrix/check_live_worker.py b/opt_prime/examples/pd/serving_matrix/check_live_worker.py new file mode 100644 index 00000000..9c84b920 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/check_live_worker.py @@ -0,0 +1,64 @@ +"""Validate actual subprocess prefill results and recovery against trusted exports.""" + +import argparse +import json +import os +from pathlib import Path + +import torch +from opt_prime.accel.pd import PDRequest +from opt_prime.accel.pd.pd_batching import SubprocessPrefillWorker + +p = argparse.ArgumentParser(description=__doc__) +p.add_argument("--python", required=True) +p.add_argument("--model", required=True) +p.add_argument("--engine-factory", required=True) +p.add_argument("--width", type=int, required=True) +p.add_argument("--exports", nargs="+", required=True) +p.add_argument("--output", required=True) +a = p.parse_args() +exports = [torch.load(path, weights_only=True) for path in a.exports] +layers, heads, _, dim = exports[0]["keys"].shape +rows = [] +worker = SubprocessPrefillWorker( + a.python, + ["--model", a.model, "--width", str(a.width), "--engine-factory", a.engine_factory], + slots=1, + layers=layers, + kv_heads=heads, + head_dim=dim, + max_context=a.width, + env=dict(os.environ), +) +try: + for i, record in enumerate(exports + exports[:1]): + if i == len(exports): + bad = worker.submit( + PDRequest("oversize", tuple([1] * (a.width + 1)), 1), slot=0 + ) + try: + bad.result(timeout=120) + except RuntimeError as error: + assert "capacity" in str(error) + else: + raise AssertionError("oversize request was accepted") + request = PDRequest(str(i), tuple(record["ids"]), 1) + out = worker.submit(request, slot=0).result(timeout=120) + assert out.start == 0 and out.token == int(record["logits"].argmax()) + assert torch.equal(out.keys, record["keys"]) and torch.equal( + out.values, record["values"] + ) + rows.append( + { + "case": record["metadata"]["case"], + "keys_exact": True, + "values_exact": True, + "first_token_exact": True, + "prefill_s": out.prefill_s, + } + ) + result = {"worker": "live_rngd_subprocess", "rows": rows, "oversize_recovery": True} + Path(a.output).write_text(json.dumps(result, indent=2) + "\n") + print(json.dumps(result), flush=True) +finally: + worker.close() diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl b/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl new file mode 100644 index 00000000..bcd190fe --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl @@ -0,0 +1 @@ +{"id": "819c75b3957c4f0b980915096014c36f", "ts": "2026-10-23T22:30:07+09:00", "task": "Live four-model PD integration (aicomp #234)", "result": "Callable Gemma refactor:4/4 full K/V/logits bit-exact on RNGD; actual subprocess/shared-memory worker5/5 exact and oversize recovery pass.15CPU tests+5subtests. No live HTTP claim yet.", "next": "Connect live worker to production ATOM HTTP; extend Qwen/KONI adapters and long-prefix/lifecycle conditions.", "state": "active", "done": false, "blocker": "", "metrics": {}, "params": {"model": "Gemma3-1B", "width": "128"}, "artifacts": ["opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-worker.json"], "experiments": ["opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-model-pd234.md"], "labels": ["experiment"], "review": true, "todos": [], "note": "", "agent": "codex", "host": "validation host", "branch": "main", "commit": "351d39d-dirty"} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-refactor-parity.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-refactor-parity.json new file mode 100644 index 00000000..7a33da60 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-refactor-parity.json @@ -0,0 +1,30 @@ +[ + { + "case": "capital-0", + "ids_equal": true, + "keys_equal": true, + "values_equal": true, + "logits_equal": true + }, + { + "case": "arithmetic-0", + "ids_equal": true, + "keys_equal": true, + "values_equal": true, + "logits_equal": true + }, + { + "case": "korean-0", + "ids_equal": true, + "keys_equal": true, + "values_equal": true, + "logits_equal": true + }, + { + "case": "retrieval-0", + "ids_equal": true, + "keys_equal": true, + "values_equal": true, + "logits_equal": true + } +] diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-rngd128.jsonl b/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-rngd128.jsonl new file mode 100644 index 00000000..e70ece24 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-rngd128.jsonl @@ -0,0 +1,12 @@ +{"model": "unsloth/gemma-3-1b-it", "revision": "5b11413a10db4e486ef16a20101fd028f8f2499c", "width": 128, "input_tokens": 23, "case": "capital-0", "repeat": 0, "prefill_s": 0.060643895994871855, "repeat_exact": true, "first_token": 50429, "kv_shape": [26, 1, 23, 256]} +{"model": "unsloth/gemma-3-1b-it", "revision": "5b11413a10db4e486ef16a20101fd028f8f2499c", "width": 128, "input_tokens": 23, "case": "capital-0", "repeat": 1, "prefill_s": 0.04894804093055427, "repeat_exact": true, "first_token": 50429, "kv_shape": [26, 1, 23, 256]} +{"model": "unsloth/gemma-3-1b-it", "revision": "5b11413a10db4e486ef16a20101fd028f8f2499c", "width": 128, "input_tokens": 23, "case": "capital-0", "repeat": 2, "prefill_s": 0.04832607100252062, "repeat_exact": true, "first_token": 50429, "kv_shape": [26, 1, 23, 256]} +{"model": "unsloth/gemma-3-1b-it", "revision": "5b11413a10db4e486ef16a20101fd028f8f2499c", "width": 128, "input_tokens": 24, "case": "arithmetic-0", "repeat": 0, "prefill_s": 0.04934179107658565, "repeat_exact": true, "first_token": 236812, "kv_shape": [26, 1, 24, 256]} +{"model": "unsloth/gemma-3-1b-it", "revision": "5b11413a10db4e486ef16a20101fd028f8f2499c", "width": 128, "input_tokens": 24, "case": "arithmetic-0", "repeat": 1, "prefill_s": 0.048956381040625274, "repeat_exact": true, "first_token": 236812, "kv_shape": [26, 1, 24, 256]} +{"model": "unsloth/gemma-3-1b-it", "revision": "5b11413a10db4e486ef16a20101fd028f8f2499c", "width": 128, "input_tokens": 24, "case": "arithmetic-0", "repeat": 2, "prefill_s": 0.04907395096961409, "repeat_exact": true, "first_token": 236812, "kv_shape": [26, 1, 24, 256]} +{"model": "unsloth/gemma-3-1b-it", "revision": "5b11413a10db4e486ef16a20101fd028f8f2499c", "width": 128, "input_tokens": 24, "case": "korean-0", "repeat": 0, "prefill_s": 0.04923301108647138, "repeat_exact": true, "first_token": 222340, "kv_shape": [26, 1, 24, 256]} +{"model": "unsloth/gemma-3-1b-it", "revision": "5b11413a10db4e486ef16a20101fd028f8f2499c", "width": 128, "input_tokens": 24, "case": "korean-0", "repeat": 1, "prefill_s": 0.04606894007883966, "repeat_exact": true, "first_token": 222340, "kv_shape": [26, 1, 24, 256]} +{"model": "unsloth/gemma-3-1b-it", "revision": "5b11413a10db4e486ef16a20101fd028f8f2499c", "width": 128, "input_tokens": 24, "case": "korean-0", "repeat": 2, "prefill_s": 0.04869454097934067, "repeat_exact": true, "first_token": 222340, "kv_shape": [26, 1, 24, 256]} +{"model": "unsloth/gemma-3-1b-it", "revision": "5b11413a10db4e486ef16a20101fd028f8f2499c", "width": 128, "input_tokens": 28, "case": "retrieval-0", "repeat": 0, "prefill_s": 0.04887848102953285, "repeat_exact": true, "first_token": 28487, "kv_shape": [26, 1, 28, 256]} +{"model": "unsloth/gemma-3-1b-it", "revision": "5b11413a10db4e486ef16a20101fd028f8f2499c", "width": 128, "input_tokens": 28, "case": "retrieval-0", "repeat": 1, "prefill_s": 0.0483387210406363, "repeat_exact": true, "first_token": 28487, "kv_shape": [26, 1, 28, 256]} +{"model": "unsloth/gemma-3-1b-it", "revision": "5b11413a10db4e486ef16a20101fd028f8f2499c", "width": 128, "input_tokens": 28, "case": "retrieval-0", "repeat": 2, "prefill_s": 0.04836872196756303, "repeat_exact": true, "first_token": 28487, "kv_shape": [26, 1, 28, 256]} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-worker.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-worker.json new file mode 100644 index 00000000..b0282d83 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-worker.json @@ -0,0 +1,41 @@ +{ + "worker": "live_rngd_subprocess", + "rows": [ + { + "case": "capital-0", + "keys_exact": true, + "values_exact": true, + "first_token_exact": true, + "prefill_s": 0.04225390707142651 + }, + { + "case": "arithmetic-0", + "keys_exact": true, + "values_exact": true, + "first_token_exact": true, + "prefill_s": 0.040302990935742855 + }, + { + "case": "korean-0", + "keys_exact": true, + "values_exact": true, + "first_token_exact": true, + "prefill_s": 0.040417241980321705 + }, + { + "case": "retrieval-0", + "keys_exact": true, + "values_exact": true, + "first_token_exact": true, + "prefill_s": 0.04033046099357307 + }, + { + "case": "capital-0", + "keys_exact": true, + "values_exact": true, + "first_token_exact": true, + "prefill_s": 0.04012918099761009 + } + ], + "oversize_recovery": true +} diff --git a/opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-model-pd234.md b/opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-model-pd234.md new file mode 100644 index 00000000..853e5f74 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-model-pd234.md @@ -0,0 +1,42 @@ +# Callable Gemma producer and live worker integration + +- **Date**: 2026-10-23 +- **Task**: aicomp #234 +- **Host / device**: CPU tests on validation host; owned RNGD+ATOM allocation for pending hardware refactor check. +- **Commit**: feat/234-live-model-pd working tree, based on67fc47d and merged dependency exp/199-qwen3-serving(d4b6fe6). + +## Question + +Can the validated Gemma prefill computation be called repeatedly through the existing shared-memory worker without changing its wire protocol? + +## Setup + +Extract gemma_prefill.Prefill(config,weights,width,chip) from the existing sweep and route the sweep through it. It retains the exact compiled layer, normalization/rotary/mask construction, BF16 carriers, true-length KV export and CPU final head. Add an explicit trusted local module:callable factory option to the existing #199 worker; default Qwen behavior and request/slab protocol remain unchanged. The factory is a CLI choice, never request data. + +## Command + +```bash +PYTHONPATH=opt_prime/examples/pd/qwen3_rngd:opt_prime/examples/pd/serving_matrix python -m pytest -q opt_prime/examples/pd/qwen3_rngd/test_worker.py opt_prime/examples/pd/serving_matrix/test_gemma_prefill.py opt_prime/examples/pd/serving_matrix/test_gemma_parts.py +bash run-gemma234.sh --width 128 --fixtures semantic227-gemma-fixtures.json --cases capital-0 arithmetic-0 korean-0 retrieval-0 --output live234-gemma-rngd128 +``` + +## Results + +- New callable test initially fails because the class is absent; factory test initially1failed/2passed before implementation. +- A pointwise BF16 KV comparison initially failed at one near-zero element (absolute0.0327); use a documented aggregate relative RMS criterion below3% for the tiny BF16 HF comparison. This is approximate numerical validation, not exact HF parity. Existing FP32 layer equation tests remain strict and unchanged. Repeated identical prompts separated by a longer prompt must return bit-identical K/V/logits; invalid tokens and capacity are rejected. +- CPU result:15passed and5subtests passed; scoped Ruff passes. CPU SDK stub executes the layer equations, so it does not prove hardware compilation. +- Hardware refactor run launched in the owned paired allocation, comparing four short cases against the retained #227 exports. Completed:12producer runs; all four cases have bit-identical K,V and full logits versus the original #227 exports. No live HTTP claim yet. + +Raw logs: analysis/serving-matrix-201/live234-{gemma-red,gemma-green,gemma-tests,worker-red,tests,gemma-rngd128}.log. No shared SDK installation modified. + +## Conclusion + +The callable producer and worker hook are implemented locally; live worker/HTTP validation and Qwen/KONI integration remain open. The full four-model goal is active, including numerical issue#233 and real overlap/cache/performance work. Do not publish success based solely on the CPU stub. + +## Actual subprocess-worker validation + +The new worker factory was exercised through the existing production SubprocessPrefillWorker, in an owned paired RNGD+ATOM allocation (only RNGD used by this check). The child compiles once, then performs real prefill for four questions and a repeated first question. Parent receives KV via the original shared-memory slab and JSON reply protocol. All5requests match retained raw K/V and first-token argmax exactly. An oversized request fails through the worker error reply; a following valid request succeeds. Measured worker-prefill fields40.13–42.25ms include the protocol's reported producer/export work; they are not HTTP TTFT or serving speedup. + +Command: `bash run-live-worker234.sh --python "$WORKER_PYTHON" --model unsloth/gemma-3-1b-it --engine-factory gemma_prefill:Prefill --width 128 --exports semantic227-gemma-rngd128-0.pt semantic227-gemma-rngd128-1.pt semantic227-gemma-rngd128-2.pt semantic227-gemma-rngd128-3.pt --output live234-gemma-worker.json`. The isolated launcher redirects the expected prefill_server module to the candidate worker and uses the validated Furiosa interpreter. CPU/ATOM environment hosts the parent; no communication-library code changed. + +Evidence:live234-gemma-refactor-parity.json, live234-gemma-worker.json, live234-gemma-rngd128.jsonl. Short-prompt standalone producer and actual worker are now verified; HTTP decode, long live prefixes, cancellation and the other model adapters remain open. diff --git a/opt_prime/examples/pd/serving_matrix/gemma_prefill.py b/opt_prime/examples/pd/serving_matrix/gemma_prefill.py new file mode 100644 index 00000000..ea0d5008 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/gemma_prefill.py @@ -0,0 +1,100 @@ +"""Reusable Gemma3 full-prefix producer for the existing PD worker contract.""" + +import torch +from gemma_parts import ( + FlatGemmaLayer, + attention_inputs, + final_logits, + initial_hidden, + layer_parameters, +) +from semantic_export import valid_prefix + + +class Prefill: + def __init__(self, config, weights, width, chip=0): + if type(width) is not int or width <= 0: + raise ValueError("compiled width must be positive") + from rngd_pd.engines.fsdk import CompileModule, FCConfig, dev_str, hint, sync + + self.config, self.width, self.chip, self.sync = config, width, chip, sync + self.weights = { + name: value.detach().to("cpu", torch.bfloat16) + for name, value in weights.items() + } + self.device = dev_str(chip) + module = FlatGemmaLayer(config) + params = [ + layer_parameters(self.weights, i) + for i in range(config["num_hidden_layers"]) + ] + self.local = [ + kind == "sliding_attention" for kind in config.get("layer_types", []) + ] + if not self.local: + self.local = [ + (i + 1) % config.get("sliding_window_pattern", 6) != 0 + for i in range(len(params)) + ] + if len(self.local) != len(params): + raise ValueError("layer types do not match layer count") + positions = { + local: attention_inputs(config, width, self.local.index(local)) + for local in set(self.local) + } + rot, mask = positions[self.local[0]] + sample = ( + torch.zeros(width, config["hidden_size"], dtype=torch.bfloat16), + *params[0][0], + *params[0][1], + rot.to(torch.bfloat16), + mask.to(torch.bfloat16), + ) + self.compiled = CompileModule.from_module( + module, + tuple(torch.zeros(t.shape, dtype=t.dtype) for t in sample), + compiler_config=FCConfig(tactic_hint=hint("ForLlmModelPrefill")), + ) + self.compiled.to(self.device) + self.params = [ + tuple(t.contiguous().to(self.device) for t in (*norms, *mats)) + for norms, mats in params + ] + self.positions = { + local: tuple(t.to(torch.bfloat16).to(self.device) for t in pair) + for local, pair in positions.items() + } + sync(chip) + + @torch.inference_mode() + def prefill(self, tokens): + ids = list(tokens) + if not 0 < len(ids) <= self.width or any( + type(t) is not int or not 0 <= t < self.config["vocab_size"] for t in ids + ): + raise ValueError("invalid tokens or prompt exceeds compiled width") + pad = self.config.get("pad_token_id") + if pad is None: + pad = 0 + x = initial_hidden( + self.weights["model.embed_tokens.weight"], + ids + [pad] * (self.width - len(ids)), + ).to(self.device) + keys, values = [], [] + for i, layer in enumerate(self.params): + x, k, v = self.compiled(x, *layer, *self.positions[self.local[i]]) + keys.append(k) + values.append(v) + self.sync(self.chip) + k = torch.stack([t.cpu().permute(1, 0, 2) for t in keys]) + v = torch.stack([t.cpu().permute(1, 0, 2) for t in values]) + k, v, last_hidden = valid_prefix(k, v, x.cpu(), len(ids)) + logits = final_logits( + last_hidden, + self.weights["model.norm.weight"], + self.weights.get( + "lm_head.weight", self.weights["model.embed_tokens.weight"] + ), + self.config["rms_norm_eps"], + ) + return k, v, logits diff --git a/opt_prime/examples/pd/serving_matrix/rngd_gemma_sweep.py b/opt_prime/examples/pd/serving_matrix/rngd_gemma_sweep.py index c585930c..8b4d1af5 100644 --- a/opt_prime/examples/pd/serving_matrix/rngd_gemma_sweep.py +++ b/opt_prime/examples/pd/serving_matrix/rngd_gemma_sweep.py @@ -6,18 +6,10 @@ from pathlib import Path import torch -from gemma_parts import ( - FlatGemmaLayer, - attention_inputs, - final_logits, - initial_hidden, - layer_parameters, -) +from gemma_prefill import Prefill from huggingface_hub import snapshot_download from inputs import exact_prompt -from rngd_pd.engines.fsdk import CompileModule, FCConfig, dev_str, hint, sync from safetensors import safe_open -from semantic_export import valid_prefix from transformers import AutoTokenizer MODEL = "unsloth/gemma-3-1b-it" @@ -30,7 +22,6 @@ a = p.parse_args() path = Path(snapshot_download(MODEL, revision=REVISION, local_files_only=True)) c = json.loads((path / "config.json").read_text()) -module = FlatGemmaLayer(c) weights = {} for shard in sorted(path.glob("*.safetensors")): with safe_open(shard, framework="pt") as f: @@ -60,35 +51,9 @@ a.width, ) cases = [{"case": "fixed", "ids": ids}] -dev = dev_str(0) start = time.perf_counter() -params = [layer_parameters(weights, i) for i in range(c["num_hidden_layers"])] -rot, mask = attention_inputs(c, a.width, 0) -sample = ( - torch.zeros(a.width, c["hidden_size"], dtype=torch.bfloat16), - *params[0][0], - *params[0][1], - rot.to(torch.bfloat16), - mask.to(torch.bfloat16), -) print(json.dumps({"compile_start": True, "width": a.width}), flush=True) -# Match the contiguous runtime tensors; zeros_like preserves transposed weight strides. -compiled = CompileModule.from_module( - module, - tuple(torch.zeros(t.shape, dtype=t.dtype) for t in sample), - compiler_config=FCConfig(tactic_hint=hint("ForLlmModelPrefill")), -) -compiled.to(dev) -params = [ - tuple(t.contiguous().to(dev) for t in (*norms, *mats)) for norms, mats in params -] -# Only two distinct positional/mask inputs, reused across the layer schedule. -positions = {} -for index in [0, 5]: - positions[index] = tuple( - t.to(torch.bfloat16).to(dev) for t in attention_inputs(c, a.width, index) - ) -sync(0) +engine = Prefill(c, weights, width=a.width) print( json.dumps( {"ready": True, "init_s": time.perf_counter() - start, "width": a.width} @@ -98,28 +63,10 @@ with torch.inference_mode(), open(a.output + ".jsonl", "w", buffering=1) as f: for case_index, case in enumerate(cases): ids = case["ids"] - padded_ids = ids + [tok.pad_token_id] * (a.width - len(ids)) previous = None for repeat in range(3): start = time.perf_counter() - x = initial_hidden(weights["model.embed_tokens.weight"], padded_ids).to(dev) - keys = [] - values = [] - for i, layer in enumerate(params): - local = (i + 1) % c.get("sliding_window_pattern", 6) != 0 - x, k, v = compiled(x, *layer, *positions[0 if local else 5]) - keys.append(k) - values.append(v) - sync(0) - k = torch.stack([t.cpu().permute(1, 0, 2) for t in keys]) - v = torch.stack([t.cpu().permute(1, 0, 2) for t in values]) - k, v, last_hidden = valid_prefix(k, v, x.cpu(), len(ids)) - logits = final_logits( - last_hidden, - weights["model.norm.weight"], - weights.get("lm_head.weight", weights["model.embed_tokens.weight"]), - c["rms_norm_eps"], - ) + k, v, logits = engine.prefill(ids) elapsed = time.perf_counter() - start assert k.shape == v.shape == (26, 1, len(ids), 256) assert all(bool(torch.isfinite(t).all()) for t in (k, v, logits)) diff --git a/opt_prime/examples/pd/serving_matrix/test_gemma_prefill.py b/opt_prime/examples/pd/serving_matrix/test_gemma_prefill.py new file mode 100644 index 00000000..60d7c19b --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/test_gemma_prefill.py @@ -0,0 +1,75 @@ +import sys +import types + +import pytest +import torch +from gemma_prefill import Prefill +from transformers import Gemma3ForCausalLM, Gemma3TextConfig + + +@pytest.fixture +def cpu_sdk(monkeypatch): + sdk = types.ModuleType("rngd_pd.engines.fsdk") + + class Compile: + @staticmethod + def from_module(module, sample, compiler_config): + return module + + sdk.CompileModule = Compile + sdk.FCConfig = lambda **kw: kw + sdk.dev_str = lambda chip: "cpu" + sdk.hint = lambda name: name + sdk.sync = lambda chip: None + for name in ["rngd_pd", "rngd_pd.engines"]: + monkeypatch.setitem(sys.modules, name, types.ModuleType(name)) + monkeypatch.setitem(sys.modules, "rngd_pd.engines.fsdk", sdk) + + +def test_reusable_gemma_prefill_matches_hf_and_reuses_without_stale_prefix(cpu_sdk): + torch.manual_seed(234) + config = Gemma3TextConfig( + hidden_size=16, + intermediate_size=32, + num_hidden_layers=6, + num_attention_heads=4, + num_key_value_heads=1, + head_dim=4, + sliding_window=4, + sliding_window_pattern=6, + query_pre_attn_scalar=4, + vocab_size=32, + pad_token_id=0, + bos_token_id=1, + eos_token_id=2, + ) + config._attn_implementation = "eager" + ref = Gemma3ForCausalLM(config).to(torch.bfloat16).eval() + engine = Prefill(config.to_dict(), ref.state_dict(), width=12) + first = None + with torch.inference_mode(): + for ids in [[1, 4, 5], [1, 7, 8, 9, 10, 11, 12], [1, 4, 5]]: + k, v, logits = engine.prefill(ids) + out = ref(input_ids=torch.tensor([ids]), use_cache=True) + assert k.shape == v.shape == (6, 1, len(ids), 4) + torch.testing.assert_close( + logits, out.logits[0, -1].float(), atol=0.02, rtol=0.08 + ) + for i, layer in enumerate(out.past_key_values.layers): + kept = layer.keys.shape[2] + for actual, expected in [ + (k[i, :, -kept:], layer.keys[0]), + (v[i, :, -kept:], layer.values[0]), + ]: + relative = ( + actual.float() - expected.float() + ).square().mean().sqrt() / expected.float().square().mean().sqrt() + assert float(relative) < 0.03, (i, float(relative)) + if len(ids) == 3: + if first is None: + first = (k.clone(), v.clone(), logits.clone()) + else: + assert all(torch.equal(a, b) for a, b in zip(first, (k, v, logits))) + for ids in [[], list(range(13)), [-1], [32]]: + with pytest.raises(ValueError): + engine.prefill(ids) From 74d0d3b934861265f175dea5c02e33cc383ea85f Mon Sep 17 00:00:00 2001 From: gspark Date: Fri, 23 Oct 2026 22:57:39 +0900 Subject: [PATCH 4/6] feat: validate live RNGD to ATOM HTTP across four models --- .../examples/pd/qwen3_rngd/test_worker.py | 38 ++ opt_prime/examples/pd/qwen3_rngd/worker.py | 19 +- .../examples/pd/serving_matrix/README.md | 4 + .../examples/pd/serving_matrix/STATUS.md | 4 + .../pd/serving_matrix/atom_single_block.py | 2 + .../pd/serving_matrix/check_live_http.py | 194 +++++++ .../serving_matrix/evidence234/events.jsonl | 1 + .../evidence234/live234-gemma-http.json | 400 +++++++++++++++ .../evidence234/live234-http-summary.json | 47 ++ .../evidence234/live234-koni-http.json | 415 +++++++++++++++ .../evidence234/live234-qwen06b-http.json | 484 ++++++++++++++++++ .../evidence234/live234-qwen4b-http.json | 400 +++++++++++++++ .../experiments/2026-10-23-live-http234.md | 44 ++ .../pd/serving_matrix/koni_prefill.py | 45 ++ .../pd/serving_matrix/long_width_variant.py | 5 + .../pd/serving_matrix/test_koni_prefill.py | 23 + 16 files changed, 2121 insertions(+), 4 deletions(-) create mode 100644 opt_prime/examples/pd/serving_matrix/check_live_http.py create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-http.json create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-http-summary.json create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-koni-http.json create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen06b-http.json create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen4b-http.json create mode 100644 opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http234.md create mode 100644 opt_prime/examples/pd/serving_matrix/koni_prefill.py create mode 100644 opt_prime/examples/pd/serving_matrix/test_koni_prefill.py diff --git a/opt_prime/examples/pd/qwen3_rngd/test_worker.py b/opt_prime/examples/pd/qwen3_rngd/test_worker.py index d7fdd2bf..8b382b0f 100644 --- a/opt_prime/examples/pd/qwen3_rngd/test_worker.py +++ b/opt_prime/examples/pd/qwen3_rngd/test_worker.py @@ -69,3 +69,41 @@ def __init__(self, config, weights, width, chip): for invalid in ["test_local_prefill", ":Prefill", "test_local_prefill:"]: with pytest.raises(ValueError): engine_class(invalid) + + +@pytest.mark.parametrize( + "config,expected", + [ + ( + { + "num_hidden_layers": 32, + "num_key_value_heads": 8, + "hidden_size": 4096, + "num_attention_heads": 32, + }, + (32, 8, 128), + ), + ( + { + "num_hidden_layers": 36, + "num_key_value_heads": 8, + "hidden_size": 2560, + "num_attention_heads": 32, + "head_dim": 128, + }, + (36, 8, 128), + ), + ( + { + "num_hidden_layers": 26, + "num_key_value_heads": 1, + "hidden_size": 1152, + "num_attention_heads": 4, + "head_dim": 256, + }, + (26, 1, 256), + ), + ], +) +def test_cache_geometry_preserves_explicit_head_dim(config, expected): + assert worker.cache_geometry(config) == expected diff --git a/opt_prime/examples/pd/qwen3_rngd/worker.py b/opt_prime/examples/pd/qwen3_rngd/worker.py index 104375bb..3b21c3f8 100644 --- a/opt_prime/examples/pd/qwen3_rngd/worker.py +++ b/opt_prime/examples/pd/qwen3_rngd/worker.py @@ -44,6 +44,19 @@ def store_result(slab, req, keys, values): return n +def cache_geometry(config): + head_dim = config.get("head_dim") + if head_dim is None: + heads, hidden = config["num_attention_heads"], config["hidden_size"] + if type(heads) is not int or heads <= 0 or hidden % heads: + raise ValueError("invalid implicit head dimension") + head_dim = hidden // heads + shape = (config["num_hidden_layers"], config["num_key_value_heads"], head_dim) + if any(type(n) is not int or n <= 0 for n in shape): + raise ValueError("invalid cache geometry") + return shape + + def engine_class(factory): """Load an explicit trusted local CLI factory; never select this from request JSON.""" from importlib import import_module @@ -93,10 +106,8 @@ def main(): config = validate(config) shape = (a.slots, 2, a.layers, a.kv_heads, a.max_context, a.head_dim) - if min(shape) <= 0 or (a.layers, a.kv_heads, a.head_dim) != ( - config["num_hidden_layers"], - config["num_key_value_heads"], - config["head_dim"], + if min(shape) <= 0 or (a.layers, a.kv_heads, a.head_dim) != cache_geometry( + config ): raise ValueError("shared-memory geometry does not match checkpoint") weights = {} diff --git a/opt_prime/examples/pd/serving_matrix/README.md b/opt_prime/examples/pd/serving_matrix/README.md index daa0cc2d..53695d9f 100644 --- a/opt_prime/examples/pd/serving_matrix/README.md +++ b/opt_prime/examples/pd/serving_matrix/README.md @@ -174,3 +174,7 @@ For Qwen use `rngd_qwen_sweep --model MODEL --experimental-long-width`; for KONI `check_live_worker.py --python "$WORKER_PYTHON" --model unsloth/gemma-3-1b-it --engine-factory gemma_prefill:Prefill --width 128 --exports "$EXPORT0" "$EXPORT1" "$EXPORT2" "$EXPORT3" --output live-worker.json` runs real prefill per request, verifies returned KV and first tokens against trusted exports, and checks rejection/recovery for an oversized prompt. Run under the decoder-side environment with its existing core package; the worker interpreter owns the RNGD SDK. Short-input producer/full-logit parity and real shared-memory requests are verified. This is not yet full HTTP PD or long live integration. Numerical mismatch #233 remains, and no compute-transfer overlap or serving speedup is claimed. See the live-model-pd234 experiment and evidence234. + +`check_live_http.py` runs actual RNGD prefill and ATOM HTTP decode from token fixtures (it does not load saved KV). Pass `--batching` with the reviewed ATOM scheduler, `--http-module` with the #214 SIGPIPE-fixed server, the model/artifact cache, `--worker-python`, factory/width and fixture/baseline JSON. It checks two serial passes, four queued clients, cancel/disconnect and reuse. Factories: `prefill:Prefill` for short Qwen3, `long_width_variant:make_prefill` for the explicit experimental long Qwen variant, `gemma_prefill:Prefill`, and `koni_prefill:Prefill` for partitioned KONI widths divisible by512. KONI uses `--kv-blocks 1` with #236; other measured artifacts use3. Explicit head_dim is preserved; Llama's missing field is inferred from hidden size/attention heads. + +All four short-input live HTTP paths pass56normal/reuse response checks and64remote prefills including cancellations. Native-output parity does not imply answer quality. Width2048 live validation is pending; hardware batch remains1 and no matched performance benefit is established. See live-http234 record. diff --git a/opt_prime/examples/pd/serving_matrix/STATUS.md b/opt_prime/examples/pd/serving_matrix/STATUS.md index b5f538c2..d1d148d4 100644 --- a/opt_prime/examples/pd/serving_matrix/STATUS.md +++ b/opt_prime/examples/pd/serving_matrix/STATUS.md @@ -59,3 +59,7 @@ Final6K matrix:48producer runs,31/32 EOS comparisons across four models/four que ## Live worker integration (#234) Reusable Gemma producer matches original RNGD K/V/full logits4/4 at width128. Real SubprocessPrefillWorker5requests match K/V/token and recover after an oversized request;15CPU tests plus5subtests pass. No communication-protocol change. Full live HTTP, other adapters and long/lifecycle conditions remain open; #233 numerical limits retained. + +## Four-model actual HTTP PD (#234/#236) + +All four models:56/56 normal/concurrent/reuse responses equal native ATOM,64RNGD prefills and0local fallbacks. Cancellation/disconnect reuse passes. B1, cache-off, short prompts; KONI uses existingk1 artifact with#236. HTTP uses#214 SIGPIPE fix. No live-transfer-overlap or throughput gain claim. Width2048 live queue pending; long/cache/hardware-batch/performance scope remains. diff --git a/opt_prime/examples/pd/serving_matrix/atom_single_block.py b/opt_prime/examples/pd/serving_matrix/atom_single_block.py index 279dd435..0095521a 100644 --- a/opt_prime/examples/pd/serving_matrix/atom_single_block.py +++ b/opt_prime/examples/pd/serving_matrix/atom_single_block.py @@ -28,6 +28,8 @@ def __init__(self, model): or m.get("layer_type", "full_attention") != "full_attention" ): raise ValueError("requires uniform full-attention cache geometry") + self.hybrid_cache = False + self.single_block = True self.io_rt = model.model[1] self.lane_block = [0] self._stage = None diff --git a/opt_prime/examples/pd/serving_matrix/check_live_http.py b/opt_prime/examples/pd/serving_matrix/check_live_http.py new file mode 100644 index 00000000..ffecd42d --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/check_live_http.py @@ -0,0 +1,194 @@ +"""Actual RNGD subprocess prefill to ATOM HTTP, with native-output and lifecycle checks.""" + +import argparse +import importlib.util +import json +import os +import sys +import threading +import time +import urllib.request +from concurrent.futures import ThreadPoolExecutor +from pathlib import Path + +p = argparse.ArgumentParser(description=__doc__) +p.add_argument("--batching", required=True) +p.add_argument("--cache-dir", required=True) +p.add_argument("--fixtures", required=True) +p.add_argument("--cases", nargs="+", required=True) +p.add_argument("--worker-python", required=True) +p.add_argument("--engine-factory", required=True) +p.add_argument("--width", type=int, required=True) +p.add_argument("--kv-blocks", type=int, default=3) +p.add_argument("--model", default="unsloth/gemma-3-1b-it") +p.add_argument("--http-module", required=True) +p.add_argument("--baseline", required=True) +p.add_argument("--output", required=True) +a = p.parse_args() +for name, path in [ + ("opt_prime.accel.platforms.atom.batching", a.batching), + ("opt_prime.accel.serve.llmd", a.http_module), +]: + spec = importlib.util.spec_from_file_location(name, path) + module = importlib.util.module_from_spec(spec) + sys.modules[name] = module + spec.loader.exec_module(module) +from opt_prime.accel.pd.pd_batching import SubprocessPrefillWorker +from opt_prime.accel.platforms.atom.engine import AtomRblnEngine +from opt_prime.accel.serve.batched import BatchedOwner, BatchedService +from opt_prime.accel.serve.llmd import serve_stage +from transformers import AutoTokenizer + +fixtures = json.loads(Path(a.fixtures).read_text()) +cases = [r for r in fixtures["cases"] if r["case"] in a.cases] +assert {r["case"] for r in cases} == set(a.cases) +assert cases and all(0 < len(r["ids"]) <= a.width for r in cases) +baseline = { + r["case"]: r["tokens"] + for r in map(json.loads, Path(a.baseline).read_text().splitlines()) +} + + +nodes = list(Path("/dev").glob("rbln[0-9]*")) +assert len(nodes) == 1 +engine = AtomRblnEngine( + devices=[int(nodes[0].name[4:])], + max_seq_len=9216, + batch_size=1, + kv_blocks=a.kv_blocks, + cache_dir=a.cache_dir, +) +worker = None +owner = thread = server = http = None +rows = [] +try: + model = a.model + engine.start(model) + c = engine.model.config.get_text_config() + worker = SubprocessPrefillWorker( + a.worker_python, + [ + "--model", + model, + "--width", + str(a.width), + "--engine-factory", + a.engine_factory, + ], + slots=1, + layers=c.num_hidden_layers, + kv_heads=c.num_key_value_heads, + head_dim=getattr(c, "head_dim", None) or c.hidden_size // c.num_attention_heads, + max_context=a.width, + env=dict(os.environ), + ) + tok = AutoTokenizer.from_pretrained(model, local_files_only=True) + b = engine.batcher(prefix_cache=False, prefill_worker=worker, local_prefill=False) + service = BatchedService( + b, + model=model, + vocab_size=engine.model.config.vocab_size, + max_output=64, + render=lambda ids: tok.decode(ids, skip_special_tokens=True), + tokenizer=tok, + eos_token_ids=tuple(fixtures["eos_ids"]), + ) + owner = BatchedOwner(service) + thread = threading.Thread(target=owner.run, daemon=True) + thread.start() + server, http = serve_stage(owner, "decode", 0) + + def request(path, body, rid): + req = urllib.request.Request( + f"http://127.0.0.1:{server.server_port}{path}", + data=json.dumps(body).encode(), + headers={"x-request-id": rid}, + ) + return urllib.request.urlopen(req, timeout=60) + + def complete(r, rid): + started = time.perf_counter() + with request( + "/v1/completions", + {"model": model, "prompt": r["ids"], "max_tokens": 64}, + rid, + ) as response: + out = json.load(response) + assert out["choices"][0]["finish_reason"] == "stop" + assert out["choices"][0]["token_ids"] == baseline[r["case"]], out + rows.append( + { + "case": r["case"], + "request": rid, + "response": out, + "latency_s": time.perf_counter() - started, + } + ) + + # Alternate long and short prefixes while blocks rotate under the same local lane. + for repeat in range(2): + for i, r in enumerate(cases): + complete(r, f"normal-{repeat}-{i}") + with ThreadPoolExecutor(max_workers=4) as clients: + list( + clients.map( + lambda pair: complete(pair[1], f"concurrent-{pair[0]}"), + enumerate(cases), + ) + ) + for mode in ["cancel", "disconnect"]: + r = cases[-1] + with request( + "/v1/completions", + { + "model": model, + "prompt": r["ids"], + "max_tokens": 64, + "stream": True, + "ignore_eos": True, + }, + mode, + ) as response: + for raw in response: + if raw.startswith(b"data: ") and b"[DONE]" not in raw: + event = json.loads(raw[6:]) + if event.get("choices") and event["choices"][0].get("text"): + break + else: + raise AssertionError("no streamed text") + if mode == "cancel": + with request("/v1/cancel", {}, mode) as cancelled: + assert cancelled.status == 202 + end = time.monotonic() + 10 + while mode in b.by_id and time.monotonic() < end: + time.sleep(0.01) + assert mode not in b.by_id + complete(cases[0], "after-" + mode) + assert b.stats_pd["local"] == 0 and sorted(b.free) == [0] + assert b.stats_pd["remote"] == len(rows) + 2 + result = { + "worker": "live_rngd_subprocess_prefill", + "rows": rows, + "stats_pd": b.stats_pd, + "free": b.free, + "cancellation_reuse": True, + } + Path(a.output).write_text(json.dumps(result, ensure_ascii=False, indent=2) + "\n") + print( + json.dumps( + {"requests": len(rows), "stats_pd": b.stats_pd, "cancellation_reuse": True} + ), + flush=True, + ) +finally: + if owner: + owner.submit("stop") + if thread: + thread.join(15) + if server: + server.shutdown() + server.server_close() + http.join(5) + if worker: + worker.close() + engine.close() diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl b/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl index bcd190fe..86b05c78 100644 --- a/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl +++ b/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl @@ -1 +1,2 @@ {"id": "819c75b3957c4f0b980915096014c36f", "ts": "2026-10-23T22:30:07+09:00", "task": "Live four-model PD integration (aicomp #234)", "result": "Callable Gemma refactor:4/4 full K/V/logits bit-exact on RNGD; actual subprocess/shared-memory worker5/5 exact and oversize recovery pass.15CPU tests+5subtests. No live HTTP claim yet.", "next": "Connect live worker to production ATOM HTTP; extend Qwen/KONI adapters and long-prefix/lifecycle conditions.", "state": "active", "done": false, "blocker": "", "metrics": {}, "params": {"model": "Gemma3-1B", "width": "128"}, "artifacts": ["opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-worker.json"], "experiments": ["opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-model-pd234.md"], "labels": ["experiment"], "review": true, "todos": [], "note": "", "agent": "codex", "host": "validation host", "branch": "main", "commit": "351d39d-dirty"} +{"id": "fdd4a316d5cb433e8b2b56028ac53379", "ts": "2026-10-23T22:52:06+09:00", "task": "Live four-model PD integration (aicomp #234)", "result": "Real RNGD->ATOM HTTP four models:56/56 normal/reuse outputs exact,64remote/0local prefills; concurrent clients and cancel/disconnect recovery pass. KONI k1 enabled by#236;22adapter tests+5subtests and43scheduler tests. Width2048 queue started.", "next": "Collect live medium-context queue; publish #236 and adapter updates, then controlled native/PD performance and remaining cache/overlap.", "state": "active", "done": false, "blocker": "", "metrics": {}, "params": {"hardware_batch": "1", "mode": "live_rngd_atom_http"}, "artifacts": ["opt_prime/examples/pd/serving_matrix/evidence234/live234-http-summary.json"], "experiments": ["opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http234.md"], "labels": ["experiment"], "review": true, "todos": [], "note": "", "agent": "codex", "host": "RNGD+ATOM host", "branch": "main", "commit": "351d39d-dirty"} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-http.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-http.json new file mode 100644 index 00000000..b822177b --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-http.json @@ -0,0 +1,400 @@ +{ + "worker": "live_rngd_subprocess_prefill", + "rows": [ + { + "case": "capital-0", + "request": "normal-0-0", + "response": { + "id": "normal-0-0", + "object": "text_completion", + "created": 1792762562, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 23, + "completion_tokens": 2, + "total_tokens": 25 + } + }, + "latency_s": 0.17397043097298592 + }, + { + "case": "arithmetic-0", + "request": "normal-0-1", + "response": { + "id": "normal-0-1", + "object": "text_completion", + "created": 1792762562, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "42\n", + "token_ids": [ + 236812, + 236778, + 107, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 24, + "completion_tokens": 4, + "total_tokens": 28 + } + }, + "latency_s": 0.08812864299397916 + }, + { + "case": "korean-0", + "request": "normal-0-2", + "response": { + "id": "normal-0-2", + "object": "text_completion", + "created": 1792762562, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "서울특별시", + "token_ids": [ + 222340, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 24, + "completion_tokens": 2, + "total_tokens": 26 + } + }, + "latency_s": 0.06688711000606418 + }, + { + "case": "retrieval-0", + "request": "normal-0-3", + "response": { + "id": "normal-0-3", + "object": "text_completion", + "created": 1792762562, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 28487, + 1618, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 28, + "completion_tokens": 3, + "total_tokens": 31 + } + }, + "latency_s": 0.07794601400382817 + }, + { + "case": "capital-0", + "request": "normal-1-0", + "response": { + "id": "normal-1-0", + "object": "text_completion", + "created": 1792762562, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 23, + "completion_tokens": 2, + "total_tokens": 25 + } + }, + "latency_s": 0.06611597491428256 + }, + { + "case": "arithmetic-0", + "request": "normal-1-1", + "response": { + "id": "normal-1-1", + "object": "text_completion", + "created": 1792762563, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "42\n", + "token_ids": [ + 236812, + 236778, + 107, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 24, + "completion_tokens": 4, + "total_tokens": 28 + } + }, + "latency_s": 0.08932010200805962 + }, + { + "case": "korean-0", + "request": "normal-1-2", + "response": { + "id": "normal-1-2", + "object": "text_completion", + "created": 1792762563, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "서울특별시", + "token_ids": [ + 222340, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 24, + "completion_tokens": 2, + "total_tokens": 26 + } + }, + "latency_s": 0.06798817799426615 + }, + { + "case": "retrieval-0", + "request": "normal-1-3", + "response": { + "id": "normal-1-3", + "object": "text_completion", + "created": 1792762563, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 28487, + 1618, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 28, + "completion_tokens": 3, + "total_tokens": 31 + } + }, + "latency_s": 0.07829866698011756 + }, + { + "case": "capital-0", + "request": "concurrent-0", + "response": { + "id": "concurrent-0", + "object": "text_completion", + "created": 1792762563, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 23, + "completion_tokens": 2, + "total_tokens": 25 + } + }, + "latency_s": 0.06778034707531333 + }, + { + "case": "arithmetic-0", + "request": "concurrent-1", + "response": { + "id": "concurrent-1", + "object": "text_completion", + "created": 1792762563, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "42\n", + "token_ids": [ + 236812, + 236778, + 107, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 24, + "completion_tokens": 4, + "total_tokens": 28 + } + }, + "latency_s": 0.15490090299863368 + }, + { + "case": "korean-0", + "request": "concurrent-2", + "response": { + "id": "concurrent-2", + "object": "text_completion", + "created": 1792762563, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "서울특별시", + "token_ids": [ + 222340, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 24, + "completion_tokens": 2, + "total_tokens": 26 + } + }, + "latency_s": 0.21974424994550645 + }, + { + "case": "retrieval-0", + "request": "concurrent-3", + "response": { + "id": "concurrent-3", + "object": "text_completion", + "created": 1792762563, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 28487, + 1618, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 28, + "completion_tokens": 3, + "total_tokens": 31 + } + }, + "latency_s": 0.29593874304555357 + }, + { + "case": "capital-0", + "request": "after-cancel", + "response": { + "id": "after-cancel", + "object": "text_completion", + "created": 1792762563, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 23, + "completion_tokens": 2, + "total_tokens": 25 + } + }, + "latency_s": 0.06744227407034487 + }, + { + "case": "capital-0", + "request": "after-disconnect", + "response": { + "id": "after-disconnect", + "object": "text_completion", + "created": 1792762563, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 23, + "completion_tokens": 2, + "total_tokens": 25 + } + }, + "latency_s": 0.06791288801468909 + } + ], + "stats_pd": { + "remote": 16, + "local": 0 + }, + "free": [ + 0 + ], + "cancellation_reuse": true +} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-http-summary.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-http-summary.json new file mode 100644 index 00000000..78dbb18f --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-http-summary.json @@ -0,0 +1,47 @@ +{ + "gemma": { + "responses": 14, + "remote_prefills": 16, + "local_prefills": 0, + "cancellation_reuse": true, + "input_tokens": [ + 23, + 24, + 28 + ] + }, + "qwen06b": { + "responses": 14, + "remote_prefills": 16, + "local_prefills": 0, + "cancellation_reuse": true, + "input_tokens": [ + 26, + 27, + 31 + ] + }, + "qwen4b": { + "responses": 14, + "remote_prefills": 16, + "local_prefills": 0, + "cancellation_reuse": true, + "input_tokens": [ + 26, + 27, + 31 + ] + }, + "koni": { + "responses": 14, + "remote_prefills": 16, + "local_prefills": 0, + "cancellation_reuse": true, + "input_tokens": [ + 137, + 138, + 139, + 143 + ] + } +} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-koni-http.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-koni-http.json new file mode 100644 index 00000000..b3a13143 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-koni-http.json @@ -0,0 +1,415 @@ +{ + "worker": "live_rngd_subprocess_prefill", + "rows": [ + { + "case": "capital-0", + "request": "normal-0-0", + "response": { + "id": "normal-0-0", + "object": "text_completion", + "created": 1792763172, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 60704, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 138, + "completion_tokens": 2, + "total_tokens": 140 + } + }, + "latency_s": 0.4229255300015211 + }, + { + "case": "arithmetic-0", + "request": "normal-0-1", + "response": { + "id": "normal-0-1", + "object": "text_completion", + "created": 1792763173, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "17 + 25 = 42.", + "token_ids": [ + 1114, + 489, + 220, + 914, + 284, + 220, + 2983, + 13, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 137, + "completion_tokens": 9, + "total_tokens": 146 + } + }, + "latency_s": 0.7874407280469313 + }, + { + "case": "korean-0", + "request": "normal-0-2", + "response": { + "id": "normal-0-2", + "object": "text_completion", + "created": 1792763174, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 115978, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 139, + "completion_tokens": 2, + "total_tokens": 141 + } + }, + "latency_s": 0.3736360300099477 + }, + { + "case": "retrieval-0", + "request": "normal-0-3", + "response": { + "id": "normal-0-3", + "object": "text_completion", + "created": 1792763174, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 18082, + 877, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 143, + "completion_tokens": 3, + "total_tokens": 146 + } + }, + "latency_s": 0.41646945395041257 + }, + { + "case": "capital-0", + "request": "normal-1-0", + "response": { + "id": "normal-1-0", + "object": "text_completion", + "created": 1792763174, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 60704, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 138, + "completion_tokens": 2, + "total_tokens": 140 + } + }, + "latency_s": 0.3646502789342776 + }, + { + "case": "arithmetic-0", + "request": "normal-1-1", + "response": { + "id": "normal-1-1", + "object": "text_completion", + "created": 1792763175, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "17 + 25 = 42.", + "token_ids": [ + 1114, + 489, + 220, + 914, + 284, + 220, + 2983, + 13, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 137, + "completion_tokens": 9, + "total_tokens": 146 + } + }, + "latency_s": 0.8413291039178148 + }, + { + "case": "korean-0", + "request": "normal-1-2", + "response": { + "id": "normal-1-2", + "object": "text_completion", + "created": 1792763176, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 115978, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 139, + "completion_tokens": 2, + "total_tokens": 141 + } + }, + "latency_s": 0.3697471059858799 + }, + { + "case": "retrieval-0", + "request": "normal-1-3", + "response": { + "id": "normal-1-3", + "object": "text_completion", + "created": 1792763176, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 18082, + 877, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 143, + "completion_tokens": 3, + "total_tokens": 146 + } + }, + "latency_s": 0.44573811802547425 + }, + { + "case": "capital-0", + "request": "concurrent-0", + "response": { + "id": "concurrent-0", + "object": "text_completion", + "created": 1792763176, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 60704, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 138, + "completion_tokens": 2, + "total_tokens": 140 + } + }, + "latency_s": 0.36879166797734797 + }, + { + "case": "arithmetic-0", + "request": "concurrent-1", + "response": { + "id": "concurrent-1", + "object": "text_completion", + "created": 1792763177, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "17 + 25 = 42.", + "token_ids": [ + 1114, + 489, + 220, + 914, + 284, + 220, + 2983, + 13, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 137, + "completion_tokens": 9, + "total_tokens": 146 + } + }, + "latency_s": 1.2019858930725604 + }, + { + "case": "korean-0", + "request": "concurrent-2", + "response": { + "id": "concurrent-2", + "object": "text_completion", + "created": 1792763178, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 115978, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 139, + "completion_tokens": 2, + "total_tokens": 141 + } + }, + "latency_s": 1.5741613419959322 + }, + { + "case": "retrieval-0", + "request": "concurrent-3", + "response": { + "id": "concurrent-3", + "object": "text_completion", + "created": 1792763178, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 18082, + 877, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 143, + "completion_tokens": 3, + "total_tokens": 146 + } + }, + "latency_s": 2.007744933012873 + }, + { + "case": "capital-0", + "request": "after-cancel", + "response": { + "id": "after-cancel", + "object": "text_completion", + "created": 1792763179, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 60704, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 138, + "completion_tokens": 2, + "total_tokens": 140 + } + }, + "latency_s": 0.3682253049919382 + }, + { + "case": "capital-0", + "request": "after-disconnect", + "response": { + "id": "after-disconnect", + "object": "text_completion", + "created": 1792763180, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 60704, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 138, + "completion_tokens": 2, + "total_tokens": 140 + } + }, + "latency_s": 0.3731464589945972 + } + ], + "stats_pd": { + "remote": 16, + "local": 0 + }, + "free": [ + 0 + ], + "cancellation_reuse": true +} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen06b-http.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen06b-http.json new file mode 100644 index 00000000..380d2f71 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen06b-http.json @@ -0,0 +1,484 @@ +{ + "worker": "live_rngd_subprocess_prefill", + "rows": [ + { + "case": "capital-0", + "request": "normal-0-0", + "response": { + "id": "normal-0-0", + "object": "text_completion", + "created": 1792762650, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 26, + "completion_tokens": 2, + "total_tokens": 28 + } + }, + "latency_s": 0.3779727650107816 + }, + { + "case": "arithmetic-0", + "request": "normal-0-1", + "response": { + "id": "normal-0-1", + "object": "text_completion", + "created": 1792762650, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "17 + 25 = 42\n\nReply with only the integer: **42**.", + "token_ids": [ + 16, + 22, + 488, + 220, + 17, + 20, + 284, + 220, + 19, + 17, + 271, + 20841, + 448, + 1172, + 279, + 7546, + 25, + 3070, + 19, + 17, + 334, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 27, + "completion_tokens": 23, + "total_tokens": 50 + } + }, + "latency_s": 0.227519836043939 + }, + { + "case": "korean-0", + "request": "normal-0-2", + "response": { + "id": "normal-0-2", + "object": "text_completion", + "created": 1792762650, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "대한민국의 수도는 서울입니다.", + "token_ids": [ + 66845, + 23573, + 125496, + 124785, + 20401, + 134013, + 16560, + 136905, + 78952, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 31, + "completion_tokens": 11, + "total_tokens": 42 + } + }, + "latency_s": 0.14687276305630803 + }, + { + "case": "retrieval-0", + "request": "normal-0-3", + "response": { + "id": "normal-0-3", + "object": "text_completion", + "created": 1792762650, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 31, + "completion_tokens": 3, + "total_tokens": 34 + } + }, + "latency_s": 0.09232904796954244 + }, + { + "case": "capital-0", + "request": "normal-1-0", + "response": { + "id": "normal-1-0", + "object": "text_completion", + "created": 1792762650, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 26, + "completion_tokens": 2, + "total_tokens": 28 + } + }, + "latency_s": 0.08383574697654694 + }, + { + "case": "arithmetic-0", + "request": "normal-1-1", + "response": { + "id": "normal-1-1", + "object": "text_completion", + "created": 1792762651, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "17 + 25 = 42\n\nReply with only the integer: **42**.", + "token_ids": [ + 16, + 22, + 488, + 220, + 17, + 20, + 284, + 220, + 19, + 17, + 271, + 20841, + 448, + 1172, + 279, + 7546, + 25, + 3070, + 19, + 17, + 334, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 27, + "completion_tokens": 23, + "total_tokens": 50 + } + }, + "latency_s": 0.22187654604204 + }, + { + "case": "korean-0", + "request": "normal-1-2", + "response": { + "id": "normal-1-2", + "object": "text_completion", + "created": 1792762651, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "대한민국의 수도는 서울입니다.", + "token_ids": [ + 66845, + 23573, + 125496, + 124785, + 20401, + 134013, + 16560, + 136905, + 78952, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 31, + "completion_tokens": 11, + "total_tokens": 42 + } + }, + "latency_s": 0.1449671690352261 + }, + { + "case": "retrieval-0", + "request": "normal-1-3", + "response": { + "id": "normal-1-3", + "object": "text_completion", + "created": 1792762651, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 31, + "completion_tokens": 3, + "total_tokens": 34 + } + }, + "latency_s": 0.09237896895501763 + }, + { + "case": "capital-0", + "request": "concurrent-0", + "response": { + "id": "concurrent-0", + "object": "text_completion", + "created": 1792762651, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 26, + "completion_tokens": 2, + "total_tokens": 28 + } + }, + "latency_s": 0.08503968501463532 + }, + { + "case": "korean-0", + "request": "concurrent-2", + "response": { + "id": "concurrent-2", + "object": "text_completion", + "created": 1792762651, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "대한민국의 수도는 서울입니다.", + "token_ids": [ + 66845, + 23573, + 125496, + 124785, + 20401, + 134013, + 16560, + 136905, + 78952, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 31, + "completion_tokens": 11, + "total_tokens": 42 + } + }, + "latency_s": 0.22497885895427316 + }, + { + "case": "arithmetic-0", + "request": "concurrent-1", + "response": { + "id": "concurrent-1", + "object": "text_completion", + "created": 1792762651, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "17 + 25 = 42\n\nReply with only the integer: **42**.", + "token_ids": [ + 16, + 22, + 488, + 220, + 17, + 20, + 284, + 220, + 19, + 17, + 271, + 20841, + 448, + 1172, + 279, + 7546, + 25, + 3070, + 19, + 17, + 334, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 27, + "completion_tokens": 23, + "total_tokens": 50 + } + }, + "latency_s": 0.44751804997213185 + }, + { + "case": "retrieval-0", + "request": "concurrent-3", + "response": { + "id": "concurrent-3", + "object": "text_completion", + "created": 1792762651, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 31, + "completion_tokens": 3, + "total_tokens": 34 + } + }, + "latency_s": 0.5371290389448404 + }, + { + "case": "capital-0", + "request": "after-cancel", + "response": { + "id": "after-cancel", + "object": "text_completion", + "created": 1792762652, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 26, + "completion_tokens": 2, + "total_tokens": 28 + } + }, + "latency_s": 0.08413173002190888 + }, + { + "case": "capital-0", + "request": "after-disconnect", + "response": { + "id": "after-disconnect", + "object": "text_completion", + "created": 1792762652, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 26, + "completion_tokens": 2, + "total_tokens": 28 + } + }, + "latency_s": 0.0885854009538889 + } + ], + "stats_pd": { + "remote": 16, + "local": 0 + }, + "free": [ + 0 + ], + "cancellation_reuse": true +} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen4b-http.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen4b-http.json new file mode 100644 index 00000000..0084d1d6 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen4b-http.json @@ -0,0 +1,400 @@ +{ + "worker": "live_rngd_subprocess_prefill", + "rows": [ + { + "case": "capital-0", + "request": "normal-0-0", + "response": { + "id": "normal-0-0", + "object": "text_completion", + "created": 1792762779, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 26, + "completion_tokens": 2, + "total_tokens": 28 + } + }, + "latency_s": 0.6855041530216113 + }, + { + "case": "arithmetic-0", + "request": "normal-0-1", + "response": { + "id": "normal-0-1", + "object": "text_completion", + "created": 1792762779, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "52", + "token_ids": [ + 20, + 17, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 27, + "completion_tokens": 3, + "total_tokens": 30 + } + }, + "latency_s": 0.19621982797980309 + }, + { + "case": "korean-0", + "request": "normal-0-2", + "response": { + "id": "normal-0-2", + "object": "text_completion", + "created": 1792762780, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 26698, + 126893, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 31, + "completion_tokens": 3, + "total_tokens": 34 + } + }, + "latency_s": 0.20220612501725554 + }, + { + "case": "retrieval-0", + "request": "normal-0-3", + "response": { + "id": "normal-0-3", + "object": "text_completion", + "created": 1792762780, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 31, + "completion_tokens": 3, + "total_tokens": 34 + } + }, + "latency_s": 0.21435286104679108 + }, + { + "case": "capital-0", + "request": "normal-1-0", + "response": { + "id": "normal-1-0", + "object": "text_completion", + "created": 1792762780, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 26, + "completion_tokens": 2, + "total_tokens": 28 + } + }, + "latency_s": 0.17381490301340818 + }, + { + "case": "arithmetic-0", + "request": "normal-1-1", + "response": { + "id": "normal-1-1", + "object": "text_completion", + "created": 1792762780, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "52", + "token_ids": [ + 20, + 17, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 27, + "completion_tokens": 3, + "total_tokens": 30 + } + }, + "latency_s": 0.20950887200888246 + }, + { + "case": "korean-0", + "request": "normal-1-2", + "response": { + "id": "normal-1-2", + "object": "text_completion", + "created": 1792762780, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 26698, + 126893, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 31, + "completion_tokens": 3, + "total_tokens": 34 + } + }, + "latency_s": 0.21188442199490964 + }, + { + "case": "retrieval-0", + "request": "normal-1-3", + "response": { + "id": "normal-1-3", + "object": "text_completion", + "created": 1792762781, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 31, + "completion_tokens": 3, + "total_tokens": 34 + } + }, + "latency_s": 0.21210102399345487 + }, + { + "case": "capital-0", + "request": "concurrent-0", + "response": { + "id": "concurrent-0", + "object": "text_completion", + "created": 1792762781, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 26, + "completion_tokens": 2, + "total_tokens": 28 + } + }, + "latency_s": 0.18024980393238366 + }, + { + "case": "arithmetic-0", + "request": "concurrent-1", + "response": { + "id": "concurrent-1", + "object": "text_completion", + "created": 1792762781, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "52", + "token_ids": [ + 20, + 17, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 27, + "completion_tokens": 3, + "total_tokens": 30 + } + }, + "latency_s": 0.3912503090687096 + }, + { + "case": "korean-0", + "request": "concurrent-2", + "response": { + "id": "concurrent-2", + "object": "text_completion", + "created": 1792762781, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 26698, + 126893, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 31, + "completion_tokens": 3, + "total_tokens": 34 + } + }, + "latency_s": 0.6002984389197081 + }, + { + "case": "retrieval-0", + "request": "concurrent-3", + "response": { + "id": "concurrent-3", + "object": "text_completion", + "created": 1792762781, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 31, + "completion_tokens": 3, + "total_tokens": 34 + } + }, + "latency_s": 0.8154195169918239 + }, + { + "case": "capital-0", + "request": "after-cancel", + "response": { + "id": "after-cancel", + "object": "text_completion", + "created": 1792762782, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 26, + "completion_tokens": 2, + "total_tokens": 28 + } + }, + "latency_s": 0.1792328970041126 + }, + { + "case": "capital-0", + "request": "after-disconnect", + "response": { + "id": "after-disconnect", + "object": "text_completion", + "created": 1792762782, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 26, + "completion_tokens": 2, + "total_tokens": 28 + } + }, + "latency_s": 0.21111171692609787 + } + ], + "stats_pd": { + "remote": 16, + "local": 0 + }, + "free": [ + 0 + ], + "cancellation_reuse": true +} diff --git a/opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http234.md b/opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http234.md new file mode 100644 index 00000000..6431c29c --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http234.md @@ -0,0 +1,44 @@ +# Four-model live RNGD to ATOM HTTP PD + +- **Date**: 2026-10-23 +- **Task**: aicomp #234, single-block support #236 +- **Host / device**: owned paired RNGD+ATOM allocation, one of each accelerator; hardware batch1, CPU threads4. +- **Commit**: adapter branch3855050 plus current HTTP/KONI changes; AtomBatcher1e54786 for Gemma/Qwen, #236 working tree based69bca73 for KONI; HTTP SIGPIPE fix9e442cd loaded process-locally. +- **SDKs**: producer furiosa-torch2026.4.0 / torch2.10.0+cpu / transformers5.19.0; decoder optimum-rbln0.11.0.post1 / rebel-compiler0.11.0 / torch2.11.0+cpu / transformers5.8.1. + +## Question + +Can each validated producer handle real HTTP-triggered prefill through SubprocessPrefillWorker, shared-memory KV import and the production ATOM scheduler/owner/server, including queued clients and cancellation/reuse? + +## Setup + +No saved KV is loaded by check_live_http.py. It reads only input/EOS fixtures and native output baselines. Each request performs live RNGD prefill, returns KV through the existing shared-memory protocol, and decodes on ATOM. Four semantic questions, two sequential passes, one four-client concurrent pass, two streaming cancellation/disconnect requests and a successful reuse after each.14normal/reuse output checks and16remote prefills per model. Concurrency queues on a B1 lane; this is not hardware batch4. + +Gemma/Qwen artifacts use context9216/k3; KONI uses its existing static context9216/k1 artifact with the #236 scheduler fix. Prefix and host caches disabled. Corrected Gemma global-causal artifact from #225; pinned revisions are unchanged from #227. Token lists and EOS finish reason must equal native ATOM baselines. This criterion does not establish answer quality (known shared wrong answers remain in #227/#233). + +## Command + +```bash +bash run-live-http234.sh --batching atom_batching231.py --http-module llmd214.py --cache-dir atom-artifacts-global225 --fixtures semantic227-gemma-fixtures.json --cases capital-0 arithmetic-0 korean-0 retrieval-0 --worker-python "$WORKER_PYTHON" --engine-factory gemma_prefill:Prefill --width 128 --baseline semantic227-gemma-atom.jsonl --output live234-gemma-http.json +``` + +The isolated launcher runs check_live_http.py under the decoder interpreter/bootstrap. For Qwen use --model Qwen/Qwen3-0.6B orQwen/Qwen3-4B, --cache-dir atom-artifacts, --engine-factory prefill:Prefill and matching qwen06b/qwen4b fixtures/baselines/output. For KONI use --model KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024, --batching atom_batching236.py, --cache-dir atom-artifacts --kv-blocks 1, --engine-factory koni_prefill:Prefill --width 512, semantic227-koni-fixtures-eos.json and semantic227-koni-atom.jsonl. No installed SDK/core files changed. + +## Results + +| Model | Prompt tokens | Compiled width | Exact normal/reuse responses | Remote/local prefills | Cancel/disconnect reuse | +|---|---:|---:|---:|---:|---| +| Gemma3-1B | 23–28 | 128 | 14/14 | 16/0 | pass | +| Qwen3-0.6B | 26–31 | 128 | 14/14 | 16/0 | pass | +| Qwen3-4B | 26–31 | 128 | 14/14 | 16/0 | pass | +| KONI-8B | 137–143 | 512 | 14/14 | 16/0 | pass | + +Total56exact responses and64actual RNGD prefills, zero local fallbacks. Each final free-lane list is[0]. Client latency observations are included in JSON but this is not a matched native-vs-PD benchmark or throughput claim. The previous vendor SIGPIPE backtraces do not appear with the separately tested #214 module; the ordinary tokenizer cleanup warning remains on KONI. + +Supporting CPU tests: #234 adapter/geometry22tests plus5subtests; #236 scheduler43tests, one existing unfused attention warning. Before #236, single-block PD fails at construction (1failed/3passed); cache/multi-lane rejection tests remain green. KONI raw config omits head_dim: worker infers128 only when absent and preserves explicit Qwen/Gemma head dimensions. + +## Conclusion + +All four models now have short-input real RNGD->ATOM HTTP evidence, replacing replay-only coverage for this condition. Remaining: live medium/long prefixes, prefill-time cancellation/fault recovery, prefix/host-cache restoration, hardware batch coverage, true compute-transfer overlap and controlled serving performance comparison. A width2048 queue for the four *-100 fixtures has started in the owned paired allocation; results are pending. Overall goal remains active. + +Raw evidence: analysis/serving-matrix-201/live234-{gemma,qwen06b,qwen4b,koni}-http.json/.log and live234-http-summary.json. Pending queue: live234-mid-queue.log. diff --git a/opt_prime/examples/pd/serving_matrix/koni_prefill.py b/opt_prime/examples/pd/serving_matrix/koni_prefill.py new file mode 100644 index 00000000..ece376aa --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/koni_prefill.py @@ -0,0 +1,45 @@ +"""Callable adapter for the validated partitioned Llama3.1/KONI prefill graph.""" + +from types import SimpleNamespace + +import torch +from koni_export import export_groups, validate + + +class Prefill: + def __init__(self, config, weights, width, chip=0): + validate(config) + if type(width) is not int or not 0 < width <= 8192 or width % 512: + raise ValueError("partitioned KONI requires multiples of512 through8192") + from koni_partitioned import PartitionedPrefill + from rngd_pd.engines.fsdk import sync + from rngd_pd.engines.model import ModelConfig + + arrays = {k: v.detach().cpu().float().numpy() for k, v in weights.items()} + self.engine = PartitionedPrefill( + ModelConfig(SimpleNamespace(**config)), + arrays, + C=width, + S=width, + group=1, + chip=chip, + cache_dir=None, + rms_tile=512, + ) + self.width, self.chip, self.sync, self.config = width, chip, sync, config + self.norm = torch.from_numpy(arrays["model.norm.weight"]) + self.head = torch.from_numpy(arrays["lm_head.weight"]) + sync(chip) + + @torch.inference_mode() + def prefill(self, tokens): + ids = list(tokens) + if not 0 < len(ids) <= self.width or any( + type(t) is not int or not 0 <= t < self.config["vocab_size"] for t in ids + ): + raise ValueError("invalid tokens or prompt exceeds compiled width") + stage = self.engine.begin_device_prefill(ids) + while not stage.advance(): + pass + self.sync(self.chip) + return export_groups(stage, self.norm, self.head, self.config["rms_norm_eps"]) diff --git a/opt_prime/examples/pd/serving_matrix/long_width_variant.py b/opt_prime/examples/pd/serving_matrix/long_width_variant.py index 91548f52..ac26a862 100644 --- a/opt_prime/examples/pd/serving_matrix/long_width_variant.py +++ b/opt_prime/examples/pd/serving_matrix/long_width_variant.py @@ -14,3 +14,8 @@ def load_variant(): namespace = {"__name__": "prefill_width8192"} exec(compile(source, "prefill_width8192", "exec"), namespace) # noqa: S102 - trusted local experimental source return namespace["Prefill"] + + +def make_prefill(config, weights, width, chip=0): + """Explicit experimental worker factory using the already validated long-width variant.""" + return load_variant()(config, weights, width=width, chip=chip) diff --git a/opt_prime/examples/pd/serving_matrix/test_koni_prefill.py b/opt_prime/examples/pd/serving_matrix/test_koni_prefill.py new file mode 100644 index 00000000..6ffc94bc --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/test_koni_prefill.py @@ -0,0 +1,23 @@ +import pytest +from koni_prefill import Prefill + + +def test_rejects_wrong_geometry_before_loading_sdk(): + with pytest.raises(ValueError, match="Llama"): + Prefill({}, {}, width=512) + + +@pytest.mark.parametrize("width", [0, 128, 513]) +def test_rejects_unsupported_width_before_loading_sdk(width): + config = { + "model_type": "llama", + "hidden_act": "silu", + "hidden_size": 4096, + "intermediate_size": 14336, + "num_attention_heads": 32, + "num_key_value_heads": 8, + "num_hidden_layers": 32, + "rope_scaling": {"rope_type": "llama3"}, + } + with pytest.raises(ValueError, match="512"): + Prefill(config, {}, width=width) From 75ce140026d37a96ca9f74c157682e2a4684c569 Mon Sep 17 00:00:00 2001 From: gspark Date: Fri, 23 Oct 2026 23:07:02 +0900 Subject: [PATCH 5/6] test: verify medium-context live HTTP PD across four models --- .../examples/pd/serving_matrix/COVERAGE.md | 20 +- .../examples/pd/serving_matrix/README.md | 2 +- .../examples/pd/serving_matrix/STATUS.md | 4 +- .../serving_matrix/evidence234/events.jsonl | 1 + .../evidence234/live234-gemma-http-mid.json | 400 ++++++++++++++ .../evidence234/live234-http-mid-summary.json | 47 ++ .../evidence234/live234-koni-http-mid.json | 445 ++++++++++++++++ .../evidence234/live234-qwen06b-http-mid.json | 490 ++++++++++++++++++ .../evidence234/live234-qwen4b-http-mid.json | 400 ++++++++++++++ .../2026-10-23-live-http-mid234.md | 42 ++ 10 files changed, 1844 insertions(+), 7 deletions(-) create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-http-mid.json create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-http-mid-summary.json create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-koni-http-mid.json create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen06b-http-mid.json create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen4b-http-mid.json create mode 100644 opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http-mid234.md diff --git a/opt_prime/examples/pd/serving_matrix/COVERAGE.md b/opt_prime/examples/pd/serving_matrix/COVERAGE.md index 9983bef9..6e8dc403 100644 --- a/opt_prime/examples/pd/serving_matrix/COVERAGE.md +++ b/opt_prime/examples/pd/serving_matrix/COVERAGE.md @@ -13,9 +13,9 @@ All direct runs use fixed output lengths ignoring EOS. Repeats match within each ## Outstanding acceptance work -- Standalone GPU HTTP covered by PR213 and ATOM HTTP by PR216: all four lifecycle checks pass through8K. Cache-off concurrent/serial equality48/48 on each backend. RNGD/heterogeneous HTTP remains incomplete. +- Standalone GPU HTTP covered by PR213 and ATOM HTTP by PR216: all four lifecycle checks pass through8K. Cache-off concurrent/serial equality48/48 on each backend. Real RNGD->ATOM short-input HTTP now passes56/56 output checks (#235/#237); medium/long live and broader conditions remain incomplete. - Qwen ATOM device/host-cache cases pass12/12 concurrent equality each (PR216). GPU BF16 cache has numerical ties; FP32 controls match48/48 (PR213). Gemma sliding-state restoration is unimplemented, KONI k1 has no spare prefix-cache blocks. -- Production integration of validated research KONI/Gemma long-prefix producers; genuine cache-aware producer chunking remains open. +- Short live producer/scheduler integration is verified for all four models. Live long prefixes and genuine cache-aware producer chunking remain open. - Layer/logit diagnosis and broader semantic fixtures for cross-backend output differences; matching a repeated capital question is not a quality evaluation. - Actual producer/consumer overlap and end-to-end serving benefit, distinct from faster CPU staging. @@ -23,12 +23,22 @@ Evidence: PR203 matrix results, PR206 staging optimization, PR209 Gemma probe, e ## EOS-aware native fixtures (#227) -192 GPU/ATOM runs, all EOS-ended;96 repeat pairs exact. Cross-backend exact cases: Qwen0.6B12/12,Qwen4B12/12,KONI12/12,Gemma11/12. Four short questions with0/100/400 repeated context notes give23–6428 input tokens. Shared wrong factual answers are retained, so this is not a general quality pass. Research EOS policy includes both generation-config and tokenizer turn-end tokens; original KONI policy failure preserved. RNGD and heterogeneous HTTP coverage of these exact semantic inputs remains missing. +192 GPU/ATOM runs, all EOS-ended;96 repeat pairs exact. Cross-backend exact cases: Qwen0.6B12/12,Qwen4B12/12,KONI12/12,Gemma11/12. Four short questions with0/100/400 repeated context notes give23–6428 input tokens. Shared wrong factual answers are retained, so this is not a general quality pass. Research EOS policy includes both generation-config and tokenizer turn-end tokens; original KONI policy failure preserved. Subsequent RNGD and live HTTP evidence is listed below; matching outputs still does not certify answer quality. ## RNGD semantic handoff follow-up (#227) -All four models now execute the same four short chat cases through RNGD prefill and GPU/ATOM continuation.32/32 decoder comparisons match native tokens through EOS,48prefill runs finite/repeat-exact. Exact saved IDs and true KV lengths verified, excluding right padding; per-model52/56/72/64slots read back exactly. Qwen/KONI original/portable importer logits agree; Gemma raw native-state roundtrip also passes. Inputs23–143 tokens (compiled width128 or512), so long semantic fixtures remain pending. This is host-staged full-prefix handoff, not actual compute/transfer overlap or production PD serving. See semantic-rngd227 record and evidence227. +All four models now execute the same four short chat cases through RNGD prefill and GPU/ATOM continuation.32/32 decoder comparisons match native tokens through EOS,48prefill runs finite/repeat-exact. Exact saved IDs and true KV lengths verified, excluding right padding; per-model52/56/72/64slots read back exactly. Qwen/KONI original/portable importer logits agree; Gemma raw native-state roundtrip also passes. Inputs23–143 tokens (compiled width128 or512), with subsequent long-context results below. This is host-staged full-prefix handoff, not actual compute/transfer overlap or production PD serving. See semantic-rngd227 record and evidence227. ## Medium semantic handoff (#227) -Inputs1526–1643tokens in width2048 buckets now pass all32 model/case/decoder EOS comparisons (four models,four cases,GPU/ATOM).48prefill runs finite/repeat-exact; true IDs/KV lengths and52/56/72/64slot readbacks verified. Native GPU/ATOM sequences agree for these cases, including shared wrong answers documented earlier. Approximately6K semantic inputs and production heterogeneous serving/overlap remain open. See semantic-mid227 experiment and evidence227. +Inputs1526–1643tokens in width2048 buckets now pass all32 model/case/decoder EOS comparisons (four models,four cases,GPU/ATOM).48prefill runs finite/repeat-exact; true IDs/KV lengths and52/56/72/64slot readbacks verified. Native GPU/ATOM sequences agree for these cases, including shared wrong answers documented earlier. Approximately6K semantic results and short live HTTP are now available below; true overlap and broader serving conditions remain open. See semantic-mid227 experiment and evidence227. + +## Long semantic handoff (#227/#233) + +Four models,48producer runs,31/32 EOS comparisons at6026–6428input tokens. Both Qwens and KONI match4/4cases on each decoder; Gemma matches3/4GPU and4/4ATOM. All KV readbacks pass. The retained Gemma arithmetic mismatch is30(nativeGPU BF16/FP32) vs25(RNGD/ATOM), both wrong. Same layer equations on GPU choose a different first token from RNGD; operator cause unresolved in#233. See semantic-long227 and evidence227. + +## Real RNGD to ATOM HTTP (#234/#236) + +All four short-input paths pass14normal/concurrent/reuse responses each:56total,64remote prefills including cancellation requests,0local fallbacks. Requests trigger actual RNGD subprocess computation; no KV replay. Each model passes explicit cancellation, socket disconnection and subsequent reuse. Gemma/Qwen usek3; static B1 KONI usesk1 with#236. SIGPIPE-safe HTTP is#214/#215. These are B1 hardware requests with queued client concurrency, not hardware batch4. Native parity includes shared wrong answers. + +Width2048 live checks now pass for all four models:56responses and64remote prefills. Short+medium total112responses/128prefills, with no local fallbacks. Width8192 live queue is pending. Full live6K, pending-prefill hardware cancellation/worker-failure recovery, GPU live PD, hybrid prefix/host restore, applicable hardware batch>1, genuine producer/transfer overlap and matched native-vs-PD latency/throughput comparisons remain unverified. Overall goal remains active. diff --git a/opt_prime/examples/pd/serving_matrix/README.md b/opt_prime/examples/pd/serving_matrix/README.md index 53695d9f..be922bfe 100644 --- a/opt_prime/examples/pd/serving_matrix/README.md +++ b/opt_prime/examples/pd/serving_matrix/README.md @@ -177,4 +177,4 @@ Short-input producer/full-logit parity and real shared-memory requests are verif `check_live_http.py` runs actual RNGD prefill and ATOM HTTP decode from token fixtures (it does not load saved KV). Pass `--batching` with the reviewed ATOM scheduler, `--http-module` with the #214 SIGPIPE-fixed server, the model/artifact cache, `--worker-python`, factory/width and fixture/baseline JSON. It checks two serial passes, four queued clients, cancel/disconnect and reuse. Factories: `prefill:Prefill` for short Qwen3, `long_width_variant:make_prefill` for the explicit experimental long Qwen variant, `gemma_prefill:Prefill`, and `koni_prefill:Prefill` for partitioned KONI widths divisible by512. KONI uses `--kv-blocks 1` with #236; other measured artifacts use3. Explicit head_dim is preserved; Llama's missing field is inferred from hidden size/attention heads. -All four short-input live HTTP paths pass56normal/reuse response checks and64remote prefills including cancellations. Native-output parity does not imply answer quality. Width2048 live validation is pending; hardware batch remains1 and no matched performance benefit is established. See live-http234 record. +All four short-input live HTTP paths pass56normal/reuse response checks and64remote prefills including cancellations. Native-output parity does not imply answer quality. Width2048 live validation also passes all four models; width8192 live queue is pending; hardware batch remains1 and no matched performance benefit is established. See live-http234 record. diff --git a/opt_prime/examples/pd/serving_matrix/STATUS.md b/opt_prime/examples/pd/serving_matrix/STATUS.md index d1d148d4..2a6d7004 100644 --- a/opt_prime/examples/pd/serving_matrix/STATUS.md +++ b/opt_prime/examples/pd/serving_matrix/STATUS.md @@ -62,4 +62,6 @@ Reusable Gemma producer matches original RNGD K/V/full logits4/4 at width128. Re ## Four-model actual HTTP PD (#234/#236) -All four models:56/56 normal/concurrent/reuse responses equal native ATOM,64RNGD prefills and0local fallbacks. Cancellation/disconnect reuse passes. B1, cache-off, short prompts; KONI uses existingk1 artifact with#236. HTTP uses#214 SIGPIPE fix. No live-transfer-overlap or throughput gain claim. Width2048 live queue pending; long/cache/hardware-batch/performance scope remains. +All four models:56/56 normal/concurrent/reuse responses equal native ATOM,64RNGD prefills and0local fallbacks. Cancellation/disconnect reuse passes. B1, cache-off, short prompts; KONI uses existingk1 artifact with#236. HTTP uses#214 SIGPIPE fix. No live-transfer-overlap or throughput gain claim. Width2048 live queue passes all four models; width8192 live queue pending; long/cache/hardware-batch/performance scope remains. + +Medium live HTTP:1526–1643tokens,56/56 exact outputs and64remote/0local; short+medium112responses/128remote. Same cancellation/disconnect reuse checks pass. Long live queue active; full goal remains open. See live-http-mid234. diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl b/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl index 86b05c78..9ab9df1b 100644 --- a/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl +++ b/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl @@ -1,2 +1,3 @@ {"id": "819c75b3957c4f0b980915096014c36f", "ts": "2026-10-23T22:30:07+09:00", "task": "Live four-model PD integration (aicomp #234)", "result": "Callable Gemma refactor:4/4 full K/V/logits bit-exact on RNGD; actual subprocess/shared-memory worker5/5 exact and oversize recovery pass.15CPU tests+5subtests. No live HTTP claim yet.", "next": "Connect live worker to production ATOM HTTP; extend Qwen/KONI adapters and long-prefix/lifecycle conditions.", "state": "active", "done": false, "blocker": "", "metrics": {}, "params": {"model": "Gemma3-1B", "width": "128"}, "artifacts": ["opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-worker.json"], "experiments": ["opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-model-pd234.md"], "labels": ["experiment"], "review": true, "todos": [], "note": "", "agent": "codex", "host": "validation host", "branch": "main", "commit": "351d39d-dirty"} {"id": "fdd4a316d5cb433e8b2b56028ac53379", "ts": "2026-10-23T22:52:06+09:00", "task": "Live four-model PD integration (aicomp #234)", "result": "Real RNGD->ATOM HTTP four models:56/56 normal/reuse outputs exact,64remote/0local prefills; concurrent clients and cancel/disconnect recovery pass. KONI k1 enabled by#236;22adapter tests+5subtests and43scheduler tests. Width2048 queue started.", "next": "Collect live medium-context queue; publish #236 and adapter updates, then controlled native/PD performance and remaining cache/overlap.", "state": "active", "done": false, "blocker": "", "metrics": {}, "params": {"hardware_batch": "1", "mode": "live_rngd_atom_http"}, "artifacts": ["opt_prime/examples/pd/serving_matrix/evidence234/live234-http-summary.json"], "experiments": ["opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http234.md"], "labels": ["experiment"], "review": true, "todos": [], "note": "", "agent": "codex", "host": "RNGD+ATOM host", "branch": "main", "commit": "351d39d-dirty"} +{"id": "50c06e38ffe04b859420a115b72f5cc6", "ts": "2026-10-23T23:05:26+09:00", "task": "Live four-model PD integration (aicomp #234)", "result": "Medium1526-1643token live RNGD->ATOM HTTP four models56/56 responses exact,64remote/0local and cancel/disconnect reuse pass. Short+medium112responses/128remote. PR237df02223 single-block support; long8192-width/*-400 queue started.", "next": "Collect long live queue; then pending-prefill/worker-failure recovery, matched native/PD performance, cache/overlap and#233 numerics.", "state": "active", "done": false, "blocker": "", "metrics": {}, "params": {"width": "2048", "hardware_batch": "1"}, "artifacts": ["opt_prime/examples/pd/serving_matrix/evidence234/live234-http-mid-summary.json"], "experiments": ["opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http-mid234.md"], "labels": ["experiment"], "review": true, "todos": [], "note": "", "agent": "codex", "host": "RNGD+ATOM host", "branch": "main", "commit": "351d39d-dirty"} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-http-mid.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-http-mid.json new file mode 100644 index 00000000..4cb2342d --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-http-mid.json @@ -0,0 +1,400 @@ +{ + "worker": "live_rngd_subprocess_prefill", + "rows": [ + { + "case": "capital-100", + "request": "normal-0-0", + "response": { + "id": "normal-0-0", + "object": "text_completion", + "created": 1792763625, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1623, + "completion_tokens": 2, + "total_tokens": 1625 + } + }, + "latency_s": 2.158342153998092 + }, + { + "case": "arithmetic-100", + "request": "normal-0-1", + "response": { + "id": "normal-0-1", + "object": "text_completion", + "created": 1792763627, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "40\n", + "token_ids": [ + 236812, + 236771, + 107, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1624, + "completion_tokens": 4, + "total_tokens": 1628 + } + }, + "latency_s": 2.0099443329963833 + }, + { + "case": "korean-100", + "request": "normal-0-2", + "response": { + "id": "normal-0-2", + "object": "text_completion", + "created": 1792763629, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 98665, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1624, + "completion_tokens": 2, + "total_tokens": 1626 + } + }, + "latency_s": 1.9934004180831835 + }, + { + "case": "retrieval-100", + "request": "normal-0-3", + "response": { + "id": "normal-0-3", + "object": "text_completion", + "created": 1792763631, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 28487, + 1618, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1628, + "completion_tokens": 3, + "total_tokens": 1631 + } + }, + "latency_s": 2.0018371921032667 + }, + { + "case": "capital-100", + "request": "normal-1-0", + "response": { + "id": "normal-1-0", + "object": "text_completion", + "created": 1792763633, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1623, + "completion_tokens": 2, + "total_tokens": 1625 + } + }, + "latency_s": 1.9967707360628992 + }, + { + "case": "arithmetic-100", + "request": "normal-1-1", + "response": { + "id": "normal-1-1", + "object": "text_completion", + "created": 1792763635, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "40\n", + "token_ids": [ + 236812, + 236771, + 107, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1624, + "completion_tokens": 4, + "total_tokens": 1628 + } + }, + "latency_s": 2.0195871680043638 + }, + { + "case": "korean-100", + "request": "normal-1-2", + "response": { + "id": "normal-1-2", + "object": "text_completion", + "created": 1792763637, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 98665, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1624, + "completion_tokens": 2, + "total_tokens": 1626 + } + }, + "latency_s": 1.9965247600339353 + }, + { + "case": "retrieval-100", + "request": "normal-1-3", + "response": { + "id": "normal-1-3", + "object": "text_completion", + "created": 1792763639, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 28487, + 1618, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1628, + "completion_tokens": 3, + "total_tokens": 1631 + } + }, + "latency_s": 2.000015356927179 + }, + { + "case": "capital-100", + "request": "concurrent-0", + "response": { + "id": "concurrent-0", + "object": "text_completion", + "created": 1792763641, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1623, + "completion_tokens": 2, + "total_tokens": 1625 + } + }, + "latency_s": 2.00175220600795 + }, + { + "case": "arithmetic-100", + "request": "concurrent-1", + "response": { + "id": "concurrent-1", + "object": "text_completion", + "created": 1792763643, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "40\n", + "token_ids": [ + 236812, + 236771, + 107, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1624, + "completion_tokens": 4, + "total_tokens": 1628 + } + }, + "latency_s": 4.0120902369963005 + }, + { + "case": "korean-100", + "request": "concurrent-2", + "response": { + "id": "concurrent-2", + "object": "text_completion", + "created": 1792763645, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 98665, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1624, + "completion_tokens": 2, + "total_tokens": 1626 + } + }, + "latency_s": 5.998096699011512 + }, + { + "case": "retrieval-100", + "request": "concurrent-3", + "response": { + "id": "concurrent-3", + "object": "text_completion", + "created": 1792763647, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 28487, + 1618, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1628, + "completion_tokens": 3, + "total_tokens": 1631 + } + }, + "latency_s": 7.989423095015809 + }, + { + "case": "capital-100", + "request": "after-cancel", + "response": { + "id": "after-cancel", + "object": "text_completion", + "created": 1792763651, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1623, + "completion_tokens": 2, + "total_tokens": 1625 + } + }, + "latency_s": 1.9823684650473297 + }, + { + "case": "capital-100", + "request": "after-disconnect", + "response": { + "id": "after-disconnect", + "object": "text_completion", + "created": 1792763655, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1623, + "completion_tokens": 2, + "total_tokens": 1625 + } + }, + "latency_s": 1.9897793129784986 + } + ], + "stats_pd": { + "remote": 16, + "local": 0 + }, + "free": [ + 0 + ], + "cancellation_reuse": true +} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-http-mid-summary.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-http-mid-summary.json new file mode 100644 index 00000000..678070d9 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-http-mid-summary.json @@ -0,0 +1,47 @@ +{ + "gemma": { + "responses": 14, + "remote_prefills": 16, + "local_prefills": 0, + "cancellation_reuse": true, + "input_tokens": [ + 1623, + 1624, + 1628 + ] + }, + "qwen06b": { + "responses": 14, + "remote_prefills": 16, + "local_prefills": 0, + "cancellation_reuse": true, + "input_tokens": [ + 1526, + 1527, + 1531 + ] + }, + "qwen4b": { + "responses": 14, + "remote_prefills": 16, + "local_prefills": 0, + "cancellation_reuse": true, + "input_tokens": [ + 1526, + 1527, + 1531 + ] + }, + "koni": { + "responses": 14, + "remote_prefills": 16, + "local_prefills": 0, + "cancellation_reuse": true, + "input_tokens": [ + 1637, + 1638, + 1639, + 1643 + ] + } +} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-koni-http-mid.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-koni-http-mid.json new file mode 100644 index 00000000..b0254943 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-koni-http-mid.json @@ -0,0 +1,445 @@ +{ + "worker": "live_rngd_subprocess_prefill", + "rows": [ + { + "case": "capital-100", + "request": "normal-0-0", + "response": { + "id": "normal-0-0", + "object": "text_completion", + "created": 1792764074, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "The capital of France is Paris.", + "token_ids": [ + 791, + 6864, + 315, + 9822, + 374, + 12366, + 13, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1638, + "completion_tokens": 8, + "total_tokens": 1646 + } + }, + "latency_s": 2.5393513729795814 + }, + { + "case": "arithmetic-100", + "request": "normal-0-1", + "response": { + "id": "normal-0-1", + "object": "text_completion", + "created": 1792764076, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "42", + "token_ids": [ + 2983, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1637, + "completion_tokens": 2, + "total_tokens": 1639 + } + }, + "latency_s": 1.323795892065391 + }, + { + "case": "korean-100", + "request": "normal-0-2", + "response": { + "id": "normal-0-2", + "object": "text_completion", + "created": 1792764077, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "대한민국의 수도는 서울입니다.", + "token_ids": [ + 113760, + 108709, + 21028, + 116992, + 16969, + 106010, + 80052, + 13, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1639, + "completion_tokens": 9, + "total_tokens": 1648 + } + }, + "latency_s": 1.7511723199859262 + }, + { + "case": "retrieval-100", + "request": "normal-0-3", + "response": { + "id": "normal-0-3", + "object": "text_completion", + "created": 1792764079, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 18082, + 877, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1643, + "completion_tokens": 3, + "total_tokens": 1646 + } + }, + "latency_s": 1.280155176995322 + }, + { + "case": "capital-100", + "request": "normal-1-0", + "response": { + "id": "normal-1-0", + "object": "text_completion", + "created": 1792764080, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "The capital of France is Paris.", + "token_ids": [ + 791, + 6864, + 315, + 9822, + 374, + 12366, + 13, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1638, + "completion_tokens": 8, + "total_tokens": 1646 + } + }, + "latency_s": 1.5194910150021315 + }, + { + "case": "arithmetic-100", + "request": "normal-1-1", + "response": { + "id": "normal-1-1", + "object": "text_completion", + "created": 1792764081, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "42", + "token_ids": [ + 2983, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1637, + "completion_tokens": 2, + "total_tokens": 1639 + } + }, + "latency_s": 1.0988063589902595 + }, + { + "case": "korean-100", + "request": "normal-1-2", + "response": { + "id": "normal-1-2", + "object": "text_completion", + "created": 1792764083, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "대한민국의 수도는 서울입니다.", + "token_ids": [ + 113760, + 108709, + 21028, + 116992, + 16969, + 106010, + 80052, + 13, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1639, + "completion_tokens": 9, + "total_tokens": 1648 + } + }, + "latency_s": 1.4861711430130526 + }, + { + "case": "retrieval-100", + "request": "normal-1-3", + "response": { + "id": "normal-1-3", + "object": "text_completion", + "created": 1792764084, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 18082, + 877, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1643, + "completion_tokens": 3, + "total_tokens": 1646 + } + }, + "latency_s": 1.0849265129072592 + }, + { + "case": "capital-100", + "request": "concurrent-0", + "response": { + "id": "concurrent-0", + "object": "text_completion", + "created": 1792764085, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "The capital of France is Paris.", + "token_ids": [ + 791, + 6864, + 315, + 9822, + 374, + 12366, + 13, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1638, + "completion_tokens": 8, + "total_tokens": 1646 + } + }, + "latency_s": 1.425872788997367 + }, + { + "case": "arithmetic-100", + "request": "concurrent-1", + "response": { + "id": "concurrent-1", + "object": "text_completion", + "created": 1792764086, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "42", + "token_ids": [ + 2983, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1637, + "completion_tokens": 2, + "total_tokens": 1639 + } + }, + "latency_s": 2.4230585580226034 + }, + { + "case": "korean-100", + "request": "concurrent-2", + "response": { + "id": "concurrent-2", + "object": "text_completion", + "created": 1792764088, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "대한민국의 수도는 서울입니다.", + "token_ids": [ + 113760, + 108709, + 21028, + 116992, + 16969, + 106010, + 80052, + 13, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1639, + "completion_tokens": 9, + "total_tokens": 1648 + } + }, + "latency_s": 3.934952615061775 + }, + { + "case": "retrieval-100", + "request": "concurrent-3", + "response": { + "id": "concurrent-3", + "object": "text_completion", + "created": 1792764089, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 18082, + 877, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1643, + "completion_tokens": 3, + "total_tokens": 1646 + } + }, + "latency_s": 5.026510157971643 + }, + { + "case": "capital-100", + "request": "after-cancel", + "response": { + "id": "after-cancel", + "object": "text_completion", + "created": 1792764091, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "The capital of France is Paris.", + "token_ids": [ + 791, + 6864, + 315, + 9822, + 374, + 12366, + 13, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1638, + "completion_tokens": 8, + "total_tokens": 1646 + } + }, + "latency_s": 1.4203430189518258 + }, + { + "case": "capital-100", + "request": "after-disconnect", + "response": { + "id": "after-disconnect", + "object": "text_completion", + "created": 1792764094, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "The capital of France is Paris.", + "token_ids": [ + 791, + 6864, + 315, + 9822, + 374, + 12366, + 13, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1638, + "completion_tokens": 8, + "total_tokens": 1646 + } + }, + "latency_s": 1.435384924057871 + } + ], + "stats_pd": { + "remote": 16, + "local": 0 + }, + "free": [ + 0 + ], + "cancellation_reuse": true +} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen06b-http-mid.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen06b-http-mid.json new file mode 100644 index 00000000..6a5b9049 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen06b-http-mid.json @@ -0,0 +1,490 @@ +{ + "worker": "live_rngd_subprocess_prefill", + "rows": [ + { + "case": "capital-100", + "request": "normal-0-0", + "response": { + "id": "normal-0-0", + "object": "text_completion", + "created": 1792763718, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1526, + "completion_tokens": 2, + "total_tokens": 1528 + } + }, + "latency_s": 0.9969441100256518 + }, + { + "case": "arithmetic-100", + "request": "normal-0-1", + "response": { + "id": "normal-0-1", + "object": "text_completion", + "created": 1792763718, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "17 + 25 = 42\n\nReply with only the integer: 42.", + "token_ids": [ + 16, + 22, + 488, + 220, + 17, + 20, + 284, + 220, + 19, + 17, + 271, + 20841, + 448, + 1172, + 279, + 7546, + 25, + 220, + 19, + 17, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1527, + "completion_tokens": 22, + "total_tokens": 1549 + } + }, + "latency_s": 0.6752042719163001 + }, + { + "case": "korean-100", + "request": "normal-0-2", + "response": { + "id": "normal-0-2", + "object": "text_completion", + "created": 1792763719, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "대한민국의 수도는 **인천**입니다.", + "token_ids": [ + 66845, + 23573, + 125496, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1531, + "completion_tokens": 14, + "total_tokens": 1545 + } + }, + "latency_s": 0.6178859820356593 + }, + { + "case": "retrieval-100", + "request": "normal-0-3", + "response": { + "id": "normal-0-3", + "object": "text_completion", + "created": 1792763719, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1531, + "completion_tokens": 3, + "total_tokens": 1534 + } + }, + "latency_s": 0.5457541500218213 + }, + { + "case": "capital-100", + "request": "normal-1-0", + "response": { + "id": "normal-1-0", + "object": "text_completion", + "created": 1792763720, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1526, + "completion_tokens": 2, + "total_tokens": 1528 + } + }, + "latency_s": 0.5465415481012315 + }, + { + "case": "arithmetic-100", + "request": "normal-1-1", + "response": { + "id": "normal-1-1", + "object": "text_completion", + "created": 1792763721, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "17 + 25 = 42\n\nReply with only the integer: 42.", + "token_ids": [ + 16, + 22, + 488, + 220, + 17, + 20, + 284, + 220, + 19, + 17, + 271, + 20841, + 448, + 1172, + 279, + 7546, + 25, + 220, + 19, + 17, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1527, + "completion_tokens": 22, + "total_tokens": 1549 + } + }, + "latency_s": 0.6642461880110204 + }, + { + "case": "korean-100", + "request": "normal-1-2", + "response": { + "id": "normal-1-2", + "object": "text_completion", + "created": 1792763721, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "대한민국의 수도는 **인천**입니다.", + "token_ids": [ + 66845, + 23573, + 125496, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1531, + "completion_tokens": 14, + "total_tokens": 1545 + } + }, + "latency_s": 0.6021285310853273 + }, + { + "case": "retrieval-100", + "request": "normal-1-3", + "response": { + "id": "normal-1-3", + "object": "text_completion", + "created": 1792763722, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1531, + "completion_tokens": 3, + "total_tokens": 1534 + } + }, + "latency_s": 0.5523455439833924 + }, + { + "case": "capital-100", + "request": "concurrent-0", + "response": { + "id": "concurrent-0", + "object": "text_completion", + "created": 1792763722, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1526, + "completion_tokens": 2, + "total_tokens": 1528 + } + }, + "latency_s": 0.5414341390132904 + }, + { + "case": "arithmetic-100", + "request": "concurrent-1", + "response": { + "id": "concurrent-1", + "object": "text_completion", + "created": 1792763723, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "17 + 25 = 42\n\nReply with only the integer: 42.", + "token_ids": [ + 16, + 22, + 488, + 220, + 17, + 20, + 284, + 220, + 19, + 17, + 271, + 20841, + 448, + 1172, + 279, + 7546, + 25, + 220, + 19, + 17, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1527, + "completion_tokens": 22, + "total_tokens": 1549 + } + }, + "latency_s": 1.227440306916833 + }, + { + "case": "korean-100", + "request": "concurrent-2", + "response": { + "id": "concurrent-2", + "object": "text_completion", + "created": 1792763724, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "대한민국의 수도는 **인천**입니다.", + "token_ids": [ + 66845, + 23573, + 125496, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1531, + "completion_tokens": 14, + "total_tokens": 1545 + } + }, + "latency_s": 1.8558082920499146 + }, + { + "case": "retrieval-100", + "request": "concurrent-3", + "response": { + "id": "concurrent-3", + "object": "text_completion", + "created": 1792763724, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1531, + "completion_tokens": 3, + "total_tokens": 1534 + } + }, + "latency_s": 2.406756103038788 + }, + { + "case": "capital-100", + "request": "after-cancel", + "response": { + "id": "after-cancel", + "object": "text_completion", + "created": 1792763725, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1526, + "completion_tokens": 2, + "total_tokens": 1528 + } + }, + "latency_s": 0.6081401809351519 + }, + { + "case": "capital-100", + "request": "after-disconnect", + "response": { + "id": "after-disconnect", + "object": "text_completion", + "created": 1792763727, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1526, + "completion_tokens": 2, + "total_tokens": 1528 + } + }, + "latency_s": 0.550125173991546 + } + ], + "stats_pd": { + "remote": 16, + "local": 0 + }, + "free": [ + 0 + ], + "cancellation_reuse": true +} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen4b-http-mid.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen4b-http-mid.json new file mode 100644 index 00000000..0e13cc7e --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen4b-http-mid.json @@ -0,0 +1,400 @@ +{ + "worker": "live_rngd_subprocess_prefill", + "rows": [ + { + "case": "capital-100", + "request": "normal-0-0", + "response": { + "id": "normal-0-0", + "object": "text_completion", + "created": 1792763846, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1526, + "completion_tokens": 2, + "total_tokens": 1528 + } + }, + "latency_s": 1.5593066349392757 + }, + { + "case": "arithmetic-100", + "request": "normal-0-1", + "response": { + "id": "normal-0-1", + "object": "text_completion", + "created": 1792763847, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "42", + "token_ids": [ + 19, + 17, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1527, + "completion_tokens": 3, + "total_tokens": 1530 + } + }, + "latency_s": 0.9446719089755788 + }, + { + "case": "korean-100", + "request": "normal-0-2", + "response": { + "id": "normal-0-2", + "object": "text_completion", + "created": 1792763848, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 26698, + 126893, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1531, + "completion_tokens": 3, + "total_tokens": 1534 + } + }, + "latency_s": 1.038334756041877 + }, + { + "case": "retrieval-100", + "request": "normal-0-3", + "response": { + "id": "normal-0-3", + "object": "text_completion", + "created": 1792763849, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1531, + "completion_tokens": 3, + "total_tokens": 1534 + } + }, + "latency_s": 1.0008713440038264 + }, + { + "case": "capital-100", + "request": "normal-1-0", + "response": { + "id": "normal-1-0", + "object": "text_completion", + "created": 1792763850, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1526, + "completion_tokens": 2, + "total_tokens": 1528 + } + }, + "latency_s": 1.0365961409406736 + }, + { + "case": "arithmetic-100", + "request": "normal-1-1", + "response": { + "id": "normal-1-1", + "object": "text_completion", + "created": 1792763851, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "42", + "token_ids": [ + 19, + 17, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1527, + "completion_tokens": 3, + "total_tokens": 1530 + } + }, + "latency_s": 0.9256328369956464 + }, + { + "case": "korean-100", + "request": "normal-1-2", + "response": { + "id": "normal-1-2", + "object": "text_completion", + "created": 1792763852, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 26698, + 126893, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1531, + "completion_tokens": 3, + "total_tokens": 1534 + } + }, + "latency_s": 0.9329322580015287 + }, + { + "case": "retrieval-100", + "request": "normal-1-3", + "response": { + "id": "normal-1-3", + "object": "text_completion", + "created": 1792763853, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1531, + "completion_tokens": 3, + "total_tokens": 1534 + } + }, + "latency_s": 0.9429352049482986 + }, + { + "case": "capital-100", + "request": "concurrent-0", + "response": { + "id": "concurrent-0", + "object": "text_completion", + "created": 1792763854, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1526, + "completion_tokens": 2, + "total_tokens": 1528 + } + }, + "latency_s": 0.9035777349490672 + }, + { + "case": "arithmetic-100", + "request": "concurrent-1", + "response": { + "id": "concurrent-1", + "object": "text_completion", + "created": 1792763855, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "42", + "token_ids": [ + 19, + 17, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1527, + "completion_tokens": 3, + "total_tokens": 1530 + } + }, + "latency_s": 1.836488423985429 + }, + { + "case": "korean-100", + "request": "concurrent-2", + "response": { + "id": "concurrent-2", + "object": "text_completion", + "created": 1792763856, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 26698, + 126893, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1531, + "completion_tokens": 3, + "total_tokens": 1534 + } + }, + "latency_s": 2.7430692090420052 + }, + { + "case": "retrieval-100", + "request": "concurrent-3", + "response": { + "id": "concurrent-3", + "object": "text_completion", + "created": 1792763857, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1531, + "completion_tokens": 3, + "total_tokens": 1534 + } + }, + "latency_s": 3.6805838339496404 + }, + { + "case": "capital-100", + "request": "after-cancel", + "response": { + "id": "after-cancel", + "object": "text_completion", + "created": 1792763858, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1526, + "completion_tokens": 2, + "total_tokens": 1528 + } + }, + "latency_s": 0.8944114779587835 + }, + { + "case": "capital-100", + "request": "after-disconnect", + "response": { + "id": "after-disconnect", + "object": "text_completion", + "created": 1792763860, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 1526, + "completion_tokens": 2, + "total_tokens": 1528 + } + }, + "latency_s": 0.9089197190478444 + } + ], + "stats_pd": { + "remote": 16, + "local": 0 + }, + "free": [ + 0 + ], + "cancellation_reuse": true +} diff --git a/opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http-mid234.md b/opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http-mid234.md new file mode 100644 index 00000000..703ea7e8 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http-mid234.md @@ -0,0 +1,42 @@ +# Four-model medium-input live HTTP PD + +- **Date**: 2026-10-23 +- **Task**: aicomp #234, #236 +- **Host / device**: owned paired RNGD+ATOM allocation; one of each, hardwareB1, context9216. SDKs/model revisions unchanged from live-http234. +- **Commit**: live adapter74d0d3b; core1e54786 for Gemma/Qwen, df02223 behavior for KONI; HTTP9e442cd. + +## Question + +Does live producer->shared memory->ATOM HTTP preserve native tokens and lifecycle behavior with longer prompts? + +## Setup + +Same check_live_http.py as the short matrix, replacing four *-0 cases by *-100 and compiled width by2048. Four questions, two serial passes, four queued clients, cancellation/disconnection and reuse. No saved KV loaded. Prefix/host cache off. Existing Gemma/Qwen k3 and KONI k1 artifacts reused. Exact output/EOS comparisons use native ATOM baseline records. Shared wrong answers remain known; parity is not quality. + +## Command + +```bash +bash run-live-http234.sh --batching atom_batching231.py --http-module llmd214.py --cache-dir atom-artifacts-global225 --kv-blocks 3 --model unsloth/gemma-3-1b-it --fixtures semantic227-gemma-fixtures.json --cases capital-100 arithmetic-100 korean-100 retrieval-100 --worker-python "$WORKER_PYTHON" --engine-factory gemma_prefill:Prefill --width 2048 --baseline semantic227-gemma-atom.jsonl --output live234-gemma-http-mid.json +bash run-live-http234.sh --batching atom_batching231.py --http-module llmd214.py --cache-dir atom-artifacts --kv-blocks 3 --model Qwen/Qwen3-0.6B --fixtures semantic227-qwen06b-fixtures.json --cases capital-100 arithmetic-100 korean-100 retrieval-100 --worker-python "$WORKER_PYTHON" --engine-factory long_width_variant:make_prefill --width 2048 --baseline semantic227-qwen06b-atom.jsonl --output live234-qwen06b-http-mid.json +bash run-live-http234.sh --batching atom_batching231.py --http-module llmd214.py --cache-dir atom-artifacts --kv-blocks 3 --model Qwen/Qwen3-4B --fixtures semantic227-qwen4b-fixtures.json --cases capital-100 arithmetic-100 korean-100 retrieval-100 --worker-python "$WORKER_PYTHON" --engine-factory long_width_variant:make_prefill --width 2048 --baseline semantic227-qwen4b-atom.jsonl --output live234-qwen4b-http-mid.json +bash run-live-http234.sh --batching atom_batching236.py --http-module llmd214.py --cache-dir atom-artifacts --kv-blocks 1 --model KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024 --fixtures semantic227-koni-fixtures-eos.json --cases capital-100 arithmetic-100 korean-100 retrieval-100 --worker-python "$WORKER_PYTHON" --engine-factory koni_prefill:Prefill --width 2048 --baseline semantic227-koni-atom.jsonl --output live234-koni-http-mid.json +``` + +This sequential queue invokes the exact short-record command per model with --width 2048 --cases capital-100 arithmetic-100 korean-100 retrieval-100 and output live234--http-mid.json. Qwen uses --engine-factory long_width_variant:make_prefill (explicit existing experimental8192 guard variant), Gemma uses gemma_prefill:Prefill, KONI uses koni_prefill:Prefill. Model-specific artifact/batching/fixture/baseline arguments are unchanged from live-http234. Queue stops on any nonzero result. + +## Results + +| Model | Actual prompt tokens | Exact responses | Remote/local prefills | Cancel/disconnect reuse | +|---|---:|---:|---:|---| +| Gemma3-1B | 1623–1628 | 14/14 | 16/0 | pass | +| Qwen3-0.6B | 1526–1531 | 14/14 | 16/0 | pass | +| Qwen3-4B | 1526–1531 | 14/14 | 16/0 | pass | +| KONI-8B | 1637–1643 | 14/14 | 16/0 | pass | + +All four queue stages exited0. Total56response checks and64live RNGD prefills, no local fallback. Together with the short matrix:112exact normal/concurrent/reuse responses and128remote prefills. Client concurrency is queued on B1, not hardware batch4. Recorded latency fields are observations; no native-vs-PD performance comparison was performed here. + +## Conclusion + +Medium-input live HTTP correctness/lifecycle passes for all four selected models. Original whole-goal scope remains open: live6K, prefill-time hardware cancellation/worker crashes, cache restoration, applicable hardware batch>1, GPU live PD, numerical fidelity and real overlap/serving benefit. After the medium queue terminated, the same owned allocation started run-live-long234.sh with width8192 and *-400 cases. That new queue is pending; do not restart while its processes are live. + +Raw evidence: analysis/serving-matrix-201/live234--http-mid.json, live234-mid-queue.log and live234-http-mid-summary.json. New queue log: live234-long-queue.log. From 04dab7cb6961103f9404c99e9fcbcaadac14b098 Mon Sep 17 00:00:00 2001 From: gspark Date: Fri, 23 Oct 2026 23:52:03 +0900 Subject: [PATCH 6/6] test: record four-model long live RNGD to ATOM HTTP results (#234) --- .../examples/pd/serving_matrix/COVERAGE.md | 6 +- .../examples/pd/serving_matrix/STATUS.md | 2 + .../serving_matrix/evidence234/events.jsonl | 1 + .../evidence234/live234-gemma-http-long.json | 397 +++++++++++++++ .../live234-http-long-summary.json | 44 ++ .../evidence234/live234-koni-http-long.json | 394 +++++++++++++++ .../live234-qwen06b-http-long.json | 457 ++++++++++++++++++ .../evidence234/live234-qwen4b-http-long.json | 400 +++++++++++++++ .../2026-10-23-live-http-long234.md | 34 ++ 9 files changed, 1732 insertions(+), 3 deletions(-) create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-http-long.json create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-http-long-summary.json create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-koni-http-long.json create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen06b-http-long.json create mode 100644 opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen4b-http-long.json create mode 100644 opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http-long234.md diff --git a/opt_prime/examples/pd/serving_matrix/COVERAGE.md b/opt_prime/examples/pd/serving_matrix/COVERAGE.md index 6e8dc403..9eb3bc2b 100644 --- a/opt_prime/examples/pd/serving_matrix/COVERAGE.md +++ b/opt_prime/examples/pd/serving_matrix/COVERAGE.md @@ -13,9 +13,9 @@ All direct runs use fixed output lengths ignoring EOS. Repeats match within each ## Outstanding acceptance work -- Standalone GPU HTTP covered by PR213 and ATOM HTTP by PR216: all four lifecycle checks pass through8K. Cache-off concurrent/serial equality48/48 on each backend. Real RNGD->ATOM short-input HTTP now passes56/56 output checks (#235/#237); medium/long live and broader conditions remain incomplete. +- Standalone GPU HTTP covered by PR213 and ATOM HTTP by PR216: all four lifecycle checks pass through8K. Cache-off concurrent/serial equality48/48 on each backend. Real RNGD->ATOM short-input HTTP now passes56/56 output checks (#235/#237); short/medium/long live checks pass168/168responses; broader conditions remain incomplete. - Qwen ATOM device/host-cache cases pass12/12 concurrent equality each (PR216). GPU BF16 cache has numerical ties; FP32 controls match48/48 (PR213). Gemma sliding-state restoration is unimplemented, KONI k1 has no spare prefix-cache blocks. -- Short live producer/scheduler integration is verified for all four models. Live long prefixes and genuine cache-aware producer chunking remain open. +- Short live producer/scheduler integration is verified for all four models. Live long prefixes now pass for all four; genuine cache-aware producer chunking remains open. - Layer/logit diagnosis and broader semantic fixtures for cross-backend output differences; matching a repeated capital question is not a quality evaluation. - Actual producer/consumer overlap and end-to-end serving benefit, distinct from faster CPU staging. @@ -41,4 +41,4 @@ Four models,48producer runs,31/32 EOS comparisons at6026–6428input tokens. Bot All four short-input paths pass14normal/concurrent/reuse responses each:56total,64remote prefills including cancellation requests,0local fallbacks. Requests trigger actual RNGD subprocess computation; no KV replay. Each model passes explicit cancellation, socket disconnection and subsequent reuse. Gemma/Qwen usek3; static B1 KONI usesk1 with#236. SIGPIPE-safe HTTP is#214/#215. These are B1 hardware requests with queued client concurrency, not hardware batch4. Native parity includes shared wrong answers. -Width2048 live checks now pass for all four models:56responses and64remote prefills. Short+medium total112responses/128prefills, with no local fallbacks. Width8192 live queue is pending. Full live6K, pending-prefill hardware cancellation/worker-failure recovery, GPU live PD, hybrid prefix/host restore, applicable hardware batch>1, genuine producer/transfer overlap and matched native-vs-PD latency/throughput comparisons remain unverified. Overall goal remains active. +Width2048 live checks now pass for all four models:56responses and64remote prefills. Short+medium total112responses/128prefills, with no local fallbacks. Width8192 live checks also pass all four models:56responses/64remote prefills at6026–6428input tokens. Combined short+medium+long:168responses/192remote prefills,0fallback. Pending-prefill hardware cancellation/worker-failure recovery, cross-host RNGD-to-GPU live PD, hybrid prefix/host restore, applicable hardware batch>1, genuine producer/transfer overlap and matched native-vs-PD latency/throughput remain unverified. GPU-to-GPU live HTTP is tested separately under#240: default BF16 concurrent35/48; explicit uncached/chunk256 producer controls#241 recover48/48concurrent and12/12native/PD serial outputs. Gemma numerical#233 remains unresolved. Overall goal remains active. diff --git a/opt_prime/examples/pd/serving_matrix/STATUS.md b/opt_prime/examples/pd/serving_matrix/STATUS.md index 2a6d7004..cc1c7e9e 100644 --- a/opt_prime/examples/pd/serving_matrix/STATUS.md +++ b/opt_prime/examples/pd/serving_matrix/STATUS.md @@ -65,3 +65,5 @@ Reusable Gemma producer matches original RNGD K/V/full logits4/4 at width128. Re All four models:56/56 normal/concurrent/reuse responses equal native ATOM,64RNGD prefills and0local fallbacks. Cancellation/disconnect reuse passes. B1, cache-off, short prompts; KONI uses existingk1 artifact with#236. HTTP uses#214 SIGPIPE fix. No live-transfer-overlap or throughput gain claim. Width2048 live queue passes all four models; width8192 live queue pending; long/cache/hardware-batch/performance scope remains. Medium live HTTP:1526–1643tokens,56/56 exact outputs and64remote/0local; short+medium112responses/128remote. Same cancellation/disconnect reuse checks pass. Long live queue active; full goal remains open. See live-http-mid234. + +Long live HTTP follow-up: all four width8192 routes pass56/56responses and64remote/0local prefills, cancellation/disconnect reuse included. Short+medium+long168/168responses/192remote. All queue stages exited0. HardwareB1, nativeATOM equality only; no quality, performance or overlap claim. See live-http-long234 record/evidence234. diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl b/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl index 9ab9df1b..a1efcedb 100644 --- a/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl +++ b/opt_prime/examples/pd/serving_matrix/evidence234/events.jsonl @@ -1,3 +1,4 @@ {"id": "819c75b3957c4f0b980915096014c36f", "ts": "2026-10-23T22:30:07+09:00", "task": "Live four-model PD integration (aicomp #234)", "result": "Callable Gemma refactor:4/4 full K/V/logits bit-exact on RNGD; actual subprocess/shared-memory worker5/5 exact and oversize recovery pass.15CPU tests+5subtests. No live HTTP claim yet.", "next": "Connect live worker to production ATOM HTTP; extend Qwen/KONI adapters and long-prefix/lifecycle conditions.", "state": "active", "done": false, "blocker": "", "metrics": {}, "params": {"model": "Gemma3-1B", "width": "128"}, "artifacts": ["opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-worker.json"], "experiments": ["opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-model-pd234.md"], "labels": ["experiment"], "review": true, "todos": [], "note": "", "agent": "codex", "host": "validation host", "branch": "main", "commit": "351d39d-dirty"} {"id": "fdd4a316d5cb433e8b2b56028ac53379", "ts": "2026-10-23T22:52:06+09:00", "task": "Live four-model PD integration (aicomp #234)", "result": "Real RNGD->ATOM HTTP four models:56/56 normal/reuse outputs exact,64remote/0local prefills; concurrent clients and cancel/disconnect recovery pass. KONI k1 enabled by#236;22adapter tests+5subtests and43scheduler tests. Width2048 queue started.", "next": "Collect live medium-context queue; publish #236 and adapter updates, then controlled native/PD performance and remaining cache/overlap.", "state": "active", "done": false, "blocker": "", "metrics": {}, "params": {"hardware_batch": "1", "mode": "live_rngd_atom_http"}, "artifacts": ["opt_prime/examples/pd/serving_matrix/evidence234/live234-http-summary.json"], "experiments": ["opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http234.md"], "labels": ["experiment"], "review": true, "todos": [], "note": "", "agent": "codex", "host": "RNGD+ATOM host", "branch": "main", "commit": "351d39d-dirty"} {"id": "50c06e38ffe04b859420a115b72f5cc6", "ts": "2026-10-23T23:05:26+09:00", "task": "Live four-model PD integration (aicomp #234)", "result": "Medium1526-1643token live RNGD->ATOM HTTP four models56/56 responses exact,64remote/0local and cancel/disconnect reuse pass. Short+medium112responses/128remote. PR237df02223 single-block support; long8192-width/*-400 queue started.", "next": "Collect long live queue; then pending-prefill/worker-failure recovery, matched native/PD performance, cache/overlap and#233 numerics.", "state": "active", "done": false, "blocker": "", "metrics": {}, "params": {"width": "2048", "hardware_batch": "1"}, "artifacts": ["opt_prime/examples/pd/serving_matrix/evidence234/live234-http-mid-summary.json"], "experiments": ["opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http-mid234.md"], "labels": ["experiment"], "review": true, "todos": [], "note": "", "agent": "codex", "host": "RNGD+ATOM host", "branch": "main", "commit": "351d39d-dirty"} +{"id": "41fd11829a7f4bd2a868afd0f12e194d", "ts": "2026-10-23T23:50:41+09:00", "task": "Live four-model PD integration (aicomp #234)", "result": "Long all4models56/56 nativeATOM output checks,64remote/0local,cancel/disconnect reuse pass. Short+medium+long168/168responses,192remote prefills. Queue70411 terminal0; no active benchmark in owned paired allocation.", "next": "Publish long evidence; next hardware pending-prefill/fault checks and matched performance/overlap, retain Gemma#233.", "state": "active", "done": false, "blocker": "", "metrics": {}, "params": {"width": "8192", "hardware_batch": "1"}, "artifacts": [{"path": "analysis/serving-matrix-201/live234-http-long-summary.json", "size": 844, "sha256": "2aa497c94edb6e28"}], "experiments": ["experiments/2026-10-23-live-http-long234.md"], "labels": ["experiment", "rngd"], "review": true, "todos": [], "note": "", "agent": "codex", "host": "xeon-max", "branch": "main", "commit": "351d39d-dirty"} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-http-long.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-http-long.json new file mode 100644 index 00000000..8c856ee9 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-gemma-http-long.json @@ -0,0 +1,397 @@ +{ + "worker": "live_rngd_subprocess_prefill", + "rows": [ + { + "case": "capital-400", + "request": "normal-0-0", + "response": { + "id": "normal-0-0", + "object": "text_completion", + "created": 1792765083, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6423, + "completion_tokens": 2, + "total_tokens": 6425 + } + }, + "latency_s": 2.059294487000443 + }, + { + "case": "arithmetic-400", + "request": "normal-0-1", + "response": { + "id": "normal-0-1", + "object": "text_completion", + "created": 1792765084, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "25", + "token_ids": [ + 236778, + 236810, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6424, + "completion_tokens": 3, + "total_tokens": 6427 + } + }, + "latency_s": 1.7813942750217393 + }, + { + "case": "korean-400", + "request": "normal-0-2", + "response": { + "id": "normal-0-2", + "object": "text_completion", + "created": 1792765086, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 98665, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6424, + "completion_tokens": 2, + "total_tokens": 6426 + } + }, + "latency_s": 1.7830313210142776 + }, + { + "case": "retrieval-400", + "request": "normal-0-3", + "response": { + "id": "normal-0-3", + "object": "text_completion", + "created": 1792765088, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 28487, + 1618, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6428, + "completion_tokens": 3, + "total_tokens": 6431 + } + }, + "latency_s": 1.8204669379629195 + }, + { + "case": "capital-400", + "request": "normal-1-0", + "response": { + "id": "normal-1-0", + "object": "text_completion", + "created": 1792765090, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6423, + "completion_tokens": 2, + "total_tokens": 6425 + } + }, + "latency_s": 1.8128947280347347 + }, + { + "case": "arithmetic-400", + "request": "normal-1-1", + "response": { + "id": "normal-1-1", + "object": "text_completion", + "created": 1792765092, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "25", + "token_ids": [ + 236778, + 236810, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6424, + "completion_tokens": 3, + "total_tokens": 6427 + } + }, + "latency_s": 1.8391432100906968 + }, + { + "case": "korean-400", + "request": "normal-1-2", + "response": { + "id": "normal-1-2", + "object": "text_completion", + "created": 1792765094, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 98665, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6424, + "completion_tokens": 2, + "total_tokens": 6426 + } + }, + "latency_s": 1.8177044560434297 + }, + { + "case": "retrieval-400", + "request": "normal-1-3", + "response": { + "id": "normal-1-3", + "object": "text_completion", + "created": 1792765095, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 28487, + 1618, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6428, + "completion_tokens": 3, + "total_tokens": 6431 + } + }, + "latency_s": 1.8186313869664446 + }, + { + "case": "arithmetic-400", + "request": "concurrent-1", + "response": { + "id": "concurrent-1", + "object": "text_completion", + "created": 1792765097, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "25", + "token_ids": [ + 236778, + 236810, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6424, + "completion_tokens": 3, + "total_tokens": 6427 + } + }, + "latency_s": 1.8222813030006364 + }, + { + "case": "capital-400", + "request": "concurrent-0", + "response": { + "id": "concurrent-0", + "object": "text_completion", + "created": 1792765099, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6423, + "completion_tokens": 2, + "total_tokens": 6425 + } + }, + "latency_s": 3.6308326860889792 + }, + { + "case": "retrieval-400", + "request": "concurrent-3", + "response": { + "id": "concurrent-3", + "object": "text_completion", + "created": 1792765101, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 28487, + 1618, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6428, + "completion_tokens": 3, + "total_tokens": 6431 + } + }, + "latency_s": 5.447109714965336 + }, + { + "case": "korean-400", + "request": "concurrent-2", + "response": { + "id": "concurrent-2", + "object": "text_completion", + "created": 1792765103, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 98665, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6424, + "completion_tokens": 2, + "total_tokens": 6426 + } + }, + "latency_s": 7.257134675048292 + }, + { + "case": "capital-400", + "request": "after-cancel", + "response": { + "id": "after-cancel", + "object": "text_completion", + "created": 1792765106, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6423, + "completion_tokens": 2, + "total_tokens": 6425 + } + }, + "latency_s": 1.8154899249784648 + }, + { + "case": "capital-400", + "request": "after-disconnect", + "response": { + "id": "after-disconnect", + "object": "text_completion", + "created": 1792765110, + "model": "unsloth/gemma-3-1b-it", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 50429, + 106 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6423, + "completion_tokens": 2, + "total_tokens": 6425 + } + }, + "latency_s": 1.791391227976419 + } + ], + "stats_pd": { + "remote": 16, + "local": 0 + }, + "free": [ + 0 + ], + "cancellation_reuse": true +} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-http-long-summary.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-http-long-summary.json new file mode 100644 index 00000000..da51cb0b --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-http-long-summary.json @@ -0,0 +1,44 @@ +{ + "models": [ + { + "model": "gemma", + "responses": 14, + "remote": 16, + "local": 0, + "cancellation_reuse": true, + "input_min": 6423, + "input_max": 6428 + }, + { + "model": "qwen06b", + "responses": 14, + "remote": 16, + "local": 0, + "cancellation_reuse": true, + "input_min": 6026, + "input_max": 6031 + }, + { + "model": "qwen4b", + "responses": 14, + "remote": 16, + "local": 0, + "cancellation_reuse": true, + "input_min": 6026, + "input_max": 6031 + }, + { + "model": "koni", + "responses": 14, + "remote": 16, + "local": 0, + "cancellation_reuse": true, + "input_min": 6137, + "input_max": 6143 + } + ], + "total_responses": 56, + "remote_prefills": 64, + "local_fallbacks": 0, + "hardware_batch": 1 +} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-koni-http-long.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-koni-http-long.json new file mode 100644 index 00000000..41262463 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-koni-http-long.json @@ -0,0 +1,394 @@ +{ + "worker": "live_rngd_subprocess_prefill", + "rows": [ + { + "case": "capital-400", + "request": "normal-0-0", + "response": { + "id": "normal-0-0", + "object": "text_completion", + "created": 1792766816, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 60704, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6138, + "completion_tokens": 2, + "total_tokens": 6140 + } + }, + "latency_s": 5.335317382006906 + }, + { + "case": "arithmetic-400", + "request": "normal-0-1", + "response": { + "id": "normal-0-1", + "object": "text_completion", + "created": 1792766820, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "42", + "token_ids": [ + 2983, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6137, + "completion_tokens": 2, + "total_tokens": 6139 + } + }, + "latency_s": 4.379292714060284 + }, + { + "case": "korean-400", + "request": "normal-0-2", + "response": { + "id": "normal-0-2", + "object": "text_completion", + "created": 1792766824, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 115978, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6139, + "completion_tokens": 2, + "total_tokens": 6141 + } + }, + "latency_s": 4.36221725505311 + }, + { + "case": "retrieval-400", + "request": "normal-0-3", + "response": { + "id": "normal-0-3", + "object": "text_completion", + "created": 1792766829, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 18082, + 877, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6143, + "completion_tokens": 3, + "total_tokens": 6146 + } + }, + "latency_s": 4.450131780933589 + }, + { + "case": "capital-400", + "request": "normal-1-0", + "response": { + "id": "normal-1-0", + "object": "text_completion", + "created": 1792766833, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 60704, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6138, + "completion_tokens": 2, + "total_tokens": 6140 + } + }, + "latency_s": 4.333481329958886 + }, + { + "case": "arithmetic-400", + "request": "normal-1-1", + "response": { + "id": "normal-1-1", + "object": "text_completion", + "created": 1792766837, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "42", + "token_ids": [ + 2983, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6137, + "completion_tokens": 2, + "total_tokens": 6139 + } + }, + "latency_s": 4.402466899016872 + }, + { + "case": "korean-400", + "request": "normal-1-2", + "response": { + "id": "normal-1-2", + "object": "text_completion", + "created": 1792766842, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 115978, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6139, + "completion_tokens": 2, + "total_tokens": 6141 + } + }, + "latency_s": 4.322912700008601 + }, + { + "case": "retrieval-400", + "request": "normal-1-3", + "response": { + "id": "normal-1-3", + "object": "text_completion", + "created": 1792766846, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 18082, + 877, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6143, + "completion_tokens": 3, + "total_tokens": 6146 + } + }, + "latency_s": 4.414992478094064 + }, + { + "case": "capital-400", + "request": "concurrent-0", + "response": { + "id": "concurrent-0", + "object": "text_completion", + "created": 1792766851, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 60704, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6138, + "completion_tokens": 2, + "total_tokens": 6140 + } + }, + "latency_s": 4.283409978961572 + }, + { + "case": "arithmetic-400", + "request": "concurrent-1", + "response": { + "id": "concurrent-1", + "object": "text_completion", + "created": 1792766855, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "42", + "token_ids": [ + 2983, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6137, + "completion_tokens": 2, + "total_tokens": 6139 + } + }, + "latency_s": 8.67299879703205 + }, + { + "case": "korean-400", + "request": "concurrent-2", + "response": { + "id": "concurrent-2", + "object": "text_completion", + "created": 1792766859, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 115978, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6139, + "completion_tokens": 2, + "total_tokens": 6141 + } + }, + "latency_s": 13.047355814022012 + }, + { + "case": "retrieval-400", + "request": "concurrent-3", + "response": { + "id": "concurrent-3", + "object": "text_completion", + "created": 1792766864, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 18082, + 877, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6143, + "completion_tokens": 3, + "total_tokens": 6146 + } + }, + "latency_s": 17.474600348970853 + }, + { + "case": "capital-400", + "request": "after-cancel", + "response": { + "id": "after-cancel", + "object": "text_completion", + "created": 1792766873, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 60704, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6138, + "completion_tokens": 2, + "total_tokens": 6140 + } + }, + "latency_s": 4.395555546972901 + }, + { + "case": "capital-400", + "request": "after-disconnect", + "response": { + "id": "after-disconnect", + "object": "text_completion", + "created": 1792766881, + "model": "KISTI-KONI/KONI-Llama3.1-8B-Instruct-20241024", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 60704, + 128009 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6138, + "completion_tokens": 2, + "total_tokens": 6140 + } + }, + "latency_s": 4.39396666304674 + } + ], + "stats_pd": { + "remote": 16, + "local": 0 + }, + "free": [ + 0 + ], + "cancellation_reuse": true +} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen06b-http-long.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen06b-http-long.json new file mode 100644 index 00000000..e9d48283 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen06b-http-long.json @@ -0,0 +1,457 @@ +{ + "worker": "live_rngd_subprocess_prefill", + "rows": [ + { + "case": "capital-400", + "request": "normal-0-0", + "response": { + "id": "normal-0-0", + "object": "text_completion", + "created": 1792765440, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6026, + "completion_tokens": 2, + "total_tokens": 6028 + } + }, + "latency_s": 3.1041212170384824 + }, + { + "case": "arithmetic-400", + "request": "normal-0-1", + "response": { + "id": "normal-0-1", + "object": "text_completion", + "created": 1792765442, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "17 + 25 = 42", + "token_ids": [ + 16, + 22, + 488, + 220, + 17, + 20, + 284, + 220, + 19, + 17, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6027, + "completion_tokens": 11, + "total_tokens": 6038 + } + }, + "latency_s": 2.572454360080883 + }, + { + "case": "korean-400", + "request": "normal-0-2", + "response": { + "id": "normal-0-2", + "object": "text_completion", + "created": 1792765445, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "대한민국의 수도는 **인천**입니다.", + "token_ids": [ + 66845, + 23573, + 125496, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6031, + "completion_tokens": 14, + "total_tokens": 6045 + } + }, + "latency_s": 2.60976382100489 + }, + { + "case": "retrieval-400", + "request": "normal-0-3", + "response": { + "id": "normal-0-3", + "object": "text_completion", + "created": 1792765447, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6031, + "completion_tokens": 3, + "total_tokens": 6034 + } + }, + "latency_s": 2.5075355779845268 + }, + { + "case": "capital-400", + "request": "normal-1-0", + "response": { + "id": "normal-1-0", + "object": "text_completion", + "created": 1792765450, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6026, + "completion_tokens": 2, + "total_tokens": 6028 + } + }, + "latency_s": 2.431598277995363 + }, + { + "case": "arithmetic-400", + "request": "normal-1-1", + "response": { + "id": "normal-1-1", + "object": "text_completion", + "created": 1792765452, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "17 + 25 = 42", + "token_ids": [ + 16, + 22, + 488, + 220, + 17, + 20, + 284, + 220, + 19, + 17, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6027, + "completion_tokens": 11, + "total_tokens": 6038 + } + }, + "latency_s": 2.365722585003823 + }, + { + "case": "korean-400", + "request": "normal-1-2", + "response": { + "id": "normal-1-2", + "object": "text_completion", + "created": 1792765455, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "대한민국의 수도는 **인천**입니다.", + "token_ids": [ + 66845, + 23573, + 125496, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6031, + "completion_tokens": 14, + "total_tokens": 6045 + } + }, + "latency_s": 2.4915975880576298 + }, + { + "case": "retrieval-400", + "request": "normal-1-3", + "response": { + "id": "normal-1-3", + "object": "text_completion", + "created": 1792765457, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6031, + "completion_tokens": 3, + "total_tokens": 6034 + } + }, + "latency_s": 2.4608081240439788 + }, + { + "case": "capital-400", + "request": "concurrent-0", + "response": { + "id": "concurrent-0", + "object": "text_completion", + "created": 1792765459, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6026, + "completion_tokens": 2, + "total_tokens": 6028 + } + }, + "latency_s": 2.436914485064335 + }, + { + "case": "arithmetic-400", + "request": "concurrent-1", + "response": { + "id": "concurrent-1", + "object": "text_completion", + "created": 1792765462, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "17 + 25 = 42", + "token_ids": [ + 16, + 22, + 488, + 220, + 17, + 20, + 284, + 220, + 19, + 17, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6027, + "completion_tokens": 11, + "total_tokens": 6038 + } + }, + "latency_s": 4.775390743045136 + }, + { + "case": "korean-400", + "request": "concurrent-2", + "response": { + "id": "concurrent-2", + "object": "text_completion", + "created": 1792765464, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "대한민국의 수도는 **인천**입니다.", + "token_ids": [ + 66845, + 23573, + 125496, + 124785, + 20401, + 134013, + 16560, + 3070, + 31328, + 129034, + 334, + 78952, + 13, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6031, + "completion_tokens": 14, + "total_tokens": 6045 + } + }, + "latency_s": 7.070237320964225 + }, + { + "case": "retrieval-400", + "request": "concurrent-3", + "response": { + "id": "concurrent-3", + "object": "text_completion", + "created": 1792765467, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6031, + "completion_tokens": 3, + "total_tokens": 6034 + } + }, + "latency_s": 9.64104292797856 + }, + { + "case": "capital-400", + "request": "after-cancel", + "response": { + "id": "after-cancel", + "object": "text_completion", + "created": 1792765472, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6026, + "completion_tokens": 2, + "total_tokens": 6028 + } + }, + "latency_s": 2.510781381977722 + }, + { + "case": "capital-400", + "request": "after-disconnect", + "response": { + "id": "after-disconnect", + "object": "text_completion", + "created": 1792765476, + "model": "Qwen/Qwen3-0.6B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6026, + "completion_tokens": 2, + "total_tokens": 6028 + } + }, + "latency_s": 2.521972832037136 + } + ], + "stats_pd": { + "remote": 16, + "local": 0 + }, + "free": [ + 0 + ], + "cancellation_reuse": true +} diff --git a/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen4b-http-long.json b/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen4b-http-long.json new file mode 100644 index 00000000..da36214f --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/evidence234/live234-qwen4b-http-long.json @@ -0,0 +1,400 @@ +{ + "worker": "live_rngd_subprocess_prefill", + "rows": [ + { + "case": "capital-400", + "request": "normal-0-0", + "response": { + "id": "normal-0-0", + "object": "text_completion", + "created": 1792766310, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6026, + "completion_tokens": 2, + "total_tokens": 6028 + } + }, + "latency_s": 5.043774194899015 + }, + { + "case": "arithmetic-400", + "request": "normal-0-1", + "response": { + "id": "normal-0-1", + "object": "text_completion", + "created": 1792766314, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "42", + "token_ids": [ + 19, + 17, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6027, + "completion_tokens": 3, + "total_tokens": 6030 + } + }, + "latency_s": 4.239778788993135 + }, + { + "case": "korean-400", + "request": "normal-0-2", + "response": { + "id": "normal-0-2", + "object": "text_completion", + "created": 1792766319, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 26698, + 126893, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6031, + "completion_tokens": 3, + "total_tokens": 6034 + } + }, + "latency_s": 4.6180367700289935 + }, + { + "case": "retrieval-400", + "request": "normal-0-3", + "response": { + "id": "normal-0-3", + "object": "text_completion", + "created": 1792766323, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6031, + "completion_tokens": 3, + "total_tokens": 6034 + } + }, + "latency_s": 4.293596021016128 + }, + { + "case": "capital-400", + "request": "normal-1-0", + "response": { + "id": "normal-1-0", + "object": "text_completion", + "created": 1792766328, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6026, + "completion_tokens": 2, + "total_tokens": 6028 + } + }, + "latency_s": 4.356954317074269 + }, + { + "case": "arithmetic-400", + "request": "normal-1-1", + "response": { + "id": "normal-1-1", + "object": "text_completion", + "created": 1792766332, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "42", + "token_ids": [ + 19, + 17, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6027, + "completion_tokens": 3, + "total_tokens": 6030 + } + }, + "latency_s": 4.4063200840028 + }, + { + "case": "korean-400", + "request": "normal-1-2", + "response": { + "id": "normal-1-2", + "object": "text_completion", + "created": 1792766336, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 26698, + 126893, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6031, + "completion_tokens": 3, + "total_tokens": 6034 + } + }, + "latency_s": 4.39458605600521 + }, + { + "case": "retrieval-400", + "request": "normal-1-3", + "response": { + "id": "normal-1-3", + "object": "text_completion", + "created": 1792766341, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6031, + "completion_tokens": 3, + "total_tokens": 6034 + } + }, + "latency_s": 4.390069373999722 + }, + { + "case": "capital-400", + "request": "concurrent-0", + "response": { + "id": "concurrent-0", + "object": "text_completion", + "created": 1792766345, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6026, + "completion_tokens": 2, + "total_tokens": 6028 + } + }, + "latency_s": 4.352759285015054 + }, + { + "case": "arithmetic-400", + "request": "concurrent-1", + "response": { + "id": "concurrent-1", + "object": "text_completion", + "created": 1792766350, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "42", + "token_ids": [ + 19, + 17, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6027, + "completion_tokens": 3, + "total_tokens": 6030 + } + }, + "latency_s": 8.775955583085306 + }, + { + "case": "korean-400", + "request": "concurrent-2", + "response": { + "id": "concurrent-2", + "object": "text_completion", + "created": 1792766354, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "서울", + "token_ids": [ + 26698, + 126893, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6031, + "completion_tokens": 3, + "total_tokens": 6034 + } + }, + "latency_s": 13.207480930024758 + }, + { + "case": "retrieval-400", + "request": "concurrent-3", + "response": { + "id": "concurrent-3", + "object": "text_completion", + "created": 1792766358, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "MAPLE", + "token_ids": [ + 17617, + 867, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6031, + "completion_tokens": 3, + "total_tokens": 6034 + } + }, + "latency_s": 17.583430355996825 + }, + { + "case": "capital-400", + "request": "after-cancel", + "response": { + "id": "after-cancel", + "object": "text_completion", + "created": 1792766367, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6026, + "completion_tokens": 2, + "total_tokens": 6028 + } + }, + "latency_s": 4.211048972909339 + }, + { + "case": "capital-400", + "request": "after-disconnect", + "response": { + "id": "after-disconnect", + "object": "text_completion", + "created": 1792766376, + "model": "Qwen/Qwen3-4B", + "choices": [ + { + "index": 0, + "text": "Paris", + "token_ids": [ + 59604, + 151645 + ], + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 6026, + "completion_tokens": 2, + "total_tokens": 6028 + } + }, + "latency_s": 4.349409435992129 + } + ], + "stats_pd": { + "remote": 16, + "local": 0 + }, + "free": [ + 0 + ], + "cancellation_reuse": true +} diff --git a/opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http-long234.md b/opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http-long234.md new file mode 100644 index 00000000..4d829c71 --- /dev/null +++ b/opt_prime/examples/pd/serving_matrix/experiments/2026-10-23-live-http-long234.md @@ -0,0 +1,34 @@ +# Long-input live RNGD to ATOM HTTP PD (complete) + +- **Date**: 2026-10-23 +- **Task**: aicomp #234 +- **Host / device**: existing owned paired RNGD+ATOM allocation; hardwareB1, context9216, same SDK/artifacts as live-http-mid234. +- **Commit**: adapter74d0d3b (evidence/docs75ce140); core1e54786 for Gemma/Qwen, df02223 behavior for KONI; HTTP9e442cd. + +## Question + +Do real HTTP-triggered prefill and decoder lifecycle checks remain correct for approximately6K token inputs? + +## Setup and command + +After run-live-mid234.sh exited0 for all models, start `bash run-live-long234.sh` in the same allocation. It uses the four exact medium-record commands with --width8192 (CLI syntax: --width 8192), *-400 instead of *-100 cases, and output live234--http-long.json. Model/factory/artifact/core module arguments are unchanged. Order:Gemma,Qwen0.6B,Qwen4B,KONI. Two sequential passes, four queued clients, cancellation/disconnect and reuse;14normal/reuse output checks per model. B1, cache-off, no saved-KV replay. + +## Results + +All four stages exited0. Each model has14/14 normal/concurrent/reuse responses matching native ATOM tokens/EOS,16remote prefills,0local fallbacks, cancellation/disconnect reuse passing and lane0 released. + +| Model | Input tokens | Responses | Remote prefills | +|---|---:|---:|---:| +| Gemma3-1B | 6423–6428 | 14/14 | 16 | +| Qwen3-0.6B | 6026–6031 | 14/14 | 16 | +| Qwen3-4B | 6026–6031 | 14/14 | 16 | +| KONI8B | 6137–6143 | 14/14 | 16 | + +Total56responses/64remote prefills. Across short+medium+long:168responses/192remote prefills,0fallback. These are B1 requests with queued client concurrency. No controlled performance result is claimed. The earlier offline31/32 long comparison includes an unresolved Gemma GPU-vs-RNGD numerical mismatch (#233); this live checker compares against nativeATOM and does not erase that discrepancy or certify answer quality. + +Local queue session70411 and all child benchmark processes completed. Queue stdout:analysis/serving-matrix-201/live234-long-queue.log. Per-model JSON and aggregate live234-http-long-summary.json are preserved in the same directory. + + +## Conclusion + +The four-model long live matrix is complete. Keep the overall goal active. Hardware batch>1, pending-prefill/worker-failure recovery, GPU live PD, cache restoration, numerical fidelity, compute-transfer overlap and matched serving performance remain open.