code wiki / (root) / nx_q4k_dot_simd2_lib.nx

nx_q4k_dot_simd2_lib.nx

buildroot/runtime/nx_q4k_dot_simd2_lib.nx

5851 B105 linesdepth 7pulls 9 transitivereach 46 importersview sourcekind librarytopic q4k
docsdependenciesstructsconstsfunctions

about

nx_q4k_dot_simd2_lib.nx -- the fused Q4_K SIMD dot with the COMPILER-EMITTED unpack (2026-09-02, LM4c). Same algebra as nx_q4k_dot_simd (nx_q4k_dot_simd_lib): per super-block the eight i32 lanes accumulate sum over all eight sub-blocks of (sc_sub*q)*col and ONE horizontal sum serves the super-block; the dmin term is a scalar sum of m_sub times the precomputed sub-block activation sums. The ONLY difference is HOW the 32 packed nibble bytes of a sub-block pair become 64 scaled i16 lanes: nx_q4k_dot_simd does it in scalar NishiLang (four u64 reads, eight bit-spreads, eight 64-bit multiplies -- about 1.4 ops per weight, the measured residual between the resident-Q4_K decode and the i16 cache route), this one calls __q4k_unpack32s, one intrinsic that nx_cc emits as 14 AVX2 instructions (vpmovzxbw, vpsrlw, vpand, vpmullw, vmovups). Bit-identical by construction: every lane ends up holding exactly (nibble * sc). REQUIRES a compiler that knows __q4k_unpack32s (nx_types OP_Q4KUNPACK32S); a consumer built with an older compiler fails to COMPILE, never silently falls back -- which is why this lives in its own lib and nx_q4k_dot_simd_lib stays as the compiler-neutral twin until the toolchain is promoted on every host. qbuf: 128 B caller scratch -- lo lanes at qbuf[0..31], hi lanes at qbuf[32..63] (i16), the layout __i16x16_madd consumes directly (two 32-byte halves per group). license_tier: ORIGINAL

dependencies 7 imports · 2 importers

nx_syscalls.nx nx_tier.nx nx_le.nx nx_tensor.nx nx_gguf.nx nx_gguf_load.nx nx_q4k_dot_simd_lib.nx nx_q4k_dot_simd2_lib.nx nx_nofloat_q4k.nx nx_q4k_simd2_gate.nx

imports: nx_syscalls.nxnx_tier.nxnx_le.nxnx_tensor.nxnx_gguf.nxnx_gguf_load.nxnx_q4k_dot_simd_lib.nx

imported by: nx_nofloat_q4k.nxnx_q4k_simd2_gate.nx

structs

none

consts

24const DS2_SUPER_BYTES: i64 = 144
25const DS2_SUPER_VALS: i64 = 256
26const DS2_SCALES_OFF: i64 = 4
27const DS2_QS_OFF: i64 = 16
28const DS2_GROUP_BYTES: i64 = 32
29const DS2_SUB_VALS: i64 = 32
30const DS2_SUBBLOCKS: i64 = 8
31const DS2_SC_HI_SHIFT: i64 = 16 // scpack = sc_lo | sc_hi << 16
32const DS2_QBUF_HI_OFF: i64 = 64 // hi lanes start 64 bytes into qbuf (32 i16)
33const DS2_HALF_BYTES: i64 = 32 // one __i16x16_madd consumes 32 bytes (16 lanes)

functions

37func nx_q4k_dot_simd2(buf: *u8, base_off: i64, n_blocks: i64, col_i16: *i64, qbuf: *i64, acc: *i64, sc_pre: *i64) -> i64