Download code/offload/dspark/kernels/mxfp4/kernels.py from ProprietaryLegal/dsv41-sampled-drafting: direct link, hf CLI and curl.
- Browser
- Download file 5.93 kB
-
https://huggingface.co/ProprietaryLegal/dsv41-sampled-drafting/resolve/main/code/offload/dspark/kernels/mxfp4/kernels.py
- Command line
-
hf download hf://ProprietaryLegal/dsv41-sampled-drafting/code/offload/dspark/kernels/mxfp4/kernels.py
-
curl -L -o kernels.py https://huggingface.co/ProprietaryLegal/dsv41-sampled-drafting/resolve/main/code/offload/dspark/kernels/mxfp4/kernels.py
5.93 kB
| """Original SM86 native-packed W4A16 kernels. No native FP4/FP8 MMA or atomics on results.""" | |
| from __future__ import annotations | |
| import triton as tr | |
| import triton.language as tl | |
| def bf16_decode(code, scale): | |
| # E2M1 magnitude as BF16 fields, then exact exponent adjustment. Integer | |
| # construction also handles scale-0 subnormals; no FTZ multiplication here. | |
| mag = code & 7 | |
| exp = tl.where(mag < 2, -1, tl.where(mag < 4, 0, tl.where(mag < 6, 1, 2))) | |
| mant = tl.where((mag == 3) | (mag == 5) | (mag == 7), 64, 0) | |
| biased = exp + scale | |
| normal = (biased << 7) | mant | |
| sub = (128 | mant) >> (1 - biased) | |
| bits = tl.where(biased > 0, normal, sub) | |
| bits = tl.where(biased >= 255, 0x7f80, bits) | |
| bits = tl.where(mag == 0, 0, bits) | ((code & 8) << 12) | |
| bits = tl.where(scale == 255, 0x7fc0, bits) | |
| return bits.to(tl.uint16).to(tl.bfloat16, bitcast=True) | |
| def decode_kernel(C, S, O, COUNT: tl.constexpr, B: tl.constexpr): | |
| i = tl.program_id(0) * B + tl.arange(0, B) | |
| c = tl.load(C+i, i < COUNT, 0).to(tl.int32) | |
| s = tl.load(S+i, i < COUNT, 127).to(tl.int32) | |
| tl.store(O+i, bf16_decode(c, s), i < COUNT) | |
| def _weights(W, S, e, k, n, N: tl.constexpr, K: tl.constexpr): | |
| p = tl.load(W + (e * (K//2) + k[:, None]//2) * N + n[None, :], | |
| (k[:, None] < K) & (n[None, :] < N), 0).to(tl.int32) | |
| c = (p >> ((k[:, None] & 1) * 4)) & 15 | |
| s = tl.load(S + (e * (K//32) + k[:, None]//32) * N + n[None, :], | |
| (k[:, None] < K) & (n[None, :] < N), 127).to(tl.int32) | |
| return bf16_decode(c, s) | |
| def linear_kernel(X, IDS, W, S, U, US, O, OU, STATUS, | |
| N: tl.constexpr, K: tl.constexpr, E: tl.constexpr, | |
| TOP: tl.constexpr, PER_SLOT: tl.constexpr, | |
| FUSED: tl.constexpr, MMA: tl.constexpr, | |
| BN: tl.constexpr, BK: tl.constexpr): | |
| route = tl.program_id(1) | |
| expert = tl.load(IDS+route) | |
| valid = (expert >= 0) & (expert < E) | |
| if not valid: | |
| tl.atomic_or(STATUS, 1) | |
| expert = tl.minimum(tl.maximum(expert, 0), E-1) | |
| row = route if PER_SLOT else route // TOP | |
| n = tl.program_id(0)*BN + tl.arange(0, BN) | |
| if MMA: | |
| m = tl.arange(0, 16) | |
| acc = tl.full((16, BN), 0, tl.float32) | |
| if FUSED: | |
| up = tl.full((16, BN), 0, tl.float32) | |
| for start in range(tr.cdiv(K, BK)): | |
| k = start*BK + tl.arange(0, BK) | |
| x = tl.load(X + row*K + k[None, :], (m[:, None] == 0) & (k[None, :] < K), 0) | |
| w = _weights(W, S, expert, k, n, N, K) | |
| acc = tl.dot(x, w, acc, out_dtype=tl.float32) | |
| if FUSED: | |
| u = _weights(U, US, expert, k, n, N, K) | |
| up = tl.dot(x, u, up, out_dtype=tl.float32) | |
| value = tl.sum(tl.where(m[:, None] == 0, acc, 0), axis=0) | |
| if FUSED: | |
| uvalue = tl.sum(tl.where(m[:, None] == 0, up, 0), axis=0) | |
| else: | |
| # One/few row SIMT control: FP32 product/reduction, decoded BF16 values. | |
| # Only BK independent partials persist, rather than the whole matrix. | |
| acc = tl.full((BK, BN), 0, tl.float32) | |
| if FUSED: | |
| up = tl.full((BK, BN), 0, tl.float32) | |
| for start in range(tr.cdiv(K, BK)): | |
| k = start*BK + tl.arange(0, BK) | |
| x = tl.load(X+row*K+k, k < K, 0).to(tl.float32) | |
| w = _weights(W, S, expert, k, n, N, K).to(tl.float32) | |
| acc += x[:, None] * w | |
| if FUSED: | |
| u = _weights(U, US, expert, k, n, N, K).to(tl.float32) | |
| up += x[:, None] * u | |
| value = tl.sum(acc, axis=0) | |
| if FUSED: | |
| uvalue = tl.sum(up, axis=0) | |
| tl.store(O+route*N+n, tl.where(valid, value, float('nan')), n < N) | |
| if FUSED: | |
| tl.store(OU+route*N+n, tl.where(valid, uvalue, float('nan')), n < N) | |
| def activation_kernel(G, U, R, A, COUNT: tl.constexpr, N: tl.constexpr, | |
| LIMIT: tl.constexpr, B: tl.constexpr): | |
| i = tl.program_id(0)*B + tl.arange(0, B) | |
| # Official linear outputs round to BF16 before clamp/SwiGLU; routing is | |
| # applied before the BF16 down input, not moved through its trained QDQ. | |
| gate = tl.minimum(tl.load(G+i, i < COUNT, 0).to(tl.bfloat16).to(tl.float32), LIMIT) | |
| up = tl.minimum(tl.maximum(tl.load(U+i, i < COUNT, 0).to(tl.bfloat16).to(tl.float32), -LIMIT), LIMIT) | |
| route = tl.load(R+i//N, i < COUNT, 0) | |
| act = gate / (1 + tl.exp(-gate)) * up * route | |
| tl.store(A+i, act.to(tl.bfloat16), i < COUNT) | |
| def combine_kernel(P, R, O, N: tl.constexpr, TOP: tl.constexpr, B: tl.constexpr): | |
| row = tl.program_id(1) | |
| n = tl.program_id(0)*B + tl.arange(0, B) | |
| total = tl.full((B,), 0, tl.float32) | |
| for slot in tl.static_range(TOP): | |
| weight = tl.load(R+row*TOP+slot) | |
| part = tl.load(P+(row*TOP+slot)*N+n, n < N, 0) | |
| total = total + part * weight | |
| tl.store(O+row*N+n, total, n < N) | |
| def native_combine_kernel(P, IDS, O, N: tl.constexpr, TOP: tl.constexpr, B: tl.constexpr): | |
| row = tl.program_id(1) | |
| n = tl.program_id(0)*B + tl.arange(0, B) | |
| total = tl.full((B,), 0, tl.float32) | |
| # Official expert-loop order. Stable slot order also handles duplicate IDs | |
| # in diagnostic inputs. TP reduction must already be complete per route. | |
| for order in tl.static_range(TOP): | |
| value = tl.full((B,), 0, tl.float32) | |
| for slot in tl.static_range(TOP): | |
| eid = tl.load(IDS+row*TOP+slot) | |
| rank = tl.full((), 0, tl.int32) | |
| for other in tl.static_range(TOP): | |
| other_id = tl.load(IDS+row*TOP+other) | |
| rank += ((other_id < eid) | ((other_id == eid) & (other < slot))).to(tl.int32) | |
| part = tl.load(P+(row*TOP+slot)*N+n, n < N, 0).to(tl.bfloat16).to(tl.float32) | |
| value = tl.where(rank == order, part, value) | |
| total = total + value | |
| tl.store(O+row*N+n, total, n < N) | |