vllm.models.deepseek_v41.amd.mono.weights942
¶
Host-side weight preparation for the gfx942 (MI300X, MI325X) mono kernels.
On gfx942 vLLM dequantizes the dense MXFP8 linears to bf16 when it loads them
and keeps their E8M0 scales. ocp_from_dequant rebuilds the original e4m3
bytes from the two, exactly. dense_copy turns OCP e4m3 bytes into the
copy the gfx942 GEMV reads (attention.gemv._step_load_942):
- FNUZ bytes. A byte keeps its bit pattern, which stands for half the OCP value in FNUZ, and its scale code is raised by one to compensate. OCP -0 (0x80) is the FNUZ NaN and becomes 0x00.
- K padded with zero bytes to a multiple of 128.
- Tile-major: for each tile of 16 rows and each 128-byte K step, the 16 rows' bytes of the step stored together (2 KB). Lane 16 j + r of the GEMV takes row r's four 8-byte chunks of lane group j (K 32 b + 8 j .. + 8, b = 0 .. 3) as two 16-byte halves, blocks 0 and 1, then blocks 2 and 3. The 2 KB hold the first halves of the 64 lanes in lane order, then the second halves, so each of the two 16-byte loads of a lane reads 1 KB that is contiguous across the wave.
chunk_q: within each 8-byte chunk the even K first, then the odd K. The MoE stages quantize their activations in that order, to match the bytes the FP4 conversion of the routed experts produces (common.gfx942.fp4x8_fnuz).
Functions:
-
codes_tile_rounds–e8m0 codes [..., rows, K / 32] (rows a multiple of 16) -> the order the
-
dense_copy–OCP e4m3 bytes [N, K] and E8M0 codes [N / 32, K / 32] -> the gfx942
-
fp4_drop_negative_zero_–Rewrite every -0 nibble (0x8) of a packed e2m1 tensor to +0, in place,
-
fp4_lane_major–Packed e2m1 rows [..., K / 2] -> each row's bytes in lane order, for
-
fp4_tile_major–Packed e2m1 rows [..., rows, K / 2] (rows a multiple of 16) -> the byte
-
linear_copy–A vLLM-loaded MXFP8 linear on gfx942 (bf16 dequantized, or e4m3 bytes)
-
moe_copies–VLLM's plain MXFP4 expert tensors before its kernel conversion (w13
-
ocp_from_dequant–The OCP e4m3 bytes [N, K] behind a bf16 weight vLLM dequantized at load
codes_tile_rounds(codes, blocks=8)
¶
e8m0 codes [..., rows, K / 32] (rows a multiple of 16) -> the order the
gfx942 ug GEMV loads. For each tile of 16 rows and each round of
blocks K blocks (moe.UG_ROUND_942), the copy stores the 16 rows'
codes of the round row after row, 16 x blocks bytes together. Lane
group j then reads the codes of its rows 4 j .. 4 j + 3 with two 16-byte
loads from one line. Row-major codes would take four 8-byte loads from
four lines.
Source code in vllm/models/deepseek_v41/amd/mono/weights942.py
dense_copy(w8, scale, chunk_q=False)
¶
OCP e4m3 bytes [N, K] and E8M0 codes [N / 32, K / 32] -> the gfx942 copy: (bytes [N, Kp], FNUZ codes [N / 32, Kp / 32]), Kp = K rounded up to 128. A padded block holds zero bytes and code 128.
Source code in vllm/models/deepseek_v41/amd/mono/weights942.py
fp4_drop_negative_zero_(w)
¶
Rewrite every -0 nibble (0x8) of a packed e2m1 tensor to +0, in place,
chunk by chunk. -0 and +0 give the same products, so vLLM's own MoE
kernels compute the same results afterwards. gfx942's FP4 conversion
(common.gfx942.fp4x8_fnuz) would turn -0 into the FNUZ NaN. Returns
how many nibbles changed.
Source code in vllm/models/deepseek_v41/amd/mono/weights942.py
fp4_lane_major(w)
¶
Packed e2m1 rows [..., K / 2] -> each row's bytes in lane order, for
fp4_tile_major. A lane of the 16 x 16 x 32 MFMA takes the dword of K
32 i + 8 j .. + 8 of a row in each 32-wide K block i, with j = lane / 16.
Within each 64-byte step (four K blocks) the copy stores lane group j's
four dwords together at bytes 16 j .. 16 j + 15, so one 16-byte load a
lane reads them, and the 4 lane groups of a row read 64 contiguous bytes.
A last 32-byte step (two K blocks, the 576-wide w2 rows) stores lane
group j's two dwords at bytes 8 j .. 8 j + 7. The scale codes keep their
order, because each K block keeps its code.
Source code in vllm/models/deepseek_v41/amd/mono/weights942.py
fp4_tile_major(w)
¶
Packed e2m1 rows [..., rows, K / 2] (rows a multiple of 16) -> the byte
order the gfx942 routed GEMVs load. For each tile of 16 rows and each
64-byte step (four K blocks), the copy stores the 64 lanes' 16 bytes in
lane order. Lane 16 j + r holds the 16 bytes that fp4_lane_major
gives lane group j of row r. One 16-byte load a lane then reads 1 KB that
is contiguous, 8 whole 128-byte lines. In the fp4_lane_major order
the same load would read 64 bytes from each of 16 rows that are K / 2
bytes apart, so it would take 16 memory requests instead of 8 and fetch
each line with two loads. On MI325X a CTA's ug GEMV takes 23.2 us in this
order and 32.5 us in the fp4_lane_major order (6 rows, all 4 waves),
with the same results bit for bit.
A last 32-byte step (two K blocks, the 576-wide w2 rows) is stored the
same way with 8 bytes a lane, 512 contiguous bytes.
Source code in vllm/models/deepseek_v41/amd/mono/weights942.py
linear_copy(w, scale)
¶
A vLLM-loaded MXFP8 linear on gfx942 (bf16 dequantized, or e4m3 bytes)
with its E8M0 codes [N / 32, K / 32] -> dense_copy with natural chunks
(the attention and shared expert activations are not reordered).
Source code in vllm/models/deepseek_v41/amd/mono/weights942.py
moe_copies(w13, w13_s, w2, w2_s, inter)
¶
VLLM's plain MXFP4 expert tensors before its kernel conversion (w13
[E, 2 Np, K / 2], w2 [E, H, Np / 2] and codes [E, rows, K / 32], with
w13's gate rows, then its up rows, each padded with zero rows from
inter to Np) -> the gfx942 mono copies: w13 [E, 2 inter, K / 2] with
gate row i at 2 i and up row i at 2 i + 1, w2 [E, H, inter / 2], their
codes alike, no -0 nibbles. The weight bytes are in fp4_tile_major
order. The w13 codes are in codes_tile_rounds order, and the w2 codes
stay row-major because a lane group reads 4 whole rows of them. Refuses
padding rows that are not zero.
Source code in vllm/models/deepseek_v41/amd/mono/weights942.py
ocp_from_dequant(w, scale)
¶
The OCP e4m3 bytes [N, K] behind a bf16 weight vLLM dequantized at load
(w = e4m3 value x 2^(code - 127), scale the codes in 32 x 32
blocks [N / 32, K / 32]). Refuses a weight the bytes do not give back
exactly.