"""Online Q/K/V packing plus native FP4 tile-streaming attention. Packing is performed afresh for every input. No weights, old activations, scores or probability matrices are cached. P is quantized only on chip. """ import triton import triton.language as tl from ._quantize import quantize, quantize_p @triton.jit def pack_qk(X, CODES, SCALES, FACTORS, M: tl.constexpr, H: tl.constexpr, SX: tl.constexpr, SH: tl.constexpr, MP: tl.constexpr, REPAIR: tl.constexpr): r=tl.program_id(0)*16+tl.arange(0,16) h=tl.program_id(1) d=tl.arange(0,128) x=tl.load(X+r[:,None]*SX+h*SH+d[None,:],r[:,None]1 if selected: if RELOAD_Q: q1=tl.load(QC+HQ*MP*64+qi,mi[:,None]=3: k1=tl.load(KC+HK*NP*64+ki);kr=tl.load(KS+HK*NP*8+ksi) score=tl.dot_scaled(q0,qs,'e2m1',k1.T,kr,'e2m1',score) if TERMS==4:score=tl.dot_scaled(q1,qr,'e2m1',k1.T,kr,'e2m1',score) score=score*qf[:,None]*kf[None,:]*0.08838834764831845 score=tl.where(ni[None,:]1 else:pv_selected=False elif REPAIR:pv_selected=selected else:pv_selected=False if (PV_REPAIR if SEPARATE else REPAIR) and LAZY_P and not (PV_FULL if SEPARATE else FULL): if pv_selected: p0,ps,p1,pr,pf=quantize_p(p,BM,BN,True,FAST_P) else: p0,ps,p1,pr,pf=quantize_p(p,BM,BN,False,FAST_P) else: p0,ps,p1,pr,pf=quantize_p(p,BM,BN,PV_REPAIR if SEPARATE else REPAIR,FAST_P) vi=((kh*tl.cdiv(N,128)+start*BN//128)*128+dd[:,None])*64+(start*BN%128)//2+tl.arange(0,BN//2)[None,:] vsi=((kh*tl.cdiv(N,128)+start*BN//128)*128+dd[:,None])*8+(start*BN%128)//16+tl.arange(0,BN//16)[None,:] if TRANSPOSE_V: vi=(kh*tl.cdiv(N,128)+start*BN//128)*128*64+((start*BN%128)//2+tl.arange(0,BN//2)[None,:])*128+dd[:,None] vsi=(kh*tl.cdiv(N,128)+start*BN//128)*128*8+((start*BN%128)//16+tl.arange(0,BN//16)[None,:])*128+dd[:,None] v0=tl.load(VC+vi);vs=tl.load(VS+vsi) vf=tl.load(VF+(kh*tl.cdiv(N,128)+start*BN//128)*128+dd) tile=tl.dot_scaled(p0,ps,'e2m1',v0.T,vs,'e2m1') if PV_REPAIR if SEPARATE else REPAIR: if pv_selected: tile=tl.dot_scaled(p1,pr,'e2m1',v0.T,vs,'e2m1',tile) if (PV_TERMS if SEPARATE else TERMS)>=3: v1=tl.load(VC+HK*NP*64+vi);vr=tl.load(VS+HK*NP*8+vsi) tile=tl.dot_scaled(p0,ps,'e2m1',v1.T,vr,'e2m1',tile) if (PV_TERMS if SEPARATE else TERMS)==4:tile=tl.dot_scaled(p1,pr,'e2m1',v1.T,vr,'e2m1',tile) acc=acc*alpha[:,None]+tile*pf[:,None]*vf[None,:];mx=nm if SPLITS==1: tl.store(O+(mi[:,None]*HQ+h)*128+dd[None,:],acc/denom[:,None],mi[:,None]=3) planes=2 if local_repair else 1 codes=torch.empty((planes,hh*padded,64),device=q.device,dtype=torch.uint8) scales=torch.empty((planes,hh*padded,8),device=q.device,dtype=torch.float8_e4m3fn) factors=torch.empty((hh*padded,),device=q.device,dtype=torch.float32) if kind=='v': pack_v[(8,np//128,hh)](x,codes,scales,factors,energy,nn,hh,x.stride(1),x.stride(2),np//128,local_repair and not defer_residual,need_energy,transpose_v,num_warps=4) else: pack_qk[(triton.cdiv(padded,16),hh)](x,codes,scales,factors,nn,hh,x.stride(1),x.stride(2),padded,local_repair and not defer_residual,num_warps=4) outputs.extend([codes,scales,factors]) return (outputs,mp,np,energy) if need_energy else (outputs,mp,np) @triton.jit def select_tiles(Q,K,ENERGY,FLAGS,M:tl.constexpr,N:tl.constexpr,HQ:tl.constexpr,HK:tl.constexpr, Q_S:tl.constexpr,Q_H:tl.constexpr,K_S:tl.constexpr,K_H:tl.constexpr, COUNT:tl.constexpr,TERMS:tl.constexpr,BT:tl.constexpr): h=tl.program_id(0);mt=tl.program_id(1);kh=h//(HQ//HK) # Sixteen MMA rows duplicate the eight fixed query samples. qi=tl.minimum(mt*128+(tl.arange(0,16)%8)*16,M-1) sample=tl.arange(0,BT*8);ki=sample//8*128+sample%8*16 dd=tl.arange(0,128) q=tl.load(Q+qi[:,None]*Q_S+h*Q_H+dd[None,:]) k=tl.load(K+tl.minimum(ki[:,None],N-1)*K_S+kh*K_H+dd[None,:]) sim=tl.dot(q,k.T)*0.08838834764831845 sim=tl.where(ki[None,:]score[:,None])|((score[None,:]==score[:,None])&(ti[None,:]score[:,None])|((score[None,:]==score[:,None])&(ti[None,:]