Track simulator fidelity experiment artifacts
This commit is contained in:
@@ -0,0 +1,266 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Audit and summarize the TP-normalized Qwen30 real-serving surface.
|
||||
|
||||
The script reads only public trace manifests and prompt-free client result
|
||||
records. It refuses to score an incomplete or contract-drifting trial.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import math
|
||||
import statistics
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
METRICS = ("ttft_ms", "tpot_ms", "e2e_ms")
|
||||
CONFIGS = tuple((tp, mns) for tp in (1, 2, 4) for mns in (8, 16, 32, 64))
|
||||
TRIALS = (1, 2, 3)
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--output-root", type=Path, required=True)
|
||||
parser.add_argument("--json-output", type=Path, required=True)
|
||||
parser.add_argument("--markdown-output", type=Path, required=True)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def nearest_rank(values: Iterable[float], percentile: float) -> float:
|
||||
ordered = sorted(values)
|
||||
if not ordered:
|
||||
raise ValueError("cannot calculate percentile of empty values")
|
||||
return ordered[math.ceil(len(ordered) * percentile) - 1]
|
||||
|
||||
|
||||
def number(value: Any, field: str) -> float:
|
||||
if not isinstance(value, (int, float)) or isinstance(value, bool):
|
||||
raise ValueError(f"{field} is not numeric: {value!r}")
|
||||
value = float(value)
|
||||
if not math.isfinite(value) or value < 0:
|
||||
raise ValueError(f"{field} is invalid: {value!r}")
|
||||
return value
|
||||
|
||||
|
||||
def load_manifest(root: Path, tp: int) -> dict[str, Any]:
|
||||
path = root / "traces" / f"tp{tp}" / "public" / "manifest.json"
|
||||
manifest = json.loads(path.read_text())
|
||||
if manifest.get("schema") != "qwen30-tp-normalized-trace-v1":
|
||||
raise ValueError(f"unexpected trace schema in {path}")
|
||||
if manifest.get("tensor_parallel_size") != tp:
|
||||
raise ValueError(f"TP mismatch in {path}")
|
||||
if manifest.get("requests") != 129:
|
||||
raise ValueError(f"unexpected request count in {path}")
|
||||
return manifest
|
||||
|
||||
|
||||
def validate_trial(
|
||||
result_path: Path, manifest: dict[str, Any], tp: int, mns: int, trial: int
|
||||
) -> tuple[dict[str, Any], dict[str, list[float]]]:
|
||||
payload = json.loads(result_path.read_text())
|
||||
if payload.get("schema") != "qwen30-exact-trace-anchor-v1":
|
||||
raise ValueError(f"unexpected result schema: {result_path}")
|
||||
|
||||
contract = payload.get("contract")
|
||||
summary = payload.get("summary")
|
||||
records = payload.get("requests")
|
||||
if not isinstance(contract, dict) or not isinstance(summary, dict) or not isinstance(records, list):
|
||||
raise ValueError(f"malformed result payload: {result_path}")
|
||||
expected_requests = int(manifest["requests"])
|
||||
checks = {
|
||||
"requests": (contract.get("requests"), expected_requests),
|
||||
"requests_file_sha256": (
|
||||
contract.get("requests_file_sha256"),
|
||||
manifest["private_jsonl_sha256"],
|
||||
),
|
||||
"row_vector_sha256": (
|
||||
contract.get("row_vector_sha256"),
|
||||
manifest["normalized_row_vector_sha256"],
|
||||
),
|
||||
"first_arrival_s": (
|
||||
contract.get("first_arrival_s"), manifest["normalized_first_arrival_s"],
|
||||
),
|
||||
"last_arrival_s": (
|
||||
contract.get("last_arrival_s"), manifest["normalized_last_arrival_s"],
|
||||
),
|
||||
"served_model_alias": (
|
||||
contract.get("served_model_alias"), "qwen3-30b-exact-trace"
|
||||
),
|
||||
}
|
||||
for field, (actual, expected) in checks.items():
|
||||
if isinstance(expected, float):
|
||||
if not isinstance(actual, (int, float)) or not math.isclose(
|
||||
float(actual), expected, abs_tol=1e-9
|
||||
):
|
||||
raise ValueError(f"{result_path}: contract {field} drift")
|
||||
elif actual != expected:
|
||||
raise ValueError(f"{result_path}: contract {field} drift")
|
||||
|
||||
if len(records) != expected_requests:
|
||||
raise ValueError(f"{result_path}: expected {expected_requests} records")
|
||||
if summary.get("completed") != expected_requests or summary.get("failed") != 0:
|
||||
raise ValueError(f"{result_path}: incomplete replay summary")
|
||||
|
||||
source_indices: set[int] = set()
|
||||
values: dict[str, list[float]] = {metric: [] for metric in METRICS}
|
||||
for record in records:
|
||||
if record.get("success") is not True:
|
||||
raise ValueError(f"{result_path}: failed request record")
|
||||
index = record.get("source_index")
|
||||
if not isinstance(index, int) or index in source_indices:
|
||||
raise ValueError(f"{result_path}: invalid source index")
|
||||
source_indices.add(index)
|
||||
if record.get("actual_input_tokens") != record.get("input_tokens"):
|
||||
raise ValueError(f"{result_path}: input usage mismatch")
|
||||
if record.get("actual_output_tokens") != record.get("requested_output_tokens"):
|
||||
raise ValueError(f"{result_path}: output usage mismatch")
|
||||
for metric in METRICS:
|
||||
if metric == "tpot_ms" and record.get(metric) is None:
|
||||
# OSL=1 prefill-only traces intentionally have no TPOT samples.
|
||||
continue
|
||||
values[metric].append(number(record.get(metric), metric))
|
||||
|
||||
if len(source_indices) != expected_requests:
|
||||
raise ValueError(f"{result_path}: missing source index")
|
||||
for metric, samples in values.items():
|
||||
if not samples:
|
||||
raise ValueError(f"{result_path}: no {metric} samples")
|
||||
|
||||
stats = {
|
||||
"tp": tp,
|
||||
"mns": mns,
|
||||
"trial": trial,
|
||||
"result_path": str(result_path),
|
||||
"requests": expected_requests,
|
||||
"metrics": {
|
||||
metric: {
|
||||
"samples": len(samples),
|
||||
"mean_ms": statistics.fmean(samples),
|
||||
"p90_ms": nearest_rank(samples, 0.90),
|
||||
}
|
||||
for metric, samples in values.items()
|
||||
},
|
||||
}
|
||||
return stats, values
|
||||
|
||||
|
||||
def aggregate(config_trials: list[dict[str, Any]], pooled: dict[str, list[float]]) -> dict[str, Any]:
|
||||
if len(config_trials) != len(TRIALS):
|
||||
raise ValueError("aggregate requires exactly three trials")
|
||||
metrics: dict[str, Any] = {}
|
||||
for metric in METRICS:
|
||||
trial_means = [row["metrics"][metric]["mean_ms"] for row in config_trials]
|
||||
trial_p90s = [row["metrics"][metric]["p90_ms"] for row in config_trials]
|
||||
values = pooled[metric]
|
||||
metrics[metric] = {
|
||||
"pooled_samples": len(values),
|
||||
"pooled_mean_ms": statistics.fmean(values),
|
||||
"pooled_p90_ms": nearest_rank(values, 0.90),
|
||||
"trial_mean_of_means_ms": statistics.fmean(trial_means),
|
||||
"trial_stddev_of_means_ms": statistics.stdev(trial_means),
|
||||
"trial_mean_of_p90s_ms": statistics.fmean(trial_p90s),
|
||||
}
|
||||
return {"trials": config_trials, "metrics": metrics}
|
||||
|
||||
|
||||
def winners(configs: dict[str, dict[str, Any]]) -> dict[str, dict[str, Any]]:
|
||||
result: dict[str, dict[str, Any]] = {}
|
||||
for metric in METRICS:
|
||||
for statistic in ("pooled_mean_ms", "pooled_p90_ms"):
|
||||
ranked = sorted(
|
||||
(
|
||||
(summary["metrics"][metric][statistic], key)
|
||||
for key, summary in configs.items()
|
||||
),
|
||||
key=lambda item: (item[0], item[1]),
|
||||
)
|
||||
result[f"{metric}:{statistic}"] = {
|
||||
"winner": ranked[0][1],
|
||||
"winner_value_ms": ranked[0][0],
|
||||
"ranking": [key for _, key in ranked],
|
||||
}
|
||||
return result
|
||||
|
||||
|
||||
def format_ms(value: float) -> str:
|
||||
return f"{value:.1f}"
|
||||
|
||||
|
||||
def render_markdown(payload: dict[str, Any]) -> str:
|
||||
lines = [
|
||||
"# Qwen3-30B-A3B TP-normalized Trace-PD: real vLLM audit",
|
||||
"",
|
||||
"All 36 fresh-server trials passed the trace contract: 129/129 exact-usage requests per trial. "
|
||||
"The smoke run is excluded. Values below pool the three trials (387 requests/config); "
|
||||
"p90 uses nearest-rank order statistics.",
|
||||
"",
|
||||
"| Config | TTFT mean/p90 (ms) | TPOT mean/p90 (ms) | E2E mean/p90 (ms) |",
|
||||
"|---|---:|---:|---:|",
|
||||
]
|
||||
for key, summary in payload["configs"].items():
|
||||
metrics = summary["metrics"]
|
||||
lines.append(
|
||||
"| {key} | {ttft_mean}/{ttft_p90} | {tpot_mean}/{tpot_p90} | {e2e_mean}/{e2e_p90} |".format(
|
||||
key=key,
|
||||
ttft_mean=format_ms(metrics["ttft_ms"]["pooled_mean_ms"]),
|
||||
ttft_p90=format_ms(metrics["ttft_ms"]["pooled_p90_ms"]),
|
||||
tpot_mean=format_ms(metrics["tpot_ms"]["pooled_mean_ms"]),
|
||||
tpot_p90=format_ms(metrics["tpot_ms"]["pooled_p90_ms"]),
|
||||
e2e_mean=format_ms(metrics["e2e_ms"]["pooled_mean_ms"]),
|
||||
e2e_p90=format_ms(metrics["e2e_ms"]["pooled_p90_ms"]),
|
||||
)
|
||||
)
|
||||
lines += ["", "## Per-metric winners", ""]
|
||||
for target, winner in payload["winners"].items():
|
||||
lines.append(
|
||||
f"- `{target}`: `{winner['winner']}` ({format_ms(winner['winner_value_ms'])} ms)"
|
||||
)
|
||||
lines.append("")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
args = parse_args()
|
||||
manifests = {tp: load_manifest(args.output_root, tp) for tp in (1, 2, 4)}
|
||||
configs: dict[str, dict[str, Any]] = {}
|
||||
for tp, mns in CONFIGS:
|
||||
key = f"tp{tp}_mns{mns}"
|
||||
trial_rows: list[dict[str, Any]] = []
|
||||
pooled = {metric: [] for metric in METRICS}
|
||||
for trial in TRIALS:
|
||||
path = args.output_root / "real" / key / f"trial{trial}" / "results" / "result.json"
|
||||
trial_stats, values = validate_trial(path, manifests[tp], tp, mns, trial)
|
||||
trial_rows.append(trial_stats)
|
||||
for metric in METRICS:
|
||||
pooled[metric].extend(values[metric])
|
||||
configs[key] = aggregate(trial_rows, pooled)
|
||||
payload = {
|
||||
"schema": "qwen30-tp-normalized-real-surface-audit-v1",
|
||||
"trace_manifests": {
|
||||
f"tp{tp}": {
|
||||
field: manifests[tp][field]
|
||||
for field in (
|
||||
"requests",
|
||||
"private_jsonl_sha256",
|
||||
"normalized_row_vector_sha256",
|
||||
"global_offered_request_rate",
|
||||
"per_gpu_offered_request_rate",
|
||||
)
|
||||
}
|
||||
for tp in manifests
|
||||
},
|
||||
"configs": configs,
|
||||
"winners": winners(configs),
|
||||
}
|
||||
args.json_output.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.markdown_output.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.json_output.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n")
|
||||
args.markdown_output.write_text(render_markdown(payload))
|
||||
print(json.dumps(payload["winners"], sort_keys=True))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
136
runs/simulator-tuning-latency-matrix-v0/dense-preflight.md
Normal file
136
runs/simulator-tuning-latency-matrix-v0/dense-preflight.md
Normal file
@@ -0,0 +1,136 @@
|
||||
# Qwen3.6-27B non-MoE/hybrid preflight and topology-smoke record
|
||||
|
||||
> **Status (2026-07-17): `TOPOLOGY-SMOKE PASS; FRONTIER COVERAGE BLOCKED`.**
|
||||
> The exact snapshot and official community-vLLM release are accepted through
|
||||
> a fresh-server TP1/TP2/TP4 GPU smoke. No Frontier Qwen3.6 contract/profile,
|
||||
> trace replay, or latency-matrix cell exists. The smoke is compatibility
|
||||
> evidence only, not simulator-fidelity or latency-selection evidence.
|
||||
|
||||
## Decision enabled by this preflight
|
||||
|
||||
The latency-matrix experiment may add its dense branch only after the exact
|
||||
model snapshot, a runnable open-source vLLM environment, and a Qwen3.6
|
||||
Frontier contract/profile root exist on the same stack. Until then, all dense
|
||||
matrix cells are **`NOT RUN`**. They are neither simulator failures nor
|
||||
evidence for dense+MoE generalization.
|
||||
|
||||
## Executed staging record (after explicit approval)
|
||||
|
||||
| Step | Evidence | Result |
|
||||
|---|---|---|
|
||||
| Immutable snapshot staging | ModelScope `Qwen/Qwen3.6-27B@cea40373b9214dd387123e68841890af30dcd469` was downloaded to `/home/admin/cpfs/wjh/models/Qwen/Qwen3.6-27B`. The downloader recorded `download_start` and `download_complete` at `2026-07-17T07:42:00Z` and `2026-07-17T07:44:45Z`, respectively, in `/home/admin/cpfs/wjh/models/.staging/qwen36-27b-20260717/download.log`. | **PASS**; 29 snapshot files, approximately 52 GiB. |
|
||||
| Snapshot integrity | Sorted per-file SHA-256 inventory: `/home/admin/cpfs/wjh/models/.staging/qwen36-27b-20260717/files.sha256`; inventory digest `031cea103726cbf27732b6971e898e210aee77f0c32e4bc703c947e0372349c4`. It includes `config.json`, tokenizer files, and all 15 `model-*.safetensors` shards; no `*.incomplete`, `*.lock`, or `*.tmp` files were found. | **PASS**. |
|
||||
| CPU config/tokenizer parser | The preinstalled system `transformers==4.57.5` rejects `model_type=qwen3_5`; this environment is excluded. A dedicated CPU-only environment with `transformers==5.5.3` successfully parsed the snapshot with `CUDA_VISIBLE_DEVICES=""`: `Qwen3_5ForConditionalGeneration`, text model type `qwen3_5_text`, 64 layers, hidden size 5120, `mamba_ssm_dtype=float32`, tokenizer length 248077. | **PASS**, but only for checkpoint/tokenizer parsing; it is not the serving runtime. |
|
||||
| Community vLLM release runtime | The initial source-build attempt was stopped before acceptance and is excluded. Official PyPI wheel `vllm==0.20.2` was staged at `wheel-probe-proxy/vllm-0.20.2-cp38-abi3-manylinux_2_35_x86_64.whl`, SHA-256 `22a7dd06eb03371298e13d6100f3dedbf307352342aaf08e87c929c60aae9b4d`, then installed into the clean environment `/home/admin/cpfs/wjh/venvs/qwen36-vllm-0.20.2`. `pip check` reports no broken requirements. | **PASS (CPU-only)**: vLLM `0.20.2`, Torch `2.11.0`, Transformers `5.14.1`; with `CUDA_VISIBLE_DEVICES=""`, `vllm.transformers_utils.config.get_config(..., trust_remote_code=False)` parses the exact snapshot as `Qwen3_5ForConditionalGeneration` / `qwen3_5`. |
|
||||
| Fresh GPU topology smoke | Fresh text-only servers on H20 TP1, TP2, TP4 used the exact release runtime with requested `MNS=8`, `MBT=8192`, BF16, chunked prefill on, prefix cache off, and one `2048 → 1` request per topology. Every response reported exactly 2048 prompt and 1 completion token; all four used GPUs were zero-memory after cleanup. Evidence root: `artifacts/qwen36/smoke-v4-20260717/`; artifact inventory SHA-256 `5b09c94e61801bfb7085257cfeea88049dfa81001f50810d85b9f87468088be0`. | **PASS (GPU compatibility)**. It establishes that TP1/2/4 can serve this model on the intended release, not that any topology has lower latency. |
|
||||
|
||||
## Confirmed model identity and architecture
|
||||
|
||||
| Item | Confirmed fact | Consequence for the experiment |
|
||||
|---|---|---|
|
||||
| Canonical source | ModelScope [`Qwen/Qwen3.6-27B`](https://www.modelscope.cn/models/Qwen/Qwen3.6-27B) | Use this repository, not an inferred Hugging Face mirror or an old Qwen3.5 checkpoint. |
|
||||
| Immutable revision | Read-only `git ls-remote --symref` on 2026-07-17 resolved `master`/`HEAD` to `cea40373b9214dd387123e68841890af30dcd469`. | Pin this commit hash in the download record. Do **not** record only the mutable name `master`. Re-resolve it immediately before an approved download; a changed hash requires a new review. |
|
||||
| Model metadata | ModelScope API reports `Architectures=["Qwen3_5ForConditionalGeneration"]` and `ModelType=["qwen3_5"]`. The official card says the artifact is a causal language model with a vision encoder. | This is dense with respect to MoE routing, but it is **not** a conventional all-attention dense transformer. The text benchmark must send no media; the model runner must still be the architecture selected from the exact checkpoint config. |
|
||||
| Text architecture (official card) | 27B parameters; hidden size 5120; padded token embedding / LM output 248320; 64 layers; `16 × (3 × (Gated DeltaNet → FFN) → 1 × (Gated Attention → FFN))`; DeltaNet has V=48/QK=16 heads of 128; gated attention has Q=24/KV=4 heads of 256 and RoPE dimension 64; FFN intermediate size 17408; native context 262144. | A Frontier profile must cover both DeltaNet/linear-state and gated-attention paths, in prefill, decode, and true mixed execution. An all-attention Qwen3.5 or Qwen3-30B/MoE profile is not a valid substitute. |
|
||||
| Tokenizer | The staged snapshot contains the tokenizer artifacts in the immutable file inventory. The earlier dedicated CPU parser reported tokenizer length `248077`; `248320` above is still only the padded embedding/output size, not the tokenizer contract. | Request input/output lengths must be tokenized with this staged tokenizer. Before trace materialization, freeze a tokenizer/config subset digest and do not borrow counts from a Qwen3.5 tokenizer. |
|
||||
|
||||
The official ModelScope card states that these artifacts are compatible with
|
||||
Transformers, vLLM, SGLang, and KTransformers. That is useful compatibility
|
||||
evidence, not a successful run on the selected `dash0` stack.
|
||||
|
||||
## Runtime provenance and excluded alternatives
|
||||
|
||||
| Evidence | Read-only observation | Verdict |
|
||||
|---|---|---|
|
||||
| System vLLM | `/usr/local/bin/vllm` reports `0.13.0rc2.dev2111+gb44b43f43.d20260309`, with Torch `2.8.0a0+5228986c39.nv25.6` and Transformers `4.57.5`. Its installed source contains `qwen3_5.py`, `qwen3_5_mtp.py`, registry entries for `Qwen3_5ForConditionalGeneration`, and branches for `qwen3_5_text`. | Architecture-family support is present, but this development build is not yet the frozen community experiment runtime. |
|
||||
| Uninstalled local source | `/home/admin/cpfs/wjh/agentic-kv/third_party/vllm_v20_build` is `v0.20.0` source with build by-products; `/home/admin/cpfs/wjh/venvs/vllm-0.20.0` does not contain a runnable vLLM/Transformers pair. | **Excluded.** It is not the experiment runtime and must not be cited as an alternative same-stack result. |
|
||||
| Qwen-specific state/page rule | The v0.20 Qwen3.5 implementation obtains Mamba/DeltaNet state settings from the checkpoint when cache dtype is auto; the actual v0.20.2 GPU smoke then resolved its attention page to 784 tokens. | The state/page rule is a model-state contract, not an optional benchmark flag. The profile and simulator must consume the observed physical page setting. |
|
||||
|
||||
Therefore the defensible statement now is: **the exact Qwen3.6-27B snapshot
|
||||
is CPU-parsed and GPU-served by the frozen official community vLLM release on
|
||||
`dash0` at TP1/2/4. It is a non-MoE hybrid model, not a conventional
|
||||
all-attention dense-transformer evidence point.**
|
||||
|
||||
## GPU topology-smoke observations (not a latency experiment)
|
||||
|
||||
The runner is a one-request topology/usage check, with a fresh server for
|
||||
each TP. Its E2E values are retained only to audit that a request completed;
|
||||
they are not steady-state samples, are not TTFT/TPOT measurements, and must
|
||||
not be ranked.
|
||||
|
||||
| TP | Exact usage | Smoke E2E (audit only) | Resolved attention page/block size | GPU KV cache at `max_model_len=4096` |
|
||||
|---|---|---:|---:|---:|
|
||||
| 1 | 2048 prompt, 1 completion | 4581.977 ms | 784 tokens | 306,289 tokens |
|
||||
| 2 | 2048 prompt, 1 completion | 5606.756 ms | 784 tokens | 1,068,600 tokens |
|
||||
| 4 | 2048 prompt, 1 completion | 6252.274 ms | 784 tokens | 2,630,087 tokens |
|
||||
|
||||
vLLM accepted the requested `--block-size 16` but then logged, at every TP,
|
||||
`Setting attention block size to 784 tokens to ensure that attention page size
|
||||
is >= mamba page size.` Thus **block size 16 is not the actual engine state
|
||||
for this model**. A later real/simulator comparison must freeze and expose the
|
||||
resolved 784-token page/state contract (or deliberately select a different
|
||||
legal engine mode before profiling); it may not label this stack as a
|
||||
block-16 comparison. First TP1 startup also compiled FlashInfer GDN kernels
|
||||
and performed a cold profile/warmup; these one-time costs remain outside all
|
||||
request-latency metrics.
|
||||
|
||||
## Initial read-only `dash0` inventory (historical; superseded where noted)
|
||||
|
||||
All paths below were inspected without mutation on 2026-07-17.
|
||||
|
||||
| Area | Observation | Consequence |
|
||||
|---|---|---|
|
||||
| Disk | `/home/admin` root filesystem: 245 GiB available. Shared CPFS mounted at `/home/admin/cpfs`: 1.1 TiB available, already 95% used. Existing `/home/admin/cpfs/wjh/models` is 1.2 TiB and `/home/admin/resource/model` is 1.7 TiB. | Stage only after an explicit capacity check; do not rely on the root filesystem or an unconstrained default cache. |
|
||||
| Checked model/cache locations | Before staging, the usual locations were absent. | **Superseded:** the immutable snapshot is now at `/home/admin/cpfs/wjh/models/Qwen/Qwen3.6-27B` and is bound by the inventory above. |
|
||||
| Main checkout | `/home/admin/cpfs/wjh/aituner/aituner` had tracked and untracked user changes. | The smoke wrote only new artifacts and did not modify its source. A future profile implementation must use an explicitly versioned source/patch root rather than treating this dirty checkout as code provenance. |
|
||||
| Frontier | Historical Frontier source exists at `/home/admin/cpfs/wjh/frontier-qwen30-vllm020-profile-v1/Frontier`, commit `d9cfeb6d8791fbf2f295dd9744c56a666171776e` (`pre-release-v0.2`), with a clean tracked tree. A source search found no `Qwen3.6`, `Qwen3_5`, or `qwen3_5` model-contract hit. | It is not an existing Qwen3.6 profile/model contract. A new dense adapter/spec must be versioned and accepted before it may be used. |
|
||||
| Existing profiler contract | The old Qwen3-30B profile launcher hard-codes `model=qwen3-a3b-30b-moe`, `--is_moe`, vLLM 0.20 API adapters, and Frontier commit `d9cf…`. | It cannot be repurposed by only changing a model path; its MoE assumptions and compatibility adapter are excluded from the dense baseline. |
|
||||
| Qwen3.6 artifacts | A read-only search of the checkout's `runs` subtree found no Qwen3.6-named run/profile/model path. | No dense Frontier profile or real/simulator output is admissible today. |
|
||||
|
||||
## Remaining gates before any latency-matrix cell
|
||||
|
||||
1. **Trace/tokenizer lock:** materialize the Qwen3.6 tokenized Fixed/Trace-P/
|
||||
Trace-PD vectors and hash the exact tokenizer/config subset. Trace-PD is
|
||||
not trace-faithful without the input, output, arrival and prefix-state
|
||||
vector.
|
||||
2. **New Frontier contract:** introduce a versioned Qwen3.6 **non-MoE hybrid** model spec
|
||||
that maps the exact `config.json` to simulator operators. It must represent
|
||||
Gated DeltaNet/linear-state, gated attention, FFN, TP collectives and KV/
|
||||
state-cache capacity, including the resolved 784-token page rule. It may
|
||||
not import the Qwen3-30B MoE routing profile, an all-attention Qwen3.5
|
||||
profile, or an unrecorded additive timing scale. Any compatibility adapter
|
||||
is a separate, hashed intervention.
|
||||
3. **Profile manifest:** collect and freeze per-TP (1/2/4) profile rows for
|
||||
the above stages over shapes covering Fixed-P, Fixed-PD, Trace-P and
|
||||
Trace-PD. Include prefill, decode and genuine mixed batches, plus TP2/TP4
|
||||
all-reduce. The manifest must bind model revision/config hash, tokenizer
|
||||
hash, vLLM/environment hash, Frontier commit/adapter hash, hardware,
|
||||
precision, profiler command, CSV hashes, and shape coverage.
|
||||
4. **CPU simulator acceptance:** reject the profile root unless every required profile
|
||||
family has finite rows for all legal TP values and requested shapes; all
|
||||
identity hashes match the real-server lock; profile/model manifests name
|
||||
Qwen3.6; and the simulator emits request-level TTFT/E2E/TPOT where defined
|
||||
for a no-GPU fixture. A missing simulator operator is a **coverage
|
||||
blocker**, not a license to borrow a Qwen30 profile.
|
||||
|
||||
Only after all four gates may a separately approved real/simulator 600-s
|
||||
latency surface begin. The GPU smoke closed the runtime/topology gate only; it
|
||||
does not close any of these simulator or evaluation gates.
|
||||
|
||||
## Evidence locations
|
||||
|
||||
- This record: `runs/simulator-tuning-latency-matrix-v0/dense-preflight.md`.
|
||||
- Matrix decision/protocol: `runs/simulator-tuning-latency-matrix-v0/experiment-card.md`.
|
||||
- Existing (excluded) MoE-v0.20 profile launcher and its hard-coded contract:
|
||||
`runs/frontier-qwen30-vllm020-profile-v1/run_frontier_linear_smoke.sh` and
|
||||
`runs/frontier-qwen30-vllm020-profile-v1/frontier_vllm020_compat.py`.
|
||||
- Existing Frontier surface runner shows the required external source,
|
||||
ReplayServe builder, profile root, request-level metric, and hash contract:
|
||||
`runs/frontier-phase-factorial-v0/run_frontier_qwen30_prefill_surface.py`.
|
||||
|
||||
## Not completed
|
||||
|
||||
- No Qwen3.6 Frontier model spec or profile exists.
|
||||
- No Qwen3.6 fixed/trace workload vector is frozen.
|
||||
- No real or simulator latency measurement exists, so this record cannot
|
||||
change the simulator-selection verdict.
|
||||
@@ -0,0 +1,144 @@
|
||||
# Existing simulator evidence audit for the no-SLO latency matrix
|
||||
|
||||
> **Scope:** local-artifact audit on 2026-07-17. This document does not run a
|
||||
> simulator or a server. It separates (1) historical evidence about
|
||||
> **SLO-feasible capacity selection** from (2) the new matrix's claim about
|
||||
> **same-trace request-level mean/p90 TTFT, TPOT, and E2E latency selection**.
|
||||
> These are different objectives; a historical top-set match is not silently
|
||||
> promoted into a no-SLO latency-tuning result.
|
||||
|
||||
## Executive verdict
|
||||
|
||||
The checked-in evidence already rules out the broad claim that Frontier (or a
|
||||
Vidur-class simulator) has *generally* solved serving-config tuning: a fully
|
||||
covered Qwen3-30B prefill-only surface has no real/simulator top-set overlap,
|
||||
with 12.5% worst regret and `τ-b=-1.0`. Conversely, two Qwen3-235B surfaces
|
||||
show that an extensively aligned, patched profile can select the capacity
|
||||
optimum in a particular envelope. Neither observation answers the new paper
|
||||
question by itself, because every completed selection result optimizes
|
||||
SLO-feasible offered throughput/GPU rather than a fixed trace's request-level
|
||||
mean/p90 latency.
|
||||
|
||||
The appropriate new claim before the latency matrix is therefore:
|
||||
|
||||
> Existing results establish both a capability envelope and a counterexample
|
||||
> for **SLO/capacity tuning**. They motivate, but do not replace, the planned
|
||||
> non-MoE-hybrid/MoE × Fixed-P/Fixed-PD/Trace-P/Trace-PD latency-selection
|
||||
> matrix.
|
||||
|
||||
## Objective boundary (non-negotiable)
|
||||
|
||||
All completed comparisons below rank a config by
|
||||
|
||||
```text
|
||||
maximum tested offered request rate / allocated GPU
|
||||
subject to a joint request SLO pass-rate threshold (normally >= 95%).
|
||||
```
|
||||
|
||||
The new matrix instead holds one trace fixed for every candidate and independently
|
||||
ranks `mean`/`p90` TTFT, TPOT (when `OSL>1`), and E2E. It has no SLO feasibility
|
||||
gate and no capacity search. The consequences are material:
|
||||
|
||||
- A capacity top-set hit can arise from a large topology margin even when
|
||||
request-level latency residuals and within-family ordering are wrong.
|
||||
- A simulator that makes every config SLO-infeasible (or ties every config) has
|
||||
not selected a config, even if its set mechanically contains the real best
|
||||
config.
|
||||
- Historical runs may contain per-request latency observations, but their
|
||||
anchors differ by config because each is a capacity search. They cannot be
|
||||
re-labelled as a same-trace latency ranking without a new fixed-trace
|
||||
analysis contract.
|
||||
|
||||
Thus **all historical regret and correlation numbers in this document are
|
||||
capacity/SLO diagnostics only**. They must not appear in a result table as
|
||||
mean/p90 TTFT, TPOT, or E2E selection evidence.
|
||||
|
||||
## Completed selection comparisons
|
||||
|
||||
`Coverage` distinguishes complete config-level rankings from request/anchor
|
||||
coverage. A completed simulator run is not semantic coverage when it has no
|
||||
finite request metrics or no discriminative ordering.
|
||||
|
||||
| Case / condition | Model, runtime, workload | Real / simulator coverage | Historical selection result | What it can establish | What it cannot establish for the new matrix |
|
||||
|---|---|---|---|---|---|
|
||||
| **Q30-mixed, old profile-only** | Qwen3-30B-A3B; community vLLM 0.20.0/CUDA 12.9; `chat_w20260311_1000` replay, time scale 0.1, input 0–8192, output overridden to 128, max concurrency 64; `TP{1,2,4}×MNS{8,16,32,64}`. | 12/12 real configs; 92 real anchors. Frontier replayed the same frozen cohort for all 92 anchors. | Real best `TP2/MNS32`; sim top `{TP4/MNS32,TP4/MNS64}`; miss; worst regret **25.63%**; `τ-b=0.0000`; 37/0/55 SLO agree/false-feasible/false-infeasible. | A profile-only simulator can select the wrong TP family under a mixed serving capacity objective. | It is not trace-faithful under the new definition: time is scaled, outputs are overridden, and the score is SLO capacity, not latency. It proves no mean/p90 latency claim. |
|
||||
| **Q30-mixed, vLLM-0.20 same-stack profile-only** | Same Qwen30/mixed 12-cell surface; BF16 H20 profiles re-collected on vLLM source `88d34…`; no serving E2E scale. | All **92/92** simulator probes completed (two CPU shards, no crash), but all 12 configs are SLO-infeasible. | No actionable selection: all 12 tie; worst tie-break regret **60.91%**; `τ-b=0.0000`; exact pair sign 7.58%. | Same-stack isolated operator provenance alone did not recover the historical capacity ordering. | “All tied” is not a top-set success and says nothing directly about fixed-trace latency ranking. The model/workload is also MoE mixed, not the dense branch. |
|
||||
| **Q30-mixed, frozen per-TP E2E calibration** | Same Qwen30/mixed surface; per-TP execution-time scales fitted on separate `coder_200` serving workloads then frozen. | 12/12 configs and 92 anchors; request-level SLO labels still have 21 false-feasible and 7 false-infeasible anchors. | Sim top `{TP2/MNS32,TP2/MNS64}` intersects real best `{TP2/MNS32}`; worst regret **0.76%**; `τ-b=0.9668`. | An action-conditioned real-serving calibration can make this *capacity* surface near-optimal. | The per-TP E2E scale is prohibited by the new matrix's information boundary. It is an upper-bound/diagnostic, not zero-shot simulator evidence and not latency evidence. |
|
||||
| **Q30 Fixed-P-like prefill-only, base Frontier** | Qwen3-30B-A3B; community vLLM 0.20.0+cu129 BF16/FA3/default CUDA graph; fixed ISL=2048, OSL=1, uniform QPS, prefix off; 12 configs `TP{1,2,4}×MNS{8,16,32,64}`, MBT=8192. | 12/12 valid real configs; 96 real/sim SLO anchor decisions, with all requested request metrics present in the accepted comparison. | Real top is all TP4 configs (8 req/s/GPU); sim top is all TP1/TP2 configs (8 vs real 7); **no overlap**; worst regret **12.50%**; `τ-b=-1.0000`; 0/32 real non-tied directions correct. | A strong counterexample: removing decode, true-mixed batch, prefix reuse, and initial-KV state is not sufficient for capacity-ranking fidelity. | It is closest only to the planned MoE Fixed-P case. It still ranks SLO capacity, not mean/p90 TTFT/E2E on one 600-s trace, so it cannot fill that matrix cell. |
|
||||
| **Q30 Fixed-P-like, A2 measured-collective fix** | Same Q30 prefill workload/configs; measured Vidur collective estimator replaces the `>100k`-element analytical fallback. | 12/12 config scores exist. Anchor grid: 60 shared real/sim labels, 36 real-only, 0 sim-only; all simulator top scores tie. | Sim top includes all 12 configs; best tie-break regret 0 but **worst=12.50%**; `τ-b=N/A` (32 simulator-only ties); 0/32 non-tied directions correct. | The collective profile is consumed after the patch; its small change does not make the capacity choice usable. | Set overlap is accidental/non-discriminative. This is a simulator-only ablation against historical SLO ground truth, not a new latency result. |
|
||||
| **Q30 Fixed-P-like, A3 batch-composition rows** | Same as A2, plus pure-prefill attention rows for MBT=8192-reachable compositions. | Same as A2: 12/12 config scores; 60 shared + 36 real-only anchor labels; no missing simulator config score. | Same non-selection as A2: all 12 tie; worst regret **12.50%**; `τ-b=N/A`; 0/32 non-tied directions correct. | Adding this static batch-profile closure did not resolve the historical capacity ranking. | It does not prove scheduler-state root cause, and cannot substitute for no-SLO request-latency ranking. |
|
||||
| **Q235 prefill-only, best-effort aligned profile** | Qwen3-235B-A22B-FP8; community vLLM 0.10.2, eager, FP8 weights/BF16 KV; length-stratified fixed 64-request cohort from `thinking_w20260327_1000`, OSL=1, prefix/speculative off; `TP{4,8}×MNS{64,128}×MBT{8192,16384}`. | 8/8 rankable real configs; refined comparisons report 33 config-load labels with 6 false-infeasible labels, not a missing simulator surface. | Exact top-set match: TP4/MBT16K/MNS64 or 128; worst regret **0**; Spearman `ρ=0.9487`; all 20 comparable real non-tie pairs correct. | With same-stack FP8/MoE profiles, measured KV capacity and explicit compatibility patches, Frontier can select one prefill-only capacity surface. | The workload is a length-stratified cohort, not Fixed-P or Trace-P; it is a different MoE model/runtime/config surface and SLO objective. It does not generalize to dense, decode, prefix reuse, or latency metrics. |
|
||||
| **Q235 Fixed-PD-like mixed (T0)** | Qwen3-235B-A22B-FP8; community vLLM 0.10.2 eager, FP8/BF16-KV; fixed ISL=2048, OSL=128, uniform QPS, prefix/spec/CUDA graph off; same 8 config surface. | **8/8** real capacity boundaries closed (68 fresh-server anchors); simulator **64/64** config×rate cells have 64 finite, non-negative, shape-exact request records; 34 measured labels with 10 false-infeasible, 0 false-feasible. | Exact TP4 top-set match; worst regret **0**; `τ-b=0.8944`; 16/20 real non-tied directions correct. | The most complete historical profile-closed mixed-capacity success. It demonstrates that a large TP4-vs-TP8 margin can tolerate sizeable absolute and within-TP residuals. | The primary 150-ms TPOT SLO was a disclosed post-pilot sensitivity (40-ms primary had no feasible capacity). It is not a fixed-trace mean/p90 TTFT/TPOT/E2E selection result, and it misses the TP8 MNS×MBT interaction. |
|
||||
|
||||
### The capability envelope is not a global solution
|
||||
|
||||
The two Q235 successes are real positive evidence, but must be reported with
|
||||
their alignment cost and failure modes:
|
||||
|
||||
- Q235 prefill used FP8/MoE serving-plan, TP/EP-aware cache-key and
|
||||
critical-lane patches, same-stack operator/collective profiles, and real KV
|
||||
capacity. It was not stock Frontier.
|
||||
- Q235 mixed required an attention profile closure (prefill + standard decode +
|
||||
true mixed) with 1,104 rows. The accepted real ground truth alone cost
|
||||
36.26 H20-GPU-hours. The simulator still flattened the TP8 MNS×MBT
|
||||
checkerboard: 10/34 labels were false-infeasible even though its global top
|
||||
set was correct.
|
||||
- The Q30 prefill counterexample used the same 12-config type of surface as
|
||||
the planned MoE Fixed-P branch and reverses the entire topology order. A
|
||||
successful Q235 capacity ranking therefore cannot be offered as evidence
|
||||
that a simulator already solves this new tuning problem.
|
||||
|
||||
## Cases that are diagnostics or plans, not valid selection evidence
|
||||
|
||||
| Artifact/case | Status and observed coverage | Why it is useful | Why it cannot enter a new-matrix verdict |
|
||||
|---|---|---|---|
|
||||
| Historical internal-runtime Q235 prefill | 8/8 real cells, but different serving/runtime contract from the aligned community-vLLM Frontier profile. | Records a real response surface and demonstrates stack sensitivity. | No fair real/simulator contract; excluded by `simulator-fidelity.md`. |
|
||||
| Historical Q235 decode-only | Only 7/8 valid real cells; capacity brackets overlap such that all eight may be optimal. Frontier lacks equivalent initial-KV/EP8 execution semantics. | Identifies initial-KV, EAGLE3, DeepEP/NVSHMEM and decode-graph state as contract gaps. | No identifiable real best and no semantically aligned simulator; no hit/regret/`τ-b` is valid. |
|
||||
| Q235 T0 pre-profile-closure smoke | Real TP4 test completed; original Frontier crash had no standard decode rows. After minimal closure, only a one/two-request representation smoke completed, with 27–35% TPOT absolute error. | Demonstrates that a simulator crash must be treated as coverage failure, not an SLO failure; motivated the full T0 profile closure. | A single-config smoke cannot select across configs and cannot support any ranking claim. |
|
||||
| Envelope F1 short-prefill pilot | Fixed ISL=512/OSL=1, 64 requests. The 512-QPS pilot covers only 0.123 s and is explicitly non-decision-bearing. | Reveals the need for a steady-arrival duration contract. | No sustained real capacity surface and no paired selection metrics. |
|
||||
| Envelope F1 steady, F2 fixed mixed, T1 exact trace | Protocol/frozen simulator artifacts exist; no paired valid real/simulator selection comparison is recorded. In particular, T1's simulator artifact is not a completed real trace evaluation. | The contracts are a useful starting point for fixed/trace workload materialization. | `NOT RUN` for the purpose of a simulator-selection result. Do not cite them as trace-faithful success/failure. |
|
||||
| Q235 protocol T1/T2 | The protocol explicitly marks T1 trace-faithful mixed and T2 strict decode-only as not run; only T0 is complete. | T1 preserves source request fields; T2 correctly requires an explicit initial-KV contract. | No real/sim coverage, hit, regret, or `τ-b` exists. |
|
||||
|
||||
## What can be reused safely
|
||||
|
||||
| Reusable input | Allowed use in the new matrix | Prohibited inference |
|
||||
|---|---|---|
|
||||
| Q30 prefill accepted artifacts | Harness conventions: fresh server, two rounds, request shape/usage validation, request-level record layout, and a known failure case for coverage gates. | Treating the old TP4/TP1/2 capacity ordering or 12.5% regret as mean/p90 TTFT/E2E selection evidence. |
|
||||
| Q235 T0 artifacts | Fixed-PD measurement practice: exact 2048/128 token accounting, separate warmup, finite request metrics, profile identity/coverage checks, and state-leakage exclusion. | Reusing its Q235 FP8/vLLM0.10 profile or TP4/TP8 conclusion for Qwen3.6 non-MoE hybrid or Qwen3-30B MoE. |
|
||||
| Q235 trace audit | Trace manifest structure: exact prompt/token lengths, arrival/session order, source hashes, tokenizer audit, and explicit source-to-runtime block-size translation. | Calling a trace-faithful latency cell complete before runtime block/cache counter parity and paired real/simulator results exist. |
|
||||
| A2/A3 ablations | A negative control for the hypothesis that better static collective or pure-prefill batch rows alone solve the Q30 residual. | Claiming the remaining error is uniquely caused by scheduler state; routing, graph/fusion, and collective composition remain alternatives. |
|
||||
|
||||
## Required interpretation in the paper and the next experiment
|
||||
|
||||
1. Say **“not solved in general”**, supported by the Q30 no-overlap
|
||||
counterexample; do not say “all simulators fail,” because the Q235 envelope
|
||||
has valid capacity-selection successes.
|
||||
2. Report the positive cases as *conditional capacity results* and disclose
|
||||
patches, profiles, real KV capacity, profile cost, and—where used—per-TP
|
||||
E2E calibration. Do not call them zero-cost tuning.
|
||||
3. Do not average these cases into an aggregate score. Model, precision,
|
||||
runtime, topology, objective, and workload differ; the average would hide
|
||||
the decision-bearing Q30 reversal.
|
||||
4. Run the new matrix exactly as specified in
|
||||
[experiment-card.md](experiment-card.md): for every legal config replay the
|
||||
same fixed or trace-derived request vector, report mean/p90 TTFT/TPOT/E2E,
|
||||
require simulator request-metric coverage, and calculate top-set hit,
|
||||
worst tie-break regret, and `τ-b` separately for each latency objective.
|
||||
`OSL=1` cases report TPOT as `N/A`, never zero.
|
||||
|
||||
## Primary evidence paths
|
||||
|
||||
- Overall completed-case synthesis and exclusions:
|
||||
[simulator-fidelity.md](../../simulator-fidelity.md).
|
||||
- Q30 prefill counterexample: [experiment card](../frontier-phase-factorial-v0/experiment-card.md),
|
||||
[accepted comparison](../frontier-phase-factorial-v0/results/final/comparison.json).
|
||||
- Q30 measured-collective/batch ablations:
|
||||
[envelope card](../frontier-fidelity-envelope-v1/experiment-card.md),
|
||||
[A2 comparison](../frontier-fidelity-envelope-v1/results/a2/comparison.json),
|
||||
[A3 comparison](../frontier-fidelity-envelope-v1/results/a3/comparison.json).
|
||||
- Q235 prefill alignment and exclusions:
|
||||
[findings](../frontier-multicase-sufficiency-v0/findings.md),
|
||||
[refined comparison](../frontier-multicase-sufficiency-v0/best_effort/fixed_cohort_evidence/v2_refined_comparison.json).
|
||||
- Q235 fixed mixed T0: [protocol](../frontier-multicase-sufficiency-v1/protocol.md),
|
||||
[smoke report](../frontier-multicase-sufficiency-v1/t0-smoke-report.md),
|
||||
[final comparison](../frontier-multicase-sufficiency-v1/results/t0-final/comparison.json).
|
||||
@@ -0,0 +1,84 @@
|
||||
# Frontier coverage audit for Qwen3.6-27B
|
||||
|
||||
> **Verdict (2026-07-17): `FAIL: original Frontier coverage`.** This is a
|
||||
> static capability result, not a latency-fidelity result. It says that the
|
||||
> examined existing Frontier cannot represent the real Qwen3.6 execution
|
||||
> contract; it does not say that a future extended simulator will be wrong.
|
||||
|
||||
## Question
|
||||
|
||||
Before spending profile or replay GPU-hours, can the checked Frontier baseline
|
||||
simulate the same model/engine state that the real server executes?
|
||||
|
||||
## Compared contracts
|
||||
|
||||
| Side | Observed contract |
|
||||
|---|---|
|
||||
| Real server | ModelScope `Qwen/Qwen3.6-27B@cea40373b9214dd387123e68841890af30dcd469`; vLLM 0.20.2, BF16; `Qwen3_5ForConditionalGeneration`; 64-layer non-MoE hybrid with three Gated DeltaNet/linear-state layers followed by one gated-attention layer per block. The release vLLM run used a FlashInfer GDN prefill kernel and changed requested `--block-size 16` to a 784-token attention/state page at TP1/2/4. |
|
||||
| Frontier baseline | `/home/admin/cpfs/wjh/frontier-qwen30-vllm020-profile-v1/Frontier`, commit `d9cfeb6d8791fbf2f295dd9744c56a666171776e`. Its model-spec directory has Qwen2/Qwen3-MoE and all-attention dense examples, but no Qwen3.6 or Qwen3_5 spec. Source search across `*.py`, `*.json`, `*.md` returned no hit for `qwen3_5`, `qwen3.6`, `GatedDeltaNet`, `DeltaNet`, `mamba`, `linear attention`, `state cache`, or `gdn`. |
|
||||
|
||||
## Frontier source model-spec inventory
|
||||
|
||||
This is the complete `frontend/configs/model_configs/*.json` inventory at the
|
||||
checked commit. It establishes that the simulator can instantiate these
|
||||
*structural specifications*; it is **not** evidence that a matching vLLM
|
||||
profile, runtime contract, or validated tuning result exists for each model.
|
||||
|
||||
| Class | Source specs |
|
||||
|---|---|
|
||||
| All-attention, non-MoE | `Llama-3.1-405B-Instruct-FP8`, `Llama-3.2-1B-Instruct`, `llama2_7b_dense_example`, `llama3.1-405b`, `llama3.1-8b`, `llama3.3-70b`, `qwen2_dense_test` |
|
||||
| MoE | `Phi-tiny-MoE-instruct`, `Qwen3-235B-A22B`, `Qwen3-235B-A22B__layers96`, `Qwen3-30B-A3B-tiny`, `deepseek-v3`, `mixtral_8x7b_moe`, `qwen2_moe_example`, `qwen3-a3b-30b-moe`, `qwen3-next-80b-a3b-instruct-reduced-l2`, `qwen3-next-80b-a3b-instruct-reduced-l20`, `Step2Mini-tiny`, `step-moe-noquant-small`, `step-moe-noquant`, `step-moe` |
|
||||
|
||||
The exact JSON architecture labels are `llama`, `qwen2`, `phimoe`,
|
||||
`qwen3_moe`, `deepseek_v3`, `mixtral`, `qwen2_moe`, `qwen3_next`,
|
||||
`step2_mini`, and `step3_text`. The separately held experimental artifacts
|
||||
in this project establish profile-and-surface evidence only for
|
||||
`Qwen3-30B-A3B` and `Qwen3-235B-A22B`; the remaining names are not
|
||||
automatically runnable or validated on H20/vLLM merely because a JSON exists.
|
||||
|
||||
## Why the missing model file is semantic, not administrative
|
||||
|
||||
The Frontier execution-time taxonomy separates `attention_prefill_execution_time`
|
||||
and `attention_decode_execution_time`; its operator context and parameter
|
||||
accounting are built from attention Q/KV heads, attention head dimension, FFN,
|
||||
and optional MoE routing. No Gated-DeltaNet/linear-state operator, state-cache
|
||||
capacity rule, or its mixed prefill/decode scheduling state was found.
|
||||
|
||||
Adding a JSON whose layer count merely matches Qwen3.6 would therefore map
|
||||
three quarters of its text layers onto an all-attention approximation. Reusing
|
||||
Qwen30/MoE or Qwen3.5 profiles has the same defect. Neither is a valid
|
||||
execution of the existing baseline.
|
||||
|
||||
## Decision
|
||||
|
||||
1. Record Frontier as **coverage failure** for the Qwen3.6 non-MoE-hybrid
|
||||
branch. Do not rank configs, fabricate high latency, or spend GPU-hours on
|
||||
an all-attention profile substitute.
|
||||
2. A new Gated-DeltaNet/state-cache model and profiling implementation would
|
||||
be an **extended Frontier** intervention. It must be evaluated separately
|
||||
from the capability of the original simulator and cannot support the claim
|
||||
that existing Frontier already solves tuning.
|
||||
3. The Qwen3.6 result cannot be presented as evidence for a conventional pure
|
||||
dense-transformer class. It is a useful non-MoE/hybrid boundary case.
|
||||
4. No runnable local checkout/version of Vidur or APEX was found; only a
|
||||
historical Vidur patch exists. Their coverage remains **unassessed**, not
|
||||
passed or failed, until their exact released artifacts are frozen and
|
||||
checked against this model/runtime contract.
|
||||
|
||||
## Next critical experiment
|
||||
|
||||
Do not extend Frontier before establishing the requested no-SLO metric on a
|
||||
model it already represents. The next direct test is the existing
|
||||
Qwen3-30B-A3B MoE branch under one same-trace Fixed-P replay surface, scored
|
||||
by mean/p90 TTFT and E2E (TPOT `N/A`), with simulator-only coverage checked
|
||||
before any real 600-s sweep. This separates a known architectural coverage
|
||||
failure from a fidelity failure on an in-scope model.
|
||||
|
||||
## Evidence locations
|
||||
|
||||
- Real topology smoke and resolved page state:
|
||||
`artifacts/qwen36/smoke-v4-20260717/` in this run directory.
|
||||
- Real model/runtime audit:
|
||||
[dense-preflight.md](dense-preflight.md).
|
||||
- No-SLO latency protocol and selection gates:
|
||||
[experiment-card.md](experiment-card.md).
|
||||
@@ -0,0 +1,82 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-labelledby="title desc">
|
||||
<title id="title">Schematic latency-selection evaluation matrix</title>
|
||||
<desc id="desc">Schematic, not measured data: dense and MoE rows, four P-only and P-plus-decode workloads, then a real-versus-simulator config-selection protocol.</desc>
|
||||
<style>
|
||||
.title { font-family: Arial, sans-serif; font-size: 30px; font-weight: bold; fill: #16212e; }
|
||||
.h { font-family: Arial, sans-serif; font-size: 18px; font-weight: bold; fill: #243142; }
|
||||
.b { font-family: Arial, sans-serif; font-size: 15px; fill: #354052; }
|
||||
.s { font-family: Arial, sans-serif; font-size: 12px; fill: #4a5564; }
|
||||
.t { font-family: Arial, sans-serif; font-size: 11px; fill: #4a5564; }
|
||||
</style>
|
||||
<rect width="1600" height="900" fill="white"/>
|
||||
<rect x="45" y="28" width="1510" height="58" rx="12" fill="#fff3cd" stroke="#d79c11" stroke-width="2"/>
|
||||
<text x="800" y="66" text-anchor="middle" class="title" fill="#714e00">SCHEMATIC — NOT MEASURED DATA</text>
|
||||
<text x="70" y="126" class="title">Can a simulator select the same low-latency config as the real engine?</text>
|
||||
<text x="70" y="153" class="b">Each model × workload × metric is one tuning task. Lower latency is better; SLO and capacity are not selection objectives.</text>
|
||||
|
||||
<text x="70" y="200" class="h">Frozen evaluation matrix</text>
|
||||
<text x="365" y="215" text-anchor="middle" class="h">Fixed-P</text>
|
||||
<text x="365" y="236" text-anchor="middle" class="s">ISL=2048 · OSL=1 · QPS=4</text>
|
||||
<text x="575" y="215" text-anchor="middle" class="h">Fixed-PD</text>
|
||||
<text x="575" y="236" text-anchor="middle" class="s">ISL=2048 · OSL=128 · QPS=4</text>
|
||||
<text x="785" y="215" text-anchor="middle" class="h">Trace-P</text>
|
||||
<text x="785" y="236" text-anchor="middle" class="s">exact input/arrival/prefix · OSL=1</text>
|
||||
<text x="995" y="215" text-anchor="middle" class="h">Trace-PD</text>
|
||||
<text x="995" y="236" text-anchor="middle" class="s">exact input/output/arrival/prefix</text>
|
||||
|
||||
<text x="92" y="317" class="h">Dense</text>
|
||||
<text x="92" y="341" class="t">Qwen/Qwen3.6-27B</text>
|
||||
<text x="92" y="357" class="t">community vLLM; profile pending</text>
|
||||
<g fill="#f4f6f8" stroke="#aab6c5" stroke-width="1.5" stroke-dasharray="6 4">
|
||||
<rect x="260" y="260" width="210" height="125" rx="8"/><rect x="470" y="260" width="210" height="125" rx="8"/>
|
||||
<rect x="680" y="260" width="210" height="125" rx="8"/><rect x="890" y="260" width="210" height="125" rx="8"/>
|
||||
</g>
|
||||
<g class="b" text-anchor="middle">
|
||||
<text x="365" y="315">P-only</text><text x="365" y="340">TTFT, E2E · TPOT N/A</text>
|
||||
<text x="575" y="315">Prefill + decode</text><text x="575" y="340">TTFT, TPOT, E2E</text>
|
||||
<text x="785" y="315">P-node trace replay</text><text x="785" y="340">output normalized to 1</text>
|
||||
<text x="995" y="315">Joint trace replay</text><text x="995" y="340">prefix/KV state retained</text>
|
||||
</g>
|
||||
<text x="680" y="373" text-anchor="middle" class="t">New Qwen3.6/community-vLLM profile contract; old internal-vLLM artifacts excluded.</text>
|
||||
|
||||
<text x="92" y="475" class="h">MoE</text>
|
||||
<text x="92" y="498" class="t">Qwen3-30B-A3B</text>
|
||||
<text x="92" y="514" class="t">community vLLM 0.20</text>
|
||||
<g fill="#eaf2fb" stroke="#7d9fbe" stroke-width="1.5">
|
||||
<rect x="260" y="415" width="210" height="125" rx="8"/><rect x="470" y="415" width="210" height="125" rx="8"/>
|
||||
<rect x="680" y="415" width="210" height="125" rx="8"/><rect x="890" y="415" width="210" height="125" rx="8"/>
|
||||
</g>
|
||||
<g class="b" text-anchor="middle">
|
||||
<text x="365" y="467">historical raw P pilot</text><text x="365" y="492">re-run as 600-s matrix</text>
|
||||
<text x="575" y="467">trace materializer exists</text><text x="575" y="492">real surface pending</text>
|
||||
<text x="785" y="467">derive held-out trace</text><text x="785" y="492">force OSL=1 only</text>
|
||||
<text x="995" y="467">T1 simulator has stalls</text><text x="995" y="492">real surface pending</text>
|
||||
</g>
|
||||
|
||||
<rect x="1160" y="195" width="365" height="345" rx="14" fill="#fbfcfe" stroke="#7d8c9c" stroke-width="2"/>
|
||||
<text x="1342" y="230" text-anchor="middle" class="h">Per-objective selection</text>
|
||||
<rect x="1185" y="252" width="315" height="70" rx="8" fill="#eef7ef" stroke="#aab6c5" stroke-width="1.5"/>
|
||||
<text x="1342" y="280" text-anchor="middle" class="h">Real engine</text>
|
||||
<text x="1342" y="304" text-anchor="middle" class="s">3 fresh-server trials → bootstrap top set</text>
|
||||
<path d="M1342 322 L1342 346" stroke="#5a6775" stroke-width="2.5"/>
|
||||
<polygon points="1336,342 1348,342 1342,351" fill="#5a6775"/>
|
||||
<rect x="1185" y="358" width="315" height="70" rx="8" fill="#edf4fb" stroke="#aab6c5" stroke-width="1.5"/>
|
||||
<text x="1342" y="386" text-anchor="middle" class="h">Simulator</text>
|
||||
<text x="1342" y="410" text-anchor="middle" class="s">complete request metrics → exact top set</text>
|
||||
<path d="M1342 428 L1342 452" stroke="#5a6775" stroke-width="2.5"/>
|
||||
<polygon points="1336,448 1348,448 1342,457" fill="#5a6775"/>
|
||||
<rect x="1185" y="464" width="315" height="54" rx="8" fill="#fff7e8" stroke="#aab6c5" stroke-width="1.5"/>
|
||||
<text x="1342" y="488" text-anchor="middle" class="h">coverage · hit · regret · τ-b</text>
|
||||
<text x="1342" y="508" text-anchor="middle" class="t">report all four; never collapse a missing cell into “slow”</text>
|
||||
|
||||
<line x1="70" y1="595" x2="1530" y2="595" stroke="#c5ced8" stroke-width="1.5"/>
|
||||
<text x="70" y="637" class="h">Decision gates</text>
|
||||
<text x="70" y="672" class="b">1. Valid trace/usage and finite applicable metrics.</text>
|
||||
<text x="70" y="703" class="b">2. Simulator covers every real-valid config; crash or scheduler stall is a coverage failure, not a latency value.</text>
|
||||
<text x="70" y="734" class="b">3. For every mean/p90 objective: top-set hit, worst tie-break regret ≤5%, and τ-b reported.</text>
|
||||
<rect x="1060" y="627" width="470" height="118" rx="10" fill="#fff3cd" stroke="#d79c11" stroke-width="1.5"/>
|
||||
<text x="1085" y="658" class="h">Information boundary</text>
|
||||
<text x="1085" y="686" class="s">Profiles/calibration are frozen before evaluation and disjoint from held-out trace sessions.</text>
|
||||
<text x="1085" y="710" class="s">No per-config E2E scale, post-hoc patch, or simulator-guided real subsetting.</text>
|
||||
<text x="70" y="850" class="t">Protocol status only: this figure does not contain experiment measurements. See experiment-card.md for trace contracts, candidate surface, provenance, and cost gate.</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.5 KiB |
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# CPU-only Frontier surface for the per-GPU-normalized Qwen3-30B Trace-PD case.
|
||||
# This script is copied to the remote experiment output directory, never into
|
||||
# the shared/dirty AITuner checkout.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
OUT="${1:?output root is required}"
|
||||
RUNNER="/home/admin/cpfs/wjh/aituner/aituner-qwen30-vllm020-profile-v1/runs/frontier-fidelity-envelope-v1/run_frontier_qwen30_exact_trace_surface.py"
|
||||
FRONTIER="/home/admin/cpfs/wjh/aituner/frontier-t1-dash0-deadc4a"
|
||||
REPLAYSERVE="/home/admin/cpfs/wjh/replayserve"
|
||||
PYTHON_DEPS="/tmp/wjh/venvs/vllm-0.20.0-cu129-profiler-v1/lib/python3.12/site-packages"
|
||||
PROFILE="/home/admin/cpfs/wjh/aituner/aituner-qwen30-vllm020-profile-v1/runs/frontier-fidelity-envelope-v1/profiles/profile-v4-trace-final"
|
||||
ALLREDUCE="/home/admin/cpfs/wjh/aituner/aituner-qwen30-vllm020-profile-v1/runs/frontier-fidelity-envelope-v1/profiles/measured-allreduce.csv"
|
||||
BASE_PUBLIC="/home/admin/cpfs/wjh/aituner/fidelity-envelope-private/trace-exact-v1/public/u0p01/frontier.csv"
|
||||
BASE_PRIVATE="/home/admin/cpfs/wjh/aituner/fidelity-envelope-private/trace-exact-v1/private/u0p01/real_requests.jsonl"
|
||||
MATERIALIZER="${OUT}/bin/materialize_qwen30_tp_normalized_trace.py"
|
||||
|
||||
printf '%s\n' "SIMULATOR_LAUNCH_ECHO host=dash0; gpu_allocation=0; model=Qwen3-30B-A3B; trace=trace-exact-v1/u0p01; requests=129; transform=t_prime=t/TP; TP={1,2,4}; per_gpu_offered_rate=0.215 req/s; surface=TP{1,2,4}xMNS{8,16,32,64}; Frontier=deadc4a321f0baaa534c6ebd17f974123733cdc2; profiles=profile-v4-trace-final; expected_wall=10-45m; output=${OUT}"
|
||||
date -u +START_UTC=%Y-%m-%dT%H:%M:%SZ
|
||||
|
||||
mkdir -p "${OUT}/provenance"
|
||||
sha256sum "${MATERIALIZER}" "${BASH_SOURCE[0]}" "${RUNNER}" "${BASE_PUBLIC}" \
|
||||
"${BASE_PRIVATE}" "${PROFILE}/manifest.json" "${ALLREDUCE}" \
|
||||
> "${OUT}/provenance/input.sha256"
|
||||
git -C "${FRONTIER}" rev-parse HEAD > "${OUT}/provenance/frontier.commit"
|
||||
git -C /home/admin/cpfs/wjh/aituner/aituner-qwen30-vllm020-profile-v1 rev-parse HEAD \
|
||||
> "${OUT}/provenance/aituner.commit"
|
||||
printf '%s\n' "${PYTHON_DEPS}" > "${OUT}/provenance/python_deps_path"
|
||||
/tmp/wjh/venvs/vllm-0.20.0-cu129-profiler-v1/bin/python -c \
|
||||
'import importlib.metadata as m; [print(f"{name}=={m.version(name)}") for name in ("plotly", "numpy", "pandas", "scikit-learn", "PyYAML")]' \
|
||||
> "${OUT}/provenance/python_deps_versions.txt"
|
||||
|
||||
for tp in 1 2 4; do
|
||||
/usr/bin/python3 "${MATERIALIZER}" \
|
||||
--base-public-csv "${BASE_PUBLIC}" \
|
||||
--base-private-jsonl "${BASE_PRIVATE}" \
|
||||
--tp "${tp}" \
|
||||
--output-root "${OUT}/traces/tp${tp}" \
|
||||
> "${OUT}/traces-tp${tp}.log"
|
||||
done
|
||||
|
||||
for tp in 1 2 4; do
|
||||
for mns in 8 16 32 64; do
|
||||
cfg="tp${tp}_mns${mns}"
|
||||
cfgout="${OUT}/simulator-retry-deps/${cfg}"
|
||||
mkdir -p "${cfgout}"
|
||||
(
|
||||
set +e
|
||||
timeout --signal=TERM --kill-after=30s 2400 /usr/bin/python3 "${RUNNER}" \
|
||||
--frontier-source "${FRONTIER}" \
|
||||
--replayserve-root "${REPLAYSERVE}" \
|
||||
--profile-root "${PROFILE}" \
|
||||
--python-deps "${PYTHON_DEPS}" \
|
||||
--output-root "${cfgout}" \
|
||||
--trace "tp${tp}=${OUT}/traces/tp${tp}/public/frontier.csv" \
|
||||
--config "${cfg}" \
|
||||
--rate-contract trace-window \
|
||||
--prefix-caching \
|
||||
--cc-backend vidur \
|
||||
--allreduce-csv "${ALLREDUCE}" \
|
||||
--timeout-seconds 1800 \
|
||||
--predictor-training-job-threads 12 \
|
||||
--continue-on-failure \
|
||||
> "${cfgout}/launcher.stdout.log" 2> "${cfgout}/launcher.stderr.log"
|
||||
printf '%s\n' "$?" > "${cfgout}/launcher.exit_code"
|
||||
exit 0
|
||||
) &
|
||||
done
|
||||
done
|
||||
wait
|
||||
|
||||
find "${OUT}" -type f ! -path '*/provenance/artifacts.sha256' -print0 \
|
||||
| sort -z | xargs -0 sha256sum > "${OUT}/provenance/artifacts.sha256"
|
||||
date -u +END_UTC=%Y-%m-%dT%H:%M:%SZ
|
||||
printf '%s\n' 'SIMULATOR_SURFACE_COMPLETE'
|
||||
@@ -0,0 +1,173 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Three fresh-server real vLLM trials for the per-GPU-normalized Qwen30
|
||||
# Trace-PD surface. This script and its JIT-tolerant harness are copied into
|
||||
# the remote output root, not the shared/dirty AITuner checkout.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
OUT="${1:?output root is required}"
|
||||
RUNNER_DIR="/home/admin/cpfs/wjh/aituner/aituner-qwen30-vllm020-profile-v1/runs/frontier-fidelity-envelope-v1"
|
||||
RUNNER="${OUT}/bin/run_qwen30_exact_trace_real_anchor_jit_tolerant.sh"
|
||||
CLIENT="${OUT}/bin/qwen30_exact_trace_client.py"
|
||||
PREFILL_CLIENT="/home/admin/cpfs/wjh/aituner/aituner-qwen30-vllm020-profile-v1/runs/frontier-phase-factorial-v0/qwen30_prefill_client.py"
|
||||
VENV_ROOT="/tmp/wjh/venvs/vllm-0.20.0-cu129-profiler-v1"
|
||||
MODEL_ROOT="/home/admin/cpfs/wjh/models/Qwen/Qwen3-30B-A3B"
|
||||
TRACE_ROOT="${OUT}/traces"
|
||||
# FlashInfer's JIT uses per-operation file locks. Reuse the smoke-populated
|
||||
# cache across fresh servers so the 36 measurement runs do not each rebuild
|
||||
# the same H20 MoE/all-reduce kernels. Server processes and metrics remain
|
||||
# isolated per run under ${OUT}/real.
|
||||
FLASHINFER_SHARED_WORKSPACE="${OUT}/flashinfer-shared-workspace"
|
||||
PORT=8200
|
||||
|
||||
declare -a WAVE_PIDS=()
|
||||
|
||||
wait_for_wave() {
|
||||
local failed=0 pid
|
||||
for pid in "${WAVE_PIDS[@]}"; do
|
||||
if ! wait "${pid}"; then
|
||||
failed=1
|
||||
fi
|
||||
done
|
||||
WAVE_PIDS=()
|
||||
if [[ "${failed}" -ne 0 ]]; then
|
||||
printf '%s\n' 'ERROR one or more real-serving runs failed; aborting surface.' \
|
||||
| tee -a "${OUT}/controller.log" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
preflight_gpus() {
|
||||
nvidia-smi --query-gpu=index,name,memory.used,utilization.gpu --format=csv,noheader \
|
||||
| tee -a "${OUT}/controller.log"
|
||||
if nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits \
|
||||
| awk '$1 != 0 {exit 1}'; then
|
||||
return 0
|
||||
fi
|
||||
printf '%s\n' 'ERROR non-idle GPU before a real-serving wave; refusing to start.' \
|
||||
| tee -a "${OUT}/controller.log" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
assert_no_our_server() {
|
||||
if pgrep -fa 'qwen3-30b-exact-trace' > "${OUT}/provenance/unexpected_server_processes.txt"; then
|
||||
printf '%s\n' 'ERROR a prior experiment server remains; refusing the next wave.' \
|
||||
| tee -a "${OUT}/controller.log" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
launch_config() {
|
||||
local trial="$1" tp="$2" mns="$3" gpus="$4"
|
||||
local config="tp${tp}_mns${mns}"
|
||||
local run_out="${OUT}/real/${config}/trial${trial}"
|
||||
local requests="${TRACE_ROOT}/tp${tp}/private/real_requests.jsonl"
|
||||
local port="${PORT}"
|
||||
PORT=$((PORT + 1))
|
||||
mkdir -p "${run_out}"
|
||||
(
|
||||
cd "${RUNNER_DIR}"
|
||||
set +e
|
||||
env \
|
||||
HOME=/tmp/wjh \
|
||||
XDG_CACHE_HOME=/tmp/wjh/.cache \
|
||||
VLLM_CACHE_ROOT=/tmp/wjh/.cache/vllm \
|
||||
CUDA_VISIBLE_DEVICES="${gpus}" \
|
||||
TP="${tp}" \
|
||||
MNS="${mns}" \
|
||||
TRACE_LABEL="tp${tp}-normalized-u0p01" \
|
||||
SERVER_PORT="${port}" \
|
||||
OUTPUT_ROOT="${run_out}" \
|
||||
REQUESTS_FILE="${requests}" \
|
||||
VENV_ROOT="${VENV_ROOT}" \
|
||||
MODEL_ROOT="${MODEL_ROOT}" \
|
||||
FLASHINFER_WORKSPACE_BASE="${FLASHINFER_SHARED_WORKSPACE}" \
|
||||
EXACT_TRACE_CLIENT="${CLIENT}" \
|
||||
timeout --signal=TERM --kill-after=60s 4200 bash "${RUNNER}" \
|
||||
> "${run_out}/launcher.stdout.log" 2> "${run_out}/launcher.stderr.log"
|
||||
local_status="$?"
|
||||
printf '%s\n' "${local_status}" > "${run_out}/launcher.exit_code"
|
||||
exit "${local_status}"
|
||||
) &
|
||||
WAVE_PIDS+=("$!")
|
||||
}
|
||||
|
||||
run_tp_wave() {
|
||||
local trial="$1" tp="$2" order="$3"
|
||||
IFS=',' read -r -a mnss <<< "${order}"
|
||||
WAVE_PIDS=()
|
||||
preflight_gpus
|
||||
assert_no_our_server
|
||||
printf 'WAVE_START trial=%s tp=%s mns=%s\n' "${trial}" "${tp}" "${order}" \
|
||||
| tee -a "${OUT}/controller.log"
|
||||
case "${tp}" in
|
||||
4)
|
||||
launch_config "${trial}" 4 "${mnss[0]}" '0,1,2,3'
|
||||
launch_config "${trial}" 4 "${mnss[1]}" '4,5,6,7'
|
||||
wait_for_wave
|
||||
preflight_gpus
|
||||
assert_no_our_server
|
||||
launch_config "${trial}" 4 "${mnss[2]}" '0,1,2,3'
|
||||
launch_config "${trial}" 4 "${mnss[3]}" '4,5,6,7'
|
||||
;;
|
||||
2)
|
||||
launch_config "${trial}" 2 "${mnss[0]}" '0,1'
|
||||
launch_config "${trial}" 2 "${mnss[1]}" '2,3'
|
||||
launch_config "${trial}" 2 "${mnss[2]}" '4,5'
|
||||
launch_config "${trial}" 2 "${mnss[3]}" '6,7'
|
||||
;;
|
||||
1)
|
||||
launch_config "${trial}" 1 "${mnss[0]}" '0'
|
||||
launch_config "${trial}" 1 "${mnss[1]}" '1'
|
||||
launch_config "${trial}" 1 "${mnss[2]}" '2'
|
||||
launch_config "${trial}" 1 "${mnss[3]}" '3'
|
||||
;;
|
||||
*)
|
||||
printf 'ERROR unsupported TP=%s\n' "${tp}" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
wait_for_wave
|
||||
preflight_gpus
|
||||
assert_no_our_server
|
||||
printf 'WAVE_COMPLETE trial=%s tp=%s\n' "${trial}" "${tp}" \
|
||||
| tee -a "${OUT}/controller.log"
|
||||
}
|
||||
|
||||
{
|
||||
printf '%s\n' "REAL_LAUNCH_ECHO host=dash0; model=Qwen3-30B-A3B; engine=vLLM-0.20.0+cu129; dtype=BF16; trace=trace-exact-v1/u0p01; requests=129; transform=t_prime=t/TP; per_gpu_offered_rate=0.215 req/s; surface=TP{1,2,4}xMNS{8,16,32,64}; trials=3; fresh_server=true; metrics=mean,p90(TTFT,TPOT,E2E); SLO=not_scored; flashinfer_cache=${FLASHINFER_SHARED_WORKSPACE}; expected_cost=13_H20-GPUh_nominal__41_H20-GPUh_max; output=${OUT}/real"
|
||||
date -u +START_UTC=%Y-%m-%dT%H:%M:%SZ
|
||||
mkdir -p "${OUT}/provenance"
|
||||
mkdir -p "${FLASHINFER_SHARED_WORKSPACE}"
|
||||
sha256sum "${BASH_SOURCE[0]}" "${RUNNER}" "${CLIENT}" "${PREFILL_CLIENT}" \
|
||||
"${MODEL_ROOT}/config.json" > "${OUT}/provenance/real-input.sha256"
|
||||
for tp in 1 2 4; do
|
||||
sha256sum "${TRACE_ROOT}/tp${tp}/public/manifest.json" \
|
||||
"${TRACE_ROOT}/tp${tp}/private/real_requests.jsonl" \
|
||||
>> "${OUT}/provenance/real-input.sha256"
|
||||
done
|
||||
"${VENV_ROOT}/bin/vllm" --version > "${OUT}/provenance/vllm.version"
|
||||
"${VENV_ROOT}/bin/python" -c 'import torch, transformers, vllm; print(f"torch={torch.__version__}"); print(f"transformers={transformers.__version__}"); print(f"vllm={vllm.__version__}")' \
|
||||
> "${OUT}/provenance/runtime.versions"
|
||||
nvidia-smi --query-gpu=index,name,uuid,driver_version,memory.total --format=csv,noheader \
|
||||
> "${OUT}/provenance/gpus.before.csv"
|
||||
|
||||
# Rotate topology and MNS order across trials to avoid a fixed temporal order.
|
||||
run_tp_wave 1 4 '8,16,32,64'
|
||||
run_tp_wave 1 2 '8,16,32,64'
|
||||
run_tp_wave 1 1 '8,16,32,64'
|
||||
run_tp_wave 2 1 '64,32,16,8'
|
||||
run_tp_wave 2 2 '64,32,16,8'
|
||||
run_tp_wave 2 4 '64,32,16,8'
|
||||
run_tp_wave 3 2 '16,32,64,8'
|
||||
run_tp_wave 3 4 '16,32,64,8'
|
||||
run_tp_wave 3 1 '16,32,64,8'
|
||||
|
||||
nvidia-smi --query-gpu=index,name,uuid,driver_version,memory.total --format=csv,noheader \
|
||||
> "${OUT}/provenance/gpus.after.csv"
|
||||
find "${OUT}/real" -type f ! -path '*/provenance/artifacts.sha256' -print0 \
|
||||
| sort -z | xargs -0 sha256sum > "${OUT}/provenance/real-artifacts.sha256"
|
||||
date -u +END_UTC=%Y-%m-%dT%H:%M:%SZ
|
||||
printf '%s\n' 'REAL_SURFACE_COMPLETE'
|
||||
} >> "${OUT}/controller.log" 2>&1
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
||||
# Qwen3-30B-A3B TP-normalized Trace-PD: real vLLM audit
|
||||
|
||||
All 36 fresh-server trials passed the trace contract: 129/129 exact-usage requests per trial. The smoke run is excluded. Values below pool the three trials (387 requests/config); p90 uses nearest-rank order statistics.
|
||||
|
||||
| Config | TTFT mean/p90 (ms) | TPOT mean/p90 (ms) | E2E mean/p90 (ms) |
|
||||
|---|---:|---:|---:|
|
||||
| tp1_mns8 | 88479.9/168185.5 | 14.3/16.3 | 137996.4/222136.0 |
|
||||
| tp1_mns16 | 17378.2/42739.8 | 20.6/25.3 | 87355.2/156177.2 |
|
||||
| tp1_mns32 | 620.5/1931.5 | 23.8/30.0 | 81051.2/162908.6 |
|
||||
| tp1_mns64 | 619.8/1956.7 | 24.1/30.4 | 82253.7/165355.3 |
|
||||
| tp2_mns8 | 95920.1/183878.8 | 9.2/10.2 | 128296.9/215848.3 |
|
||||
| tp2_mns16 | 34443.0/77922.4 | 14.1/16.1 | 82936.7/137726.4 |
|
||||
| tp2_mns32 | 1050.6/2521.8 | 18.0/21.3 | 62267.5/117239.3 |
|
||||
| tp2_mns64 | 375.8/1148.6 | 18.2/21.6 | 62353.6/118392.3 |
|
||||
| tp4_mns8 | 102605.9/193359.7 | 6.8/7.2 | 126405.4/209092.4 |
|
||||
| tp4_mns16 | 35042.6/74281.3 | 8.8/9.6 | 65779.1/110374.3 |
|
||||
| tp4_mns32 | 6296.2/19159.9 | 12.2/13.8 | 47944.5/83825.7 |
|
||||
| tp4_mns64 | 246.0/685.5 | 13.2/15.4 | 44985.1/83763.6 |
|
||||
|
||||
## Per-metric winners
|
||||
|
||||
- `ttft_ms:pooled_mean_ms`: `tp4_mns64` (246.0 ms)
|
||||
- `ttft_ms:pooled_p90_ms`: `tp4_mns64` (685.5 ms)
|
||||
- `tpot_ms:pooled_mean_ms`: `tp4_mns8` (6.8 ms)
|
||||
- `tpot_ms:pooled_p90_ms`: `tp4_mns8` (7.2 ms)
|
||||
- `e2e_ms:pooled_mean_ms`: `tp4_mns64` (44985.1 ms)
|
||||
- `e2e_ms:pooled_p90_ms`: `tp4_mns64` (83763.6 ms)
|
||||
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Isolated copy of the real-anchor harness. It extends the startup budget for
|
||||
# an uncached H20 FlashInfer MoE JIT and uses an artifact-pinned trace client
|
||||
# that routes requests to the explicit server alias. It is run from the clean
|
||||
# source directory so its warm-up client remains snapshot-pinned.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
OUTPUT_ROOT="${OUTPUT_ROOT:?OUTPUT_ROOT is required}"
|
||||
REQUESTS_FILE="${REQUESTS_FILE:?REQUESTS_FILE is required}"
|
||||
TP="${TP:?TP is required}"
|
||||
MNS="${MNS:?MNS is required}"
|
||||
TRACE_LABEL="${TRACE_LABEL:?TRACE_LABEL is required}"
|
||||
SERVER_PORT="${SERVER_PORT:?SERVER_PORT is required}"
|
||||
VENV_ROOT="${VENV_ROOT:-/tmp/wjh/venvs/vllm-0.20.0-cu129-profiler-v1}"
|
||||
MODEL_ROOT="${MODEL_ROOT:-/home/admin/cpfs/wjh/models/Qwen/Qwen3-30B-A3B}"
|
||||
FLASHINFER_WORKSPACE_BASE="${FLASHINFER_WORKSPACE_BASE:-/tmp/wjh/flashinfer-workspace-vllm020-profiler-v1}"
|
||||
SERVER_READY_ATTEMPTS="${SERVER_READY_ATTEMPTS:-300}"
|
||||
EXACT_TRACE_CLIENT="${EXACT_TRACE_CLIENT:-qwen30_exact_trace_client.py}"
|
||||
SERVED_MODEL="qwen3-30b-exact-trace"
|
||||
SERVER_PID=""
|
||||
|
||||
mkdir -p "${OUTPUT_ROOT}/logs" "${OUTPUT_ROOT}/provenance" "${OUTPUT_ROOT}/results" \
|
||||
"${FLASHINFER_WORKSPACE_BASE}"
|
||||
exec > >(tee -a "${OUTPUT_ROOT}/logs/controller.log") 2>&1
|
||||
|
||||
cleanup() {
|
||||
if [[ -n "${SERVER_PID}" ]] && kill -0 "${SERVER_PID}" 2>/dev/null; then
|
||||
kill -TERM -- "-${SERVER_PID}" 2>/dev/null || true
|
||||
for _ in $(seq 1 30); do
|
||||
kill -0 "${SERVER_PID}" 2>/dev/null || break
|
||||
sleep 1
|
||||
done
|
||||
kill -KILL -- "-${SERVER_PID}" 2>/dev/null || true
|
||||
fi
|
||||
SERVER_PID=""
|
||||
}
|
||||
trap cleanup EXIT HUP INT TERM
|
||||
|
||||
IFS=',' read -r -a GPU_IDS <<< "${CUDA_VISIBLE_DEVICES:?fleet GPU allocation is required}"
|
||||
if [[ "${#GPU_IDS[@]}" -ne "${TP}" ]]; then
|
||||
echo "ERROR: expected ${TP} GPUs, got ${CUDA_VISIBLE_DEVICES}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REQUEST_COUNT="$(wc -l < "${REQUESTS_FILE}")"
|
||||
echo "QWEN30_EXACT_TRACE_REAL_LAUNCH_ECHO host=$(hostname) gpus=${CUDA_VISIBLE_DEVICES} model=${MODEL_ROOT} runtime=vLLM-0.20.0+cu129 dtype=BF16 config=TP${TP}_MNS${MNS}_MBT8192 trace=${TRACE_LABEL} requests=${REQUEST_COUNT} source=${REQUESTS_FILE} arrivals=TP-normalized input_output_prompt=exact prefix=on block=16 metrics=mean,p90(TTFT,TPOT,E2E) SLO=not-scored flashinfer_workspace=${FLASHINFER_WORKSPACE_BASE} output=${OUTPUT_ROOT} ready_budget_s=$((SERVER_READY_ATTEMPTS * 3)) hard_wall=4200s"
|
||||
date -u +"START_UTC=%Y-%m-%dT%H:%M:%SZ"
|
||||
sha256sum "${BASH_SOURCE[0]}" "${EXACT_TRACE_CLIENT}" \
|
||||
../frontier-phase-factorial-v0/qwen30_prefill_client.py \
|
||||
> "${OUTPUT_ROOT}/provenance/source.sha256"
|
||||
sha256sum "${REQUESTS_FILE}" > "${OUTPUT_ROOT}/provenance/requests.sha256"
|
||||
sha256sum "${MODEL_ROOT}/config.json" > "${OUTPUT_ROOT}/provenance/model.sha256"
|
||||
nvidia-smi --query-gpu=index,name,uuid,driver_version --format=csv,noheader \
|
||||
> "${OUTPUT_ROOT}/provenance/gpus.csv"
|
||||
|
||||
export TOKENIZERS_PARALLELISM=false
|
||||
export VLLM_USE_V1=1
|
||||
export TORCH_CUDA_ARCH_LIST=9.0
|
||||
export HF_HUB_OFFLINE=1
|
||||
export TRANSFORMERS_OFFLINE=1
|
||||
export FLASHINFER_WORKSPACE_BASE
|
||||
ulimit -n 65536
|
||||
|
||||
setsid "${VENV_ROOT}/bin/vllm" serve "${MODEL_ROOT}" \
|
||||
--host 127.0.0.1 --port "${SERVER_PORT}" --served-model-name "${SERVED_MODEL}" \
|
||||
--tensor-parallel-size "${TP}" --gpu-memory-utilization 0.92 \
|
||||
--max-model-len 40960 --max-num-batched-tokens 8192 --max-num-seqs "${MNS}" \
|
||||
--enable-prefix-caching --enable-chunked-prefill --no-enable-log-requests \
|
||||
> "${OUTPUT_ROOT}/logs/server.log" 2>&1 &
|
||||
SERVER_PID=$!
|
||||
READY=0
|
||||
for _ in $(seq 1 "${SERVER_READY_ATTEMPTS}"); do
|
||||
if curl -fsS --max-time 2 "http://127.0.0.1:${SERVER_PORT}/v1/models" \
|
||||
> "${OUTPUT_ROOT}/results/models.json" 2>/dev/null; then
|
||||
READY=1
|
||||
break
|
||||
fi
|
||||
if ! kill -0 "${SERVER_PID}" 2>/dev/null; then
|
||||
tail -200 "${OUTPUT_ROOT}/logs/server.log"
|
||||
exit 1
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
if [[ "${READY}" -ne 1 ]]; then
|
||||
echo "ERROR server did not become ready within $((SERVER_READY_ATTEMPTS * 3)) seconds" >&2
|
||||
tail -200 "${OUTPUT_ROOT}/logs/server.log"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"${VENV_ROOT}/bin/python" ../frontier-phase-factorial-v0/qwen30_prefill_client.py \
|
||||
--port "${SERVER_PORT}" --served-model "${SERVED_MODEL}" \
|
||||
--model-path "${MODEL_ROOT}" --rate 1 --requests 4 --input-tokens 512 \
|
||||
--output "${OUTPUT_ROOT}/results/warmup.json"
|
||||
|
||||
"${VENV_ROOT}/bin/python" "${EXACT_TRACE_CLIENT}" \
|
||||
--port "${SERVER_PORT}" --requests-file "${REQUESTS_FILE}" \
|
||||
--output "${OUTPUT_ROOT}/results/result.json" --served-model "${SERVED_MODEL}" \
|
||||
--tpot-slo-ms 150 \
|
||||
--timeout-seconds 1800
|
||||
|
||||
cleanup
|
||||
find "${OUTPUT_ROOT}" -type f ! -path '*/provenance/artifacts.sha256' -print0 \
|
||||
| sort -z | xargs -0 sha256sum > "${OUTPUT_ROOT}/provenance/artifacts.sha256"
|
||||
date -u +"END_UTC=%Y-%m-%dT%H:%M:%SZ"
|
||||
echo "QWEN30_EXACT_TRACE_REAL_ANCHOR_COMPLETE"
|
||||
Reference in New Issue
Block a user