Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
122 commits
Select commit Hold shift + click to select a range
a5fc67f
zz
benenzhu Jun 4, 2026
6d989eb
zz
benenzhu Jun 6, 2026
ad15b44
zz
benenzhu Jun 7, 2026
177a74e
zz
benenzhu Jun 7, 2026
8e73213
zz
benenzhu Jun 7, 2026
4c583c8
zz
benenzhu Jun 8, 2026
b510918
zz
benenzhu Jun 8, 2026
b115edf
Add runnable Kimi mxfp4 16384 FlyDSL path
benenzhu Jun 9, 2026
7671649
Relax Kimi mxfp4 GEMM1 pre-barrier wait
benenzhu Jun 9, 2026
40aaeb3
Checkpoint runnable Kimi mxfp4 FlyDSL GEMM1
benenzhu Jun 9, 2026
6ff8329
Pipeline Kimi mxfp4 GEMM1 LDS loads
benenzhu Jun 9, 2026
c4a9fbf
Checkpoint runnable Kimi mxfp4 GEMM1 optimization
benenzhu Jun 9, 2026
1af39d1
Optimize Kimi mxfp4 GEMM1 scheduling
benenzhu Jun 9, 2026
eac281a
Document Kimi GEMM1 resource audit
benenzhu Jun 9, 2026
9a5b943
Tune Kimi GEMM1 epilogue max lowering
benenzhu Jun 9, 2026
a471ed4
Optimize Kimi mxfp4 FlyDSL GEMM2
benenzhu Jun 9, 2026
a091cb4
Optimize Kimi MXFP4 scatter reduce
benenzhu Jun 9, 2026
e83e61b
Optimize Kimi MXFP4 sort cumsum
benenzhu Jun 9, 2026
b898759
Profile Kimi MXFP4 under graph replay by default
benenzhu Jun 9, 2026
9882c62
Stabilize Kimi MXFP4 graph profiling
benenzhu Jun 9, 2026
e9a76f0
Align Kimi sort place and scatter kernels
benenzhu Jun 9, 2026
75045f9
Tune Kimi sort placement loop
benenzhu Jun 9, 2026
cb53288
Record rejected Kimi sort padding loop
benenzhu Jun 9, 2026
5e38bf8
Align Kimi sort place padding path
benenzhu Jun 9, 2026
a94e936
Align Kimi mxfp4 GEMM1 AGPR path
benenzhu Jun 9, 2026
af6e440
zz
benenzhu Jun 9, 2026
e0926a9
Add FlyDSL Kimi BM16 mxfp4 small path
benenzhu Jun 9, 2026
8e08047
Optimize Kimi BM16 mxfp4 FlyDSL pipeline
benenzhu Jun 9, 2026
15c83c9
Align Kimi BM16 inline quant schedule
benenzhu Jun 9, 2026
e397730
Increase small-M benchmark graph sampling
benenzhu Jun 9, 2026
41928f0
Add Kimi BM16 stage benchmark
benenzhu Jun 9, 2026
4809143
Document Kimi BM16 profiling follow-ups
benenzhu Jun 9, 2026
50d80b0
Align Kimi BM16 GEMM1 epilogue
benenzhu Jun 9, 2026
35b9849
Align Kimi BM16 GEMM2 A LDS load
benenzhu Jun 9, 2026
3f925bb
Tune Kimi BM16 profiling and atomics
benenzhu Jun 9, 2026
233a9b1
Stabilize BM16 graph profiling defaults
benenzhu Jun 9, 2026
c61b4a9
Document BM16 sort DPP scan trials
benenzhu Jun 9, 2026
16ca792
Increase BM16 graph measurement stability
benenzhu Jun 9, 2026
e2fb3dd
Stabilize BM16 measurements and GEMM1 epilogue
benenzhu Jun 9, 2026
1d2afab
Use bounded BM16 graph profiler window
benenzhu Jun 9, 2026
3834bc3
Increase graph benchmark sampling
benenzhu Jun 9, 2026
7d790e7
Hoist BM16 GEMM1 A LDS reads
benenzhu Jun 9, 2026
2cd67f0
Document rejected BM16 GEMM1 wait trial
benenzhu Jun 9, 2026
fd2df0a
Increase benchmark sampling defaults
benenzhu Jun 9, 2026
318e6a7
Document rejected BM16 scheduling trials
benenzhu Jun 10, 2026
9f2af55
Tune benchmark sampling for BM16 profiling
benenzhu Jun 10, 2026
7e18f44
Document rejected BM16 sort prefix trial
benenzhu Jun 10, 2026
3b7bbaf
Document rejected BM16 GEMM2 split barrier trial
benenzhu Jun 10, 2026
6b31b07
Document rejected BM16 GEMM2 schedule barrier trial
benenzhu Jun 10, 2026
157b899
Align BM16 GEMM2 scale loads
benenzhu Jun 10, 2026
9668463
Align BM16 GEMM1 scale loads
benenzhu Jun 10, 2026
e7a0d98
Declare BM16 GEMM1 block size
benenzhu Jun 10, 2026
53f3525
zz
benenzhu Jun 10, 2026
ea30a49
zz
benenzhu Jun 10, 2026
0dc34ca
slower but not mlir
benenzhu Jun 10, 2026
322b80f
slower but not mlir
benenzhu Jun 10, 2026
1a0f8a4
zz
benenzhu Jun 11, 2026
0b3bd15
zz
benenzhu Jun 11, 2026
a7971ae
slower but not mlir
benenzhu Jun 15, 2026
ed93804
Optimize hgemm tail prefetch scheduling
benenzhu Jun 16, 2026
3518e5b
Document wave0 hgemm first ops
benenzhu Jun 16, 2026
bf7611e
Format wave0 hgemm ops list
benenzhu Jun 16, 2026
e701d3b
Document full wave0 hgemm schedule
benenzhu Jun 16, 2026
63ed364
zz
benenzhu Jun 16, 2026
c3aeb87
Add K32 register-prefetch pipeline to bf16 hgemm (+22%: 837->1025 TFL…
benenzhu Jun 17, 2026
6f21eb0
Interleave RP1 ds_reads via full-K0 register carry (+3%: 1025->1051 T…
benenzhu Jun 17, 2026
4916942
Interleave RP1 bfld prefetch into MFMA shadows (+6%: 1051->1113 TFLOPS)
benenzhu Jun 17, 2026
28825ca
Add bf16 hgemm RP1 final ISA snapshot (1117 TFLOPS, 8192x8192x16384)
benenzhu Jun 17, 2026
ed9d509
Add cleaned (pure) ISA of bf16 hgemm RP1 1117 TFLOPS kernel
benenzhu Jun 17, 2026
a561252
Add hotloop-table skill + bf16 hgemm RP1 hot-loop table
benenzhu Jun 17, 2026
6b3e67d
Tighten RP1 tail vmcnt to provably-safe bound (LDG_WAIT_COUNT//2)
benenzhu Jun 18, 2026
3fbb4cb
Make both RP1 half barriers carry vmcnt(8) + lgkmcnt(0) for provable …
benenzhu Jun 18, 2026
8c65b64
Add A/B coarse preshuffle ([256,BLOCK_K] tiles contiguous) to bf16 hgemm
benenzhu Jun 18, 2026
9987b5c
Add pure ISA + hotloop table for preshuffle bf16 hgemm (~1313 TFLOPS)
benenzhu Jun 18, 2026
9a17cd5
Split preshuffle global-address math into invariant + k-stepped term …
benenzhu Jun 18, 2026
2e5ffdd
Add optional XCD-swizzle CTA remap (off by default; L2 up but perf ne…
benenzhu Jun 18, 2026
9ff9796
Delay first-half bfld drip by one MFMA row (-80% buffer_load issue st…
benenzhu Jun 18, 2026
12a18d9
Add bufferload-cycle-table skill (per-tile buffer_load gap/stall comp…
benenzhu Jun 18, 2026
676aecc
Drop sc0 (glc) from read-only A/B buffer_load_lds
benenzhu Jun 18, 2026
76d94d4
Add pure ISA + hotloop table for bf16 hgemm RP1 (preshuffle, no-sc0)
benenzhu Jun 18, 2026
1cbcd5e
Add fp8_gemm_4wave pure ISA (8192x8192x16384, ~2973 TFLOPS)
benenzhu Jun 18, 2026
a847939
Ride K-step on scalar soffset in preshuffle buffer_load (share vaddr …
benenzhu Jun 18, 2026
6b0901d
Fix preshuffle cache-line alignment: K32 sub-group as outer K axis (+…
benenzhu Jun 18, 2026
6458b91
Add fp8_gemm_4wave_opt: pin MFMA accumulator in AGPR (+8%: 2982->3226…
benenzhu Jun 19, 2026
829de46
fp8_opt: relax main-loop barrier vmcnt 16->32 (~+0.4%, 3226->~3240 TF…
benenzhu Jun 21, 2026
24c1424
slower but not mlir
benenzhu Jun 22, 2026
9bc116a
fp8_gemm_4wave: pin MFMA accumulator in AGPR (+5~13% across medium-la…
benenzhu Jun 22, 2026
a99e43a
Merge branch 'zty_fp8_4wave_opt_pr' into zty_dev_moe
benenzhu Jun 25, 2026
9222112
fp4_gemm_4wave: 4-wave MXFP4 GEMM (cos 0.999999, ~2455 TFLOPS @ 8192^3)
benenzhu Jun 25, 2026
1b7db95
fp4_gemm_4wave: pin MFMA accumulator in AGPR via inline asm (+58%, 24…
benenzhu Jun 25, 2026
6781e55
fp4_gemm_4wave: depth-1 scale prefetch -> 4109 TFLOPS (beats 4071 bas…
benenzhu Jun 25, 2026
ea98e29
fp4_gemm_4wave: interleave ds_read/buffer_load into MFMA shadow -> 43…
benenzhu Jun 25, 2026
644c229
fp4_gemm_4wave: roll K-loop into scf.for unroll-2 (fix icache overflo…
benenzhu Jun 25, 2026
8a9cf5b
fp4_gemm_4wave: add mn_aligned epilogue fast-path (skip per-store bou…
benenzhu Jun 25, 2026
9ceee2d
gitignore: exclude scratch experiments, handoff notes, and snapshot WIP
benenzhu Jun 26, 2026
fe6acc5
Merge remote-tracking branch 'origin/main' into zty_dev_moe
benenzhu Jun 26, 2026
a006b20
fp4_gemm_4wave: cut arch VGPR 252->220 via single-symbol LDS + inline…
benenzhu Jun 29, 2026
ed17e7b
fp4_gemm_4wave: scale load via inline-asm buffer_load, fix vmcnt acco…
benenzhu Jun 29, 2026
5859f7f
fp4_gemm_4wave: depth-2 end-of-step scale prefetch -> vmcnt(16), 4281…
benenzhu Jun 29, 2026
3d9c3ff
fp4_gemm_4wave: interleave the two tail steps' ds_reads into MFMA shadow
benenzhu Jun 29, 2026
6788c9e
fp4_gemm_4wave: m0 set-once + s_add increment for g2s (gcnasm async-c…
benenzhu Jun 29, 2026
9395ee3
have error learning now
benenzhu Jun 30, 2026
15575f3
zty_tmp
benenzhu Jul 1, 2026
467e700
fp4_gemm_4wave: scale via dwordx4-lds gather, fix prologue vmcnt orde…
benenzhu Jul 1, 2026
0e37270
fp4_gemm_4wave: co-issue scale gather in MFMA shadow
benenzhu Jul 1, 2026
f89d596
fp4_gemm_4wave: hide scale half-1 ds_read in MFMA shadow
benenzhu Jul 1, 2026
594d4cc
fp4_gemm_4wave: VGPR-carry scale (depth-3) + strided MFMA interleave
benenzhu Jul 3, 2026
9e21f0e
fp4_gemm_4wave: precompute scale-gather m0 base, drop per-gather read…
benenzhu Jul 3, 2026
62dca41
mfma-coverage skill: switch to next_free pipeline exposure model
benenzhu Jul 3, 2026
2cd4910
mfma-coverage skill: rank blockers by authoritative stall field, not …
benenzhu Jul 3, 2026
eee276e
mfma-coverage skill: exposed = stall field intersected with idle gaps…
benenzhu Jul 3, 2026
df9f154
mfma-coverage skill: occupancy-only attribution with %exp + %all columns
benenzhu Jul 3, 2026
9b091b4
fp4_gemm_4wave: precompute g2s m0 base, drop per-load readfirstlane
benenzhu Jul 3, 2026
2be5eb5
Merge remote-tracking branch 'upstream/main' into zty_dev_moe
benenzhu Jul 3, 2026
79d9c86
fp4_gemm_4wave: restore clean identifier names (drop __N value-annota…
benenzhu Jul 3, 2026
170b1f2
add
benenzhu Jul 3, 2026
b32cbdc
add
benenzhu Jul 3, 2026
326b2c3
zty_tmp
benenzhu Jul 3, 2026
112d21c
zty_tmp
benenzhu Jul 3, 2026
88d5323
delete skills
benenzhu Jul 6, 2026
b296d89
Update SKILL.md
benenzhu Jul 6, 2026
17d2740
Merge branch 'main' into 4wave_fp4_gemm_opt
benenzhu Jul 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .claude/skills/4wave-mfma-coverage-analysis/SKILL.md
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.
---

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.

???

Copy link
Copy Markdown
Contributor Author

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.


# 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 .claude/skills/4wave-mfma-coverage-analysis/scripts/mfma_coverage.py
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()
Loading