suayptalha's picture
Initial release
e70aa91
Raw History Blame Contribute Delete
5.58 kB
"""Triton circuit kernels adapted from Qwenputer by Divyansh Agrawal.
MIT license: see third_party/QWENPUTER_LICENSE.
Changes: explicit per-row active masks to freeze halted batch rows.
"""
import triton
import triton.language as tl
@triton.jit
def _ffn_kernel(x_ptr, y_ptr, D, U, rpa, ixa, wa, rpb, ixb, wb, coef, outd, active_ptr,
BLOCK: tl.constexpr, KA: tl.constexpr, KB: tl.constexpr):
pid = tl.program_id(0)
bat = tl.program_id(1)
if tl.load(active_ptr + bat) == 0:
return
u = pid * BLOCK + tl.arange(0, BLOCK)
m = u < U
xb = x_ptr + bat * D
a0 = tl.load(rpa + u, mask=m, other=0)
na = tl.load(rpa + u + 1, mask=m, other=0) - a0
ka = tl.arange(0, KA)
ma = m[:, None] & (ka[None, :] < na[:, None])
ia = tl.load(ixa + a0[:, None] + ka[None, :], mask=ma, other=0)
av = tl.sum(tl.load(wa + a0[:, None] + ka[None, :], mask=ma, other=0.0)
* tl.load(xb + ia, mask=ma, other=0.0), axis=1)
b0 = tl.load(rpb + u, mask=m, other=0)
nb = tl.load(rpb + u + 1, mask=m, other=0) - b0
kb = tl.arange(0, KB)
mb = m[:, None] & (kb[None, :] < nb[:, None])
ib = tl.load(ixb + b0[:, None] + kb[None, :], mask=mb, other=0)
bv = tl.sum(tl.load(wb + b0[:, None] + kb[None, :], mask=mb, other=0.0)
* tl.load(xb + ib, mask=mb, other=0.0), axis=1)
val = tl.load(coef + u, mask=m, other=0.0) * av * tl.maximum(bv, 0.0)
od = tl.load(outd + u, mask=m, other=0)
tl.atomic_add(y_ptr + bat * D + od, val, mask=m)
@triton.jit
def _lag_load(xb, hb, i, m, D):
"""The lagged residual: index lag * D + d (lag 0: x, lags 1..3: the history)."""
lo = i < D
return tl.where(lo, tl.load(xb + i, mask=m & lo, other=0.0),
tl.load(hb + i - D, mask=m & (i >= D), other=0.0))
@triton.jit
def _rows(xb, hb, D, rp, ix, w, base, ch, KP: tl.constexpr):
"""relu of 128 sparse rows (row base + ch) over the lagged residual."""
r0 = tl.load(rp + base + ch)
n = tl.load(rp + base + ch + 1) - r0
kk = tl.arange(0, KP)
mk = kk[None, :] < n[:, None]
i = tl.load(ix + r0[:, None] + kk[None, :], mask=mk, other=0)
acc = tl.sum(tl.load(w + r0[:, None] + kk[None, :], mask=mk, other=0.0)
* _lag_load(xb, hb, i, mk, D), axis=1)
return tl.maximum(acc, 0.0)
@triton.jit
def _scalar(xb, hb, D, rp, ix, w, vh):
lane = tl.arange(0, 32)
s0 = tl.load(rp + vh)
n = tl.load(rp + vh + 1) - s0
mk = lane < n
i = tl.load(ix + s0 + lane, mask=mk, other=0)
return tl.sum(tl.load(w + s0 + lane, mask=mk, other=0.0) * _lag_load(xb, hb, i, mk, D), axis=0)
@triton.jit
def _head_kernel(x_ptr, h_ptr, S_ptr, y_ptr, D, V,
qrp, qix, qw, krp, kix, kw, vrp, vix, vw, zrp, zix, zw,
arp, aix, aw, brp, bix, bw, bconst, odim, ow, khead, nrows,
active_ptr, KQ: tl.constexpr, KK: tl.constexpr, KV: tl.constexpr, KZ: tl.constexpr,
QHOT: tl.constexpr):
vh = tl.program_id(0)
bat = tl.program_id(1)
if tl.load(active_ptr + bat) == 0:
return
ch = tl.arange(0, 128)
xb = x_ptr + bat * D
hb = h_ptr + bat * 3 * D
h = tl.load(khead + vh)
k = _rows(xb, hb, D, krp, kix, kw, h * 128, ch, KK)
v = _rows(xb, hb, D, vrp, vix, vw, vh * 128, ch, KV)
z = _rows(xb, hb, D, zrp, zix, zw, vh * 128, ch, KZ)
q = _rows(xb, hb, D, qrp, qix, qw, h * 128, ch, KQ)
bv = _scalar(xb, hb, D, brp, bix, bw, vh) + tl.load(bconst + vh)
Sb = S_ptr + (bat * V + vh) * 16384
nr = tl.load(nrows + vh) # > 0: the head decays, in its first nr rows
if nr > 0:
av = _scalar(xb, hb, D, arp, aix, aw, vh)
fac = tl.where(av == 0.0, 1.0, tl.where(av == 110.0, 0.5, 0.0))
if fac != 1.0:
for r in range(nr):
tl.store(Sb + r * 128 + ch, tl.load(Sb + r * 128 + ch) * fac)
kmax = tl.max(k, axis=0)
krow = tl.argmax(k, axis=0)
if (kmax > 0.0) & (bv == 1.0):
tl.store(Sb + krow * 128 + ch, v)
tl.debug_barrier()
# the read: the sum of the rows whose query is set (multi-hot queries have equal values)
o = tl.zeros([128], dtype=tl.float32)
for _ in range(QHOT):
qm = tl.max(q, axis=0)
qi = tl.argmax(q, axis=0)
if qm > 0.0:
o += tl.load(Sb + qi * 128 + ch)
q = tl.where(ch == qi, 0.0, q)
ref = tl.sum(tl.where(ch < 2, o * o, 0.0), axis=0)
norm = tl.math.sqrt_rn(ref / 128.0)
out = tl.where(ref > 0.0, tl.math.div_rn(o, tl.where(ref > 0.0, norm, 1.0)), 0.0)
wv = tl.load(ow + vh * 128 + ch)
dd = tl.load(odim + vh * 128 + ch)
tl.atomic_add(y_ptr + bat * D + dd, out * z * wv, mask=wv != 0.0)
@triton.jit
def _apply_kernel(x_ptr, y_ptr, h_ptr, D, active_ptr, HIST: tl.constexpr, BLOCK: tl.constexpr):
"""x += y, y = 0; with HIST, the lag history (h: [3, D] per row, h[0] = lag 1) moves on
first, the input x becoming lag 1."""
pid = tl.program_id(0)
bat = tl.program_id(1)
if tl.load(active_ptr + bat) == 0:
return
i = pid * BLOCK + tl.arange(0, BLOCK)
m = i < D
xo = x_ptr + bat * D + i
x = tl.load(xo, mask=m, other=0.0)
if HIST:
hb = h_ptr + bat * 3 * D + i
h1 = tl.load(hb + D, mask=m, other=0.0)
h0 = tl.load(hb, mask=m, other=0.0)
tl.store(hb + 2 * D, h1, mask=m)
tl.store(hb + D, h0, mask=m)
tl.store(hb, x, mask=m)
yo = y_ptr + bat * D + i
tl.store(xo, x + tl.load(yo, mask=m, other=0.0), mask=m)
tl.store(yo, tl.zeros([BLOCK], dtype=tl.float32), mask=m)