adding profiling context - #477
Conversation
Review: overlap with ATOM's existing annotations + a few correctness itemsThanks for the PR. The capture-trace-per-bs split is a clear win, but the roofline annotation overlaps heavily with annotations ATOM already emits, and the way it's layered hits a known GPU-trace pitfall. Details below. 1. The roofline annotation duplicates the existing
|
| roofline field (new) | already present in existing label |
|---|---|
bs (actually total tokens) |
tok=total_tokens_num |
context_{n} / generation_{n} |
p= (prefill seqs) / d= (decode seqs) |
sq (sum N_Q) |
tok= |
sk (sum N_KV) |
ctx=context_lens (existing is per-request; new is the sum) |
sqsq (sum N_Q^2) |
not present |
sqsk (sum N_Q*N_KV) |
not present |
So the only genuinely new information is sqsq and sqsk (the quadratic terms needed for the roofline FLOP estimate). Everything else is a restatement or sub-set of what's already in the trace.
2. Layering it on forward() nests it above the existing label and likely loses the GPU annotation
The new annotation wraps forward(), while prefill[]/decode[] wraps run_model() (called by forward), so the trace ends up nested:
execute_..._context_...(roofline) <- forward level (CPU annotation)
\-- prefill[bs= tok= ctx=] <- run_model level
A nested outer record_function does not produce a GPU-side annotation (only a CPU-timeline one) — we hit this before in this codebase. That means the roofline label probably won't carry GPU kernel time, which is exactly what a roofline analysis needs.
Suggested fix: drop the new forward()-level record_function and append sqsq/sqsk (and the sk sum if wanted) directly to the existing prefill[]/decode[] labels in run_model(). That layer is already a GPU-recognized annotation, it removes the duplication and nesting, and tools/parse_trace.py already keys off the prefill[/decode[ prefixes — so extending those fields is a smaller change than introducing a separate execute_... format.
Also note bs in the new annotation means "total tokens", which collides in name with the existing bs (effective batch size) while differing in value (they diverge significantly for prefill). Please rename to avoid confusion.
3. Smaller correctness / convention items
build_profile_annotationdocstring is wrong (scheduler.py): it says "Return a context manager that annotates..." but the function returnsNoneand mutatesscheduled_batch.profile_annotation. The docstring also listsR_C/R_Gfields that aren't in the emitted string.- New env var not registered:
ATOM_ENABLE_ROOFLINE_ANNOTATIONis read raw viaos.environ.get(...)in two places. Per convention allATOM_*vars belong inatom/utils/envs.py, anddocs/environment_variables.mdshould be updated. record_functionwithout exception safety (model_runner.pyforward): manualctx.__enter__()/ctx.__exit__(None,None,None)leaks the annotation ifrun_modelraises. Use awithblock (this disappears entirely if you adopt the suggestion in section 2).prof.step()alignment instart_capture_profileris fragile: correctness relies on exactly 2step()calls per bs againstschedule(wait=1, warmup=0, active=1). Addassert self._profile_bs_idx < len(self.graph_bs)inon_trace_readyand a comment documenting the "2 steps per bs" invariant, otherwise a future edit silently mislabels traces or raisesIndexError.- No tests added: at minimum a pure-Python unit test for
build_profile_annotation(fake seqs, assert the prefill/decode aggregates) would cover the new logic without needing a GPU.
The capture-trace-per-bs change (replacing the old single-blob capture profiler in engine_core) looks good and doesn't overlap with anything existing.
1 & 2 — Duplication + the nested
|
Review: adding profiling contextAdds opt-in profiling detail: per-batch-size CUDA-graph capture traces ( Findings (most severe first)1. 2. 3. Naming: "roofline" is misleading, and
Suggest dropping "roofline" and naming things for what they are, e.g. 4. 5. 6. 7. #1 is the only correctness bug (confined to the profiling path); #2 and #3 are the clearest cleanup/naming items; #4–7 are robustness/accuracy/docs. |
|
Just chiming in here -- this capture+replay method is important for the work in my org. |
ChuanLi1101
left a comment
There was a problem hiding this comment.
Thanks for the updates — the capture-trace-per-bs split looks good. Two things before I can approve:
1. Correctness bug (blocking): int32 overflow in compute_roofline_aggregates.
num_scheduled_tokens is stored as np.int32, so in the prefill branch nq = num_tokens is an np.int32 and nq*nq / nq*nkv overflow once a prefill/chunk exceeds ~46341 tokens (e.g. np.int32(65536)**2 == 0). Long-context prefills would emit sqsq=0/garbage. Please cast nq = int(num_tokens) (or int64). The new unit test uses plain Python ints, so it won't catch this — please add a case with a large N_Q.
2. Merge conflicts: the branch is currently conflicting with main; please rebase/resolve.
The remaining items from my Jul 5 review (naming "roofline"/sqsq/sqsk/sk, the assert in on_trace_ready that can abort capture at startup, the dead EngineCore start/stop_profiler, nq=1 undercounting MTP, and the capture_traces doc gap) are non-blocking — a quick reply on each would help. Once #1 and the conflicts are handled I'll re-review.
|
Thanks @ChuanLi1101 — addressed the blocking items and went through the rest of the Jul 5 list too. 1. int32 overflow (blocking) — fixed. nq = int(num_tokens)
nkv = int(seq.num_tokens) if decode else int(seq.num_cached_tokens) + nqAdded a regression test that feeds 2. Merge conflicts — resolving. Rebasing onto latest Non-blocking items from the Jul 5 review: Naming (
if self._profile_bs_idx >= len(self.graph_bs):
logger.warning(...); returnDead
capture_traces doc gap. Added section 5.6 CUDA-Graph Capture Traces to Minor: per-step Unit tests updated accordingly. |
ChuanLi1101
left a comment
There was a problem hiding this comment.
Thanks for the thorough follow-up — all my blocking items and the Jul 5 findings are addressed. Verified on ec41d3e:
- int32 overflow (blocking) fixed:
nq = int(num_tokens)andnkv = int(...)incompute_roofline_aggregates, plus atest_no_int32_overflow_large_prefillregression test (N_Q=65536 →sqsq == nq*nq, not 0). - Merge conflicts resolved — branch is now
MERGEABLE. - Dead EngineCore
start/stop_profiler/print_mtp_statisticsremoved; profiler control stays on the_handle_*utility path. on_trace_readynow log-and-skips instead ofassert, so a cadence mismatch can't abort capture at startup.- Decode branch now uses the scheduled query-token count (no longer hardcoded
nq=1), so MTP/spec-decode isn't undercounted (+ test). - Env flag cached once as
self._detailed_annotation_enabled— no per-iterationos.getenv. - Naming/docs: renamed to
ATOM_ENABLE_DETAILED_ANNOTATION; docs now state these are attention-quadratic terms only (a full roofline still needs GEMM FLOPs + bytes).capture_traces/bs_<bs>_rank<rank>.json.gzdocumented in the serving guide.
All new behavior stays gated behind profile_active + the env flag, so the production path is untouched. LGTM.
|
Approving on the condition that CI passes and the benchmark shows no perf degradation before merge. The new logic is gated behind |
|
Re-ran the failed jobs — still red, but all failures are infra, none related to this PR:
Re-running just lands on the same broken environment. This needs infra to fix the aiter artifact digest, bump/pre-cache the model download, and clean the runners. @LingPeng — could you help? I'll re-approve once CI is green. |
ChuanLi1101
left a comment
There was a problem hiding this comment.
Re-approving. All my blocking items and the Jul 5 findings have been addressed and verified (int32 overflow fixed + regression test, merge conflicts resolved, dead EngineCore start/stop_profiler removed, on_trace_ready log-and-skips instead of assert, decode branch uses the scheduled query-token count for MTP, env flag cached, renamed to ATOM_ENABLE_DETAILED_ANNOTATION + docs updated, capture_traces artifact documented). All new behavior stays gated behind profile_active + ATOM_ENABLE_DETAILED_ANNOTATION, so the production inference path is untouched.
Note on CI — the lightweight gates (black, ruff, non-GPU unit tests, docs build) are green. The remaining red jobs are all infrastructure, not code:
- Required check Accuracy (DeepSeek-R1-0528-FP4 MTP): empty HF Bearer token →
Illegal header value b'Bearer ', so the 97GB model can't resolve/download and hitsMODEL_DOWNLOAD_TIMEOUT=30m→ aborts. Not PR-related. - Non-required jobs (DeepSeek-V4-Pro TP8 SGLang, DeepSeek-V4-Flash, GLM-5.2, MiniMax-M3): GPU memory unbalanced / GPUs occupied by stale processes, plus the same empty-HF-token issue. The same DeepSeek-V4-Pro model passes in the ATOM Test workflow on a clean runner.
Once infra restores the HF token / pre-caches the models and the required Accuracy (DeepSeek-R1-0528-FP4 MTP) check re-runs green, this is good to merge.
|
Following further review of the annotation portion of this PR, I would like to revise my earlier assessment. My previous comment characterized the emitted fields as "attention-quadratic terms only." That understated the problem: the computation in Affected models:
In addition, the aggregate is a single batch-level scalar with no per-layer distinction. It therefore cannot represent the mixed layer types within a single model (DSv4 interleaves dense-MLA and CSA layers; Qwen3-Next interleaves GDN and full-attention layers). The fields are only meaningful for genuinely dense-attention models (R1 / V3 / V3-0324), which are a minority of what we serve. Separately, on naming. Only the environment variable was renamed ( Regarding the label keys: I reviewed Recommendation: I suggest splitting this PR. The per-batch-size capture-trace change is self-contained and useful, and can be merged on its own. For the annotation portion, please either (a) compute the terms per layer against the actual |
|
Implemented the naming changes from roofline->detailed |
Motivation
This PR aims to make the profile traces collected during ATOM run more detailed. It introduces 2 broad changes:
Technical Details
--mark-traceannotation.ATOM_ENABLE_DETAILED_ANNOTATION=1gives you annotations in the trace file needed for calculating roofline metrics.Test Plan
Test Result
Submission Checklist