Per-layer staged-image engine for the eleven translated denoiser Swin layers: descriptors (verified offsets per phase), cut recipes that splice an isolated native phase into NVIDIA's PTX, wave templates, epilogue notes and GPU probes. The isolated phase-8 splice produces a byte-identical final 4K frame but is slower than the translated body (14.90 vs 6.59 ms) - a correctness experiment, not a shipping improvement; docs/rr-engine.md records the design and the next direct-converter win (B operands built from transposed accumulators).
917 lines
46 KiB
Markdown
917 lines
46 KiB
Markdown
# `cuda_dldn_engine_swin_dec2_kernel` — the epilogues of phases 1…38
|
||
|
||
Companion to `kernels/rr/rr_layer_spec.py dec2`. Everything below was read out of
|
||
`~/.cache/d4r-rr-corpus/0021-PREPASS_ENTRYPOINT_NAME.ptx`, entry
|
||
`cuda_dldn_engine_swin_dec2_kernel` (15796 statements).
|
||
|
||
## 0. Conventions
|
||
|
||
* **`sNNNN` is a statement index** in the linearisation `rr_layer_spec.py`
|
||
documents (statements of the entry body; a wrapped `{ … }` block and a 4-line
|
||
`mma.sync` count as one statement, numbered at their first line). **`LNNNNN`
|
||
is the physical line** of the same instruction in the corpus file, so every
|
||
claim can be checked with `sed -n 'LNNNNN,LNNNNN p' …ptx`.
|
||
* An **epilogue** is the run of statements between one phase's last `mma` and
|
||
the next phase's first `mma`. Because phase 1 is the first GEMM, the prologue
|
||
(s1–s451) doubles as phase 1's prelude and is described here too.
|
||
* `W` denotes the prepared weight image: `ld.param.u64 %rd1,
|
||
[cuda_dldn_engine_swin_dec2_kernel_param_0+40]` (s7, `L1035`) and
|
||
`cvta.to.global.u64 %rd32, %rd1` (s8, `L1036`). Every
|
||
`ld.weak.global.ca.v4.u32` reads `W + 16*laneid + imm`.
|
||
* The C/D register layout and the weight-addressing formula are fixed (see the
|
||
settled notes): `C/D reg0 = (row g, cols 2t,2t+1)`, `reg1 = (row g+8, same
|
||
cols)`, `g = laneid>>2`, `t = laneid&3`.
|
||
* Anything I could not pin down from the PTX is in §7 under **uncharacterised**.
|
||
|
||
## 1. Shared vocabulary
|
||
|
||
### 1.1 Addresses and parameters an epilogue touches
|
||
|
||
| symbol | how it is obtained | statements |
|
||
|---|---|---|
|
||
| `param_0` | `mov.b64 %rd7, …_param_0` | s1, L1018 |
|
||
| `W` (weight image) | `ld.param.u64 %rd1, [param_0+40]` → `cvta… %rd32, %rd1` | s7/s8, L1035–L1036 |
|
||
| extents `(ex, ey)` | `ld.param.v2.u32 {%r2147, %r2148}, [param_0+0]` | s13, L1041 |
|
||
| `%r7 = 8·ex`, `%r8 = ey·8·ex` | `shl.b32 %r7, %r2147, 3` / `mul.lo.s32 %r8, %r2148, %r7` | s14/s15, L1042–L1043 |
|
||
| block origins `%r1`, `%r2` | `sub.s32 %r1, %r2142, %r2143` / `sub.s32 %r2, %r2146, %r2144` | s6/s12, L1034/L1040 |
|
||
| `%rd33` = `param_0+8` | `ld.param.u64 %rd33, [param_0+8]` | s28, L1056 |
|
||
| **texture / skip input** | `ld.param.u64 %rd2, [%rd7+24]` = `param_0+24` | s2288, L4638 |
|
||
| **output plane arena** | `ld.param.u64 %rd571, [%rd7+48]` = `param_0+48` → `cvta… %rd4, %rd571` | s15333/s15334, L36645–L36646 |
|
||
| block-origin table | `ld.param.v2.u16 {%rs264, %rs265}, [param_0+80]` | s4, L1032 |
|
||
| window index `tid.z` | `mov.u32 %r2350, %tid.z` | s378, L1408 |
|
||
| shared arena | `.shared .align 4 .b8 _ZZ33…dec2_kernel…E4smem[9600]` | L1027 (declaration; not a statement) |
|
||
| per-lane weight address | `mul.wide.u32 %rd, %laneid, 16` + `add.s64 %rd, W, %rd` | every load block, e.g. s11444–s11445, L24247–L24248 |
|
||
| per-lane *table* address | `shl.b32 %r, %laneid, 2` → `cvt.u64.u32` → `and.b64 %rd, %r, 12` → `add.s64 %rd, %rd32, %rd` = `W + ((laneid·4)&12)` | e.g. s12456–s12460, L27063–L27068 |
|
||
|
||
The last row matters: the `ld.global.v2.u16` / `ld.global.u32` table loads in an
|
||
epilogue read `W + ((laneid<<2)&12) + off`, i.e. **the same 16-byte slot is read
|
||
by the four lanes with equal `laneid&3`, and consecutive loads pick consecutive
|
||
4-byte words inside one 64-byte record** — so those tables are indexed by
|
||
column, not by row.
|
||
|
||
Two per-`tid.z` strides exist, both in phase 1's prelude and nowhere else:
|
||
|
||
| group | base | statements |
|
||
|---|---|---|
|
||
| phase 1's B | `W + 12288·tid.z + 16·laneid` | s379–s384, L1409–L1416 |
|
||
| phase 1's C bias | `W + 192·tid.z + ((laneid·4)&12) + 49152…49328` | s432–s439, L1512–L1521 |
|
||
|
||
`%r2350·12288` (s379) is the only `×12288` in the file and `%r2350·96 → ×2`
|
||
(s432/s433) the only `×192`, so no other phase's loads carry a window term.
|
||
|
||
### 1.2 Constants that survive between epilogues
|
||
|
||
| register | first definition | f32/f64 literal | value used (after the `cvt` to f16) |
|
||
|---|---|---|---|
|
||
| `%f476` | s7488 `mov.f32 %f476, 0f3C8CCB50` | 0.017186790704727173 | f16 `0x2466` = 0.017181396484375 |
|
||
| `%fd383` | s7492 `mov.f64 %fd383, 0dBFE1CC0000000000` | −0.55615234375 | f16 `0xB873` |
|
||
| `%fd385` | s7497 `mov.f64 %fd385, 0d3FE1CC0000000000` | +0.55615234375 | f16 `0x3873` |
|
||
| `%f478` | s7503 `mov.f32 %f478, 0f3F6D6000` | 0.92724609375 | f16 `0x3B6B` |
|
||
| `%f480` | s7508 `mov.f32 %f480, 0f3FB00000` | 1.375 | f16 `0x3D80` |
|
||
| `%fd1` | s6132 `mov.f64 %fd1, 0d3F20000000000000` | 2⁻¹³ | f16 `0x0800` = 0.0001220703125 |
|
||
| `%f861` | s12301 `mov.f32 %f861, 0f3ED306EB` | 0.4121621549129486 | f16 `0x3698` = 0.412109375 |
|
||
| `%f862` | s12304 `mov.f32 %f862, 0f3DA60DD6` | 0.0810810774564743 | f16 `0x2D30` = 0.0810546875 |
|
||
| `%f863` | s12307 `mov.f32 %f863, 0f3F000000` | 0.5 | f16 `0x3800` |
|
||
| `%f864` | s12310 `mov.f32 %f864, 0f40000000` | 2.0 | f16 `0x4000` |
|
||
|
||
`%f861…%f864` are materialised **inside E14** (s12301–s12312) and only re-`cvt`
|
||
by E16, E18, E20, …, E36 (`s12642 cvt.rn.f16.f32 low, %f861`, …). `%fd1` is
|
||
defined once, in E1 (s6132), and only re-`cvt` by E13.
|
||
|
||
Also live across the region, as in the sibling kernel: `%r5908 = 1`
|
||
(s5595, `L8140`) and `%r5919 = -1` (s6074, `L9586`) supply the butterfly delta
|
||
and the membermask of every `shfl.sync.bfly.b32` in the epilogues
|
||
(`s6075 shfl.sync.bfly.b32 %r5842,%r5838,%r5908,%r5845,%r5919`); the
|
||
group/width operand is per-instruction.
|
||
|
||
### 1.3 Two quantisation helpers
|
||
|
||
* `cvt.rn.satfinite.e4m3x2.f16x2` — the requantisation used everywhere
|
||
(`f16x2_to_e4m3x2_satfinite_bits` in `ptx/lib/zluda_ptx_impl.cpp`).
|
||
* `cvt.rn.f16x2.e4m3x2` — its inverse, the *unpack*, used only when a shared
|
||
tile that was stored e4m3-packed is read back (E1: 96 of them, s5594–s5690,
|
||
L8139–L8437).
|
||
* `rcp.approx.ftz.f32`, `rsqrt.approx.ftz.f32`, `ex2.approx.ftz.f32`,
|
||
`div.approx.ftz.f32` — always wrapped as
|
||
`cvt.f32.f16 → op → cvt.rn.f16.f32` (round each step through f16).
|
||
|
||
## 2. Summary
|
||
|
||
| epilogue | range | stmts | named operation |
|
||
|---|---|---|---|
|
||
| E1 | s596–s7088 | 6493 | patch expand into shared + per-column RMS norm + gain + restage |
|
||
| E2 | s7113–s7119 | 7 | next-B weight loads (P3) |
|
||
| E3 | s7144–s7150 | 7 | next-B weight loads (P4) |
|
||
| E4 | s7175–s7181 | 7 | next-B weight loads (P5) |
|
||
| E5 | s7206–s7212 | 7 | next-B weight loads (P6) |
|
||
| E6 | s7237–s7243 | 7 | next-B weight loads (P7) |
|
||
| E7 | s7268–s7438 | 171 | score-bias C-seed loads (24×512 B) + 80 packs → P8's A and B |
|
||
| E8 | s7487–s11329 | 3843 | cubic-exponent softmax, V transpose, pack |
|
||
| E9 | s11378–s11546 | 169 | pack P9's D → shared, per-column table → P10's C, next B |
|
||
| E10 | s11559–s11577 | 19 | 1 shared A fragment + 6 next-B loads (P11) |
|
||
| E11 | s11590–s11608 | 19 | 1 shared A fragment + 6 next-B loads (P12) |
|
||
| E12 | s11621–s11639 | 19 | 1 shared A fragment + 6 next-B loads (P13) |
|
||
| E13 | s11652–s12287 | 636 | RMS norm of P13's D + gain, packs → P14's A and P16's A, next B/C |
|
||
| E14 | s12300–s12556 | 257 | clamped-cubic activation of P14's D, per-column table + residual → P15's C |
|
||
| E15 | s12569–s12628 | 60 | 24 packs → P16's A, next B, P16's C bias |
|
||
| E16 | s12641–s12804 | 164 | clamped-cubic activation of P16's D → P17's A, next B |
|
||
| E17 | s12817–s12876 | 60 | 24 packs → P18's A, next B, P18's C bias |
|
||
| E18 | s12889–s13052 | 164 | activation of P18's D → P19's A, next B |
|
||
| E19 | s13065–s13124 | 60 | 24 packs → P20's A, next B, P20's C bias |
|
||
| E20 | s13137–s13300 | 164 | activation of P20's D → P21's A, next B |
|
||
| E21 | s13313–s13372 | 60 | 24 packs → P22's A, next B, P22's C bias |
|
||
| E22 | s13385–s13548 | 164 | activation of P22's D → P23's A, next B |
|
||
| E23 | s13561–s13620 | 60 | 24 packs → P24's A, next B, P24's C bias |
|
||
| E24 | s13633–s13796 | 164 | activation of P24's D → P25's A, next B |
|
||
| E25 | s13809–s13868 | 60 | 24 packs → P26's A, next B, P26's C bias |
|
||
| E26 | s13881–s14044 | 164 | activation of P26's D → P27's A, next B |
|
||
| E27 | s14057–s14116 | 60 | 24 packs → P28's A, next B, P28's C bias |
|
||
| E28 | s14129–s14292 | 164 | activation of P28's D → P29's A, next B |
|
||
| E29 | s14305–s14364 | 60 | 24 packs → P30's A, next B, P30's C bias |
|
||
| E30 | s14377–s14540 | 164 | activation of P30's D → P31's A, next B |
|
||
| E31 | s14553–s14612 | 60 | 24 packs → P32's A, next B, P32's C bias |
|
||
| E32 | s14625–s14788 | 164 | activation of P32's D → P33's A, next B |
|
||
| E33 | s14801–s14860 | 60 | 24 packs → P34's A, next B, P34's C bias |
|
||
| E34 | s14873–s15036 | 164 | activation of P34's D → P35's A, next B |
|
||
| E35 | s15049–s15108 | 60 | 24 packs → P36's A, next B, P36's C bias |
|
||
| E36 | s15121–s15284 | 164 | activation of P36's D → P37's A, next B |
|
||
| E37 | s15297–s15504 | 208 | pack → 12 guarded plane-arena scatter → B/C for P38 |
|
||
| E38 | s15511–s15796 | 286 | 4 D stores → shared, row max, softmax, 9+2 texture reads, surface store |
|
||
|
||
---
|
||
|
||
## 3. The epilogues
|
||
|
||
### E1 — s596–s7088: patch expand, RMS norm, gain, restage
|
||
|
||
6493 statements; op histogram (top): 1103 `add.s32`, 477 `shl.b32`, 446
|
||
`mov.b32`, 413 `$label`, 409 `sub.s32`, 355 `min.u32`, 288 `mul.f16`, 120
|
||
`cvt.rn.satfinite.e4m3x2.f16x2`, 96 `cvt.rn.f16x2.e4m3x2`, 96
|
||
`rsqrt.approx.ftz.f32`, 42 `st.shared.*` (34 `u32` + 2 `v2.u16` + 6 `v4.u32`),
|
||
42 `ld.shared.*` (24 `v2.u16` + 18 `v4.u32`), 36 `ld.global.v2.u16`, 8
|
||
`shfl.sync.bfly.b32`, 1 `ld.param`, 2 `ld.weak…`.
|
||
|
||
Sub-sections (bounded by the first/last statement of each op):
|
||
|
||
| range | what |
|
||
|---|---|
|
||
| s596–s702 | the head packs of phase 1's D (72 `cvt.rn.satfinite…`), → `%r9…%r41` |
|
||
| s716–s1478 | per-lane index arithmetic + the 36 guarded patch stores (34 `st.shared.u32` s770–s1460 + 2 `st.shared.v2.u16` s743/s1478); 1st `bar.sync` at s1480 |
|
||
| s1524–s2287 | 24 `ld.shared.v2.u16` read back of the packed patch |
|
||
| s2288 | `ld.param.u64 %rd2, [%rd7+24]`: **the patch-gather buffer** |
|
||
| s2444–s5593 | 24 clamped `ld.global.v2.u16` gathered from that buffer |
|
||
| s5594–s5690 | 96 `cvt.rn.f16x2.e4m3x2` unpacks of the read-back patch |
|
||
| s5693–s6276 | the sum trees (196 `add.f16` exact + 52 `add.f16x2`) |
|
||
| s6132 | the 2⁻¹³ constant `%fd1` (s6132 `mov.f64 %fd1, 0d3F20000000000000`) |
|
||
| s6075–s6128 | the 8 `shfl.sync.bfly.b32` (first at s6075) |
|
||
| s6282–s6659 | 96 `rsqrt.approx.ftz.f32`, each `cvt.f32.f16 → rsqrt → cvt.rn.f16.f32` |
|
||
| s6668–s6679 | **gain loads** `W + ((laneid·4)&12) + {49920…50096}` (12 `ld.global.v2.u16`) |
|
||
| s5693–s6966 | the 288 `mul.f16` (two groups: `inv · gain` then `x · (inv·gain)`) |
|
||
| s7008–s7054 | 24 packs → the 6 `st.shared.v4.u32` at s7008/7021/7034/7044/7049/7054 |
|
||
| s7059–s7082 | `bar.sync` (s7059) + 18 `ld.shared.v4.u32` (s7064–s7082) → phases 2…7's A |
|
||
| s7083–s7088 | 2 `ld.weak` (s7086/s7088) → **phase 2's B** |
|
||
|
||
Evidence for the patch scatter (36 stores):
|
||
|
||
```
|
||
s743 L2836: st.shared.v2.u16 [%r2373], {%rs192, %rs193}
|
||
s770 L2865: st.shared.u32 [%r2386], %r9
|
||
s800 L2897: st.shared.u32 [%r2403], %r10
|
||
s1478 L3641: st.shared.v2.u16 [%r2787], {%rs262, %rs263}
|
||
s7008 L11717: st.shared.v4.u32 [%r6091], {%r6095, %r6094, %r6093, %r6092}
|
||
s7044 L11788: st.shared.v4.u32 [%r6110+6144], {%r6114, %r6113, %r6112, %r6111}
|
||
s7054 L11798: st.shared.v4.u32 [%r6110+7168], {%r6122, %r6121, %r6120, %r6119}
|
||
```
|
||
|
||
Each patch store is guarded exactly as in the sibling kernel
|
||
(`setp.gt.u32 %p…, %r…, 9` / `or.pred` / `@%p bra …`; the same
|
||
`(row·40 + col·8 + t)·4` index form — cf. `rrswin_dec1_epilogues.md` §3/E1,
|
||
which carries the same 400-block emitter). The second staging area is at
|
||
`[%r6091]`, `[%r6091+512]`, `[%r6091+1024]`, `[%r6110+6144]`,
|
||
`[%r6110+6656]`, `[%r6110+7168]`, where `%r6091 = smem + tid.z·2048`
|
||
(s6994 `shl.b32 … %r2350, 11`) and `%r6110 = smem + tid.z·3072` (s7040).
|
||
|
||
The norm:
|
||
|
||
```
|
||
s6132 L9664: mov.f64 %fd1, 0d3F20000000000000 // 2^-13
|
||
s5693 L8430: add.f16 %rs456,%rs457,%rs458
|
||
s6282 L10110: rsqrt.approx.ftz.f32 fl, fl
|
||
s6668 L10735: ld.global.v2.u16 {%rs1959, %rs1960}, [%rd247+49936]
|
||
s6681 L10749: mul.f16 %rs…, %rs…, %rs… // inv * gain
|
||
```
|
||
|
||
**There is no mean subtraction and no `1/N`.** The accumulated quantity is the
|
||
raw sum of squares of the 3 patch channels plus the constant 2⁻¹³, and the norm
|
||
is applied per *column* (the gain is read at `W + ((laneid<<2)&12) + off`, so it
|
||
is constant across rows).
|
||
|
||
**Inputs:** phase 1's D (`%r593…%r826`, 12 fragments — phase 1 has `nA = 12`),
|
||
`W`, `param_0+8`, `param_0+24`, `%r1/%r2/%r7/%r8/%r2147/%r2148`, `%r2350`
|
||
(`tid.z`).
|
||
**Outputs (live past s7088):** the patch-expand `st.shared` regions, the 18
|
||
`ld.shared.v4.u32` A fragments `%r18995…%r19066`, phase 2's B
|
||
`%r6125…%r6132`, the 4 constants of §1.2 (`%fd1`, `%f861…%f864` are *not* yet
|
||
defined here).
|
||
|
||
### E2…E6 — s7113–s7243: next-B loads
|
||
|
||
Five 7-statement blocks of identical shape:
|
||
|
||
```
|
||
s7113 L12005: mov.u32 %r6373, %laneid
|
||
s7114 L12007: mul.wide.u32 %rd…, %r6373, 16
|
||
s7115 L12008: add.s64 %rd…, %rd2?, %rd…
|
||
s7117 L12017: ld.weak.global.ca.v4.u32 { %r6374,…%r6377},[%rd250]
|
||
s7119 L12021: ld.weak.global.ca.v4.u32 { %r6378,…%r6381},[%rd251]
|
||
```
|
||
|
||
| epilogue | weight block | destination phase |
|
||
|---|---|---|
|
||
| E2 | 50112…50636 | P3's B |
|
||
| E3 | 53184…53708 | P4's B |
|
||
| E4 | 51136…51660 | P5's B |
|
||
| E5 | 54208…54732 | P6's B |
|
||
| E6 | 52160…52684 | P7's B |
|
||
|
||
The weight sub-image is laid out **P2, P4, P6, P3, P5, P7** (blocks of 1024
|
||
bytes at `W + 50112 + 1024·k`), not in phase order.
|
||
|
||
### E7 — s7268–s7438: score-bias C-seed loads + packs → P8's A and B
|
||
|
||
171 statements, no `ld.global` outside the two groups below.
|
||
|
||
* **24 loads** `W + 16·laneid + 56256 + 512·i`, `i = 0…23`, at s7272…s7318
|
||
(L12922…L13014) into `%r7619…%r7714`; the last block's `add.s64` is
|
||
`s7317 add.s64 %rd283, %rd467, 17920`. Byte block
|
||
`[56256, 68544)` = 24 × 512 = 12288 bytes — **phase 8's C score-bias seed**
|
||
(the phase table prints the last *slot* offset, 68044).
|
||
* **80 packs / 40 b32**, s7319–s7438, whose sources are registers written by
|
||
**phases 3…7's mma** (`%r7129/%r7149/…`, `%r7229/…`, `%r7360…`). The two
|
||
destinations are `%r8161…%r8272` (**phase 8's B**) and `%r7907…%r8030`
|
||
(**phase 8's A**), e.g.
|
||
|
||
```
|
||
s7320 L13020: cvt.rn.satfinite.e4m3x2.f16x2 %rs1984, %r7149
|
||
s7321 L13022: mov.b32 %r8161, {%rs1983, %rs1984}
|
||
s7391 L13185: cvt.rn.satfinite.e4m3x2.f16x2 %rs2032, %r7149
|
||
s7393 L13190: mov.b32 %r7907, {%rs2031, %rs2032}
|
||
```
|
||
|
||
`s7439` then consumes them: `mma … {A=%r7907,%r7908,%r7909,%r7910},
|
||
{B=%r8161,%r8162}, {C=%r7619,%r7620}`. `%r7149` is phase 3's first D
|
||
(s7089–s7112) and `%r7129`/`%r7360` likewise belong to phases 3/4/6/7, so both
|
||
of phase 8's operands are packs of the six preceding projections.
|
||
|
||
### E8 — s7487–s11329: cubic-exponent softmax, V transpose, pack
|
||
|
||
**Byte-identical in kind to `cuda_dldn_engine_swin_enc0_kernel`'s E5** (see
|
||
`rrswin_enc0_epilogues.md` §3/E5): 1048 `mov.b32`, 672 `cvt.rn.f16.f32`, 384
|
||
`cvt.rn.f16.f64`, 192 each of `fma.rn.f16x2` / `cvt.f32.f16` /
|
||
`rcp.approx.ftz.f32` / `mul.f16`, 144 packs, 48 `movmatrix`, 16
|
||
`shfl.sync.bfly.b32`, 96 each of `max/min/neg/abs.f16x2`.
|
||
|
||
Sub-sections:
|
||
|
||
| range | what |
|
||
|---|---|
|
||
| s7488–s7513 | the 5 constants (§1.2 of the sibling file): s7488 `0f3C8CCB50`, s7492/s7497 the f64 clamps, s7503/s7508 the cubic pair |
|
||
| s7514–s9604 | 96 per-element groups (scale, clamp, cubic, `and.b32 …,2145419232`) |
|
||
| s9605–s9690 | in-lane partial sums (`add.f16x2`) |
|
||
| s9691–s9820 | 16 `shfl.sync.bfly` → 8 row sums |
|
||
| s9821–s10582 | 192 `rcp.approx.ftz.f32` → 96 reciprocals |
|
||
| s10583–s11065 | 192 `mul.f16` → 96 probabilities |
|
||
| s11066–s11113 | 48 `movmatrix.sync.trans.aligned.m8n8.b16` of **phase 7's** D |
|
||
| s11114–s11328 | 144 packs |
|
||
|
||
Evidence:
|
||
|
||
```
|
||
s7514 L13706: and.b32 %r…, %r…, 2145419232 // 0x7FE07FE0
|
||
s9691 L20503: shfl.sync.bfly.b32 %r10441,%r10437,%r5908,%r10444,%r5919
|
||
s9821 L20829: rcp.approx.ftz.f32 fl, fl
|
||
s11066 L23128: movmatrix.sync.trans.aligned.m8n8.b16 %r10801, %r7378
|
||
s11114 L23272: cvt.rn.satfinite.e4m3x2.f16x2 %rs3432, %r10809
|
||
```
|
||
|
||
`%r10801` is the first movmatrix result and its source `%r7378` is phase 7's
|
||
first D (s7244–s7267); the movmatrix sources run over phase 7's 48 D registers.
|
||
The transposed results become **phase 9's B** (`%r11407 ← mov.b32
|
||
{%rs3431,%rs3432}` at s11116 after the pack at s11114), and the probability packs
|
||
(`%r11113 ← mov.b32 {%rs3479,%rs3480}` at s11188) become **phase 9's A**.
|
||
|
||
The per-element function is the same cubic-exponent approximation as enc0's E5
|
||
(no row maximum, no bias add):
|
||
|
||
```
|
||
m = clamp(f16(x * 0.017181396484375), -0.55615234375, +0.55615234375)
|
||
u = f16(1.375 + m*(0.92724609375 - m*m))
|
||
expval = f16 from bits ((u_bits << 5) & 0x7FE07FE0)
|
||
```
|
||
|
||
**Memory:** none (0 `ld.*`, 0 `st.*` in 3843 statements).
|
||
|
||
### E9 — s11378–s11546: pack P9's D → shared, per-column table → P10's C
|
||
|
||
169 statements: 32 packs, 8 `add.f16`, 6 `ld.weak`, 12 `ld.global.v2.u16`,
|
||
4 `st.shared.v4.u32`, 1 `ld.shared.v4.u32`.
|
||
|
||
```
|
||
s11378 L24111: bar.sync 0
|
||
s11384 L24120: cvt.rn.satfinite.e4m3x2.f16x2 %rs3576, %r11141
|
||
s11396 L24147: st.shared.v4.u32 [%r19198], {%r19202, %r19201, %r19200, %r19199}
|
||
s11435 L24234: st.shared.v4.u32 [%r19198+1536], {%r19214, %r19213, %r19212, %r19211}
|
||
s11436 L24235: bar.sync 0
|
||
s11442 L24243: ld.shared.v4.u32 {%r19219,…%r19222}, [%r19218]
|
||
s11446 L24249: add.s64 %rd284, %rd469, 68544
|
||
s11451 L24259: add.s64 %rd286, %rd469, 69568
|
||
s11463 L24280: ld.global.v2.u16 {%rs4886, %rs4887}, [%rd473+136144]
|
||
s11475 L24293: add.f16 %rs3610,%rs4909,%rs459
|
||
s11477 L24300: mov.b32 %r11589, {%rs3607, %rs3610}
|
||
```
|
||
|
||
* **32 packs of phase 9's D** → 16 b32 → four `st.shared.v4.u32` at
|
||
`[%r19198 + {0,512,1024,1536}]`; the `bar.sync` pair makes them visible, then
|
||
**one `ld.shared.v4.u32` gives the first A fragment of phase 10**.
|
||
* **6 `ld.weak` at `W + 16·laneid + {68544, 69056, 69568, 70080, 70592, 71104}`**
|
||
→ phase 10's B.
|
||
* **12 `ld.global.v2.u16` at `W + ((laneid·4)&12) + {136128…136304}`** — a
|
||
per-column vector (12 words per lane = 96 columns).
|
||
* **48 `add.f16`** adding that vector to register pairs, producing the 24
|
||
registers `%r11589 %r11590 %r11599 %r11600 …` = **phase 10's C**
|
||
(confirmed at s11547: `C = {%r11589, %r11590}`).
|
||
|
||
**Which registers the table is added to is ambiguous in this file.** The
|
||
operands are `%rs456/%rs459` and their 22 siblings, and the *only* textual
|
||
definition of `%rs456/%rs459` is at `s5693/s5694` (L8430/L8434) inside **E1**
|
||
(the E1 sum-of-squares tree); nothing between s5694 and s11475 writes them. So
|
||
either E9's residual is genuinely carried from E1, or the printed PTX reuses a
|
||
register name across two disjoint live ranges without a rename. See §7/U1.
|
||
|
||
### E10/E11/E12 — s11559–s11639: one shared A fragment + next-B loads
|
||
|
||
Three 19-statement blocks:
|
||
|
||
```
|
||
s11562 L24597: ld.shared.v4.u32 {%r19226,…%r19229}, [%r19225+2048]
|
||
s11566 L24603: add.s64 %rd290, %rd475, 90048
|
||
s11571 L24613: add.s64 %rd292, %rd475, 91072
|
||
```
|
||
|
||
| epilogue | shared A offset | weight block | destination phase |
|
||
|---|---|---|---|
|
||
| E10 | `+2048` | 90048…92620 | P11's A, B |
|
||
| E11 | `+4096` | 111552…114124 | P12's A, B |
|
||
| E12 | `+6144` | 133056…135628 | P13's A, B |
|
||
|
||
Each takes its single A fragment from the same shared staging region E9 wrote
|
||
(offsets 2048/4096/6144 relative to `%r19216`) and reads 6 consecutive 512-byte
|
||
weight fragments. All three phases take `C = 0`.
|
||
|
||
### E13 — s11652–s12287: RMS norm of P13's D + gain
|
||
|
||
636 statements; 182 `mov.b32`, 144 `mul.f16`, 76 `add.f16`, 26 `add.f16x2`,
|
||
48 `rsqrt.approx.ftz.f32`, 4 `shfl.sync.bfly`, 24 packs, 12 `ld.global.v2.u16`.
|
||
|
||
| range | op |
|
||
|---|---|
|
||
| s11654–s11749 | unpack P13's D halves (`%r12019…`) and square them (48 `mul.f16`, s11655–s11749) |
|
||
| s11750–s11804 | in-lane `add.f16x2` partial sums |
|
||
| s11776–s11794 | 4 `shfl.sync.bfly.b32` |
|
||
| s11875–s11878 | `add.f16` of the halves, then `+ 2⁻¹³` (`%fd1`, defined at s6132) |
|
||
| s11883–s12068 | 48 `rsqrt.approx.ftz.f32` |
|
||
| s12072–s12083 | **gain loads** `W + ((laneid·4)&12) + {136336, 136352, …, 136496, 136320}` (12 `ld.global.v2.u16`) |
|
||
| s12085–s12226 | 96 `mul.f16` — `inv · gain` then `x · (inv·gain)` |
|
||
| s12231–s12242 | next-B loads `W + {136512, 137024, 137536, 138048, 138560, 139072}` → phase 14's B |
|
||
| s12248–s12251 | `ld.global.u32` at `W + ((laneid·4)&12) + {139584, 139600, 139616, 139632}` → **phase 14's C bias** |
|
||
| s12252–s12287 | 24 packs → `%r12414…%r12457`, **phase 14's A** |
|
||
|
||
At s12157/s12158 the same epilogue also emits a *second* scaled copy of P13's D:
|
||
|
||
```
|
||
s12157 L26127: mul.f16 %rs4190,%rs4360,%rs4046
|
||
s12158 L26130: mov.b32 %r18435, {%rs4190, %rs4193}
|
||
```
|
||
|
||
`%rs4360` is the unpack of P13's first D (s11654). The 24 registers
|
||
`%r18435…%r18458` are re-used by **every** even phase's A pack (E15 s12594,
|
||
E17 s12842, E19 …, and E37 s15297's neighbours), i.e. **phases 14, 16, 18, …,
|
||
P36 all share one A operand** derived from phase 13.
|
||
|
||
### E14 — s12300–s12556: activation of P14's D, table + residual → P15's C
|
||
|
||
257 statements. Three things happen:
|
||
|
||
1. **s12301–s12440: the clamped-cubic activation** on the 8 f16x2 registers
|
||
`%r12382 %r12392 %r12383 %r12393 %r12442 %r12452 %r12443 %r12453` (phase 14's
|
||
D). This is the epilogue that materialises `%f861…%f864` (s12301–s12312):
|
||
|
||
```
|
||
s12313 L26578: neg.f16x2 %r12467,%r12466
|
||
s12314 L26582: max.f16x2 %r12469,%r12382,%r12467
|
||
s12315 L26586: min.f16x2 %r12472,%r12469,%r12466
|
||
s12316 L26590: abs.f16x2 %r12475,%r12472
|
||
s12317 L26594: mul.f16x2 %r12477,%r12464,%r12475
|
||
s12318 L26598: sub.f16x2 %r12480,%r12463,%r12477
|
||
s12319 L26602: mul.f16x2 %r12483,%r12472,%r12480
|
||
s12320 L26606: add.f16x2 %r12486,%r12465,%r12483
|
||
s12321 L26610: mul.f16x2 %r12489,%r12382,%r12486
|
||
```
|
||
|
||
Per element: `y = clamp(x,−2,+2)`, `g = 0.5 + y·(0.412109375 − 0.0810546875·|y|)`,
|
||
`out = x·g` — the same cubic ramp as the sibling kernel's E10. **Reproduce
|
||
the formula, not SiLU/GELU.**
|
||
2. **s12441–s12472: next-B and table loads.** Six `ld.weak` at
|
||
`W + {139648, 140160, 140672, 141184, 141696, 142208}` → phase 15's B; and
|
||
12 `ld.global.v2.u16` at `W + ((laneid·4)&12) + {142720…142896}`.
|
||
3. **s12473–s12556: the residual/table add and the packs.** 48 `add.f16`
|
||
(`add.f16 %rs4361,%rs4957,%rs4363` at s12473) combine the table with the 24
|
||
registers whose halves come from `s11654 L24951: mov.b32 {%rs4360, %rs4363},
|
||
%r12019` — **phase 13's D**. The 24 results `%r12737…%r12848` are
|
||
**phase 15's C**; the 8 packs at s12545–s12556 give **phase 15's A**.
|
||
|
||
So phase 15 computes `D15 = act(D14)·B15 + (D13 + table@142720)`.
|
||
|
||
### E15 — s12569–s12628: packs of the shared A, next B, P16's C bias
|
||
|
||
60 statements:
|
||
|
||
```
|
||
s12572 L27414: add.s64 %rd320, %rd494, 142912
|
||
s12589 L27445: ld.global.u32 %r12908, [%rd497+145984]
|
||
s12593 L27450: cvt.rn.satfinite.e4m3x2.f16x2 %rs4511, %r18436
|
||
s12594 L27453: cvt.rn.satfinite.e4m3x2.f16x2 %rs4510, %r18435
|
||
```
|
||
|
||
* six `ld.weak` at `W + {142912, 143424, 143936, 144448, 144960, 145472}`
|
||
→ phase 16's B;
|
||
* four `ld.global.u32` at `W + ((laneid·4)&12) + {145984, 146000, 146016,
|
||
146032}` → **phase 16's C bias**;
|
||
* **24 packs of `%r18435…%r18458`** — the *shared* A that E13 produced — so
|
||
phase 16's A is bit-identical to phase 14's… (checked: `%r12971 ← mov.b32
|
||
{%rs4510, %rs4511}` at s12595 and `%r12971` is phase 16's first A register;
|
||
contrast phase 14's first A register `%r12414 ← mov.b32 {%rs4334, %rs4335}` at
|
||
s12254, sourced from `%r18435` at s12253 — the same register, so yes,
|
||
**identical**).
|
||
|
||
### E16/E18/…/E36 — the 164-statement activation epilogues
|
||
|
||
Twelve shape-identical 164-statement epilogues (shape hash `706fcc703f68`):
|
||
36 `mov.b32`, 32 `cvt.rn.f16.f32`, 24 `mul.f16x2`, 8 each
|
||
`neg/max/min/abs/sub/add.f16x2`, 6 `ld.weak`, no `ld.global`, no constants of
|
||
their own (they re-`cvt` `%f861…%f864`).
|
||
|
||
Each applies the E14 activation to its own phase's D and packs 8 b32 → the next
|
||
odd phase's A, and reads 6 weight fragments → the next odd phase's B.
|
||
Evidence (E16):
|
||
|
||
```
|
||
s12642 L27622: cvt.rn.f16.f32 low, %f861
|
||
s12651 L27649: max.f16x2 %r13026,%r12939,%r13024 // phase 16's D
|
||
s12658 L27677: mul.f16x2 %r13046,%r12939,%r13043
|
||
s12782 L28107: ld.weak.global.ca.v4.u32 { %r13253,…},[%rd326] // W+146048
|
||
s12795 L28135: mov.b32 %r13397, {%rs4534, %rs4535} // phase 17's A
|
||
```
|
||
|
||
**No table add and no residual**: these epilogues produce only A and B.
|
||
|
||
### E17/E19/…/E37-pre — the 60-statement pack epilogues
|
||
|
||
Eleven shape-identical 60-statement epilogues (shape hash `a7b578456a5a`):
|
||
24 packs, 12 `mov.b32`, 6 `ld.weak`, 4 `ld.global.u32`.
|
||
|
||
```
|
||
s12594 L27453: cvt.rn.satfinite.e4m3x2.f16x2 %rs4510, %r18435
|
||
s12842 L28285: cvt.rn.satfinite.e4m3x2.f16x2 %rs4542, %r18435
|
||
```
|
||
|
||
Each packs the same 24 registers `%r18435…%r18458` (so every even phase
|
||
P16, P18, …, P36 gets the identical A operand), reads 6 weight fragments → the
|
||
next even phase's B, and 4 `ld.global.u32` → the next even phase's C bias
|
||
(E15→P16@145984, E17→P18@152192, E19→P20@158400, E21→P22@164608,
|
||
E23→P24@170816, E25→P26@177024, E27→P28@183232, E29→P30@189440,
|
||
E31→P32@195648, E33→P34@201856, E35→P36@208064).
|
||
|
||
#### Shape of the whole MLP region (E13–E37)
|
||
|
||
```
|
||
E13 normed tile → P14's A (s12252) ; shared tile T = %r18435… (s12158)
|
||
P14: A = f(D13), B = W14, C = bias@139584 → D14 (48×96×96)
|
||
E14: act(D14) → P15's A ; P15's C = D13 + table@142720
|
||
P15: A = act(D14), B = W15, C = D13+table → D15 (16×96×32)
|
||
E15: pack T → P16's A ; B = W16 ; P16's C = bias@145984
|
||
P16: A = pack(T), B = W16, C = bias@145984 → D16 (48×96×96)
|
||
E16: act(D16) → P17's A ; B = W17
|
||
P17: A = act(D16), B = W17, C = D15 → D17 (16×96×32)
|
||
E17: pack T → P18's A ; B = W18 ; P18's C = bias@152192
|
||
P18: A = pack(T), B = W18, C = bias → D18
|
||
E18: act(D18) → P19's A ; P19's C = D17
|
||
… (the same two-phase motif repeats with the bias offsets of §2 until)
|
||
P37: A = act(D36), B = W37, C = D35 → D37
|
||
E37: pack D37 → 12 plane-arena stores ; P38: B = W38, C = bias@212736
|
||
P38: A = those packs, B = W38, C = bias → D38 (48×48×96)
|
||
```
|
||
|
||
The claim "odd phase's C = previous odd phase's D" is machine-checked for every
|
||
odd phase from P17 on (P15 is the exception, whose C is the register pair E14
|
||
builds). The claim "even phase's C comes from a `ld.global.u32`" holds for
|
||
P14…P38.
|
||
|
||
### E37 — s15297–s15504: pack → 12 guarded plane-arena stores → B/C for P38
|
||
|
||
208 statements; the only `st.global` in the entry (12 of them, all here).
|
||
|
||
**(a) requantise, s15297–s15332.** 12 groups of `2 cvt + 1 mov.b32` → the 12
|
||
b32 `%r481…%r492` (phase 37's D).
|
||
|
||
**(b) plane-arena scatter, s15333–s15482.**
|
||
|
||
```
|
||
s15333 L36645: ld.param.u64 %rd571, [%rd7+48] // = param_0+48
|
||
s15336 L36650: shr.u32 %r493, %r18989, 2 // g = laneid>>2
|
||
s15337 L36651: and.b32 %r494, %r18989, 3 // t = laneid&3
|
||
s15340 L36654: add.s32 %r19271, %r480, %r19269 // y = %r480 + (laneid>>5)
|
||
s15346 L36660: add.s32 %r19277, %r1, %r19270 // x = %r1 + (g&7)
|
||
s15351 L36665: shl.b32 %r19278, %r19277, 3 // x<<3
|
||
s15352 L36666: mad.lo.s32 %r495, %r7, %r19271, %r19278
|
||
s15354 L36668: selp.b32 %r496, -1, %r19279, %p1
|
||
s15359 L36674: st.global.u32 [%rd573], %r481
|
||
```
|
||
|
||
Stride register `%r7 = 8·ex` (s14). Each store is `idx = 8·ex·y + 8·x + d`,
|
||
`d = t` or `t|4`, guarded by
|
||
`(y<0)|(y≥ey)|(laneid>63)|(x<0)|(x≥ex)` (s15341–s15350, L36655–L36664); a guard
|
||
failure stores `-1` as the index, which the following `setp.lt.s32` + `bra`
|
||
turns into "skip the store".
|
||
|
||
Store values, bases and column offsets (`g = laneid>>2`, `t = laneid&3`,
|
||
`%r480 = %r2 + 2·tid.z` at s11653/L24950, `%r8 = ey·8·ex`):
|
||
|
||
| store | stmt | value | index base | d |
|
||
|---|---|---|---|---|
|
||
| 1 | s15359 | `%r481` | `idx1` | `t` |
|
||
| 2 | s15368 | `%r482` | `idx1` | `t\|4` |
|
||
| 3 | s15401 | `%r483` | `idx2` | `t` |
|
||
| 4 | s15409 | `%r484` | `idx2` | `t\|4` |
|
||
| 5 | s15419 | `%r485` | `idx1 + %r8` | `t` |
|
||
| 6 | s15427 | `%r486` | `idx1 + %r8` | `t\|4` |
|
||
| 7 | s15437 | `%r487` | `idx2 + %r8` | `t` |
|
||
| 8 | s15445 | `%r488` | `idx2 + %r8` | `t\|4` |
|
||
| 9 | s15455 | `%r489` | `idx1 + 2·%r8` | `t` |
|
||
| 10 | s15463 | `%r490` | `idx1 + 2·%r8` | `t\|4` |
|
||
| 11 | s15473 | `%r491` | `idx2 + 2·%r8` | `t` |
|
||
| 12 | s15481 | `%r492` | `idx2 + 2·%r8` | `t\|4` |
|
||
|
||
with the two bases built as `mad.lo.s32 %rBASE, 8·ex, y, 8·x`:
|
||
|
||
| base | stmt | y | x |
|
||
|---|---|---|---|
|
||
| `idx1 = %r495` | s15352, L36666 | `%r480 + (laneid>>5)` | `%r1 + (g&7)` |
|
||
| `idx2 = %r499` | s15394, L36712 | `%r19505 + ((g+8)>>3)` | `%r1 + ((g+8)&7)` |
|
||
|
||
`%r19505` is a *second* row origin:
|
||
`s15370 mov.u32 %r19511, %ctaid.y` / `s15372 shl.b32 %r19509, %r19511, 3` /
|
||
`s15375 sub.s32 %r19506, %r19509, %r19510` / `s15376 add.s32 %r19505, %r19506,
|
||
%r19507` with `%r19507 = 2·tid.z` (s15373/s15374), i.e.
|
||
`ctaid.y·8 − origin_y + 2·tid.z` — so the two halves of this scatter start at
|
||
different rows. The `+%r8` (s15412 `mad.lo.s32 %r502, %r2148, %r19493, %r495`)
|
||
and `+2·%r8` (s15466 `mad.lo.s32 %r511, %r2148, %r19496, %r505`) forms then step
|
||
one and two rows further.
|
||
|
||
**(c) next B/C, s15483–s15504.**
|
||
|
||
```
|
||
s15492 L36832: add.s64 %rd596, %rd600, 211200
|
||
s15493 L36834: ld.weak.global.ca.v4.u32 { %r19307,…%r19310},[%rd596]
|
||
s15497 L36842: ld.weak.global.ca.v4.u32 { %r19315,…%r19318},[%rd598]
|
||
s15503 L36851: ld.global.u32 %r19329, [%rd604+212736]
|
||
s15504 L36852: ld.global.u32 %r19339, [%rd604+212752]
|
||
```
|
||
|
||
Three weight fragments at `W + {211200, 211712, 212224}` → phase 38's B, two
|
||
`u32` at `W + ((laneid&3)·4 &12) + {212736, 212752}` → phase 38's C bias.
|
||
|
||
### E38 — s15511–s15796: the final epilogue
|
||
|
||
286 statements; it consumes phase 38's four D accumulators (`%r19360 %r19370
|
||
%r19497 %r19498`) and writes the surface.
|
||
|
||
**(a) staging, s15511–s15542.**
|
||
|
||
```
|
||
s15511 L36895: bar.sync 0
|
||
s15522 L36908: st.shared.u32 [%r520], %r19360
|
||
s15526 L36913: st.shared.u32 [%r520+16], %r19370
|
||
s15539 L36927: st.shared.u32 [%r522], %r19361
|
||
s15541 L36930: st.shared.u32 [%r522+16], %r19371
|
||
```
|
||
|
||
Four guarded stores of the phase-38 D pairs into shared, indexed from
|
||
`%r518 = laneid>>2`, `%r519 = laneid&3` and `%tid.z`.
|
||
|
||
**(b) coordinates and bounds check, s15543–s15570.**
|
||
|
||
```
|
||
s15551 L36941: mov.u32 %r19403, %tid.x
|
||
s15559 L36949: add.s32 %r525, %r1, %r523 // x
|
||
s15560 L36950: add.s32 %r526, %r19512, %r524 // y
|
||
s15565 L36955: ld.param.v2.u32 {%r19418, %r19419}, [%rd634]
|
||
s15570 L36960: @%p412 bra $L__BB1_486
|
||
```
|
||
|
||
**(c) row max over 5 shared values, s15571–s15591.**
|
||
|
||
```
|
||
s15577 L36968: ld.shared.u32 %r19421, [%r19470]
|
||
s15583 L36974: ld.shared.u32 %r19442, [%r19470+16]
|
||
s15585 L36977: max.f16x2 %r19420,%r19421,%r19422
|
||
s15590 L36994: max.f16 %rs4961,%rs4958,%rs4963
|
||
s15592 L36999: sub.f16x2 %r19429,%r19421,%r19443
|
||
```
|
||
|
||
Five `u32` (= 10 f16) per row, reduced in registers — **no warp shuffle**.
|
||
|
||
**(d) softmax, s15592–s15676.**
|
||
|
||
```
|
||
s15595 L37007: mul.ftz.f32 %f905, %f865, 0f3FB8AA3B // * log2e
|
||
s15596 L37008: ex2.approx.ftz.f32 %f867, %f905
|
||
s15651 L37126: add.ftz.f32 %f922, %f920, %f882 // running row sum
|
||
s15653 L37128: div.approx.ftz.f32 %f883, %f904, %f922 // 1/rowsum, %f904 = 1.0
|
||
```
|
||
|
||
`y = 2^((x−max)·log2e)`, `p = y·(1/Σy)` in f16, five f16x2 registers.
|
||
|
||
**(e) 3×3 colour texture, s15677–s15758.**
|
||
|
||
```
|
||
s15677 L37176: ld.param.v2.f32 {%f924, %f925}, [%rd635+136]
|
||
s15683 L37182: ld.param.u64 %rd622, [%rd635+88]
|
||
s15685 L37185: tex.base.2d.v4.f16.f32 {%rs4986,%rs4987,%rs4988,%rs4989}, [%rd606, {%f884,%f885}]
|
||
s15687 L37189: fma.rn.f16 %rs4990,%rs4986,%rs5000,%rs4983
|
||
```
|
||
|
||
`%rd635 = param_0` (s15571), so the colour texture handle is **`param_0+88`**
|
||
and the coordinate scales are **`param_0+136`**. Nine
|
||
`tex.base.2d.v4.f16.f32` (s15685, 15697, 15709, 15721, 15726, 15732, 15744,
|
||
15750, 15755) cover the 3×3 neighbourhood of clamped `(x−1, x, x+1) ×
|
||
(y−1, y, y+1)`, accumulated into 3 channels with `fma.rn.f16`.
|
||
|
||
**(f) the two integer-coordinate textures, s15759–s15762.**
|
||
|
||
```
|
||
s15759 L37357: ld.param.u64 %rd624, [%rd635+96]
|
||
s15760 L37359: tex.base.2d.v4.f16.s32 {%rs5130,%rs5131,%rs5132,%rs5133}, [%rd624, {%r525,%r526}]
|
||
s15761 L37361: ld.param.u64 %rd626, [%rd635+104]
|
||
s15762 L37363: tex.base.2d.v4.f16.s32 {%rs5134,%rs5135,%rs5136,%rs5137}, [%rd626, {%r525,%r526}]
|
||
```
|
||
|
||
**These are the `+96` / `+104` texture reads the brief asks about** — handles at
|
||
`param_0+96` and `param_0+104`, sampled at the *integer* pixel coordinate
|
||
`(%r525, %r526)`.
|
||
|
||
**(g) combine, sigmoid gate, surface store, s15763–s15796.**
|
||
|
||
```
|
||
s15763 L37366: cvt.f32.f16 %f902, %rs5138
|
||
s15764 L37369: mul.ftz.f32 %f935, %f902, 0fBFB8AA3B
|
||
s15765 L37370: ex2.approx.ftz.f32 %f936, %f935
|
||
s15766 L37371: add.ftz.f32 %f937, %f936, 0f3F800000
|
||
s15767 L37372: div.approx.ftz.f32 %f903, %f904, %f937 // 1/(1+2^(-log2e·v))
|
||
s15770 L37382: sub.f16 %rs5141,%rs5140,%rs5139 // 1 - sigmoid
|
||
s15771 L37386: mul.f16 %rs5144,%rs5118,%rs5139 // acc * sigmoid
|
||
s15772 L37390: fma.rn.f16 %rs5187,%rs5130,%rs5141,%rs5144// + tex96 * (1-sig)
|
||
s15777 L37410: set.nan.f16.f16 %rs5165,%rs5134,%rs5134 // + tex104 unless NaN
|
||
s15793 L37449: mov.u16 %rs5186, 0
|
||
s15794 L37451: sust.b.2d.v4.b16.zero [%rd629, {%r19489,%r526}], {%rs5187,%rs5188,%rs5189,%rs5186}
|
||
```
|
||
|
||
`%rd629 = param_0+112` (s15582). The store column is `%r525·8`
|
||
(s15792 `shl.b32 %r19489, %r525, 3`), the row `%r526`; the fourth channel is
|
||
the zero literal, so this is a **3-channel write into a 4-channel surface**.
|
||
The `set.nan`/`bra` triad (s15777–s15790) adds the `+104` read only when it is
|
||
not NaN.
|
||
|
||
**Inputs:** the 4 returned D registers, `param_0+{48,88,96,104,112,136}`, the
|
||
shared scratch, constants `0f3FB8AA3B`, `0fBFB8AA3B`, `0f3F800000`.
|
||
**Outputs:** none (the kernel returns, s15796).
|
||
|
||
---
|
||
|
||
## 4. Texture reads, surface writes, and the `+24` input
|
||
|
||
| what | where |
|
||
|---|---|
|
||
| `param_0+8` — input feature plane arena, read by phase 1's A loads | prologue s66…s451 (60 `ld.global`) |
|
||
| `param_0+24` — the patch-gather source E1 reads | s2288 (`ld.param.u64 %rd2, [%rd7+24]`) and the 24 `ld.global.v2.u16` at s2444…s5593 |
|
||
| `param_0+48` — the plane arena E37 scatters phase 37's output to | s15333, 12 `st.global.u32` at s15359…s15481 |
|
||
| `param_0+88` — the colour texture handle | s15683, 9 `tex.base.2d.v4.f16.f32` at s15685…s15755 |
|
||
| `param_0+96` — texture handle #2 (integer coords) | s15759/s15760 |
|
||
| `param_0+104` — texture handle #3 (integer coords) | s15761/s15762 |
|
||
| `param_0+112` — the output surface | s15582, `sust.b.2d.v4.b16.zero` s15794 |
|
||
| `param_0+136` — two f32 texture coordinate scales | s15677 |
|
||
|
||
**The skip input at `+24` supplies the patch-gather source.** E1 reads it once
|
||
per lane per stencil position and never writes it; the buffer is addressed in
|
||
4-byte elements (one f16x2 = 2 channels) with index
|
||
`clamp(row)·8·ex + clamp(col)·8 + clamp(t,0,7)`:
|
||
|
||
```
|
||
s2318 L4671: mad.lo.s32 %r3078, %r3068, %r7, %r3077 // clamp_row*(8*ex) + clamp_col*8
|
||
s2440 L4800: add.s32 %r19540, %r2996, %r2992 // + clamp(t, - , 7)
|
||
s2442 L4803: mul.wide.u32 %rd191, %r19540, 4
|
||
s2444 L4805: ld.global.v2.u16 {%rs314, %rs315}, [%rd192]
|
||
```
|
||
|
||
The same index form and the same 24-gather shape as the sibling kernel's §3/E1.
|
||
|
||
**The surface writes** are `param_0+112` (E38, s15794), a 4-channel b16 surface
|
||
written with 3 live channels. The **plane-arena writes** are E37's 12
|
||
`st.global.u32` to `param_0+48` (s15359…s15481).
|
||
|
||
**Nothing reads `param_0+48` back** in this entry: `param_0+48` is the source of
|
||
exactly one `ld.param` (s15333) and never the base of a load. Likewise the
|
||
texture handles at `+88/+96/+104` are only ever `tex.*` operands.
|
||
|
||
## 5. The phase table, M/N/K checked
|
||
|
||
`rr_layer_spec.py dec2`'s phase table with `M/16 · N/8 · K/32 == mma` evaluated
|
||
on every row:
|
||
|
||
| # | stmts | M | N | K | mma | M/16·N/8·K/32 | holds? | weight bytes (rel. `W`) | bias bytes |
|
||
|---|---|---|---|---|---|---|---|---|---|
|
||
| 1 | s452–s595 | 192 | 384 | 128 | 144 | 12·48·4 = 2304 | **no** | 0…11788 (+12288·`tid.z`) | 49152…49328 (+192·`tid.z`) |
|
||
| 2 | s7089–s7112 | 96 | 32 | 32 | 24 | 6·4·1 = 24 | yes | 50112…50636 | – |
|
||
| 3 | s7120–s7143 | 96 | 32 | 32 | 24 | 24 | yes | 53184…53708 | – |
|
||
| 4 | s7151–s7174 | 96 | 32 | 32 | 24 | 24 | yes | 51136…51660 | – |
|
||
| 5 | s7182–s7205 | 96 | 32 | 32 | 24 | 24 | yes | 54208…54732 | – |
|
||
| 6 | s7213–s7236 | 96 | 32 | 32 | 24 | 24 | yes | 52160…52684 | – |
|
||
| 7 | s7244–s7267 | 96 | 32 | 32 | 24 | 24 | yes | 55232…55756 | – |
|
||
| 8 | s7439–s7486 | 64 | 96 | 32 | 48 | 4·12·1 = 48 | yes | **none** | 56256…68044 |
|
||
| 9 | s11330–s11377 | 192 | 96 | 96 | 48 | 12·12·3 = 432 | **no** | **none** | – |
|
||
| 10 | s11547–s11558 | 16 | 96 | 32 | 12 | 1·12·1 = 12 | yes | 68544…71116 | – |
|
||
| 11 | s11578–s11589 | 16 | 96 | 32 | 12 | 12 | yes | 90048…92620 | – |
|
||
| 12 | s11609–s11620 | 16 | 96 | 32 | 12 | 12 | yes | 111552…114124 | – |
|
||
| 13 | s11640–s11651 | 16 | 96 | 32 | 12 | 12 | yes | 133056…135628 | – |
|
||
| 14 | s12288–s12299 | 48 | 96 | 96 | 12 | 3·12·3 = 108 | **no** | 136512…139084 | 139584…139632 |
|
||
| 15 | s12557–s12568 | 16 | 96 | 32 | 12 | 12 | yes | 139648…142220 | – |
|
||
| 16 | s12629–s12640 | 48 | 96 | 96 | 12 | 108 | **no** | 142912…145484 | 145984…146032 |
|
||
| 17 | s12805–s12816 | 16 | 96 | 32 | 12 | 12 | yes | 146048…148620 | – |
|
||
| 18 | s12877–s12888 | 48 | 96 | 96 | 12 | 108 | **no** | 149120…151692 | 152192…152240 |
|
||
| 19 | s13053–s13064 | 16 | 96 | 32 | 12 | 12 | yes | 152256…154828 | – |
|
||
| 20 | s13125–s13136 | 48 | 96 | 96 | 12 | 108 | **no** | 155328…157900 | 158400…158448 |
|
||
| 21 | s13301–s13312 | 16 | 96 | 32 | 12 | 12 | yes | 158464…161036 | – |
|
||
| 22 | s13373–s13384 | 48 | 96 | 96 | 12 | 108 | **no** | 161536…164108 | 164608…164656 |
|
||
| 23 | s13549–s13560 | 16 | 96 | 32 | 12 | 12 | yes | 164672…167244 | – |
|
||
| 24 | s13621–s13632 | 48 | 96 | 96 | 12 | 108 | **no** | 167744…170316 | 170816…170864 |
|
||
| 25 | s13797–s13808 | 16 | 96 | 32 | 12 | 12 | yes | 170880…173452 | – |
|
||
| 26 | s13869–s13880 | 48 | 96 | 96 | 12 | 108 | **no** | 173952…176524 | 177024…177072 |
|
||
| 27 | s14045–s14056 | 16 | 96 | 32 | 12 | 12 | yes | 177088…179660 | – |
|
||
| 28 | s14117–s14128 | 48 | 96 | 96 | 12 | 108 | **no** | 180160…182732 | 183232…183280 |
|
||
| 29 | s14293–s14304 | 16 | 96 | 32 | 12 | 12 | yes | 183296…185868 | – |
|
||
| 30 | s14365–s14376 | 48 | 96 | 96 | 12 | 108 | **no** | 186368…188940 | 189440…189488 |
|
||
| 31 | s14541–s14552 | 16 | 96 | 32 | 12 | 12 | yes | 189504…192076 | – |
|
||
| 32 | s14613–s14624 | 48 | 96 | 96 | 12 | 108 | **no** | 192576…195148 | 195648…195696 |
|
||
| 33 | s14789–s14800 | 16 | 96 | 32 | 12 | 12 | yes | 195712…198284 | – |
|
||
| 34 | s14861–s14872 | 48 | 96 | 96 | 12 | 108 | **no** | 198784…201356 | 201856…201904 |
|
||
| 35 | s15037–s15048 | 16 | 96 | 32 | 12 | 12 | yes | 201920…204492 | – |
|
||
| 36 | s15109–s15120 | 48 | 96 | 96 | 12 | 108 | **no** | 204992…207564 | 208064…208112 |
|
||
| 37 | s15285–s15296 | 16 | 96 | 32 | 12 | 12 | yes | 208128…210700 | – |
|
||
| 38 | s15505–s15510 | 48 | 48 | 96 | 6 | 3·6·3 = 54 | **no** | 211200…212236 | 212736…212752 |
|
||
|
||
**Every phase whose `M/16·N/8·K/32` does not equal `mma` is one the tool also
|
||
marks `grid = band`**, and every phase that holds is marked `full`. The
|
||
mismatch factors are not constant (P1 ×16, P9 ×9, P14/…/P36 ×9, P38 ×9), so `M`,
|
||
`N` and `K` cannot all be taken at face value for those rows. For P14 the reason
|
||
is checkable and structural:
|
||
|
||
```
|
||
s12288 D=%r12342 A=%r12414 B=%r12293 C=bias@139584 (bo 136512)
|
||
s12290 D=%r12362 A=%r12434 B=%r12297 C=%r12342 (bo 137024)
|
||
```
|
||
|
||
— the same D accumulates products with B fragments from *different* 512-byte
|
||
blocks and two *different* A quads. Under the settled weight formula
|
||
(`n = 16·tt + 8·(b>>3) + (L>>2)`, verified on enc0) P14's six blocks span
|
||
`n = 0…95`, so `N = 96` is supported; then the 3-mma chains must be summing over
|
||
`M` or `K`, and neither is separately readable from the fragment structure.
|
||
See §7/U2.
|
||
|
||
**Which phases read no weight operand:** **P8 and P9**. Both take `B` from
|
||
registers the preceding epilogue packed (E7 packs phases 3…7's D for P8's A and
|
||
B; E8 packs the probabilities and the transposed P7 for P9's A and B). Their
|
||
`bo` is `None` for every mma.
|
||
|
||
**Weight image extent as the tool measures it:** the largest resolved offset is
|
||
**212752** (s15504, 4 bytes wide) ⇒ **212756 bytes** (1082 distinct slots).
|
||
Phase 1's B and C bias carry the only `tid.z` terms (`W + 12288·tid.z`,
|
||
`W + 192·tid.z`); with `tid.z ∈ {0,1}` (E38 rejects `tid.z > 1` at s15561
|
||
`setp.gt.u32 %p406, %r19503, 1`) the extra 12288 bytes stay inside 212756.
|
||
**(INFERENCE** — the tool drops the `tid.z` term, so the per-window base cannot
|
||
be read off it directly.)
|
||
|
||
## 6. The plane arena (param_0 + 48) and the per-launch tables
|
||
|
||
* `param_0+8` is read 60 times in the prologue (s66…s451) as the **input feature
|
||
plane** that builds phase 1's 12 A fragments.
|
||
* `param_0+24` is the **patch-gather source** (see §4); it is read, never written.
|
||
* `param_0+48` is the **output plane arena**: written by E37's 12
|
||
`st.global.u32` (s15359…s15481), never read. The entry has exactly 12
|
||
`st.global` and no other global store.
|
||
* The only other `ld.param` sites are the 4 in the prologue (§1.1) and the 5 in
|
||
E38 (`[%rd635+88/96/104/112/136]`, s15683/15759/15761/15582/15677) plus
|
||
`[%rd7+48]` (s15333), `[%rd7+24]` (s2288) and the two `param_0+40` re-reads
|
||
(s15483/s15484).
|
||
|
||
There is **no per-launch table generated into the plane arena by this kernel**:
|
||
the arena is only written (E37), and every table that looks like one
|
||
(`W + ((laneid<<2)&12) + {49920, 136128, 136320, 142720, …}`) lives in the
|
||
*weight image*, not the arena.
|
||
|
||
## 7. Uncharacterised
|
||
|
||
**U1. E9's residual registers.** The 24 registers that E9's per-column table
|
||
adds into (`%rs456/%rs459` and their siblings, s11473–s11544) have exactly one
|
||
textual definition each, at s5693/s5694 (L8430/L8434) inside **E1** — nothing
|
||
between s5694 and s11473 writes them (`grep -n '%rs456\b'` returns L8430, L8913,
|
||
L11184, L24297 only). So either the value is genuinely carried from E1's
|
||
sum-of-squares tree, or the printed PTX reuses a register name across two
|
||
disjoint live ranges without a rename. The two readings differ in what phase
|
||
10's C *is* (a table plus E1's partial sums, versus a table plus something
|
||
unnameable), so I will not guess. *Missing:* a shared-memory/register dump at
|
||
s11473, or the pre-rename SSA.
|
||
|
||
**U2. The true `M/N/K` of the thirteen banded phases (P1, P9, P14, P16, …,
|
||
P36, P38).** For those rows `M/16·N/8·K/32 ≠ mma` (§5). `nA` counts distinct A
|
||
*register quads*, which can be either distinct `M`-tiles or distinct `K`-slices
|
||
of the same tile, and the accumulator chains mix distinct B operands, so the
|
||
two cannot be separated from the fragment structure. *Missing:* a run with a
|
||
weight-image dump, the `_prep` permutation, or the high-level layer definition.
|
||
|
||
**U3. The identity of the 12288-byte score bias (P8's C).** E7 loads it as 24
|
||
tiles × 512 bytes at `W + 56256`. Whether it is a relative position bias, a
|
||
learned score bias, or a per-lane constant cannot be decided from the PTX: it is
|
||
an opaque blob in a permuted weight image. *Missing:* the image's layout
|
||
description or the model's parameter names.
|
||
|
||
**U4. The identity of the per-column tables.** `W+49920…50096` (E1 gain),
|
||
`W+136128…136304` (E9), `W+136320…136496` (E13 gain), `W+142720…142896` (E14)
|
||
are all read with the same `W + ((laneid<<2)&12) + off` pattern (12 words per
|
||
lane). Their *role* is computable (E1/E13: multiply the inverse RMS; E9/E14:
|
||
added to a residual before the next GEMM) but their *names* are not. The GEMM
|
||
biases at `+49152`, `+139584`, `+145984`, `+152192`, `+158400`, `+164608`,
|
||
`+170816`, `+177024`, `+183232`, `+189440`, `+195648`, `+201856`, `+208064`,
|
||
`+212736` are the same case.
|
||
|
||
**U5. E1's patch-expand geometry.** As in the sibling kernel, the 36 guarded
|
||
`st.shared` are emitted as ~400 basic blocks with 413 labels and I could not
|
||
reduce the lane→(row,col) map to a closed form. Established: 34 `u32` + 2
|
||
`v2.u16` patch stores, a second staging area of 6 `v4.u32` stores at
|
||
`smem + tid.z·{2048,3072} + {0,512,1024,6144,6656,7168}`, and the whole 9600-byte
|
||
shared allocation. *Missing:* the source-level patchify expression or a
|
||
shared-memory dump.
|
||
|
||
**U6. Whether `param_0+8` is an input plane or a scratch table.** The prologue
|
||
reads it 60 times with 4-byte elements and never writes it, and E1 does not read
|
||
it (E1 reads `param_0+24`). So `+8` and `+24` are two different input buffers;
|
||
which one holds the noisy colour plane and which the feature planes cannot be
|
||
decided from the PTX. *Missing:* the host-side launch arguments.
|
||
|
||
**U7. The `tid.z` strides.** Phase 1's B and bias carry `×12288` and `×192`
|
||
per-window strides and no later phase carries one. Whether the image is a
|
||
concatenation of per-window sub-images or `tid.z` selects a batch element whose
|
||
weights are interleaved cannot be decided here; consequently the "212756 bytes"
|
||
of §5 is a lower bound.
|
||
|
||
**U8. The logical meaning of E38's final expression.** The tail computes
|
||
`out = acc·σ(v) + tex96·(1−σ(v)) + tex104` on the three channels gathered from
|
||
the 3×3 colour stencil and the two integer-coordinate textures. The PTX gives
|
||
the arithmetic exactly (§3/E38(g)) but not what model term it corresponds to.
|
||
*Missing:* the high-level source or a reference implementation.
|
||
|
||
**U9. Why every even phase shares one A operand.** E13 emits two scaled copies
|
||
of phase 13's D (the normed packs `%r12414…` at s12252 and `%r18435…` at
|
||
s12158) and phases 14, 16, …, 36 all pack the second one. That makes the A
|
||
operands of those twelve GEMMs bit-identical; whether that is the intended
|
||
computation (one shared projection) or a consequence of a missed optimisation
|
||
cannot be decided from the PTX. *Missing:* the high-level layer definition.
|
||
|
||
## 8. Quick acceptance index
|
||
|
||
| requirement | where |
|
||
|---|---|
|
||
| every epilogue named and ranged | §2, §3 (E1…E38) |
|
||
| phase-1 epilogue's patch expand + norm | §3/E1 |
|
||
| the norm (`E1`, `E13`) | §3/E1, §3/E13 — raw sum of squares + 2⁻¹³, no mean, no 1/N |
|
||
| the attention (score, softmax, P·V) | §3/E7, E8, E9; §3/E9's table add |
|
||
| the activations | §3/E14 (materialises `%f861…%f864`), E16, E18, …, E36 |
|
||
| the patch expand | §3/E1 (36 `st.shared`), §7/U5 |
|
||
| the final epilogue, textures at +96/+104, surface | §3/E38, §4 |
|
||
| the texture reads at +96/+104 | §3/E38(f), s15760 / s15762 |
|
||
| the skip input at +24 | §3/E1 (s2288), §4 |
|
||
| the plane-arena writes | §3/E37 (s15359…s15481), §4, §6 |
|
||
| the phase table with M/N/K checked | §5 |
|
||
| weight image extent | §5 (212756 bytes, 1082 slots) |
|
||
| which phases read no weight | §5 (P8, P9) |
|
||
| uncharacterised | §7 |
|