Skip to content

Classify graph-replay synthetic ops by GPU kernel name#677

Open
rkarhila-amd wants to merge 14 commits into
mainfrom
feature/kernel-synthetic-op-categorization
Open

Classify graph-replay synthetic ops by GPU kernel name#677
rkarhila-amd wants to merge 14 commits into
mainfrom
feature/kernel-synthetic-op-categorization

Conversation

@rkarhila-amd

@rkarhila-amd rkarhila-amd commented May 29, 2026

Copy link
Copy Markdown

Summary

  • Extend categorize_torch_op() so TreePerf placeholder ops ({parent}->{kernel} (Synthetic Op)) are categorized from the underlying GPU kernel via classify_kernels, not the graph-launch parent name.
  • Map CK/AITER kernels to TraceLens buckets (GEMM, MoE_unfused, GroupQuant, RMSNorm, elementwise, MoE_aux, etc.) instead of other.
  • Add unit tests in tests/test_synthetic_op_kernel_categorization.py.

Sample output

Analysis of SGLang Minimax 2.5 traces. Before this fix, everything launched in graphs was categorised as "other" and no rooflines are provided. After the fix, kernels in graphs are categorised correctly and rooflines and potential improvements are calculated.

Top Operations without fix on main branch 2026/06/08:

Rank Category Time (ms) % of Compute Time Ops
1 other 5995.619 98.50% 498

Top Operations with this fix

Rank Category Time (ms) % of Compute Time Ops Potential improvement (time, E2E %)
1 GEMM 1283.434 21.1% 14 ~652.8–870.9 ms (8.5–11.3%)
2 elementwise 1290.999 21.2% 505 ~621.2–827.8 ms (8.1–10.7%)
3 MoE_unfused 1275.301 21.0% 6 ~507.9–676.7 ms (6.6–8.8%)
4 GroupQuant 571.695 9.4% 12 ~426.2–568.0 ms (5.5–7.4%)
5 RMSNorm 568.149 9.3% 10 ~423.1–564.2 ms (5.5–7.3%)
6 MoE_aux 457.841 7.5% 6 ~341.4–455.5 ms (4.4–5.9%)
7 SDPA_fwd 451.240 7.4% 2 ~238.2–317.5 ms (3.1–4.1%)

Smoketest on vllm

Top operations from analysis of a small Qwen3-0.6B vllm trace with graphs. Kernels in graphs are found and rooflines are estimated.

Rank Category Time (ms) % of Compute Time Ops Potential improvement (time, E2E %)
1 InferenceAttention 7.093 24.9% 16 ~5.1–6.9 ms (1.4–1.9%)
2 GEMM 9.533 33.5% 39 ~3.2–4.2 ms (0.9–1.2%)
3 triton 6.937 24.4% 79 no roofline
4 other 1.710 6.0% 27 no roofline

Context

Graph-replay traces often attribute GPU work under hipGraphLaunch / cudaGraphLaunch without a normal aiter:: / aten:: CPU op. This is the open-source counterpart to TraceLens-internal #458.

Regression test updates

Refreshed checked-in CSV golden files (commit 23e80f9a) after intentional reporting changes from synthetic-op categorization and new graph-replay perf models. All 43 targeted regression cases now pass locally.

Test module Cases updated Why references changed
test_perf_report_regression.py 12 traces (h100 × 6, mi300 × 5, perf_model/normalization) Parent op category: otherSDPA_fwd / elementwise; has_perf_model: FalseTrue; normalization trace row order + RMSNorm perf_params (ScalarList dtype fallback)
test_compare_perf_reports.py compare_test_e2e h100 + mi300 Qwen references Category rollups and intersect sheets reflect SDPA/elementwise split out of other
test_inference_perf_report.py graph_full, graph_piecewise Graph-replay MoE aux + elementwise synthetic ops leave other; has_perf_model flags set
test_detect_recompute.py mi300/resnet_act_checkpoint unified_perf_summary row order shifts when grouping keys change

Trace directories touched (62 CSV files): h100/* (6 workloads), mi300/* (5 workloads + recompute), compare_test_e2e/reference/*, inference/graph_full, inference/graph_piecewise, perf_model/normalization.

Unchanged (still pass): mi210/gpu_only_trace, torch_compile_triton/trace.

Test plan

  • pytest tests/test_synthetic_op_kernel_categorization.py -v
  • pytest tests/test_perf_report_regression.py tests/test_compare_perf_reports.py tests/test_inference_perf_report.py tests/test_detect_recompute.py
  • Re-run inference perf report + orchestrator on a graph-replay + capture trace and confirm other bucket shrinks and gemm_ops.csv / moe_unfused_ops.csv populate

Made with Cursor

@rkarhila-amd
rkarhila-amd marked this pull request as ready for review May 29, 2026 06:54
@rkarhila-amd
rkarhila-amd requested review from a team, ajassani and gabeweisz as code owners May 29, 2026 06:54
@rkarhila-amd

rkarhila-amd commented Jun 3, 2026

Copy link
Copy Markdown
Author

The regression test fails because in earlier version any operations inside cuda graph were categorised as "other" whereas this PR gives them explicit categorisation.

This PR Test specification
SPDA_fwd other
elementwise other

This PR cannot pass the test as it makes a more fine grained analysis. We need this feature implemented in this way or another. Codeowners please comment @ajassani @gabeweisz @AMD-AGI/perf-opt

@gabeweisz

Copy link
Copy Markdown
Collaborator

The regression test fails because in earlier version any operations inside cuda graph were categorised as "other" whereas this PR gives them explicit categorisation.

This PR Test specification
SPDA_fwd other
elementwise other
This PR cannot pass the test as it makes a more fine grained analysis. We need this feature implemented in this way or another. Codeowners please comment @ajassani @gabeweisz @AMD-AGI/perf-opt

The thing to do in this case is to update the reference outputs. We will be able to see how they changed in the deltas in the CSVs and make sure that they make sense.

I think we have a script that you can use to update the reference results. If not, you can manually find the right files or ask Cursor or whichever tool you like to do it for you

Comment thread TraceLens/PerfModel/torch_op_mapping.py Outdated
)
return None
ktl, knl = kt.lower(), kernel_name.lower()
if kt == "KV Cache Store":

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to see a loop over a dict rather than this long list of if statements - I think that is a bit more maintainable

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, mappings should be in same format as for the non-graph kernels.

While working on this, I understood that the suggested change only affects reporting, and perf models are not applied to the kernels in graphs.

I'll see how massive overhaul it takes to get that bit working.

@rkarhila-amd

Copy link
Copy Markdown
Author

Turned out to be quite an overhaul. Currently developed with only a single trace. I'll test with a few more cases tomorrow.

@rkarhila-amd

Copy link
Copy Markdown
Author

The PR affects almost 80 files but majority of them are test cases.

PR covers now the kernel types inside graphs that were listed in PR description chart. Still tested only on sglang,
I'll try to find useful vLLM task to see how badly it breaks on that side.

@rkarhila-amd
rkarhila-amd force-pushed the feature/kernel-synthetic-op-categorization branch from 25319cc to 93acdaf Compare June 16, 2026 10:15
@rkarhila-amd

Copy link
Copy Markdown
Author

This looks like its working satisfactorily now. I'm running a final end-to-end test on sglang side. Still missing vllm test case, I'll get it tomorrow.

FYI @devalshahamd I had an improperly activated patch in last traces, now I'm testing with properly instrumented Kimi-K2.6-MXFP4 traces accessible to AMDeers in sharepoint.

@rkarhila-amd
rkarhila-amd force-pushed the feature/kernel-synthetic-op-categorization branch from b68d10e to 21d9435 Compare June 18, 2026 09:35
@rkarhila-amd

Copy link
Copy Markdown
Author

Finally verified that these changes didn't break vllm trace handling.

Please review now.

If this is too much in one go, I can try to break it up to parts, for example I put considerable work on (directing cursor to) optimize the perf tree building in trace merging, and reduced the compute time for some of the operations from hours to seconds. (No matter how I try to avoid it, I somehow always find my way back to tweaking transducers and graph operations). That could be its own PR. The rest is difficult to split.

@rkarhila-amd
rkarhila-amd force-pushed the feature/kernel-synthetic-op-categorization branch from 0c3c6dc to ba7846a Compare July 1, 2026 16:34
rkarhila-amd and others added 11 commits July 7, 2026 06:59
…etrics

- Classify hipGraphLaunch/cudaGraphLaunch synthetic ops by underlying GPU kernel name
- Resolve perf models for synthetics via SGLang capture linking and kernel heuristics
- Compute roofline metrics for off-tree synthetics via gpu_events
- Use per-kernel duration instead of hipGraphLaunch envelope time for synthetics

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Add capture-link augmentation for truncated MoE shapes and pointer-only RMSNorm launches, register dedicated perf models for kernel_moe_gemm and dynamic_per_group_scaled_quant, and prefer those rules over generic kernel-type mappings so graph-replay synthetics get roofline metrics in analysis.

Co-authored-by: Cursor <cursoragent@cursor.com>
Register MoE sorting/top-k and decode-attention perf models, fix RMSNorm
ScalarList dtype fallback, and expose roofline_time_fraction in priority_data.

Co-authored-by: Cursor <cursoragent@cursor.com>
…tion.

Update checked-in CSV golden files after graph-replay kernels move from
other to SDPA_fwd, elementwise, and MoE_aux and gain perf models.

Co-authored-by: Cursor <cursoragent@cursor.com>
Match surrounding KERNEL_TYPE_RULES formatting in classify_kernels.py.

Co-authored-by: Cursor <cursoragent@cursor.com>
Reformat classify_kernels, perf_model_extensions, and trace_sglang_capture_link
so lint CI passes with the pinned Black version.

Co-authored-by: Cursor <cursoragent@cursor.com>
Graph launch nodes get execute_* annotations; synthetic GPU ops inherit
annotations from ancestors. graph_decode_attention_kernel reads parsed
sq/sk for N_Q/N_KV. UserWarnings flag defaulted dims/dtypes in graph
replay perf models. Tests cover annotation parsing and SDPA params.

Co-authored-by: Cursor <cursoragent@cursor.com>
Re-run formatter against merge-base with origin/main so CI lint stays green.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add time-sorted event indexing for capture merge, tqdm milestones during
TreePerfAnalyzer init and pseudo-op extensions, parent-pointer cycle guards,
and targeted pseudo-op kernel detection to avoid full-tree scans on large traces.

Co-authored-by: Cursor <cursoragent@cursor.com>
MoE fused uses a one-pass subtree flag for cpu_op descendants; unfused Triton
batches parent child-list rewrites. MLA decode/prefill use a stage1/donor
index plus batched cpu_root_nodes updates via inject_pseudo_op_wrap_children
(cpu_roots_acc) to avoid O(M×R) list rescans. apply_pseudo_op_extensions logs
MoE branch choice, extension order, per-extension timings, and supports
TRACELENS_PSEUDO_OPS_LOG for stderr diagnostics without --show-progress.

Co-authored-by: Cursor <cursoragent@cursor.com>
rkarhila-amd and others added 3 commits July 7, 2026 06:59
Co-authored-by: Cursor <cursoragent@cursor.com>
Serialize grouped call stacks as strings, strip parent_module whitespace, and drop per-kernel call_stack from unified summaries so graph inference golden CSVs match again.

Co-authored-by: Cursor <cursoragent@cursor.com>
Update sglang_decode and sglang_prefilldecode reference CSVs to reflect
call_stack enrichment and synthetic-op categorization from this branch;
the golden CSVs added to main in #791 pre-date these features.
Apply Black 26.1.0 to tree_perf.py (touched by the rebase onto main).

Co-authored-by: Cursor <cursoragent@cursor.com>
@rkarhila-amd
rkarhila-amd force-pushed the feature/kernel-synthetic-op-categorization branch from ba7846a to bd6c955 Compare July 7, 2026 07:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants