-
Notifications
You must be signed in to change notification settings - Fork 76
4wave fp4 gemm opt #798
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
benenzhu
wants to merge
122
commits into
ROCm:main
Choose a base branch
from
benenzhu:4wave_fp4_gemm_opt
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+680
−145
Open
4wave fp4 gemm opt #798
Changes from all commits
Commits
Show all changes
122 commits
Select commit
Hold shift + click to select a range
a5fc67f
zz
benenzhu 6d989eb
zz
benenzhu ad15b44
zz
benenzhu 177a74e
zz
benenzhu 8e73213
zz
benenzhu 4c583c8
zz
benenzhu b510918
zz
benenzhu b115edf
Add runnable Kimi mxfp4 16384 FlyDSL path
benenzhu 7671649
Relax Kimi mxfp4 GEMM1 pre-barrier wait
benenzhu 40aaeb3
Checkpoint runnable Kimi mxfp4 FlyDSL GEMM1
benenzhu 6ff8329
Pipeline Kimi mxfp4 GEMM1 LDS loads
benenzhu c4a9fbf
Checkpoint runnable Kimi mxfp4 GEMM1 optimization
benenzhu 1af39d1
Optimize Kimi mxfp4 GEMM1 scheduling
benenzhu eac281a
Document Kimi GEMM1 resource audit
benenzhu 9a5b943
Tune Kimi GEMM1 epilogue max lowering
benenzhu a471ed4
Optimize Kimi mxfp4 FlyDSL GEMM2
benenzhu a091cb4
Optimize Kimi MXFP4 scatter reduce
benenzhu e83e61b
Optimize Kimi MXFP4 sort cumsum
benenzhu b898759
Profile Kimi MXFP4 under graph replay by default
benenzhu 9882c62
Stabilize Kimi MXFP4 graph profiling
benenzhu e9a76f0
Align Kimi sort place and scatter kernels
benenzhu 75045f9
Tune Kimi sort placement loop
benenzhu cb53288
Record rejected Kimi sort padding loop
benenzhu 5e38bf8
Align Kimi sort place padding path
benenzhu a94e936
Align Kimi mxfp4 GEMM1 AGPR path
benenzhu af6e440
zz
benenzhu e0926a9
Add FlyDSL Kimi BM16 mxfp4 small path
benenzhu 8e08047
Optimize Kimi BM16 mxfp4 FlyDSL pipeline
benenzhu 15c83c9
Align Kimi BM16 inline quant schedule
benenzhu e397730
Increase small-M benchmark graph sampling
benenzhu 41928f0
Add Kimi BM16 stage benchmark
benenzhu 4809143
Document Kimi BM16 profiling follow-ups
benenzhu 50d80b0
Align Kimi BM16 GEMM1 epilogue
benenzhu 35b9849
Align Kimi BM16 GEMM2 A LDS load
benenzhu 3f925bb
Tune Kimi BM16 profiling and atomics
benenzhu 233a9b1
Stabilize BM16 graph profiling defaults
benenzhu c61b4a9
Document BM16 sort DPP scan trials
benenzhu 16ca792
Increase BM16 graph measurement stability
benenzhu e2fb3dd
Stabilize BM16 measurements and GEMM1 epilogue
benenzhu 1d2afab
Use bounded BM16 graph profiler window
benenzhu 3834bc3
Increase graph benchmark sampling
benenzhu 7d790e7
Hoist BM16 GEMM1 A LDS reads
benenzhu 2cd67f0
Document rejected BM16 GEMM1 wait trial
benenzhu fd2df0a
Increase benchmark sampling defaults
benenzhu 318e6a7
Document rejected BM16 scheduling trials
benenzhu 9f2af55
Tune benchmark sampling for BM16 profiling
benenzhu 7e18f44
Document rejected BM16 sort prefix trial
benenzhu 3b7bbaf
Document rejected BM16 GEMM2 split barrier trial
benenzhu 6b31b07
Document rejected BM16 GEMM2 schedule barrier trial
benenzhu 157b899
Align BM16 GEMM2 scale loads
benenzhu 9668463
Align BM16 GEMM1 scale loads
benenzhu e7a0d98
Declare BM16 GEMM1 block size
benenzhu 53f3525
zz
benenzhu ea30a49
zz
benenzhu 0dc34ca
slower but not mlir
benenzhu 322b80f
slower but not mlir
benenzhu 1a0f8a4
zz
benenzhu 0b3bd15
zz
benenzhu a7971ae
slower but not mlir
benenzhu ed93804
Optimize hgemm tail prefetch scheduling
benenzhu 3518e5b
Document wave0 hgemm first ops
benenzhu bf7611e
Format wave0 hgemm ops list
benenzhu e701d3b
Document full wave0 hgemm schedule
benenzhu 63ed364
zz
benenzhu c3aeb87
Add K32 register-prefetch pipeline to bf16 hgemm (+22%: 837->1025 TFL…
benenzhu 6f21eb0
Interleave RP1 ds_reads via full-K0 register carry (+3%: 1025->1051 T…
benenzhu 4916942
Interleave RP1 bfld prefetch into MFMA shadows (+6%: 1051->1113 TFLOPS)
benenzhu 28825ca
Add bf16 hgemm RP1 final ISA snapshot (1117 TFLOPS, 8192x8192x16384)
benenzhu ed9d509
Add cleaned (pure) ISA of bf16 hgemm RP1 1117 TFLOPS kernel
benenzhu a561252
Add hotloop-table skill + bf16 hgemm RP1 hot-loop table
benenzhu 6b3e67d
Tighten RP1 tail vmcnt to provably-safe bound (LDG_WAIT_COUNT//2)
benenzhu 3fbb4cb
Make both RP1 half barriers carry vmcnt(8) + lgkmcnt(0) for provable …
benenzhu 8c65b64
Add A/B coarse preshuffle ([256,BLOCK_K] tiles contiguous) to bf16 hgemm
benenzhu 9987b5c
Add pure ISA + hotloop table for preshuffle bf16 hgemm (~1313 TFLOPS)
benenzhu 9a17cd5
Split preshuffle global-address math into invariant + k-stepped term …
benenzhu 2e5ffdd
Add optional XCD-swizzle CTA remap (off by default; L2 up but perf ne…
benenzhu 9ff9796
Delay first-half bfld drip by one MFMA row (-80% buffer_load issue st…
benenzhu 12a18d9
Add bufferload-cycle-table skill (per-tile buffer_load gap/stall comp…
benenzhu 676aecc
Drop sc0 (glc) from read-only A/B buffer_load_lds
benenzhu 76d94d4
Add pure ISA + hotloop table for bf16 hgemm RP1 (preshuffle, no-sc0)
benenzhu 1cbcd5e
Add fp8_gemm_4wave pure ISA (8192x8192x16384, ~2973 TFLOPS)
benenzhu a847939
Ride K-step on scalar soffset in preshuffle buffer_load (share vaddr …
benenzhu 6b0901d
Fix preshuffle cache-line alignment: K32 sub-group as outer K axis (+…
benenzhu 6458b91
Add fp8_gemm_4wave_opt: pin MFMA accumulator in AGPR (+8%: 2982->3226…
benenzhu 829de46
fp8_opt: relax main-loop barrier vmcnt 16->32 (~+0.4%, 3226->~3240 TF…
benenzhu 24c1424
slower but not mlir
benenzhu 9bc116a
fp8_gemm_4wave: pin MFMA accumulator in AGPR (+5~13% across medium-la…
benenzhu a99e43a
Merge branch 'zty_fp8_4wave_opt_pr' into zty_dev_moe
benenzhu 9222112
fp4_gemm_4wave: 4-wave MXFP4 GEMM (cos 0.999999, ~2455 TFLOPS @ 8192^3)
benenzhu 1b7db95
fp4_gemm_4wave: pin MFMA accumulator in AGPR via inline asm (+58%, 24…
benenzhu 6781e55
fp4_gemm_4wave: depth-1 scale prefetch -> 4109 TFLOPS (beats 4071 bas…
benenzhu ea98e29
fp4_gemm_4wave: interleave ds_read/buffer_load into MFMA shadow -> 43…
benenzhu 644c229
fp4_gemm_4wave: roll K-loop into scf.for unroll-2 (fix icache overflo…
benenzhu 8a9cf5b
fp4_gemm_4wave: add mn_aligned epilogue fast-path (skip per-store bou…
benenzhu 9ceee2d
gitignore: exclude scratch experiments, handoff notes, and snapshot WIP
benenzhu fe6acc5
Merge remote-tracking branch 'origin/main' into zty_dev_moe
benenzhu a006b20
fp4_gemm_4wave: cut arch VGPR 252->220 via single-symbol LDS + inline…
benenzhu ed17e7b
fp4_gemm_4wave: scale load via inline-asm buffer_load, fix vmcnt acco…
benenzhu 5859f7f
fp4_gemm_4wave: depth-2 end-of-step scale prefetch -> vmcnt(16), 4281…
benenzhu 3d9c3ff
fp4_gemm_4wave: interleave the two tail steps' ds_reads into MFMA shadow
benenzhu 6788c9e
fp4_gemm_4wave: m0 set-once + s_add increment for g2s (gcnasm async-c…
benenzhu 9395ee3
have error learning now
benenzhu 15575f3
zty_tmp
benenzhu 467e700
fp4_gemm_4wave: scale via dwordx4-lds gather, fix prologue vmcnt orde…
benenzhu 0e37270
fp4_gemm_4wave: co-issue scale gather in MFMA shadow
benenzhu f89d596
fp4_gemm_4wave: hide scale half-1 ds_read in MFMA shadow
benenzhu 594d4cc
fp4_gemm_4wave: VGPR-carry scale (depth-3) + strided MFMA interleave
benenzhu 9e21f0e
fp4_gemm_4wave: precompute scale-gather m0 base, drop per-gather read…
benenzhu 62dca41
mfma-coverage skill: switch to next_free pipeline exposure model
benenzhu 2cd4910
mfma-coverage skill: rank blockers by authoritative stall field, not …
benenzhu eee276e
mfma-coverage skill: exposed = stall field intersected with idle gaps…
benenzhu df9f154
mfma-coverage skill: occupancy-only attribution with %exp + %all columns
benenzhu 9b091b4
fp4_gemm_4wave: precompute g2s m0 base, drop per-load readfirstlane
benenzhu 2be5eb5
Merge remote-tracking branch 'upstream/main' into zty_dev_moe
benenzhu 79d9c86
fp4_gemm_4wave: restore clean identifier names (drop __N value-annota…
benenzhu 170b1f2
add
benenzhu b32cbdc
add
benenzhu 326b2c3
zty_tmp
benenzhu 112d21c
zty_tmp
benenzhu 88d5323
delete skills
benenzhu b296d89
Update SKILL.md
benenzhu 17d2740
Merge branch 'main' into 4wave_fp4_gemm_opt
benenzhu File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| --- | ||
| name: 4wave-mfma-coverage-analysis | ||
| description: From an ATT trace, find which hot-loop instructions are NOT hidden behind MFMA execution -- i.e. what is keeping cyc/mfma above the MFMA execute floor (16 for fp4 16x16x128, 32 for fp8 16x16x128). Models the matrix unit as a pipeline (next_free) for the EXPOSED cycles, then tiles those idle cycles by OCCUPYING instruction (issue_dur + stall, intersected with the idle gaps) so the ranking says which non-MFMA ops steal issue bandwidth between MFMAs. Reports %exp and %all. Use when a GEMM/attention kernel is MFMA-bound and is 256 threads/4waves and you want to push cyc/mfma toward the floor, or which non-MFMA op is the biggest exposed stall. | ||
| --- | ||
|
|
||
| # MFMA Coverage Analysis | ||
|
|
||
| ## The model | ||
|
|
||
| **Step 1 — EXPOSED via next_free (matrix-unit pipeline).** Each MFMA occupies ONE EXEC-cycle execute slot, but consecutive MFMAs can **issue < EXEC apart** and still both be hidden (dense fp4 MFMAs issue (4~8) cyc apart yet each execute-slot is 16). | ||
| Track `next_free` = the cycle the unit becomes free: | ||
| - MFMA issues at `t <= next_free` → hidden; `next_free += EXEC` | ||
| - MFMA issues at `t > next_free` → unit IDLE for `t - next_free` → **EXPOSED** | ||
|
|
||
| EXPOSED = sum of idle gaps; shrink toward 0 so cyc/mfma → EXEC(This replaces an older union-of-`[issue,issue+EXEC)` model that over-reported exposure.) | ||
|
|
||
| **Step 2 — attribute EXPOSED by OCCUPANCY.** For every idle cycle, credit it to whichever instruction was on the issue port then. Each non-MFMA instruction occupies `[its issue, next instruction's issue)` = its issue_dur PLUS any stall (r[2]) — we do NOT split issue vs stall, and do NOT ask "who blocks". The question is simply: while the matrix unit sat idle, which non-MFMA ops were stealing issue bandwidth? Intersect each op's occupancy with the idle gaps and sum. This tiles the whole EXPOSED window (every idle cycle has an owner), so the ranking directly says which ops must be REMOVED / SHRUNK from between the MFMAs to push cyc/mfma toward the floor. | ||
|
|
||
| Two percent columns: **%exp** (of the EXPOSED cycles) and **%all** (of the whole window incl. MFMA — the real wall-clock lever, since MFMA execute is ~85%+). | ||
|
|
||
| Example (fp4_gemm_4wave, cyc/mfma 18.73, EXPOSED 6344 = 14.4% of all): `buffer_load_dwordx4 30%exp/4.3%all · v_readfirstlane 17%/2.5% · s_barrier 16%/2.3% · s_waitcnt(lgkmcnt) 8%/1.2% · s_add_i32 6%/0.8% · ds_read_b128 6%/0.8% · …`. | ||
| Read it as: the exposed time is scale/g2s **gather + readfirstlane + address arithmetic** stealing issue slots between MFMAs; cut their count/occupancy. | ||
| Row schema: `[cycle, issue_dur, stall, total_dur, code_id]`; s_waitcnt is split vmcnt / lgkmcnt so you see whether VMEM or LDS waits dominate. | ||
|
|
||
| EXEC is the MFMA **execute** latency, NOT issue latency: | ||
| - fp4 `mfma_scale_f32_16x16x128_f8f6f4` → **16** | ||
| - fp8 `mfma..16x16x128` → **32** (its issue latency) | ||
| Pass the right `--exec`. | ||
|
|
||
| ## How to run | ||
|
|
||
| ```bash | ||
| # 1. capture ATT on an idle GPU | ||
| # 2. run, first without --range to print the cycle span: | ||
| python3 .claude/skills/mfma-coverage-analysis/scripts/mfma_coverage.py <dispatch_dir> | ||
| # 3. pick a mid steady slice spanning ~10 outer-loop iters, re-run: | ||
| python3 .claude/skills/mfma-coverage-analysis/scripts/mfma_coverage.py \ | ||
| <dispatch_dir> --range 219000,245000 --exec 16 | ||
| ``` | ||
|
|
||
| Output: MFMA-covered %, EXPOSED % (and % of all), cyc/mfma vs floor, then the exposed | ||
| cycles tiled by OCCUPYING instruction with two columns (%exp, %all). | ||
|
|
||
| ## Reading it | ||
|
|
||
| - **Attack the top occupancy ops** = the non-MFMA instructions eating the most idle | ||
| cycles between MFMAs. Reduce their COUNT or per-op occupancy so more MFMAs pack in: | ||
| fewer/cheaper address ops, precompute wave-uniform values once (kill readfirstlane), | ||
| merge/spread loads, deepen prefetch so a value is on the port earlier. | ||
| - **buffer_load / ds_read high** → too many gathers/reads issue between MFMAs; merge | ||
| (wider load), move to a different MFMA's shadow, or cut the count. | ||
| - **v_readfirstlane high** → v→s serialization; precompute the wave-uniform SGPR once | ||
| outside the loop instead of per-use. | ||
| - **s_add / s_and / v_cmp / s_lshl** (address & loop arithmetic) → recompute less; hoist loop-invariants, use s_add increment chains, fold offsets into instruction immediates. | ||
| - **s_barrier high** → per-iter cross-wave sync (4 waves finish the iter at slightly different times). Structural for a fixed wave count; not cuttable without changing sync granularity / wave layout. | ||
| - **s_waitcnt(lgkmcnt/vmcnt)** → LDS/VMEM waits; deepen the corresponding prefetch or relax the count. Usually small once loads are hidden. | ||
|
|
||
| ## Caveats | ||
|
|
||
| - Uses one wave file (se0_sm0_sl0_wv0.json by default). Different waves are | ||
| equivalent repeats; pass `--wave` to check another. | ||
| - Occupancy tiles the EXPOSED window with no gaps (every idle cycle has an owner), so | ||
| %exp sums to ~100. It counts issue_dur + stall together on purpose — the goal is | ||
| "what steals issue bandwidth between MFMAs", not "who stalls". | ||
| - Row schema: `[cycle, issue_dur, stall, total_dur, code_id]`; | ||
| `code.json["code"][cid][0]` is the asm text. (See att-hotloop-benchmark for the | ||
| complementary barrier-window cyc/mfma summary.) | ||
142 changes: 142 additions & 0 deletions
142
.claude/skills/4wave-mfma-coverage-analysis/scripts/mfma_coverage.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| #!/usr/bin/env python3 | ||
| """Find which instructions are NOT hidden behind MFMA in a GEMM hot loop. | ||
|
|
||
| Model: each MFMA occupies a fixed execute window of EXEC cycles from its issue | ||
| cycle. Back-to-back MFMAs tile [c, c+EXEC) windows; while the matrix unit is busy | ||
| any co-issued scalar/VMEM/LDS op is "free". Cycles OUTSIDE the union of those | ||
| windows are EXPOSED -- the matrix unit idles there, so cyc/mfma > EXEC. We attribute | ||
| each exposed gap to the (non-MFMA) instruction at its start = what blocked the next | ||
| MFMA from issuing on time. | ||
|
|
||
| Input: an ATT rocprofv3 UI dispatch dir (has code.json + se*_wv*.json). Pick the | ||
| steady-state cycle window with --range (avoid prologue/tail). | ||
|
|
||
| Usage: | ||
| python3 mfma_coverage.py <dispatch_dir> [--wave se0_sm0_sl0_wv0.json] | ||
| [--range LO,HI] [--exec 16] | ||
|
|
||
| # find a steady window first (cycles): the script prints the wave cycle span; | ||
| # pick a mid slice spanning ~10 outer loop iterations. | ||
|
|
||
| Notes: | ||
| - EXEC is the MFMA execute latency, NOT the issue latency. fp4 | ||
| mfma_scale_f32_16x16x128 ~ 16; fp8 16x16x128 ~ 32. Pass --exec accordingly. | ||
| - "idle" gaps = pure latency stalls (waitcnt drain / dependency) with no issuing | ||
| instruction; real wins come from cutting the named-instruction gaps. | ||
| """ | ||
| import argparse | ||
| import collections | ||
| import glob | ||
| import json | ||
| import os | ||
| import sys | ||
|
|
||
|
|
||
| def load(dispatch_dir, wave): | ||
| code = json.load(open(os.path.join(dispatch_dir, "code.json")))["code"] | ||
| if wave: | ||
| wpath = os.path.join(dispatch_dir, wave) | ||
| else: | ||
| cands = sorted(glob.glob(os.path.join(dispatch_dir, "se*_wv0.json"))) | ||
| wpath = cands[0] | ||
| wj = json.load(open(wpath)) | ||
| return code, wj["wave"]["instructions"], os.path.basename(wpath) | ||
|
|
||
|
|
||
| def op_of(code, cid): | ||
| a = code[cid][0].strip().split() if cid < len(code) else ["?"] | ||
| return a[0] if a else "?" | ||
|
|
||
|
|
||
| def main(): | ||
| ap = argparse.ArgumentParser() | ||
| ap.add_argument("dispatch_dir") | ||
| ap.add_argument("--wave", default=None) | ||
| ap.add_argument("--range", default=None, help="LO,HI cycle window (steady state)") | ||
| ap.add_argument("--exec", type=int, default=16, dest="exec_cyc", help="MFMA execute latency") | ||
| args = ap.parse_args() | ||
|
|
||
| code, insts, wname = load(args.dispatch_dir, args.wave) | ||
| cyc = [r[0] for r in insts] | ||
| print(f"wave={wname} inst cycle span {min(cyc)}..{max(cyc)} n={len(insts)}") | ||
| if not args.range: | ||
| print("pass --range LO,HI (a mid steady slice, ~10 outer iters). e.g. " | ||
| f"--range {min(cyc) + (max(cyc)-min(cyc))//4},{min(cyc) + (max(cyc)-min(cyc))//2}") | ||
| return | ||
| lo, hi = (int(x) for x in args.range.split(",")) | ||
| seg = sorted((r for r in insts if lo <= r[0] < hi), key=lambda r: r[0]) | ||
| span = hi - lo | ||
|
|
||
| E = args.exec_cyc | ||
| mfma = sorted(r[0] for r in seg if op_of(code, r[4]).startswith("v_mfma")) | ||
| if not mfma: | ||
| print("no MFMA in window") | ||
| return | ||
|
|
||
| # next_free model (matrix-unit pipeline): each MFMA occupies ONE E-cycle execute | ||
| # slot, but slots pipeline -- consecutive MFMAs can ISSUE < E apart and still both | ||
| # be hidden (the unit stays busy). Track next_free = when the matrix unit frees. | ||
| # - issue t <= next_free : hidden (co-issued in the shadow); slot advances +E | ||
| # - issue t > next_free : the unit was IDLE for (t - next_free) -> EXPOSED | ||
| # This fixes the older union-of-[issue,issue+E) model, which capped overlapping | ||
| # windows and so mislabeled shadow-hidden loads (dense 8-cyc-apart MFMAs) as | ||
| # exposed. Blame each exposed gap on the first non-MFMA op issuing inside it. | ||
| next_free = mfma[0] | ||
| gaps = [] | ||
| for t in mfma: | ||
| if t > next_free: | ||
| gaps.append((next_free, t)) | ||
| next_free = t + E | ||
| else: | ||
| next_free = next_free + E | ||
| exp = sum(b - a for a, b in gaps) | ||
| cov = span - exp | ||
| print(f"\nsegment [{lo},{hi}) span={span} mfma={len(mfma)} exec={E}") | ||
| print(f"MFMA-covered: {cov} ({cov*100//span}%) EXPOSED: {exp} ({exp*100//span}%)") | ||
| print(f"cyc/mfma = {span/len(mfma):.2f} (floor = {E})") | ||
|
|
||
| # OCCUPANCY attribution: for every EXPOSED cycle (matrix unit idle), credit it to | ||
| # whatever instruction was occupying the issue port then. Each non-MFMA instruction | ||
| # occupies [its issue, next instruction's issue) -- i.e. its issue_dur PLUS any | ||
| # stall (r[2]); we do NOT separate issue vs stall, we just ask "while the matrix | ||
| # unit sat idle, which op was on the port?". Intersect each op's occupancy span | ||
| # with the next_free idle gaps and sum. This tiles the whole EXPOSED window with no | ||
| # gaps (every idle cycle has an owner), so the ranking directly says: to push | ||
| # cyc/mfma toward the floor, which non-MFMA ops must be REMOVED / SHRUNK from | ||
| # between the MFMAs. (Stall-vs-issue and who-"blocks" views were dropped -- what | ||
| # matters for MFMA-bound speedup is total occupancy stealing issue bandwidth.) | ||
| # Row = [cycle, issue_dur, stall, total_dur, code_id]. | ||
| def label(cid): | ||
| t = code[cid][0].strip() if cid < len(code) else "?" | ||
| o = op_of(code, cid) | ||
| if o == "s_waitcnt": | ||
| v, l = "vmcnt" in t, "lgkmcnt" in t | ||
| return "s_waitcnt(vm+lgkm)" if v and l else "s_waitcnt(vmcnt)" if v else \ | ||
| "s_waitcnt(lgkmcnt)" if l else "s_waitcnt" | ||
| return o | ||
|
|
||
| def gap_overlap(a, b): | ||
| tot = 0 | ||
| for g0, g1 in gaps: | ||
| if g1 <= a or g0 >= b: | ||
| continue | ||
| tot += min(g1, b) - max(g0, a) | ||
| return tot | ||
|
|
||
| ni = [r for r in seg if not op_of(code, r[4]).startswith("v_mfma")] | ||
| ni.sort(key=lambda r: r[0]) | ||
| occ = collections.Counter() | ||
| for i, r in enumerate(ni): | ||
| nxt = ni[i + 1][0] if i + 1 < len(ni) else hi | ||
| c = gap_overlap(r[0], nxt) | ||
| if c: | ||
| occ[label(r[4])] += c | ||
| total = exp or 1 | ||
| print(f"\n== EXPOSED {exp} cyc ({exp*100/span:.1f}% of全局) by occupying instruction ==") | ||
| print(f" {'cyc':>6} {'%exp':>5} {'%all':>5} op") | ||
| for o, c in occ.most_common(18): | ||
| print(f" {c:>6} {c*100//total:>4d}% {c*100/span:>4.1f}% {o}") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
???
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to remove the Chinese words, this skill can print how many mfma cycles cost in the hot loops. And how many instrcutions we can optimize to (co-issue/hide the latency between the mfma istructions).
For this kernels. It costs about 18.06 cycles/mfma, while the lower bound is 16 cycles. Pretty close.
However, one drawback is that it can't optimize frequency reduction/optimize the power.