onwx / tools /glue_cpu /glue_cpu.cpp
ryugyosoft's picture
onwx 0.9.0: Qwen3.6 35B-A3B experts from the SSD (~7 GB of memory), images, faster MTP; changelog shown with updates
5123724 verified
Raw History Blame Contribute Delete
43.2 kB
// glue_cpu: the onwx all-NPU prefill's glue ops (xd_gen pfx_glue.cc / pfx_glue.py) on the CPU, on the same buffers
// (the mapped BOs) in the same DDR layouts, with the NPU kernels' arithmetic reproduced step by step (bf16 hi / lo
// splits, 3-product fp32 multiplies, the division-free sigmoid, the FWHT's butterfly order, the bfp16ebs8 rounding),
// so the next NPU GEMM reads the same X tiles. AVX-512 (Zen 5); a persistent thread pool (pinned: the least
// performant core class when there are 2+, else every physical core; Windows: EcoQoS).
//
// cg_info(int out[8]) [0] AVX-512 usable [1] efficiency classes (mask) [2] chosen cores [3] physical cores
// cg_init(nthreads, mode) the pool (0: one a chosen core); mode bits: 1 pin, 2 EcoQoS (Windows). Returns threads.
// cg_run(op, M, H, I, ND, KO, NO, ZB, a0, a1, a2, a3, dbg)
// op: 0 n1 (h P X) 1 r1n (h Y P X) 2 r3n (h Y P X) 3 r3 (h Y P) 4 act (Y P X) 5 dno (O Z P X) 6 rotp (O P X)
// 7 rotb (O P X) - the buffers in pfx_glue.py's ARGS order; P the layer's parameter buffer (make_P: headers,
// sign bits, CT, the DNO weight). dbg (optional): the rotated fp32 activations [M][K] before the bfp16
// conversion. Returns 0 (or -1: no AVX-512 / bad op, -2: bad rotation block). P's op header [12]: the
// rotation block (0 / 1024: H_1024 a chunk; 512: two H_512 a chunk; 4096: + the 4-chunk butterfly / 2).
// cg_set(key, val) test knobs (0: the bfp rounding variant, 1: rsqrt variant, 2: reduce order)
#include <immintrin.h>
#include <atomic>
#include <algorithm>
#include <cmath>
#include <condition_variable>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <mutex>
#include <thread>
#include <vector>
#ifdef _WIN32
#include <intrin.h>
#include <windows.h>
#define API extern "C" __declspec(dllexport)
#else
#include <cpuid.h>
#include <dirent.h>
#include <pthread.h>
#include <sched.h>
#include <unistd.h>
#define API extern "C" __attribute__((visibility("default")))
#endif
typedef __m512 V;
typedef __m512i VI;
static int g_knob[8];
// (only the kernels below are AVX-512 code: the rest - the CPU check, the core list, the pool - runs on any x86-64,
// so a CPU without AVX-512 gets cg_info()[0] = 0 / cg_init() = -1 instead of an illegal instruction)
#if defined(__GNUC__) && !defined(_MSC_VER)
#pragma GCC push_options
#pragma GCC target("avx512f,avx512bw,avx512dq,avx512vl,fma")
#endif
// ---------------------------------------------------------------- the NPU's arithmetic (pfx_sig.h)
static inline V bc(float x) { return _mm512_set1_ps(x); }
static inline VI ibc(int x) { return _mm512_set1_epi32(x); }
// fp32 -> bf16 (round to nearest even), kept as fp32
static inline V bfr(V v) {
VI u = _mm512_castps_si512(v);
VI lsb = _mm512_and_si512(_mm512_srli_epi32(u, 16), ibc(1));
u = _mm512_add_epi32(u, _mm512_add_epi32(ibc(0x7fff), lsb));
return _mm512_castsi512_ps(_mm512_and_si512(u, ibc((int)0xffff0000u)));
}
static float bfs(float x) { // (scalar: a bf16 constant, bbc())
uint32_t u;
memcpy(&u, &x, 4);
u = (u + 0x7fff + ((u >> 16) & 1)) & 0xffff0000u;
memcpy(&x, &u, 4);
return x;
}
struct T2 {
V h, l;
};
static inline T2 sp2(V v) {
T2 r;
r.h = bfr(v);
r.l = bfr(_mm512_sub_ps(v, r.h));
return r;
}
static inline V fma_(V a, V b, V c) { return _mm512_fmadd_ps(a, b, c); } // (a * b exact for bf16 a, b)
static inline V mulf(V a, V b) {
T2 x = sp2(a), y = sp2(b);
V r = _mm512_mul_ps(x.h, y.h);
r = fma_(x.h, y.l, r);
return fma_(x.l, y.h, r);
}
static inline V addf(V a, V b, float sb) {
T2 y = sp2(b);
V s = bc(sb);
V r = fma_(y.h, s, a);
return fma_(y.l, s, r);
}
static inline V rsqrt16(V x) {
V r;
if (g_knob[1] == 1) { // (variant: the AVX-512 14-bit estimate)
r = _mm512_rsqrt14_ps(x);
} else {
r = _mm512_div_ps(bc(1.0f), _mm512_sqrt_ps(x));
}
V hx = mulf(x, bc(0.5f));
for (int k = 0; k < 2; k++)
r = mulf(r, addf(bc(1.5f), mulf(hx, mulf(r, r)), -1.0f));
return r;
}
static float C_S1, C_S2, C_P4, C_R1, C_R2;
static void init_consts() {
C_S1 = bfs(-1.4453125f);
C_S2 = bfs(0.00262451171875f);
C_P4 = bfs(0.00961812911f);
C_R1 = bfs(-1.4545455f);
C_R2 = bfs(0.32323232f);
}
// sigmoid(x) for bf16 x (pfx_sig.h sigm)
static inline V sigm(V x) {
V ta = _mm512_mul_ps(x, bc(C_S1));
ta = fma_(x, bc(C_S2), ta);
V u = _mm512_castsi512_ps(_mm512_or_si512(_mm512_castps_si512(ta), ibc((int)0x80000000u)));
u = _mm512_max_ps(u, bc(-126.0f));
V um = _mm512_add_ps(u, bc(12582912.0f));
V n = _mm512_sub_ps(um, bc(12582912.0f));
V f = _mm512_sub_ps(u, n);
VI e = _mm512_sub_epi32(_mm512_castps_si512(um), ibc(0x4B400000 - 127));
V pw = _mm512_castsi512_ps(_mm512_slli_epi32(e, 23));
T2 fs = sp2(f);
V p = fma_(fs.h, bc(C_P4), bc(0.0555041087f));
p = fma_(fs.h, bfr(p), bc(0.240226507f));
p = fma_(fs.h, bfr(p), bc(0.693147181f));
{
T2 ps = sp2(p);
V r = fma_(ps.h, fs.h, bc(1.0f));
r = fma_(ps.h, fs.l, r);
p = fma_(ps.l, fs.h, r);
}
V s2 = bfr(pw);
T2 ps = sp2(p);
V ea = _mm512_mul_ps(ps.h, s2);
ea = fma_(ps.l, s2, ea);
T2 es = sp2(ea);
V da = _mm512_add_ps(ea, bc(1.0f));
T2 d = sp2(da);
V dd = bfr(_mm512_mul_ps(d.h, d.h));
V ra = fma_(d.h, bc(C_R1), bc(2.1212121f));
ra = fma_(dd, bc(C_R2), ra);
{
V r0 = ra;
T2 rs = sp2(r0);
V res = _mm512_fnmadd_ps(d.h, rs.h, bc(1.0f));
res = _mm512_fnmadd_ps(d.h, rs.l, res);
res = _mm512_fnmadd_ps(d.l, rs.h, res);
ra = fma_(rs.h, bfr(res), r0);
}
V r = ra;
T2 rs = sp2(r);
V er = _mm512_mul_ps(es.h, rs.h);
er = fma_(es.h, rs.l, er);
er = fma_(es.l, rs.h, er);
__mmask16 neg = _mm512_cmp_ps_mask(x, bc(0.0f), _CMP_LT_OQ);
return _mm512_mask_blend_ps(neg, r, er);
}
// the accumulator's fp32 add (measured on the NPU's residual adds): the smaller operand rounded (to nearest even) to 2
// bits below the larger one's ulp, then the sum rounded to fp32 (IEEE: exact alignment). Done in fp64 (exact).
static inline __m512d addm_pd(__m512d a, __m512d b) {
__m512d na = _mm512_abs_pd(a), nb = _mm512_abs_pd(b);
__mmask8 ab = _mm512_cmp_pd_mask(na, nb, _CMP_GE_OQ);
__m512d big = _mm512_mask_blend_pd(ab, b, a), sm = _mm512_mask_blend_pd(ab, a, b);
__m512d e = _mm512_getexp_pd(big); // floor(log2 |big|) (-inf for 0)
__m512d c = _mm512_scalef_pd(_mm512_set1_pd(1.5), _mm512_add_pd(e, _mm512_set1_pd(27.0)));
sm = _mm512_sub_pd(_mm512_add_pd(sm, c), c);
return _mm512_add_pd(big, sm);
}
static inline V addm(V a, V b) {
if (g_knob[2] == 1 && !g_knob[3])
return _mm512_add_ps(a, b);
__m512d lo = addm_pd(_mm512_cvtps_pd(_mm512_castps512_ps256(a)), _mm512_cvtps_pd(_mm512_castps512_ps256(b)));
__m512d hi = addm_pd(_mm512_cvtps_pd(_mm512_extractf32x8_ps(a, 1)), _mm512_cvtps_pd(_mm512_extractf32x8_ps(b, 1)));
return _mm512_insertf32x8(_mm512_castps256_ps512(_mm512_cvtpd_ps(lo)), _mm512_cvtpd_ps(hi), 1);
}
// sigmoid(x) and silu(x) / 32 of every bf16 x (sigm, mulf: the NPU's results exactly; 2 x 256 KB, made once)
alignas(64) static float g_sig[65536], g_sz[65536];
static void init_tables() {
alignas(64) int idx[16];
for (int b = 0; b < 65536; b += 16) {
for (int i = 0; i < 16; i++)
idx[i] = (b + i) << 16;
V x = _mm512_castsi512_ps(_mm512_loadu_si512(idx));
V sb = sigm(x);
_mm512_store_ps(g_sig + b, sb);
_mm512_store_ps(g_sz + b, mulf(_mm512_mul_ps(x, bc(0.03125f)), sb));
}
}
static inline VI bfidx(V x) { return _mm512_srli_epi32(_mm512_castps_si512(x), 16); } // (x a bf16 value)
static inline V bf16x16(const uint16_t *p) { // 16 bf16 -> fp32
__m256i b = _mm256_loadu_si256((const __m256i *)p);
return _mm512_castsi512_ps(_mm512_slli_epi32(_mm512_cvtepu16_epi32(b), 16));
}
static inline V bf16x8x2(const uint16_t *p0, const uint16_t *p1) { // 8 + 8 bf16 -> fp32
__m128i a = _mm_loadu_si128((const __m128i *)p0), b = _mm_loadu_si128((const __m128i *)p1);
__m256i c = _mm256_inserti128_si256(_mm256_castsi128_si256(a), b, 1);
return _mm512_castsi512_ps(_mm512_slli_epi32(_mm512_cvtepu16_epi32(c), 16));
}
static inline V ld8x2(const float *p0, const float *p1) {
return _mm512_insertf32x8(_mm512_castps256_ps512(_mm256_loadu_ps(p0)), _mm256_loadu_ps(p1), 1);
}
// ---------------------------------------------------------------- FWHT 1024 (the NPU's stage order)
static inline V negv(V a) { return _mm512_xor_ps(a, bc(-0.0f)); }
static inline V fadd(V a, V b) { return g_knob[3] ? addm(a, b) : _mm512_add_ps(a, b); }
static inline V fsub(V a, V b) { return g_knob[3] ? addm(a, negv(b)) : _mm512_sub_ps(a, b); }
static inline void bfly(float *x, int h) { // stage of stride h >= 16
for (int i = 0; i < 1024; i += 2 * h)
for (int j = i; j < i + h; j += 16) {
V a = _mm512_load_ps(x + j), b = _mm512_load_ps(x + j + h);
_mm512_store_ps(x + j, fadd(a, b));
_mm512_store_ps(x + j + h, fsub(a, b));
}
}
static VI P8, P4, P2, P1;
static void init_perm() {
int a[16];
for (int s : {8, 4, 2, 1}) {
for (int i = 0; i < 16; i++)
a[i] = i ^ s;
VI v = _mm512_loadu_si512(a);
(s == 8 ? P8 : s == 4 ? P4 : s == 2 ? P2 : P1) = v;
}
}
static inline V intra(V v, VI perm, __mmask16 up) { // stride s < 16 inside the vector: lo + hi | lo - hi
V w = _mm512_permutexvar_ps(perm, v);
return _mm512_mask_blend_ps(up, fadd(v, w), fsub(w, v));
}
static void fwht(float *x, bool skip512 = false) { // (skip512: two H_512 blocks - Prism's block 512)
bfly(x, 16);
bfly(x, 32);
bfly(x, 64);
bfly(x, 128);
bfly(x, 256);
if (!skip512)
bfly(x, 512);
for (int j = 0; j < 1024; j += 16) {
V v = _mm512_load_ps(x + j);
v = intra(v, P8, 0xFF00);
v = intra(v, P4, 0xF0F0);
v = intra(v, P2, 0xCCCC);
v = intra(v, P1, 0xAAAA);
_mm512_store_ps(x + j, v);
}
}
// ---------------------------------------------------------------- bfp16ebs8: 8 values -> exponent byte + 8 int8
static inline void bfp8(const float *v, uint8_t *o) {
__m256 x = _mm256_loadu_ps(v);
__m256 ax = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), x);
__m256 m1 = _mm256_max_ps(ax, _mm256_permute2f128_ps(ax, ax, 1));
m1 = _mm256_max_ps(m1, _mm256_shuffle_ps(m1, m1, 0x4E));
m1 = _mm256_max_ps(m1, _mm256_shuffle_ps(m1, m1, 0xB1));
uint32_t mb = (uint32_t)_mm_cvtsi128_si32(_mm_castps_si128(_mm256_castps256_ps128(m1)));
int E = (int)(mb >> 23); // the max's biased exponent: value = m * 2^(E - 133)
if (E == 0) { // (zero / denormal block)
memset(o, 0, 9);
return;
}
int sh = 133 - E; // scale 2^sh (E in 1..254: sh in -121..132)
__m256 sc;
{
int e2 = sh + 127;
if (e2 < 1 || e2 > 254) { // (out of fp32's range: scale in two steps)
float s = ldexpf(1.0f, sh);
sc = _mm256_set1_ps(s);
} else {
sc = _mm256_castsi256_ps(_mm256_set1_epi32(e2 << 23));
}
}
__m256 y = _mm256_mul_ps(x, sc);
__m256 r = _mm256_round_ps(y, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
// (the NPU: a value rounding to +128 moves the block to the next exponent; -128 stays)
if (g_knob[0] != 1 && _mm256_movemask_ps(_mm256_cmp_ps(r, _mm256_set1_ps(127.0f), _CMP_GT_OQ))) {
E++;
y = _mm256_mul_ps(y, _mm256_set1_ps(0.5f));
r = _mm256_round_ps(y, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
r = _mm256_min_ps(_mm256_max_ps(r, _mm256_set1_ps(-128.0f)), _mm256_set1_ps(127.0f));
__m256i iv = _mm256_cvtps_epi32(r);
__m128i lo = _mm256_castsi256_si128(iv), hi = _mm256_extracti128_si256(iv, 1);
__m128i p16 = _mm_packs_epi32(lo, hi);
__m128i p8 = _mm_packs_epi16(p16, p16);
o[0] = (uint8_t)E;
_mm_storel_epi64((__m128i *)(o + 1), p8);
}
// ---------------------------------------------------------------- an op
enum { N1, R1N, R3N, R3, ACT, DNO, ROTP, ROTB, MOEG, MOEA, MOES };
static const int ROTB_T[6][4] = {{0, 1, 512, 0}, {512, 2, 256, 544}, {1312, 1, 512, 0},
{2112, 1, 512, 0}, {2624, 2, 256, 544}, {3424, 1, 512, 0}};
static const int HW_ = 1536, CT_IN = 10752, CT_POST = 18944;
struct Op {
int op, M, H, I, ND, KO, NO, ZB, KX, KS, NMT, NB, nunits, nq;
int rb, G; // the rotation block (P header [12]; 0: 1024) / the 1024-chunks it spans
size_t S; // words between Y pieces (32 M)
float *h;
const uint16_t *Y, *Z, *Ob;
const float *Of;
uint8_t *X;
float *dbg;
float invh;
std::vector<float> ct, sg, dw;
// [MoE] (cg_moe)
const uint8_t *Xs;
const int32_t *idx;
const float *wt;
int nk; // (MOES: rows a token)
};
struct alignas(64) Scratch {
float wk[8][4096]; // 8 tokens x (up to 4) 1024-chunks of one rotation block
};
static inline uint8_t *xblk(const Op &g, int T, int ks, int i) { // the 72 B of block T, K-tile ks, i
int trg = T >> 3, z = T & 7, r = trg & 3, mt = trg >> 2;
size_t w = ((size_t)(r * g.NMT + mt) * g.KS + ks) * 2304 + (z >> 1) * 576 + i * 36 + (z & 1) * 18;
return g.X + w * 4;
}
// the 8 tokens' blocks of columns c .. c + 7 -> 72 B (as bfp8, two tokens a vector)
static inline void bfp72(const Scratch &s, int c, uint8_t *o) {
alignas(16) uint8_t mb[16];
for (int a = 0; a < 8; a += 2) {
V v = ld8x2(s.wk[a] + c, s.wk[a + 1] + c);
V ax = _mm512_abs_ps(v);
V m = _mm512_max_ps(ax, _mm512_permute_ps(ax, 0xB1));
m = _mm512_max_ps(m, _mm512_permute_ps(m, 0x4E));
m = _mm512_max_ps(m, _mm512_shuffle_f32x4(m, m, 0xB1));
VI E = _mm512_srli_epi32(_mm512_castps_si512(m), 23);
V y = _mm512_scalef_ps(v, _mm512_cvtepi32_ps(_mm512_sub_epi32(ibc(133), E)));
V r = _mm512_roundscale_ps(y, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
__mmask16 over = _mm512_cmp_ps_mask(r, bc(127.0f), _CMP_GT_OQ);
if (over) { // (a value rounding to +128: the block's exponent + 1)
__mmask16 bm = (__mmask16)(((over & 0xFF) ? 0xFF : 0) | ((over & 0xFF00) ? 0xFF00 : 0));
E = _mm512_mask_add_epi32(E, bm, E, ibc(1));
y = _mm512_mask_mul_ps(y, bm, y, bc(0.5f));
r = _mm512_roundscale_ps(y, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__mmask16 nz = _mm512_cmpneq_epi32_mask(E, _mm512_setzero_si512());
r = _mm512_maskz_mov_ps(nz, _mm512_max_ps(r, bc(-128.0f)));
_mm_store_si128((__m128i *)mb, _mm512_cvtsepi32_epi8(_mm512_cvtps_epi32(r)));
uint8_t *p = o + a * 9;
p[0] = (uint8_t)_mm_cvtsi128_si32(_mm512_castsi512_si128(E));
memcpy(p + 1, mb, 8);
p[9] = (uint8_t)_mm_cvtsi128_si32(_mm512_extracti32x4_epi32(E, 2));
memcpy(p + 10, mb + 8, 8);
}
}
// the unit's 8 tokens x G chunks (q0 ..) -> FWHT per chunk (Prism's block: 512 leaves the last stage out, 4096 adds
// the 4-chunk butterfly / 2 after the chunks, as the decode kernels) -> X (and dbg)
static void emit(const Op &g, Scratch &s, int T, int q0) {
if (!(g_knob[6] & 2))
for (int a = 0; a < 8; a++)
for (int j = 0; j < g.G; j++)
fwht(s.wk[a] + j * 1024, g.rb == 512);
if (g.G == 4)
for (int a = 0; a < 8; a++) {
float *x = s.wk[a];
for (int c = 0; c < 1024; c += 16) {
V x0 = _mm512_load_ps(x + c), x1 = _mm512_load_ps(x + 1024 + c);
V x2 = _mm512_load_ps(x + 2048 + c), x3 = _mm512_load_ps(x + 3072 + c);
V p = _mm512_add_ps(x0, x1), m = _mm512_sub_ps(x0, x1), u = _mm512_add_ps(x2, x3), w = _mm512_sub_ps(x2, x3);
V h = bc(0.5f);
_mm512_store_ps(x + c, _mm512_mul_ps(_mm512_add_ps(p, u), h));
_mm512_store_ps(x + 1024 + c, _mm512_mul_ps(_mm512_add_ps(m, w), h));
_mm512_store_ps(x + 2048 + c, _mm512_mul_ps(_mm512_sub_ps(p, u), h));
_mm512_store_ps(x + 3072 + c, _mm512_mul_ps(_mm512_sub_ps(m, w), h));
}
}
if (g_knob[6] & 4)
return;
for (int j = 0; j < g.G; j++) {
int q = q0 + j;
if (g.dbg)
for (int a = 0; a < 8; a++)
memcpy(g.dbg + (size_t)(T * 8 + a) * g.KX + q * 1024, s.wk[a] + j * 1024, 4096);
for (int kk = 0; kk < 8; kk++)
for (int i = 0; i < 16; i++) {
uint8_t *o = xblk(g, T, q * 8 + kk, i);
int c = j * 1024 + kk * 128 + i * 8;
if (g_knob[4])
for (int a = 0; a < 8; a++)
bfp8(s.wk[a] + c, o + a * 9);
else
bfp72(s, c, o);
}
}
}
// 1 / rms of 16 lanes of sums of squares s (sc: the mean's scale)
static inline V rms_r(V s, float sc) { return rsqrt16(addf(mulf(s, bc(sc)), bc(1e-6f), 1.0f)); }
static void unit_norm(const Op &g, Scratch &s, int T) {
int NPC = g.H / 64, np = g.op == R1N ? g.NO : (g.op == R3N || g.op == R3) ? g.ND : 0;
float *hb = g.h + (size_t)T * NPC * 576;
V acc[4] = {_mm512_setzero_ps(), _mm512_setzero_ps(), _mm512_setzero_ps(), _mm512_setzero_ps()};
for (int p = 0; p < NPC; p++) {
float *hp = hb + p * 576;
for (int yp = 0; yp < np; yp++) {
const uint16_t *y = g.Y + ((size_t)(p * np + yp) * g.S + (size_t)T * 256) * 2;
for (int v = 0; v < 512; v += 16)
_mm512_storeu_ps(hp + v, addm(_mm512_loadu_ps(hp + v), bf16x16(y + v)));
}
if (g.op == R3)
continue;
for (int j = 0; j < 8; j++)
for (int k = 0; k < 4; k++) {
T2 x = sp2(_mm512_loadu_ps(hp + j * 64 + 16 * k));
acc[k] = fma_(x.h, x.h, acc[k]);
acc[k] = fma_(x.h, _mm512_add_ps(x.l, x.l), acc[k]);
}
}
if (g.op == R3)
return;
alignas(64) float sq[64], ss[16];
for (int k = 0; k < 4; k++)
_mm512_store_ps(sq + 16 * k, acc[k]);
for (int i = 0; i < 16; i++)
ss[i] = 4096.0f;
for (int a = 0; a < 8; a++) {
float t = 0.0f;
for (int b = 0; b < 8; b++)
t += sq[a * 8 + b];
ss[a] = t;
}
alignas(64) float rt[16];
_mm512_store_ps(rt, rms_r(_mm512_load_ps(ss), g.invh));
for (int q = 0; q < g.H / 1024; q++) {
for (int a = 0; a < 8; a++) {
V r = bc(rt[a]);
for (int c = 0; c < 1024; c += 16) { // columns c .. c + 15: piece c / 64, j = (c % 64) / 8 (2 of them)
int col = q * 1024 + c;
const float *hp = hb + (col >> 6) * 576 + ((col & 63) >> 3) * 64 + a * 8;
V x = ld8x2(hp, hp + 64);
V v = mulf(mulf(x, _mm512_loadu_ps(g.ct.data() + col)), r);
_mm512_store_ps(s.wk[a] + (q % g.G) * 1024 + c, v);
}
}
if (q % g.G == g.G - 1)
emit(g, s, T, q - g.G + 1);
}
}
static void unit_act(const Op &g, Scratch &s, int T, int q, int off) { // (fills chunk q at wk + off)
size_t NB = g.NB;
for (int u = 0; u < 16; u++) {
int mg = q * 32 + u, mu = mg + 16;
const uint16_t *yg = g.Y + (((size_t)(mg >> 1) * NB + T) * 512 + (mg & 1) * 256) * 2;
const uint16_t *yu = g.Y + (((size_t)(mu >> 1) * NB + T) * 512 + (mu & 1) * 256) * 2;
for (int a = 0; a < 8; a++)
for (int j = 0; j < 8; j += 2) { // columns u*64 + j*8 .. +16
V gt = bf16x8x2(yg + j * 64 + a * 8, yg + (j + 1) * 64 + a * 8);
V up = bf16x8x2(yu + j * 64 + a * 8, yu + (j + 1) * 64 + a * 8);
int c = u * 64 + j * 8;
V us = _mm512_mul_ps(up, _mm512_loadu_ps(g.sg.data() + q * 1024 + c));
V gu = _mm512_mul_ps(gt, us);
V sb = g_knob[7] ? sigm(gt) : _mm512_i32gather_ps(bfidx(gt), g_sig, 4);
_mm512_store_ps(s.wk[a] + off + c, (g_knob[6] & 1) ? gu : mulf(gu, sb));
}
}
}
static void unit_dno(const Op &g, Scratch &s, int T, int q, int off) {
size_t NB = g.NB;
for (int hd = 0; hd < 8; hd++) {
int head = q * 8 + hd;
const float *ob = g.Of + ((size_t)head * NB + T) * 1024;
for (int a = 0; a < 8; a++)
for (int w = 0; w < 128; w += 16)
_mm512_store_ps(s.wk[a] + off + hd * 128 + w, _mm512_loadu_ps(ob + (w >> 5) * 256 + a * 32 + (w & 31)));
}
alignas(64) float ssum[64];
for (int i = 0; i < 64; i++) { // (head i >> 3, token i & 7)
const float *p = s.wk[i & 7] + off + (i >> 3) * 128;
alignas(64) float l[64];
for (int k = 0; k < 4; k++) {
V acc = _mm512_setzero_ps();
for (int h2 = 0; h2 < 2; h2++) {
T2 x = sp2(_mm512_load_ps(p + h2 * 64 + 16 * k));
acc = fma_(x.h, x.h, acc);
acc = fma_(x.h, _mm512_add_ps(x.l, x.l), acc);
}
_mm512_store_ps(l + 16 * k, acc);
}
for (int n = 32; n >= 1; n >>= 1) // (reduce: halving)
for (int k = 0; k < n; k++)
l[k] = l[k] + l[k + n];
ssum[i] = l[0];
}
alignas(64) float rt[64];
for (int k = 0; k < 4; k++)
_mm512_store_ps(rt + 16 * k, rms_r(_mm512_load_ps(ssum + 16 * k), 1.0f / 128.0f));
for (int hd = 0; hd < 8; hd++)
for (int hz = 0; hz < 2; hz++) {
int p = q * 16 + hd * 2 + hz;
const uint16_t *z = g.Z + ((size_t)(g.ZB + p) * g.S + (size_t)T * 256) * 2;
for (int a = 0; a < 8; a++) {
V r = bc(rt[hd * 8 + a]);
for (int j = 0; j < 8; j += 2) {
int w = hz * 64 + j * 8; // within the head
V zv = bf16x8x2(z + j * 64 + a * 8, z + (j + 1) * 64 + a * 8);
V sgv = _mm512_loadu_ps(g.sg.data() + q * 1024 + hd * 128 + w);
V sz = g_knob[7] ? mulf(_mm512_mul_ps(zv, sgv), sigm(zv))
: _mm512_mul_ps(_mm512_i32gather_ps(bfidx(zv), g_sz, 4), _mm512_mul_ps(sgv, bc(32.0f)));
V rw = mulf(_mm512_loadu_ps(g.dw.data() + w), r);
float *pp = s.wk[a] + off + hd * 128 + w;
_mm512_store_ps(pp, mulf(mulf(_mm512_load_ps(pp), rw), sz));
}
}
}
}
static void unit_rot(const Op &g, Scratch &s, int T, int q, int off) {
for (int a = 0; a < 8; a++) {
int t = T * 8 + a;
const float *sgq = g.sg.data() + q * 1024;
if (g.op == ROTP) {
const uint16_t *y = g.Ob + ((size_t)t * 2176 + q * 544) * 2;
for (int i = 0; i < 1024; i += 16)
_mm512_store_ps(s.wk[a] + off + i, _mm512_mul_ps(bf16x16(y + i), _mm512_loadu_ps(sgq + i)));
} else {
const int *rb = ROTB_T[q];
int i = 0;
for (int pc = 0; pc < rb[1]; pc++) {
const uint16_t *y = g.Ob + ((size_t)t * 4224 + rb[0] + pc * rb[3]) * 2;
for (int e = 0; e < 2 * rb[2]; e += 16, i += 16)
_mm512_store_ps(s.wk[a] + off + i, _mm512_mul_ps(bf16x16(y + e), _mm512_loadu_ps(sgq + i)));
}
}
}
}
// ---------------------------------------------------------------- [MoE] the prefill's expert glue (cg_moe)
// MOEG: rows of an M-token X (bfp16 tiles, K 2048: KS 16) -> segments of 256 rows (X layouts of M = 256), row r of
// the output = token idx[r] (-1: zeros); each token's 8 values of a column group are 9 bytes of their own (one
// exponent a token), so this is a byte gather - exactly the values of the source X. Unit: 8 output rows.
// MOEA: Y [rows][1024] bf16 (gate | up) -> silu(gate) * up, x' = H_512 (s * a) / 32 (s: g.sg, 512) -> X of K 512
// (KS 4) per 256-row segment. Unit: 8 rows.
// MOES: h (glue layout [T][H / 64][576] fp32) += sum_k wt[t * nk + k] * Y[idx[t * nk + k]] (bf16 rows of 2048; idx
// -1: none). Unit: 8 tokens (one h block: no two threads write a token).
static inline uint8_t *xrec(uint8_t *X, int NMT, int KS, int t, int gcol) { // token t's 9 bytes of column group
int T = t >> 3, a = t & 7, trg = T >> 3, z = T & 7, r = trg & 3, mt = trg >> 2, ks = gcol >> 4, i = gcol & 15;
size_t w = ((size_t)(r * NMT + mt) * KS + ks) * 2304 + (z >> 1) * 576 + i * 36 + (z & 1) * 18;
return X + w * 4 + a * 9;
}
static void unit_moeg(const Op &g, int u) {
int S = g.KX, nb = S / 8, seg = u / nb, blk = u % nb; // (S: rows a segment, 64 or 256)
uint8_t *dst = g.X + (size_t)seg * S * 2048 * 9 / 8;
int nmt_src = g.M / 256;
for (int a = 0; a < 8; a++) {
int row = blk * 8 + a, t = g.idx[seg * S + row];
for (int gc = 0; gc < 256; gc++) {
uint8_t *d = xrec(dst, S >= 256 ? S / 256 : 1, 16, row, gc);
if (t < 0)
memset(d, 0, 9);
else
memcpy(d, xrec((uint8_t *)g.Xs, nmt_src, 16, t, gc), 9);
}
}
}
static void unit_moea(const Op &g, Scratch &s, int u) {
int S = g.KX, nb = S / 8, seg = u / nb, blk = u % nb;
for (int a = 0; a < 8; a++) {
const uint16_t *y = g.Y + ((size_t)seg * S + blk * 8 + a) * 1024;
float *x = s.wk[a];
for (int c = 0; c < 512; c += 16) {
V gt = bf16x16(y + c), up = bf16x16(y + 512 + c);
alignas(64) float gg[16];
_mm512_store_ps(gg, gt);
for (int k = 0; k < 16; k++)
gg[k] = gg[k] / (1.0f + expf(-gg[k]));
V v = _mm512_mul_ps(_mm512_mul_ps(_mm512_load_ps(gg), up), _mm512_loadu_ps(g.sg.data() + c));
_mm512_store_ps(x + c, v);
}
for (int c = 512; c < 1024; c += 16)
_mm512_store_ps(x + c, _mm512_setzero_ps());
fwht(x, true); // (two H_512 blocks: the second is all zeros)
}
uint8_t *X = g.X + (size_t)seg * S * 512 * 9 / 8;
int nmt = S >= 256 ? S / 256 : 1;
for (int kk = 0; kk < 4; kk++)
for (int i = 0; i < 16; i++) {
int T = blk;
int trg = T >> 3, z = T & 7, r = trg & 3, mt = trg >> 2;
size_t w = ((size_t)(r * nmt + mt) * 4 + kk) * 2304 + (z >> 1) * 576 + i * 36 + (z & 1) * 18;
bfp72(s, kk * 128 + i * 8, X + w * 4);
}
}
static void unit_moes(const Op &g, int u) {
int NPC = g.H / 64;
for (int a = 0; a < 8; a++) {
int t = u * 8 + a;
if (t >= g.M)
return;
float *hb = g.h + (size_t)u * NPC * 576;
for (int k = 0; k < g.nk; k++) {
int r = g.idx[t * g.nk + k];
if (r < 0)
continue;
V w = bc(g.wt[t * g.nk + k]);
const uint16_t *y = g.Y + (size_t)r * g.H;
for (int c = 0; c < g.H; c += 16) {
V yv = bf16x16(y + c);
for (int hh = 0; hh < 2; hh++) {
int cc = c + 8 * hh;
float *hp = hb + (cc >> 6) * 576 + ((cc & 63) >> 3) * 64 + a * 8;
__m256 y8 = hh ? _mm512_extractf32x8_ps(yv, 1) : _mm512_castps512_ps256(yv);
_mm256_storeu_ps(hp, _mm256_fmadd_ps(y8, _mm512_castps512_ps256(w), _mm256_loadu_ps(hp)));
}
}
}
}
}
// a unit: the 2 blocks of an X z-pair (one thread writes whole 2304-B runs of X: no shared cache lines)
static void do_unit(const Op &g, Scratch &s, int u) {
if (g.op == MOEG)
return unit_moeg(g, u);
if (g.op == MOEA)
return unit_moea(g, s, u);
if (g.op == MOES)
return unit_moes(g, u);
int ng = g.nq / g.G; // (a unit: one rotation block of the row, 2 token blocks)
int T = 2 * (g.op <= R3 ? u : u / ng), q0 = g.op <= R3 ? 0 : (u % ng) * g.G;
for (int t = T; t < T + 2; t++) {
if (g.op <= R3) {
unit_norm(g, s, t);
continue;
}
for (int j = 0; j < g.G; j++)
switch (g.op) {
case ACT:
unit_act(g, s, t, q0 + j, j * 1024);
break;
case DNO:
unit_dno(g, s, t, q0 + j, j * 1024);
break;
default:
unit_rot(g, s, t, q0 + j, j * 1024);
}
emit(g, s, t, q0);
}
}
#if defined(__GNUC__) && !defined(_MSC_VER)
#pragma GCC pop_options
#endif
// ---------------------------------------------------------------- cores / the pool
static std::vector<int> g_cores; // chosen logical processors (one a physical core)
static int g_classes = 0, g_phys = 0;
#ifdef _WIN32
static std::vector<GROUP_AFFINITY> g_aff;
static void find_cores() {
DWORD len = 0;
GetLogicalProcessorInformationEx(RelationProcessorCore, nullptr, &len);
std::vector<uint8_t> buf(len);
if (!GetLogicalProcessorInformationEx(RelationProcessorCore, (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)buf.data(), &len))
return;
int lo = 255;
for (DWORD off = 0; off < len;) {
auto *q = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(buf.data() + off);
g_classes |= 1 << q->Processor.EfficiencyClass;
lo = q->Processor.EfficiencyClass < lo ? q->Processor.EfficiencyClass : lo;
g_phys++;
off += q->Size;
}
bool two = (g_classes & (g_classes - 1)) != 0;
for (DWORD off = 0; off < len;) {
auto *q = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(buf.data() + off);
if (!two || q->Processor.EfficiencyClass == lo) {
GROUP_AFFINITY ga = q->Processor.GroupMask[0];
for (int b = 0; b < 64; b++)
if (ga.Mask & (1ull << b)) { // (one logical processor a core)
GROUP_AFFINITY one{};
one.Group = ga.Group;
one.Mask = 1ull << b;
g_aff.push_back(one);
g_cores.push_back(ga.Group * 64 + b);
break;
}
}
off += q->Size;
}
}
static void pin_self(int k, int mode) {
if ((mode & 1) && !g_aff.empty())
SetThreadGroupAffinity(GetCurrentThread(), &g_aff[k % g_aff.size()], nullptr);
if (mode & 2) {
THREAD_POWER_THROTTLING_STATE st{};
st.Version = THREAD_POWER_THROTTLING_CURRENT_VERSION;
st.ControlMask = THREAD_POWER_THROTTLING_EXECUTION_SPEED;
st.StateMask = THREAD_POWER_THROTTLING_EXECUTION_SPEED;
SetThreadInformation(GetCurrentThread(), ThreadPowerThrottling, &st, sizeof(st));
}
}
static bool has_avx512() {
int r[4];
__cpuidex(r, 0, 0);
if (r[0] < 7)
return false;
__cpuidex(r, 1, 0);
if (!(r[2] & (1 << 27))) // OSXSAVE
return false;
unsigned long long xcr = _xgetbv(0);
if ((xcr & 0xE6) != 0xE6) // the OS saves the zmm state
return false;
__cpuidex(r, 7, 0);
bool f = (r[1] & (1 << 16)) && (r[1] & (1 << 17)) && (r[1] & (1 << 30)) && (r[1] & (1 << 31)); // F DQ BW VL
return f;
}
#else
static long rd_long(const char *path) {
FILE *f = fopen(path, "r");
if (!f)
return -1;
long v = -1;
if (fscanf(f, "%ld", &v) != 1)
v = -1;
fclose(f);
return v;
}
static void find_cores() {
int n = (int)sysconf(_SC_NPROCESSORS_CONF);
std::vector<long> perf(n, -1), key(n, -1);
char p[256];
for (int c = 0; c < n; c++) {
snprintf(p, sizeof p, "/sys/devices/system/cpu/cpu%d/topology/core_id", c);
long core = rd_long(p);
snprintf(p, sizeof p, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", c);
long pkg = rd_long(p);
if (core < 0)
continue;
key[c] = pkg * 100000 + core;
snprintf(p, sizeof p, "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", c);
perf[c] = rd_long(p);
if (perf[c] <= 0) {
snprintf(p, sizeof p, "/sys/devices/system/cpu/cpu%d/acpi_cppc/highest_perf", c);
perf[c] = rd_long(p);
}
}
std::vector<int> first; // one logical cpu a physical core
for (int c = 0; c < n; c++) {
if (key[c] < 0)
continue;
bool dup = false;
for (int f : first)
dup |= key[f] == key[c];
if (!dup)
first.push_back(c);
}
g_phys = (int)first.size();
long lo = -1, hi = -1;
for (int c : first)
if (perf[c] > 0) {
lo = lo < 0 || perf[c] < lo ? perf[c] : lo;
hi = perf[c] > hi ? perf[c] : hi;
}
bool two = lo > 0 && hi > lo * 5 / 4; // (2 classes: the fastest cores > 1.25 x the slowest)
g_classes = two ? 3 : 1;
for (int c : first)
if (!two || perf[c] <= lo * 23 / 20)
g_cores.push_back(c);
}
static void pin_self(int k, int mode) {
if ((mode & 1) && !g_cores.empty()) {
cpu_set_t s;
CPU_ZERO(&s);
CPU_SET(g_cores[k % g_cores.size()], &s);
pthread_setaffinity_np(pthread_self(), sizeof s, &s);
}
}
static bool has_avx512() {
__builtin_cpu_init();
return __builtin_cpu_supports("avx512f") && __builtin_cpu_supports("avx512bw") &&
__builtin_cpu_supports("avx512dq") && __builtin_cpu_supports("avx512vl");
}
#endif
struct Pool {
std::vector<std::thread> th;
std::mutex mu;
std::condition_variable cv, done;
uint64_t gen = 0;
int pending = 0;
const Op *job = nullptr;
std::atomic<int> next{0};
bool quit = false;
};
static Pool *g_pool = nullptr;
static std::once_flag g_once;
static void global_init() {
init_consts();
find_cores();
if (has_avx512()) {
init_perm();
init_tables();
}
}
static void worker(int k, int mode) {
pin_self(k, mode);
Scratch *s = (Scratch *)
#ifdef _WIN32
_aligned_malloc(sizeof(Scratch), 64);
#else
aligned_alloc(64, sizeof(Scratch));
#endif
uint64_t seen = 0;
for (;;) {
const Op *g;
{
std::unique_lock<std::mutex> lk(g_pool->mu);
g_pool->cv.wait(lk, [&] { return g_pool->quit || g_pool->gen != seen; });
if (g_pool->quit)
break;
seen = g_pool->gen;
g = g_pool->job;
}
for (int u; (u = g_pool->next.fetch_add(1)) < g->nunits;)
do_unit(*g, *s, u);
{
std::lock_guard<std::mutex> lk(g_pool->mu);
if (--g_pool->pending == 0)
g_pool->done.notify_all();
}
}
#ifdef _WIN32
_aligned_free(s);
#else
free(s);
#endif
}
API void cg_info(int *out) {
std::call_once(g_once, global_init);
out[0] = has_avx512() ? 1 : 0;
out[1] = g_classes;
out[2] = (int)g_cores.size();
out[3] = g_phys;
out[4] = g_pool ? (int)g_pool->th.size() : 0;
for (int i = 0; i < (int)g_cores.size() && i < 3; i++)
out[5 + i] = g_cores[i];
}
API void cg_set(int key, int val) {
if (key >= 0 && key < 8)
g_knob[key] = val;
}
API int cg_init(int nthreads, int mode) {
std::call_once(g_once, global_init);
if (!has_avx512())
return -1;
if (g_pool)
return (int)g_pool->th.size();
g_pool = new Pool();
int n = nthreads > 0 ? nthreads : (int)(g_cores.empty() ? 4 : g_cores.size());
for (int k = 0; k < n; k++)
g_pool->th.emplace_back(worker, k, mode);
return n;
}
API void cg_close() {
if (!g_pool)
return;
{
std::lock_guard<std::mutex> lk(g_pool->mu);
g_pool->quit = true;
}
g_pool->cv.notify_all();
for (auto &t : g_pool->th)
t.join();
delete g_pool;
g_pool = nullptr;
}
API int cg_run(int op, int M, int H, int I, int ND, int KO, int NO, int ZB, void *a0, void *a1, void *a2, void *a3,
float *dbg) {
if (!g_pool && cg_init(0, 3) < 0)
return -1;
if (op < 0 || op > ROTB)
return -1;
Op g;
g.op = op;
g.M = M, g.H = H, g.I = I, g.ND = ND, g.KO = KO, g.NO = NO, g.ZB = ZB;
g.S = (size_t)32 * M;
g.NB = M / 8;
g.NMT = M / 256;
g.h = nullptr, g.Y = g.Z = g.Ob = nullptr, g.Of = nullptr, g.X = nullptr;
g.dbg = dbg;
const int32_t *P;
void *a[4] = {a0, a1, a2, a3};
switch (op) {
case N1: g.h = (float *)a[0], P = (const int32_t *)a[1], g.X = (uint8_t *)a[2]; break;
case R1N: case R3N: g.h = (float *)a[0], g.Y = (const uint16_t *)a[1], P = (const int32_t *)a[2], g.X = (uint8_t *)a[3]; break;
case R3: g.h = (float *)a[0], g.Y = (const uint16_t *)a[1], P = (const int32_t *)a[2]; break;
case ACT: g.Y = (const uint16_t *)a[0], P = (const int32_t *)a[1], g.X = (uint8_t *)a[2]; break;
case DNO: g.Of = (const float *)a[0], g.Z = (const uint16_t *)a[1], P = (const int32_t *)a[2], g.X = (uint8_t *)a[3]; break;
default: g.Ob = (const uint16_t *)a[0], P = (const int32_t *)a[1], g.X = (uint8_t *)a[2];
}
g.KX = op == ACT ? I : (op >= DNO ? KO : H);
g.KS = g.KX / 128;
int oi = op == ROTB ? ROTP : op; // (the P slot: rotb uses rotp's)
const int32_t *hd = P + oi * HW_, *hd2 = P + oi * HW_ + 1024;
memcpy(&g.invh, hd + 10, 4);
g.rb = hd[12] ? hd[12] : 1024;
if (g.rb != 512 && g.rb != 1024 && g.rb != 4096)
return -2;
g.G = g.rb == 4096 ? 4 : 1;
int nsg = op == ACT ? I : KO;
g.sg.resize(nsg + 64);
for (int c = 0; c < nsg; c++) {
int w = c >> 5;
uint32_t bits = w < 448 ? (uint32_t)hd[64 + w] : (uint32_t)hd2[128 + w - 448];
g.sg[c] = (bits >> (c & 31)) & 1 ? -0.03125f : 0.03125f;
}
if (op == DNO) {
g.dw.resize(128);
memcpy(g.dw.data(), hd2, 512);
}
if (op == N1 || op == R1N || op == R3N) {
int ctin = CT_IN, ctpost = H <= 4096 ? CT_POST : CT_IN + 2 * H;
const float *cf = (const float *)P + (op == R1N ? ctpost : ctin);
g.ct.resize(H);
for (int c = 0; c < H; c++)
g.ct[c] = cf[(c >> 8) * 512 + (c & 255)];
}
if (op <= R3) {
g.nq = H / 1024;
g.nunits = g.NB / 2;
} else {
g.nq = (op == ACT ? I : KO) / 1024;
g.nunits = g.NB / 2 * (g.nq / g.G);
}
{
std::lock_guard<std::mutex> lk(g_pool->mu);
g_pool->job = &g;
g_pool->next.store(0);
g_pool->pending = (int)g_pool->th.size();
g_pool->gen++;
}
g_pool->cv.notify_all();
{
std::unique_lock<std::mutex> lk(g_pool->mu);
g_pool->done.wait(lk, [] { return g_pool->pending == 0; });
}
return 0;
}
// [MoE] cg_moe(op, M, H, n, a0, a1, a2, a3): MOEG (M source tokens, n segments of H rows - 64 / 256): a0 X src, a1 idx
// [n * H], a2 X out | MOEA (n segments of H rows): a0 Y [n * H][1024] bf16, a1 the 512 signs (float +-1), a2 X out |
// MOES (M tokens, n = rows a token; H the width): a0 h, a1 Y [rows][H] bf16, a2 idx [M * n], a3 wt [M * n]
API int cg_moe(int op, int M, int H, int n, void *a0, void *a1, void *a2, void *a3) {
if (!g_pool && cg_init(0, 3) < 0)
return -1;
Op g;
g.op = op, g.M = M, g.H = H, g.nk = n;
g.h = nullptr, g.Y = g.Z = g.Ob = nullptr, g.Of = nullptr, g.X = nullptr, g.dbg = nullptr;
g.Xs = nullptr, g.idx = nullptr, g.wt = nullptr;
g.rb = 1024, g.G = 1;
if (op == MOEG) {
g.Xs = (const uint8_t *)a0, g.idx = (const int32_t *)a1, g.X = (uint8_t *)a2;
g.KX = H, g.H = 2048;
g.nunits = n * (H / 8);
} else if (op == MOEA) {
g.KX = H, g.H = 2048;
g.Y = (const uint16_t *)a0, g.X = (uint8_t *)a2;
g.sg.resize(512);
for (int c = 0; c < 512; c++)
g.sg[c] = ((const float *)a1)[c] * 0.03125f;
g.nunits = n * (g.KX / 8);
} else if (op == MOES) {
g.h = (float *)a0, g.Y = (const uint16_t *)a1, g.idx = (const int32_t *)a2, g.wt = (const float *)a3;
g.nunits = (M + 7) / 8;
} else
return -1;
{
std::lock_guard<std::mutex> lk(g_pool->mu);
g_pool->job = &g;
g_pool->next.store(0);
g_pool->pending = (int)g_pool->th.size();
g_pool->gen++;
}
g_pool->cv.notify_all();
{
std::unique_lock<std::mutex> lk(g_pool->mu);
g_pool->done.wait(lk, [] { return g_pool->pending == 0; });
}
return 0;
}
// [0.8] the MoE router of T tokens (decode / MTP verify), on the calling thread: xn = x / rms(x) * g; the NPU router's
// 16 best candidates (approx: int4 logits, a row of astride floats a token) re-scored exactly (R's rows . xn); the
// top-k of those by score, their softmax (norm_topk); the shared expert's gate sigmoid(sg . xn)
#ifndef _MSC_VER
__attribute__((target("avx2,fma")))
#endif
static float dotf(const float *a, const float *b, int n) { // (AVX2 + FMA: every CPU with an XDNA NPU has them)
__m256 s0 = _mm256_setzero_ps(), s1 = s0, s2 = s0, s3 = s0;
for (int i = 0; i < n; i += 32) {
s0 = _mm256_fmadd_ps(_mm256_loadu_ps(a + i), _mm256_loadu_ps(b + i), s0);
s1 = _mm256_fmadd_ps(_mm256_loadu_ps(a + i + 8), _mm256_loadu_ps(b + i + 8), s1);
s2 = _mm256_fmadd_ps(_mm256_loadu_ps(a + i + 16), _mm256_loadu_ps(b + i + 16), s2);
s3 = _mm256_fmadd_ps(_mm256_loadu_ps(a + i + 24), _mm256_loadu_ps(b + i + 24), s3);
}
__m256 v = _mm256_add_ps(_mm256_add_ps(s0, s1), _mm256_add_ps(s2, s3));
float r[8];
_mm256_storeu_ps(r, v);
return ((r[0] + r[1]) + (r[2] + r[3])) + ((r[4] + r[5]) + (r[6] + r[7]));
}
API int cg_route(int T, int hid, int E, int topk, const float *H, const float *approx, int astride, const float *R,
const float *sg, const float *g, int32_t *top, float *p, float *ws) {
if (hid % 32 || E > 4096 || topk > 16)
return -1;
std::vector<float> xn(hid);
std::vector<int> ord(E);
for (int t = 0; t < T; t++) {
const float *x = H + (size_t)t * hid;
float ss = dotf(x, x, hid);
float s = sqrtf(ss / (float)hid + 1e-6f);
for (int i = 0; i < hid; i++)
xn[i] = x[i] / s * g[i];
const float *a = approx + (size_t)t * astride;
for (int i = 0; i < E; i++)
ord[i] = i;
std::nth_element(ord.begin(), ord.begin() + 16, ord.end(), [a](int u, int v) { return a[u] > a[v]; });
int cand[16];
float lc[16];
for (int k = 0; k < 16; k++) {
cand[k] = ord[k];
lc[k] = dotf(R + (size_t)cand[k] * hid, xn.data(), hid);
}
int o[16];
for (int k = 0; k < 16; k++)
o[k] = k;
std::sort(o, o + 16, [&](int u, int v) { return lc[u] > lc[v] || (lc[u] == lc[v] && cand[u] < cand[v]); });
float mx = lc[o[0]], sum = 0;
for (int k = 0; k < topk; k++) {
top[t * topk + k] = cand[o[k]];
p[t * topk + k] = expf(lc[o[k]] - mx);
sum += p[t * topk + k];
}
for (int k = 0; k < topk; k++)
p[t * topk + k] /= sum;
ws[t] = 1.0f / (1.0f + expf(-dotf(sg, xn.data(), hid)));
}
return 0;
}
// [0.8] the MTP verify's MoE slots: the union of T tokens' top-k experts (sorted) + the shared expert, n groups of 2
// slots (>= ngmin); MOEH2 group g's two header blocks get each token's weights of the group's slots at xs + 16 t
// (0: an expert the token did not choose; tokens T..VT-1: 0). Returns the groups (-1: more than ngmax).
API int cg_union(int T, int VT, int topk, const int32_t *top, const float *p, const float *ws, int shared, int ngmin,
int ngmax, int64_t *slots, int32_t *mh, int blk_w, int xs) {
int u[64], n = 0;
for (int i = 0; i < T * topk; i++)
u[n++] = top[i];
std::sort(u, u + n);
n = (int)(std::unique(u, u + n) - u);
int ng = (n + 2) / 2 > ngmin ? (n + 2) / 2 : ngmin;
if (ng > ngmax)
return -1;
for (int s = 0; s < 2 * ng; s++)
slots[s] = s < n ? u[s] : s == n ? shared : 0;
for (int g = 0; g < ng; g++)
for (int t = 0; t < VT; t++)
for (int j = 0; j < 2; j++) {
int s = 2 * g + j;
float w = 0.0f;
if (t < T) {
if (s == n)
w = ws[t];
else if (s < n)
for (int k = 0; k < topk; k++)
if (top[t * topk + k] == u[s])
w = p[t * topk + k];
}
int32_t bits;
std::memcpy(&bits, &w, 4);
mh[(g * 4 + 0) * blk_w + xs + 16 * t + j] = bits;
mh[(g * 4 + 1) * blk_w + xs + 16 * t + j] = bits;
}
return ng;
}
// [0.8] a MoE program's weight fills pointed at experts: im[pos[i]] = base[i] + slots[slot_of[i]] * step (mod 2^32)
API void cg_patch(int n, uint32_t *im, const int64_t *pos, const int64_t *base, const int64_t *slot_of,
const int64_t *slots, int64_t step) {
for (int i = 0; i < n; i++)
im[pos[i]] = (uint32_t)(base[i] + slots[slot_of[i]] * step);
}
// [0.9] the experts a layer's router would pick for T rows (the expert streaming's prefetch: the next layer's router
// on this layer's h): xn = x / rms(x) * g, all E logits, the k best (any order) -> top [T * k]
API int cg_predict(int T, int hid, int E, int k, const float *H, const float *R, const float *g, int32_t *top) {
if (hid % 32 || k > E)
return -1;
std::vector<float> xn(hid), lg(E);
std::vector<int> ord(E);
for (int t = 0; t < T; t++) {
const float *x = H + (size_t)t * hid;
float s = sqrtf(dotf(x, x, hid) / (float)hid + 1e-6f);
for (int i = 0; i < hid; i++)
xn[i] = x[i] / s * g[i];
for (int e = 0; e < E; e++) {
lg[e] = dotf(R + (size_t)e * hid, xn.data(), hid);
ord[e] = e;
}
std::nth_element(ord.begin(), ord.begin() + k, ord.end(), [&](int u, int v) { return lg[u] > lg[v]; });
for (int j = 0; j < k; j++)
top[t * k + j] = ord[j];
}
return 0;
}