From 288f7b239f777c7980ea5a4983082bb0dd9c099b Mon Sep 17 00:00:00 2001 From: Gahow Wang Date: Thu, 23 Jul 2026 23:58:49 +0800 Subject: [PATCH] Add code long-context attention profiling grid --- runs/frontier-code-trace-v0/README.md | 8 +- .../check_longctx_profile_repeats.py | 79 ++++++++++++++++++ .../frontier-code-trace-v0/experiment-card.md | 33 +++++++- .../run_flashattn_code_longctx.sh | 80 +++++++++++++++++++ .../profile_vllm020_flashattn.py | 5 +- 5 files changed, 196 insertions(+), 9 deletions(-) create mode 100644 runs/frontier-code-trace-v0/check_longctx_profile_repeats.py create mode 100644 runs/frontier-code-trace-v0/run_flashattn_code_longctx.sh diff --git a/runs/frontier-code-trace-v0/README.md b/runs/frontier-code-trace-v0/README.md index fe6d48a..3c8fb4d 100644 --- a/runs/frontier-code-trace-v0/README.md +++ b/runs/frontier-code-trace-v0/README.md @@ -33,7 +33,9 @@ max_model_len_recommendation != null selected.selected_window_stats.max_model_len_coverage[推荐值].coverage = 1.0 ``` -旧记录预计 source block size 为 512、推荐 max model len 为 131072,但禁止把这两个值写死为实验事实。 +全量审计已确认 source block size=512;development source window 若 100% +覆盖需要 262144,但正式 server cap 以 session-sampled paired cell 的实际 +`ISL+OSL max` 向上对齐,不能把 full-window 262144 无条件套到低 rho cell。 审计会单独记录并排除 `input_length<=0` 或 `output_length<=0` 的 source 行;这些行只有在 raw trace 同样显示 zero usage/empty response 时才按 “未发生模型执行”处理,不能无记录过滤。 @@ -89,14 +91,14 @@ python3 runs/frontier-s3-real-v0/remap_hash_blocks.py \ 现有 real runner 新增了三个显式环境变量,chat 默认行为不变: ```bash -MAX_MODEL_LEN=131072 \ +MAX_MODEL_LEN=ACTUAL_CELL_MAX_ROUNDED_UP \ TRACE_INPUT_ROOT=/absolute/path/to/materialized/code-cell \ ALLOW_SYNTHETIC_PROMPTS=true \ OUTPUT_ROOT=/absolute/path/to/new/output \ bash runs/frontier-s3-real-v0/run_full_real.sh RHO_LABEL tp4_mns16 1 PORT ``` -- `MAX_MODEL_LEN` 必须等于 manifest 推荐值; +- `MAX_MODEL_LEN` 必须覆盖 manifest 中该 paired cell 的实际最大请求; - `TRACE_INPUT_ROOT` 内必须有 `real_requests.jsonl` 和 `manifest.json`; - synthetic prompt 默认拒绝,只有在 experiment card 明确降级 claim 后才设为 `true`; - runner 会在启动前扫描 paired requests,若任何 `ISL+OSL` 超 cap 立即失败。 diff --git a/runs/frontier-code-trace-v0/check_longctx_profile_repeats.py b/runs/frontier-code-trace-v0/check_longctx_profile_repeats.py new file mode 100644 index 0000000..a1b83f5 --- /dev/null +++ b/runs/frontier-code-trace-v0/check_longctx_profile_repeats.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +"""Check fresh-process repeat stability for the code long-context grid.""" + +from __future__ import annotations + +import argparse +import json +from pathlib import Path + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser() + parser.add_argument("--first", type=Path, nargs="+", required=True) + parser.add_argument("--second", type=Path, nargs="+", required=True) + parser.add_argument("--output", type=Path, required=True) + parser.add_argument("--max-relative-difference", type=float, default=0.05) + return parser.parse_args() + + +def load(paths: list[Path]) -> dict[tuple[int, str], dict]: + rows: dict[tuple[int, str], dict] = {} + for path in paths: + payload = json.loads(path.read_text()) + for row in payload["rows"]: + if row.get("error"): + raise ValueError( + f"{path}: failed profile row {row['config']['batch_spec']}" + ) + key = ( + int(row["tensor_parallel_size"]), + str(row["config"]["batch_spec"]), + ) + if key in rows: + raise ValueError(f"duplicate row {key}") + rows[key] = row + return rows + + +def main() -> None: + args = parse_args() + first = load(args.first) + second = load(args.second) + if first.keys() != second.keys(): + raise ValueError( + f"repeat key mismatch: first_only={sorted(first.keys()-second.keys())}, " + f"second_only={sorted(second.keys()-first.keys())}" + ) + comparisons = [] + for key in sorted(first): + left = float(first[key]["mean_time"]) + right = float(second[key]["mean_time"]) + relative = abs(left - right) / ((left + right) / 2) + comparisons.append( + { + "tp": key[0], + "batch_spec": key[1], + "first_mean_s": left, + "second_mean_s": right, + "relative_difference": relative, + "pass": relative <= args.max_relative_difference, + } + ) + maximum = max(item["relative_difference"] for item in comparisons) + payload = { + "schema": "frontier-code-longctx-repeat-check-v1", + "threshold": args.max_relative_difference, + "maximum_relative_difference": maximum, + "status": "PASS" if maximum <= args.max_relative_difference else "FAIL", + "comparisons": comparisons, + } + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n") + print(json.dumps({"status": payload["status"], "max": maximum})) + if payload["status"] != "PASS": + raise SystemExit(1) + + +if __name__ == "__main__": + main() diff --git a/runs/frontier-code-trace-v0/experiment-card.md b/runs/frontier-code-trace-v0/experiment-card.md index e43f658..c2822a9 100644 --- a/runs/frontier-code-trace-v0/experiment-card.md +++ b/runs/frontier-code-trace-v0/experiment-card.md @@ -67,10 +67,15 @@ strict decode-only 必须同时具备: ### G2:`max_model_len` data gate -候选 cap 固定为 `40960/65536/98304/131072/262144`,选能 **100% 覆盖选中窗口 `ISL+OSL`** 的最小值。规则: +source-window audit 先用 `40960/65536/98304/131072/262144` 给出完整 +窗口上界;真实 server 则使用能 **100% 覆盖该 rho 实际 paired requests +的 `ISL+OSL`** 的最小 16-token 对齐值。规则: -- 若 max≤131072,主路径使用 131072 或更小的审计推荐值; -- 若存在 >131072 请求,不允许悄悄过滤。优先验证 262144;若 runtime 不可行,必须预注册过滤比例,并把 claim 改为“≤131072 子群”; +- sampling 只按 session-coherent `sampling_u`,不得按 token length 过滤; +- full source window 的 cap 用于记录 workload envelope,不强迫低 rho cell + 为未被抽中的 outlier 预留 KV capacity; +- 若某 paired cell max≤131072,使用 131072 或更小的对齐值;超过 + 131072 时按该 cell 实际 max 向上对齐,而不是直接跳到 262144; - Frontier 的 trace max tokens、predictor max tokens/request、vLLM `--max-model-len` 三处使用同一个 manifest 值。 ### G3:prompt 与 prefix fidelity @@ -87,7 +92,7 @@ strict decode-only 必须同时具备: 现有 profile-v5 的 KV context 上界约 32k,对 code 不足。根据 development window 的 uncached-ISL 分布生成 profile-v6-code-longctx: -- full chunk:`q8k`,context 至少覆盖 32k/48k/64k/80k/96k/112k/120k; +- full chunk:`q8k`,context 至少覆盖 40k/56k/72k/88k/104k/120k/128k; - tail chunk:从真实 `ISL mod 8192` 的 p50/p90 选择 2–4k/4–6k 代表点; - TP1/2/4 分开采集,复测 `q1ks8k/q8ks32k` anchor; - 每点至少两次 fresh-process repeat;CV≤5%,anchor drift≤10%; @@ -203,3 +208,23 @@ mode-specific: - code trace 来自 GLM5.1 业务,serving model 是 Qwen3-30B;若无原 prompt text,测试只能保持 shape/prefix 结构,不能证明内容相关 routing fidelity; - `max_model_len=128k/256k` 解决的是接入上界,不自动解决 32k 以上 profile 外推; - strict decode-only 只测 decode engine;完整 PD 分离还需要单独建模 prefill、KV transfer、backpressure 与 KV-ready arrival。 + +## 执行记录(2026-07-23) + +- fleet probe:dash1–dash4 均为 8×H20;32 张卡 memory.used=0、 + utilization=0、无 compute process、uncorrected ECC=0; +- 两个 formatted trace 都严格满足 512-token source hash contract; +- 0513:2,108,130 个有效请求、6090 个 zero-usage source 行;稳定 + development window=`[3480,7140)`,61min、1,078,928 请求; +- 0529:1,977,423 个有效请求、6031 个 zero-usage source 行;冻结为 + held-out,稳定候选 window=`[2640,6240)`; +- development window:ISL p50/p90/p99/max = + 20,051/88,224/125,803/202,371;OSL p50/p90/p99/max = + 78/758/6449/131,072;`ISL+OSL max=202,745`; +- full-window 131072 coverage=99.399%,262144 coverage=100%。但 + session sampling 的候选 `rho<=0.0032` 实际 max total=137,016,因此 + primary server cap 将按最终 cell max 对齐,不为未抽中的 202k outlier + 直接预留 262k; +- source 无 Qwen-aligned prompt/token IDs。raw canonical prompt 使用 GLM + token contract,不能同时保持 Qwen token content 与 trace ISL;本 campaign + 采用 synthetic Qwen tokens 保持 length/hash/prefix shape,并降级内容 claim。 diff --git a/runs/frontier-code-trace-v0/run_flashattn_code_longctx.sh b/runs/frontier-code-trace-v0/run_flashattn_code_longctx.sh new file mode 100644 index 0000000..cb3e52e --- /dev/null +++ b/runs/frontier-code-trace-v0/run_flashattn_code_longctx.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# Long-context FlashAttention profile grid for the code-trace campaign. + +set -euo pipefail + +TP="${TP:?TP must be set to 1, 2, or 4}" +case "${TP}" in + 1|2|4) ;; + *) echo "ERROR: invalid TP=${TP}" >&2; exit 1 ;; +esac + +OUTPUT_ROOT="${OUTPUT_ROOT:?OUTPUT_ROOT must be set}" +MAX_MODEL_LEN="${MAX_MODEL_LEN:-147456}" +VENV_ROOT="${VENV_ROOT:-/home/admin/cpfs/wjh/venvs/vllm-0.20.0-cu129-workload-regime-v2}" +VLLM_SOURCE="${VLLM_SOURCE:-/home/admin/cpfs/wjh/agentic-kv/third_party/vllm_v20_build}" +MODEL="${MODEL:-/home/admin/cpfs/wjh/models/Qwen/Qwen3-30B-A3B}" +CAMPAIGN_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROFILE_SCRIPT="${CAMPAIGN_ROOT}/../frontier-qwen30-vllm020-profile-v1/profile_vllm020_flashattn.py" + +# Development window: +# ISL p90=88,224, p99=125,803; sampled rho<=0.0032 max total=137,016. +# Tail query distribution modulo 8192: +# p10=495, p25=1477, p50=3594, p75=5917, p90=7246. +# The full-chunk grid reaches 131,072 tokens of existing context; tail shapes +# cover query-size variation at representative long contexts. +BATCH_SPECS=( + q8ks48k q8ks64k q8ks80k q8ks96k q8ks112k q8ks128k q8ks136k + q512s128k q2ks66k q4ks100k q6ks134k + q1ks8k q512s4k +) + +mkdir -p "${OUTPUT_ROOT}/logs" "${OUTPUT_ROOT}/provenance" "${OUTPUT_ROOT}/raw" +exec > >(tee -a "${OUTPUT_ROOT}/logs/code-longctx-grid.log") 2>&1 + +IFS=',' read -r -a GPU_IDS <<< "${CUDA_VISIBLE_DEVICES:?one allocated fleet GPU is required}" +if [[ "${#GPU_IDS[@]}" -ne 1 ]]; then + echo "ERROR: expected exactly one GPU, got ${CUDA_VISIBLE_DEVICES}" >&2 + exit 1 +fi + +test -x "${VENV_ROOT}/bin/python" +test -f "${VLLM_SOURCE}/benchmarks/attention_benchmarks/runner.py" +test -f "${MODEL}/config.json" +test -f "${PROFILE_SCRIPT}" + +echo "PROFILE_LAUNCH_ECHO host=$(hostname) gpu=${CUDA_VISIBLE_DEVICES} tp=${TP} max_model_len=${MAX_MODEL_LEN} specs=${BATCH_SPECS[*]}" +date -u +"START_UTC=%Y-%m-%dT%H:%M:%SZ" +nvidia-smi --query-gpu=index,name,driver_version,memory.used,utilization.gpu \ + --format=csv,noheader +git -C "${CAMPAIGN_ROOT}/../.." rev-parse HEAD \ + > "${OUTPUT_ROOT}/provenance/aituner.commit" +git -C "${VLLM_SOURCE}" rev-parse HEAD \ + > "${OUTPUT_ROOT}/provenance/vllm-source.commit" +sha256sum "${PROFILE_SCRIPT}" "${BASH_SOURCE[0]}" \ + > "${OUTPUT_ROOT}/provenance/source.sha256" +uv pip freeze --python "${VENV_ROOT}/bin/python" \ + > "${OUTPUT_ROOT}/provenance/pip-freeze.txt" +printf '%s\n' "${BATCH_SPECS[@]}" \ + > "${OUTPUT_ROOT}/provenance/batch-specs.txt" +printf '%s\n' "${MAX_MODEL_LEN}" \ + > "${OUTPUT_ROOT}/provenance/max-model-len.txt" + +timeout --signal=TERM --kill-after=30s 1800 \ + "${VENV_ROOT}/bin/python" "${PROFILE_SCRIPT}" \ + --vllm-source "${VLLM_SOURCE}" \ + --model "${MODEL}" \ + --output "${OUTPUT_ROOT}/raw/flashattn-code-longctx-tp${TP}.json" \ + --tp "${TP}" \ + --batch-specs "${BATCH_SPECS[@]}" \ + --warmup-iters 5 \ + --repeats 10 \ + --max-model-len "${MAX_MODEL_LEN}" \ + --profile-kv-update + +test -s "${OUTPUT_ROOT}/raw/flashattn-code-longctx-tp${TP}.json" +sha256sum "${OUTPUT_ROOT}/raw/flashattn-code-longctx-tp${TP}.json" \ + "${OUTPUT_ROOT}/provenance"/* > "${OUTPUT_ROOT}/artifacts.sha256" +nvidia-smi --query-gpu=index,name,memory.used,utilization.gpu --format=csv,noheader +date -u +"END_UTC=%Y-%m-%dT%H:%M:%SZ" +echo "FLASHATTN_CODE_LONGCTX_COMPLETE tp=${TP} cases=${#BATCH_SPECS[@]}" diff --git a/runs/frontier-qwen30-vllm020-profile-v1/profile_vllm020_flashattn.py b/runs/frontier-qwen30-vllm020-profile-v1/profile_vllm020_flashattn.py index 200762e..2cbd637 100644 --- a/runs/frontier-qwen30-vllm020-profile-v1/profile_vllm020_flashattn.py +++ b/runs/frontier-qwen30-vllm020-profile-v1/profile_vllm020_flashattn.py @@ -37,6 +37,7 @@ def parse_args() -> argparse.Namespace: ) parser.add_argument("--warmup-iters", type=int, default=3) parser.add_argument("--repeats", type=int, default=5) + parser.add_argument("--max-model-len", type=int, default=40960) parser.add_argument("--device", default="cuda:0") parser.add_argument("--profile-kv-update", action="store_true") parser.add_argument( @@ -115,7 +116,7 @@ def main() -> None: trust_remote_code=False, dtype="bfloat16", seed=0, - max_model_len=40960, + max_model_len=args.max_model_len, ) cache_config = CacheConfig(block_size=config.block_size, cache_dtype="auto") cache_config.num_gpu_blocks = max_num_blocks @@ -124,7 +125,7 @@ def main() -> None: scheduler_config = SchedulerConfig( max_num_seqs=256, max_num_batched_tokens=8192, - max_model_len=40960, + max_model_len=args.max_model_len, is_encoder_decoder=False, enable_chunked_prefill=True, )