From 12350a494fb792fa94046279b525953e1e70c91e Mon Sep 17 00:00:00 2001 From: Dennis Paul Date: Tue, 14 Jul 2026 16:26:07 +0200 Subject: [PATCH 01/79] =?UTF-8?q?prefill:=20batch=20the=20attention=20inpu?= =?UTF-8?q?t=20projections=20=E2=80=94=20bit-identical,=20-4.5%=20prefill?= =?UTF-8?q?=20(#152)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * prefill: batch the attention input projections (q_a/q_b/kv_a) over the prompt During prefill the three attention input projections were called one row at a time (matmul_qt(..., 1)) inside the loop over the S prompt tokens, while o_proj right below already runs batched and moe() already does a batch-union. Batching them over all S rows lets each weight row be read once for the whole prompt instead of once per token. Measured on Zen5 + RTX 5090, GLM-5.2 int4, 78 layers, DSA on, OMP tuning on, prefill run to completion (engine's own timings, upstream/dev @ 6d3ed7e): prompt projection/RoPE total prefill 256 22.7s -> 17.7s (-22%) 120.9s -> 115.4s (-4.5%) 512 45.5s -> 36.3s (-20%) 231.4s -> 222.7s (-3.8%) Output is BIT-IDENTICAL to dev: summed log-lik of a fixed 1023-token passage is -4987.458316 before and after (SCORE mode, CPU, deterministic). Decode (S=1) is untouched — same calls, same kernel. matmul_qt_ex(..., allow_idot=0) keeps the projections on the EXACT int4 kernel. This matters: batching alone would push S past the S>=g_i4s gate (2 on x86) and silently move them onto IDOT's int8-quantized activations, which costs +0.169 nats/token on markdown/code and +0.084 on prose (perplexity +18.4% / +8.7%, measured) for only 1.4% more speed now that #95 made the exact kernel fast. The gate is a decode-era speed threshold; it should not be crossed by a batching change. Also: matmul_qt documents the IDOT threshold as "configurable via I4S", but the getenv was missing and the knob did nothing. Wire it up — it is what isolates the kernel switch from the batching win. * prefill: batch the DSA indexer's ix_wk projection too Same per-token bug as the attention projections, one block below: ix_wk was called one row at a time inside the prefill loop, so its weights were re-read for every token on every DSA layer. matmul_qt_ex(..., 0) keeps it on the exact int4 kernel for the same reason as the attention projections: batching alone would push S past the S>=g_i4s gate and silently change the activation quantization. Output stays BIT-IDENTICAL (summed log-lik over 1023 tokens, in-distribution): prose -2295.245383 (unchanged) markdown -3272.146403 (unchanged) Speed, 256-token prompt, 3 alternating reps each (Zen5 + RTX 5090, dev + the attention-projection commit as the baseline): projection/RoPE 17.54s (sd 0.20) -> 16.96s (sd 0.15) -3.3% total prefill 115.34s (sd 0.82) -> 113.69s (sd 0.35) -1.4% Both separated beyond 2 sd. Small, but it is free and bit-identical. ix_wq/ix_wp are left alone on purpose: they sit inside an `omp parallel for` and are skipped entirely below index_topk context, so batching them is a different change with a different risk profile. --------- Co-authored-by: JustVugg --- c/glm.c | 86 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 23 deletions(-) diff --git a/c/glm.c b/c/glm.c index 07fae16..8b061db 100644 --- a/c/glm.c +++ b/c/glm.c @@ -461,6 +461,7 @@ static void matmul_i2(float *y, const float *x, const uint8_t *q2, const float * #else #define IDOT_KERNEL "scalar" #endif +static int g_lmhead_exact=0; /* PROBE: LMHEAD_EXACT=1 -> pin lm_head to the exact int8 kernel */ static int g_idot=1; #if defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) static int g_i4s=1; /* SDOT presente: int4 IDOT conviene anche a S=1 (decode). Misurato @@ -706,7 +707,16 @@ static void quant_scratch(size_t xn, size_t sn, int8_t **xq, float **sx){ *xq=g_qscratch.xq; *sx=g_qscratch.sx; } -static void matmul_qt(float *y, const float *x, QT *w, int S){ +/* allow_idot=0: forza il kernel int4/int8 ESATTO (attivazioni f32). Serve alle proiezioni di + * attenzione: sono sensibili alla quantizzazione int8 delle attivazioni dell'IDOT. Misurato su + * GLM-5.2 int4, 1023 token, log-lik -5040.33 (esatto) -> -5160.47 (IDOT) = +0.117 nat/token, + * ~+12% perplexity. Gli altri matmul del prefill (o_proj, kv_b, expert) tengono l'IDOT. + * EN: allow_idot=0 forces the EXACT int4/int8 kernel (f32 activations). The attention + * projections need it: IDOT's int8 activation quantization costs +0.117 nats/token there + * (~+12% perplexity), measured. Every other prefill matmul keeps IDOT as before. */ +static void matmul_qt_ex(float *y, const float *x, QT *w, int S, int allow_idot); +static void matmul_qt(float *y, const float *x, QT *w, int S){ matmul_qt_ex(y,x,w,S,1); } +static void matmul_qt_ex(float *y, const float *x, QT *w, int S, int allow_idot){ #ifdef COLI_METAL /* Large row-batches (prefill: kv_b reconstruction, o_proj, dense MLP, step_all logits) * amortize Metal's ~5ms submit latency; small-S decode matmuls stay on CPU (NEON wins). @@ -737,7 +747,7 @@ static void matmul_qt(float *y, const float *x, QT *w, int S){ * EN: int8 IDOT always wins (1.4-2.5x). int4 IDOT: on AVX2 the author found S=1 didn't * pay (S>=2 gate); on ARM/SDOT single-token DOES pay (see g_i4s / PR #9 for the VNNI * twin). Threshold configurable via I4S. */ - if(g_idot && (w->fmt==1 || (w->fmt==2 && S>=g_i4s))){ + if(allow_idot && g_idot && (w->fmt==1 || (w->fmt==2 && S>=g_i4s))){ int I=w->I; int8_t *xq; float *sx; if(S<0 || I<0 || (size_t)S>SIZE_MAX/(size_t)(I?I:1)){ fprintf(stderr,"matmul_qt: shape overflow\n"); exit(1); } quant_scratch((size_t)S*I,(size_t)S,&xq,&sx); @@ -1578,23 +1588,38 @@ static void attention_rows(Model *m, Layer *l, int layer, float *x, int S, int p #endif float *ctx=falloc((int64_t)S*H*vh); float *Q=falloc((int64_t)S*H*qh); /* query (roped) dei token nuovi */ - float *QR=falloc((int64_t)S*c->q_lora), *comp=falloc(c->kv_lora+c->qk_rope); - /* 1) per ogni token nuovo: query roped + latente normato e k_rot roped -> in cache. - * QR tiene il residuo q_a per TUTTE le posizioni: serve anche all'indexer DSA. */ + int cw=c->kv_lora+c->qk_rope; + float *QR=falloc((int64_t)S*c->q_lora), *comp=falloc((int64_t)S*cw); + /* 1) query roped + latente normato e k_rot roped -> in cache. + * QR tiene il residuo q_a per TUTTE le posizioni: serve anche all'indexer DSA. + * + * BATCH-ROWS: le tre proiezioni girano su tutte le S righe in un colpo solo, come gia' fa + * o_proj (matmul_qt(...,S) sotto) e come fa moe() con la batch-union. Una riga per volta + * il peso veniva ri-letto per OGNI token; a S righe si legge una volta sola. + * matmul_qt_ex(...,0): restano sul kernel int4 ESATTO. Con l'IDOT (che il gate S>=g_i4s + * abiliterebbe da solo appena S>1) il prefill sarebbe molto piu' veloce ma la qualita' + * cala: -5040.33 -> -5158.68 di log-lik su 1023 token (~+12% perplexity). Il batch da + * solo e' bit-identical all'originale; il kernel no. Vedi issue. + * EN: batch the three projections over all S rows, like o_proj below and moe()'s + * batch-union. matmul_qt_ex(...,0) keeps them on the EXACT int4 kernel: letting S>1 pull + * them into IDOT is much faster but costs ~12% perplexity (measured). Batching alone is + * bit-identical to upstream; the kernel switch is not. */ + matmul_qt_ex(QR, x, &l->q_a, S, 0); + for(int s=0;sq_lora; + rmsnorm(qr, qr, l->q_a_ln, c->q_lora, c->eps); } /* q_b legge il residuo NORMATO */ + matmul_qt_ex(Q, QR, &l->q_b, S, 0); + matmul_qt_ex(comp, x, &l->kv_a, S, 0); for(int s=0;skv; - const float *xs=x+(int64_t)s*D; int pos=positions?positions[s]:pos_base+s; - float *qresid=QR+(int64_t)s*c->q_lora; - matmul_qt(qresid, xs, &l->q_a, 1); - rmsnorm(qresid, qresid, l->q_a_ln, c->q_lora, c->eps); - float *qfull=Q+(int64_t)s*H*qh; matmul_qt(qfull, qresid, &l->q_b, 1); + int pos=positions?positions[s]:pos_base+s; + float *qfull=Q+(int64_t)s*H*qh; for(int h=0;hqk_nope, pos, c); - matmul_qt(comp, xs, &l->kv_a, 1); + const float *cs=comp+(int64_t)s*cw; float *Ldst=coli_kv_row(ks->Lc[layer],pos,c->kv_lora); float *Rdst=coli_kv_row(ks->Rc[layer],pos,c->qk_rope); - memcpy(Ldst, comp, c->kv_lora*sizeof(float)); + memcpy(Ldst, cs, c->kv_lora*sizeof(float)); rmsnorm(Ldst, Ldst, l->kv_a_ln, c->kv_lora, c->eps); /* latente normato */ - memcpy(Rdst, comp+c->kv_lora, c->qk_rope*sizeof(float)); + memcpy(Rdst, cs+c->kv_lora, c->qk_rope*sizeof(float)); rope_interleave(Rdst, pos, c); /* k_rot roped, condiviso fra teste */ } /* ---- DSA lightning indexer ---- @@ -1605,14 +1630,23 @@ static void attention_rows(Model *m, Layer *l, int layer, float *x, int S, int p if(m->has_dsa && layern_layers && ((!kvs && m->kv_start[layer]==0) || kvs)){ int nh=c->index_nh, hd=c->index_hd; dtopk=c->index_topk; if(c->idx_type[layer]){ + /* BATCH-ROWS, come le proiezioni di attenzione sopra: ix_wk (D x index_hd) veniva + * ri-letto per OGNI token. matmul_qt_ex(...,0) lo tiene sul kernel int4 ESATTO: + * il batch da solo supererebbe il gate S>=g_i4s e cambierebbe la quantizzazione + * delle attivazioni. Cosi' l'output resta bit-identical. + * EN: batch ix_wk over all S rows like the attention projections; allow_idot=0 + * keeps it on the exact int4 kernel so the result stays bit-identical. */ + float *KD=falloc((int64_t)S*hd); + matmul_qt_ex(KD, x, &m->ix_wk[layer], S, 0); for(int s=0;skv; - const float *xs=x+(int64_t)s*D; int pos=positions?positions[s]:pos_base+s; + int pos=positions?positions[s]:pos_base+s; float *kd=coli_kv_row(ks->Ic[layer],pos,hd); - matmul_qt(kd, xs, &m->ix_wk[layer], 1); + memcpy(kd, KD+(int64_t)s*hd, (size_t)hd*sizeof(float)); layernorm(kd, m->ix_knw[layer], m->ix_knb[layer], hd, 1e-6f); rope_interleave(kd, pos, c); /* primi qk_rope dim, interleaved */ } + free(KD); if((int64_t)S*dtopk > m->dsa_scap){ free(m->dsa_sel); free(m->dsa_nsel); m->dsa_scap=(int64_t)S*dtopk; @@ -2475,7 +2509,7 @@ static float *step(Model *m, const int *ids, int S, int pos_base){ if(m->has_mtp && S>=2 && g_draft>0) mtp_absorb(m, ids+1, x, S-1, pos_base); float *last=falloc(D); rmsnorm(last, x+(int64_t)(S-1)*D, m->final_norm, D, c->eps); double th0=now_s(); - float *logit=falloc(c->vocab); matmul_qt(logit,last,&m->lm_head,1); + float *logit=falloc(c->vocab); matmul_qt_ex(logit,last,&m->lm_head,1,!g_lmhead_exact); m->t_head += now_s()-th0; free(x); free(last); return logit; } @@ -2490,7 +2524,7 @@ static float *step_all(Model *m, const int *ids, int S, int pos_base){ if(m->hlast) memcpy(m->hlast, x+(int64_t)(S-1)*D, D*sizeof(float)); float *lo=falloc((int64_t)S*c->vocab), *row=falloc(D); for(int s=0;sfinal_norm, D, c->eps); - matmul_qt(lo+(int64_t)s*c->vocab, row, &m->lm_head, 1); } + matmul_qt_ex(lo+(int64_t)s*c->vocab, row, &m->lm_head, 1, !g_lmhead_exact); } free(x); free(row); return lo; } @@ -2524,7 +2558,7 @@ static float *step_decode_batch(Model *m, const DecodeRow *rows, int S){ rmsnorm(norm+(int64_t)s*D,x+(int64_t)s*D,m->final_norm,D,c->eps); double th0=now_s(); float *logit=falloc((int64_t)S*c->vocab); - matmul_qt(logit,norm,&m->lm_head,S); + matmul_qt_ex(logit,norm,&m->lm_head,S,!g_lmhead_exact); m->t_head+=now_s()-th0; free(x); free(norm); return logit; @@ -2573,12 +2607,12 @@ static int mtp_draft(Model *m, int next_tok, int kv, int G, int *draft){ double n_eh=0; for(int d=0;d=2; int t_pre=-1; - if(dbg){ rmsnorm(row, hx, m->mtp_norm, D, c->eps); matmul_qt(logit, row, &m->lm_head, 1); + if(dbg){ rmsnorm(row, hx, m->mtp_norm, D, c->eps); matmul_qt_ex(logit, row, &m->lm_head, 1, !g_lmhead_exact); t_pre=mtp_argmax(logit, c->vocab); } layer_forward(m, &m->mtpL, li, hx, 1, pos, nrm, tmp); double n_post=0; for(int d=0;dmtp_norm, D, c->eps); - matmul_qt(logit, row, &m->lm_head, 1); + matmul_qt_ex(logit, row, &m->lm_head, 1, !g_lmhead_exact); int t2=mtp_argmax(logit, c->vocab); if(dbg) fprintf(stderr,"[mtp2] pos=%d in_tok=%d ||eh||=%.1f ||post||=%.1f pre_blk=%d post_blk=%d\n", pos, tok, sqrt(n_eh), sqrt(n_post), t_pre, t2); @@ -2826,8 +2860,8 @@ static void forward_all(Model *m, const int *ids, int S, int *pred){ float *lo=falloc(c->vocab); float *row=falloc(D); for(int s=0;sfinal_norm, D, c->eps); - matmul_qt(lo, row, &m->lm_head, 1); + rmsnorm(row, x+(int64_t)s*D, m->final_norm, D, c->eps); /* heap row (#183) */ + matmul_qt_ex(lo, row, &m->lm_head, 1, !g_lmhead_exact); /* exact-mode knob (#152) */ int best=0; float bv=lo[0]; for(int i=1;ivocab;i++) if(lo[i]>bv){bv=lo[i];best=i;} pred[s]=best; } @@ -2864,7 +2898,7 @@ static void run_score(Model *m, const char *path){ double lp=0; int greedy=1; for(int pos=ctxlen-1; posfinal_norm, D, c->eps); - matmul_qt(lo,row,&m->lm_head,1); + matmul_qt_ex(lo,row,&m->lm_head,1,!g_lmhead_exact); int am; lp += logprob_target(lo,c->vocab,ids[pos+1],&am); if(!am) greedy=0; } printf("%.6f %d %d\n", lp, contlen, greedy); fflush(stdout); @@ -4014,6 +4048,12 @@ int main(int argc, char **argv){ g_repin = getenv("REPIN")?atoi(getenv("REPIN")):0; /* RFC: re-pin ogni n token emessi (0=off) / live re-pin every n emitted tokens (0=off) */ g_absorb = getenv("ABSORB")?atoi(getenv("ABSORB")):-1; /* -1 auto: assorbita per S<=4 */ g_dsa_force = getenv("DSA_FORCE")?atoi(getenv("DSA_FORCE")):0; + g_lmhead_exact = getenv("LMHEAD_EXACT")?atoi(getenv("LMHEAD_EXACT")):0; + /* matmul_qt documenta la soglia int4-IDOT come "configurabile con I4S" ma il getenv non + * c'era: la variabile non aveva alcun effetto. I4S= -> IDOT int4 solo per S>=n. + * EN: matmul_qt documents the int4 IDOT threshold as "configurable via I4S", but the + * getenv was missing, so the knob did nothing. I4S= -> int4 IDOT only for S>=n. */ + if(getenv("I4S")) g_i4s=atoi(getenv("I4S")); g_temp = getenv("TEMP")?atof(getenv("TEMP")):-1; /* -1 = auto (1.0 chat/testo, greedy altrove) */ g_nuc = getenv("NUCLEUS")?atof(getenv("NUCLEUS")):0.90f; /* piu' stretto dell'ufficiale 0.95: la coda int4 e' rumore */ if(getenv("SEED")) g_rng = (uint64_t)atoll(getenv("SEED"))*0x9E3779B97F4A7C15ULL+1; From 9b08cbc5436cec7638243889786298e325836614 Mon Sep 17 00:00:00 2001 From: LewfKrad Date: Tue, 14 Jul 2026 10:28:36 -0400 Subject: [PATCH 02/79] =?UTF-8?q?cuda-dll:=20make=20the=20Windows=20CUDA?= =?UTF-8?q?=20build=20work=20as=20shipped=20=E2=80=94=20MSVC=20host=20flag?= =?UTF-8?q?s,=20CUDA=5FPATH=20defaults,=20POSIX=20shim=20in=20kernel=20tes?= =?UTF-8?q?t=20(#158,=20#157)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * cuda-dll: fix Windows build — MSVC host flags, CUDA_PATH default, POSIX setenv shim in the kernel test (#157) First hardware validation of the #131 CUDA_DLL path (RTX PRO 6000 Blackwell sm_120, MSVC 14.44 + CUDA 13.2, MSYS2 UCRT64 host build) found three blockers that made 'make cuda-dll' unbuildable as shipped: - NVCCFLAGS passed GCC-style -Xcompiler=-Wall,-Wextra to the MSVC host compiler (hard error D8021). Use -Xcompiler=-W3 on Windows — dash form, since MSYS make mangles /W3 into a filesystem path. - NVCC defaulted to $(CUDA_HOME)/bin/nvcc with CUDA_HOME=/usr/local/cuda; on Windows default CUDA_HOME from the installer's CUDA_PATH and NVCC to plain 'nvcc' from PATH (CUDA_PATH contains spaces, which the unquoted recipe checks cannot survive; an MSVC PATH environment is already required). - tests/test_backend_cuda.cu used POSIX setenv/unsetenv (undefined under MSVC); add a two-line _putenv_s shim. Also corrects the stale '11 API symbols' comment (the header exports 15 and backend_loader.c resolves all 15). Validated: make cuda-dll (stock flags) + make glm CUDA_DLL=1 ARCH=native → [CUDA] device init on sm_120, tiny oracle TF 32/32 + greedy 20/20, kernel suite 'q8/q4/q2/f32 correctness ok', graceful no-dll fallback, plain build byte-identical CPU behavior. Co-Authored-By: Claude Opus 4.8 * cuda: fix heap corruption in expert_host_release on Windows (CUDA_RELEASE_HOST=1) expert_host_release() freed the expert slab with plain free(), but the slab is posix_memalign'd — which compat.h maps to _aligned_malloc on Windows, so free() corrupts the CRT heap: instant 0xC0000374 crash on the first released expert. This is the exact pattern the compat.h audit fixed at the original expert_load site ("l'unico sito che libera memoria aligned e' free(s->slab)"); this call site was added later and reintroduced it. compat_aligned_free is plain free on POSIX, so non-Windows behavior is unchanged. fslab stays plain free (malloc/falloc on the CPU path). Found running the VRAM expert tier on real hardware (80 GB resident on an RTX PRO 6000, CUDA_RELEASE_HOST=1 to avoid 80 GB of host double-residency — reproducible crash before, clean generation after). Co-Authored-By: Claude Opus 4.8 --------- Co-authored-by: lEWFkRAD <186512915+lEWFkRAD@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 Co-authored-by: JustVugg --- c/Makefile | 22 +++++++++++++++++++++- c/glm.c | 7 ++++++- c/tests/test_backend_cuda.cu | 8 ++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/c/Makefile b/c/Makefile index e794d4b..b04cf63 100644 --- a/c/Makefile +++ b/c/Makefile @@ -105,10 +105,30 @@ INSTALL ?= install # clean. See backend_loader.c and README "cuda-dll" below. CUDA ?= 0 CUDA_DLL ?= 0 +ifneq ($(IS_WIN),) +# the CUDA installer sets CUDA_PATH system-wide (e.g. C:\Program Files\NVIDIA +# GPU Computing Toolkit\CUDA\v13.2); fall back to it before the POSIX default. +# NVCC defaults to plain `nvcc` from PATH: CUDA_PATH contains spaces, which the +# unquoted recipe checks cannot survive — and the cuda-dll recipe already +# requires an MSVC environment (vcvars64) on PATH, so requiring the CUDA bin +# directory too is symmetric. The installer adds it by default. +CUDA_HOME ?= $(subst \,/,$(CUDA_PATH)) +NVCC ?= nvcc +else CUDA_HOME ?= /usr/local/cuda NVCC ?= $(CUDA_HOME)/bin/nvcc +endif CUDA_ARCH ?= native +ifneq ($(IS_WIN),) +# nvcc's host compiler on Windows is MSVC cl.exe: the GCC-style +# -Xcompiler=-Wall,-Wextra is rejected ("D8021 invalid numeric argument +# '/Wextra'"), which made `make cuda-dll` unbuildable as shipped. -W3 is +# the MSVC warning level (dash form, NOT /W3: MSYS make would mangle the +# slash-form into a filesystem path). +NVCCFLAGS ?= -O3 -std=c++17 -arch=$(CUDA_ARCH) -Xcompiler=-W3 +else NVCCFLAGS ?= -O3 -std=c++17 -arch=$(CUDA_ARCH) -Xcompiler=-Wall,-Wextra +endif ifeq ($(IS_WIN),) PYTHON ?= python3 else @@ -169,7 +189,7 @@ backend_loader.o: backend_loader.c backend_cuda.h compat.h # compiler, required by nvcc on Windows) into coli_cuda.dll. Run this from a # shell that has the MSVC environment set (e.g. after vcvars64.bat, or from a # "x64 Native Tools Command Prompt"). COLI_CUDA_BUILDING_DLL enables -# __declspec(dllexport) so the 11 API symbols are exported. +# __declspec(dllexport) so the 15 API symbols are exported. cuda-dll: backend_cuda.cu backend_cuda.h @command -v $(NVCC) >/dev/null 2>&1 || { echo "nvcc not found: set CUDA_HOME or NVCC" >&2; exit 1; } @command -v cl >/dev/null 2>&1 || { echo "cl.exe (MSVC) not in PATH — run vcvars64.bat first" >&2; exit 1; } diff --git a/c/glm.c b/c/glm.c index 8b061db..498a927 100644 --- a/c/glm.c +++ b/c/glm.c @@ -1497,7 +1497,12 @@ static void expert_host_release(Model *m, ESlot *s){ if(s->fslab) compat_munlock(s->fslab,(size_t)s->fslab_cap*sizeof(float)); #endif int64_t bytes=qt_bytes(&s->g)+qt_bytes(&s->u)+qt_bytes(&s->d); - free(s->slab); free(s->fslab); s->slab=NULL; s->fslab=NULL; s->slab_cap=s->fslab_cap=0; + /* slab is posix_memalign'd: on Windows that is _aligned_malloc, and plain + * free() corrupts the CRT heap (0xC0000374) — same bug the compat.h audit + * fixed at the original expert_load site. fslab is plain malloc/falloc + * on the CPU path, so its free() stays plain (Metal path frees it before + * re-alloc and never reaches here with an aligned fslab on _WIN32). */ + compat_aligned_free(s->slab); free(s->fslab); s->slab=NULL; s->fslab=NULL; s->slab_cap=s->fslab_cap=0; QT *q[3]={&s->g,&s->u,&s->d}; for(int k=0;k<3;k++){ q[k]->qf=NULL; q[k]->q8=NULL; q[k]->q4=NULL; q[k]->s=NULL; } m->resident_bytes-=bytes; if(m->resident_bytes<0) m->resident_bytes=0; diff --git a/c/tests/test_backend_cuda.cu b/c/tests/test_backend_cuda.cu index 58ef250..a9eb48f 100644 --- a/c/tests/test_backend_cuda.cu +++ b/c/tests/test_backend_cuda.cu @@ -5,6 +5,14 @@ #include #include +#ifdef _WIN32 +/* MSVC has no POSIX setenv/unsetenv */ +static int setenv(const char *name, const char *value, int overwrite) { + (void)overwrite; return _putenv_s(name, value); +} +static int unsetenv(const char *name) { return _putenv_s(name, ""); } +#endif + static int close_enough(const float *got, const float *want, int n) { for (int i = 0; i < n; i++) { if (std::fabs(got[i] - want[i]) > 1e-4f) { From 504fcdd930916bb287a17d05ce323907949cfb49 Mon Sep 17 00:00:00 2001 From: Fabio Rovai <146086869+fabio-rovai@users.noreply.github.com> Date: Tue, 14 Jul 2026 15:31:09 +0100 Subject: [PATCH 03/79] SCHEMA=: JSON-Schema -> GBNF compiler for grammar-forced drafts (#148) * SCHEMA=: JSON-Schema -> GBNF compiler for grammar-forced drafts (#48/#70 follow-up) schema_gbnf.h compiles a practical JSON-Schema subset (strict objects, string/ number/integer/boolean/null, enum/const, arrays with items, nesting) into the byte-level GBNF subset grammar.h parses, so structured-output workloads get grammar-forced drafts without hand-writing GBNF. Unsupported keywords fail soft: the engine runs without a grammar and output is unchanged (drafts are verified, never constraints - a wrong compile can only cost acceptance, not correctness). grammar_setup: GRAMMAR= (raw GBNF) keeps precedence; SCHEMA= feeds the compiler into the same gr_parse path. 8 test groups in tests/test_schema_gbnf.c walk compiled grammars end-to-end through the PDA (forced spans, enum disambiguation, nested instances, escapes, leading-zero rejection, fail-closed fallbacks). Co-Authored-By: Claude Fable 5 * schema_gbnf: whitespace-tolerant emission (jws at separators) Measured on GLM-5.2 current main (#146): the greedy continuation writes sloppy JSON (spaces after colons, fences, long free text) and a compact-only grammar desyncs at the first stray space, forfeiting every span after it. jws points are not forced themselves (two legal bytes) but the multi-byte spans around them keep drafting and the walker survives non-compact output - strictly acceptance-positive for a verified draft source. Tests re-derived for the new span boundaries + a sloppy-instance walk. Co-Authored-By: Claude Fable 5 --------- Co-authored-by: Claude Fable 5 Co-authored-by: JustVugg --- c/Makefile | 5 +- c/glm.c | 28 +++-- c/schema_gbnf.h | 246 +++++++++++++++++++++++++++++++++++++ c/tests/test_schema_gbnf.c | 155 +++++++++++++++++++++++ 4 files changed, 426 insertions(+), 8 deletions(-) create mode 100644 c/schema_gbnf.h create mode 100644 c/tests/test_schema_gbnf.c diff --git a/c/Makefile b/c/Makefile index b04cf63..f779d94 100644 --- a/c/Makefile +++ b/c/Makefile @@ -135,7 +135,7 @@ else PYTHON ?= python endif CUDA_OBJ = -TEST_BINS = tests/test_json$(EXE) tests/test_st$(EXE) tests/test_tier$(EXE) tests/test_grammar$(EXE) tests/test_decode_batch$(EXE) tests/test_idot$(EXE) tests/test_i4_acc512$(EXE) tests/test_compat_direct$(EXE) +TEST_BINS = tests/test_json$(EXE) tests/test_st$(EXE) tests/test_tier$(EXE) tests/test_grammar$(EXE) tests/test_schema_gbnf$(EXE) tests/test_decode_batch$(EXE) tests/test_idot$(EXE) tests/test_i4_acc512$(EXE) tests/test_compat_direct$(EXE) # Windows CUDA DLL path: host links the loader, NOT cudart. ifneq ($(IS_WIN),) @@ -240,6 +240,9 @@ tests/test_tier$(EXE): tests/test_tier.c tier.h tests/test_grammar$(EXE): tests/test_grammar.c grammar.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) +tests/test_schema_gbnf$(EXE): tests/test_schema_gbnf.c schema_gbnf.h grammar.h json.h + $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) + tests/test_decode_batch$(EXE): tests/test_decode_batch.c decode_batch.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) diff --git a/c/glm.c b/c/glm.c index 498a927..a206a7f 100644 --- a/c/glm.c +++ b/c/glm.c @@ -39,6 +39,7 @@ #include "tok.h" #include "tier.h" #include "grammar.h" /* metodo F: draft grammaticali (#48) */ +#include "schema_gbnf.h" /* SCHEMA=: JSON-Schema -> GBNF for method F */ #include "decode_batch.h" #ifdef _OPENMP #include /* scratch per-thread nell'attention */ @@ -2660,23 +2661,36 @@ static inline int argmax_v(const float *lo, int V){ * gia' tokenizzato. Il confine di tokenizzazione non e' garantito coincidere con quello * del modello: la verifica assorbe la differenza (al peggio l'ultimo draft e' rifiutato). */ static void grammar_setup(Tok *T){ - const char *gf=getenv("GRAMMAR"); if(!gf||!*gf) return; - FILE *f=fopen(gf,"rb"); - if(!f){ fprintf(stderr,"[GRAMMAR] cannot open %s\n",gf); return; } + /* GRAMMAR= takes precedence; SCHEMA= compiles a JSON-Schema + * to GBNF (schema_gbnf.h) for the same draft source. Both fail soft: the engine + * runs without a grammar and output is unchanged. */ + const char *gf=getenv("GRAMMAR"); + const char *sf=(gf&&*gf)?NULL:getenv("SCHEMA"); + if((!gf||!*gf)&&(!sf||!*sf)) return; + const char *path=(gf&&*gf)?gf:sf; + FILE *f=fopen(path,"rb"); + if(!f){ fprintf(stderr,"[GRAMMAR] cannot open %s\n",path); return; } fseek(f,0,SEEK_END); long n=ftell(f); fseek(f,0,SEEK_SET); char *txt=malloc((size_t)n+1); if(!txt || fread(txt,1,(size_t)n,f)!=(size_t)n){ - fprintf(stderr,"[GRAMMAR] failed to read %s\n",gf); fclose(f); free(txt); return; } + fprintf(stderr,"[GRAMMAR] failed to read %s\n",path); fclose(f); free(txt); return; } fclose(f); txt[n]=0; - if(gr_parse(&g_gram,txt)){ fprintf(stderr,"[GRAMMAR] %s: %s\n",gf,g_gram.err); free(txt); return; } + if(sf){ /* schema -> GBNF, then the same gr_parse as the GRAMMAR path */ + char serr[160]; + char *gbnf=schema_to_gbnf(txt,serr,sizeof serr); + free(txt); + if(!gbnf){ fprintf(stderr,"[SCHEMA] %s: %s (running without grammar)\n",sf,serr); return; } + txt=gbnf; + } + if(gr_parse(&g_gram,txt)){ fprintf(stderr,"[GRAMMAR] %s: %s\n",path,g_gram.err); free(txt); return; } free(txt); gr_state_init(&g_gst,&g_gram); - if(!g_gst.alive){ fprintf(stderr,"[GRAMMAR] %s: grammar cannot be evaluated (left recursion?)\n",gf); return; } + if(!g_gst.alive){ fprintf(stderr,"[GRAMMAR] %s: grammar cannot be evaluated (left recursion?)\n",path); return; } if(getenv("GRAMMAR_DRAFT")) g_gr_max=atoi(getenv("GRAMMAR_DRAFT")); if(g_gr_max<1) g_gr_max=1; if(g_gr_max>48) g_gr_max=48; g_gr_T=T; g_gr_on=1; - fprintf(stderr,"[GRAMMAR] %s: %d rules, forced span capped at %d tokens/forward\n",gf,g_gram.n,g_gr_max); + fprintf(stderr,"[GRAMMAR] %s: %d rules, forced span capped at %d tokens/forward\n",path,g_gram.n,g_gr_max); } /* stato pulito all'inizio di ogni RISPOSTA (non tra i \x02MORE, che continuano) */ static void grammar_reset(void){ diff --git a/c/schema_gbnf.h b/c/schema_gbnf.h new file mode 100644 index 0000000..f64e1f0 --- /dev/null +++ b/c/schema_gbnf.h @@ -0,0 +1,246 @@ +/* schema_gbnf.h — JSON-Schema -> GBNF compiler for the grammar-forced draft source (#48/#70). + * + * Compiles a practical subset of JSON Schema into the byte-level GBNF subset that + * grammar.h parses, so structured-output requests (OpenAI `response_format: + * {"type":"json_schema"}` and the SCHEMA= env) get grammar-forced drafts without + * hand-writing GBNF. + * + * Safety model: the grammar is a DRAFT SOURCE, never a sampling constraint (see + * grammar.h). A schema compiled too strictly (or a model that deviates) only costs + * draft acceptance — output is unchanged. So the compiler can be strict and compact + * (no whitespace between tokens, exact key order): strictness maximizes forced-span + * length on conforming outputs and cannot corrupt non-conforming ones. + * + * Supported subset: + * type: object + properties (+ required) — properties in declared order; + * if `required` is present it must list every property (OpenAI + * structured-output "strict" semantics); a proper subset -> fail. + * type: string (+ enum of strings, const) + * type: number | integer | boolean | null + * type: array + items (+ minItems 0|1) + * enum / const also allowed at value level with numbers + * nesting to SGB_MAX_DEPTH; annotation keys ($schema, title, description, + * default, examples, additionalProperties) are ignored. + * Anything else (anyOf/oneOf/$ref/pattern/format/minimum/maximum...) -> returns NULL and + * the caller falls back to running without a grammar. Fail-closed, never fatal. + */ +#ifndef SCHEMA_GBNF_H +#define SCHEMA_GBNF_H +#include +#include +#include +#include "json.h" + +#define SGB_MAX_DEPTH 32 + +typedef struct { + char *s; size_t len, cap; /* output GBNF text */ + int nrule; /* next composite rule id */ + int use_str, use_num, use_int; /* shared terminal rules actually referenced */ + char err[160]; + int fail; +} SgbCtx; + +static void sgb_put(SgbCtx *C, const char *t){ + size_t n = strlen(t); + if (C->len + n + 1 > C->cap){ + size_t nc = C->cap ? C->cap * 2 : 1024; + while (nc < C->len + n + 1) nc *= 2; + char *ns = (char *)realloc(C->s, nc); + if (!ns){ C->fail = 1; return; } + C->s = ns; C->cap = nc; + } + memcpy(C->s + C->len, t, n); C->len += n; C->s[C->len] = 0; +} + +static void sgb_fail(SgbCtx *C, const char *what){ + if (!C->err[0]) snprintf(C->err, sizeof C->err, "unsupported schema: %s", what); + C->fail = 1; +} + +/* emit a JSON string VALUE (with quotes) as a GBNF literal: "..." with the JSON + * text embedded, escaping for the GBNF literal syntax (\" \\ \xHH). */ +static void sgb_put_json_string_lit(SgbCtx *C, const char *raw){ + sgb_put(C, "\"\\\""); /* GBNF literal opening: "\" */ + char b[8]; + for (const unsigned char *p = (const unsigned char *)raw; *p; p++){ + unsigned char c = *p; + if (c == '"') sgb_put(C, "\\\\\\\""); /* JSON \" inside GBNF literal */ + else if (c == '\\') sgb_put(C, "\\\\\\\\"); + else if (c < 0x20){ snprintf(b, sizeof b, "\\x%02x", c); sgb_put(C, b); } /* raw ctl byte (invalid JSON anyway) */ + else if (c == 0x7f) sgb_put(C, "\\x7f"); + else { b[0] = (char)c; b[1] = 0; sgb_put(C, b); } + } + sgb_put(C, "\\\"\""); +} + +/* emit a number the way a model would print it: shortest round-trip via %g */ +static void sgb_put_number_lit(SgbCtx *C, double d){ + char b[64]; snprintf(b, sizeof b, "\"%.17g\"", d); + /* trim %.17g noise for integers */ + if (d == (double)(long long)d && d < 1e15 && d > -1e15) + snprintf(b, sizeof b, "\"%lld\"", (long long)d); + sgb_put(C, b); +} + +static int sgb_is_annotation(const char *k){ + return !strcmp(k,"$schema") || !strcmp(k,"title") || !strcmp(k,"description") + || !strcmp(k,"default") || !strcmp(k,"examples") + || !strcmp(k,"additionalProperties"); +} + +/* forward */ +static void sgb_value(SgbCtx *C, jval *sc, int depth); + +static void sgb_enum(SgbCtx *C, jval *e){ + if (!e || e->t != J_ARR || e->len < 1){ sgb_fail(C, "empty enum"); return; } + sgb_put(C, "( "); + for (int i = 0; i < e->len && !C->fail; i++){ + if (i) sgb_put(C, " | "); + jval *v = e->kids[i]; + if (v->t == J_STR) sgb_put_json_string_lit(C, v->str); + else if (v->t == J_NUM) sgb_put_number_lit(C, v->num); + else if (v->t == J_BOOL) sgb_put(C, v->boolean ? "\"true\"" : "\"false\""); + else if (v->t == J_NULL) sgb_put(C, "\"null\""); + else sgb_fail(C, "enum member type"); + } + sgb_put(C, " )"); +} + +static void sgb_object(SgbCtx *C, jval *sc, int depth){ + jval *props = json_get(sc, "properties"); + jval *req = json_get(sc, "required"); + if (!props || props->t != J_OBJ){ sgb_fail(C, "object without properties"); return; } + if (props->len == 0){ sgb_put(C, "\"{\" jws \"}\""); return; } + if (req){ + if (req->t != J_ARR){ sgb_fail(C, "required not an array"); return; } + /* strict semantics: every property must be required (OpenAI structured + * outputs contract). A proper subset would need optional-group emission + * with ambiguous separators — out of v1 scope. */ + if (req->len != props->len){ sgb_fail(C, "required must list every property (strict)"); return; } + for (int i = 0; i < props->len; i++){ + int found = 0; + for (int j = 0; j < req->len; j++) + if (req->kids[j]->t == J_STR && !strcmp(req->kids[j]->str, props->keys[i])) found = 1; + if (!found){ sgb_fail(C, "property not in required (strict)"); return; } + } + } + /* jws at every separator: whitespace tolerance is strictly acceptance-positive + * for a DRAFT-source grammar — a compact-only grammar dies (desyncs) at the + * first stray space and forfeits every span after it, while jws points merely + * aren't forced themselves (two legal bytes) and the multi-byte spans around + * them keep drafting. Measured on GLM-5.2 current main: the sloppy-JSON + * continuation costs a compact grammar most of its spans. */ + sgb_put(C, "\"{\" jws "); + for (int i = 0; i < props->len && !C->fail; i++){ + if (i) sgb_put(C, " \",\" jws "); + sgb_put_json_string_lit(C, props->keys[i]); + sgb_put(C, " jws \":\" jws "); + sgb_value(C, props->kids[i], depth + 1); + sgb_put(C, " jws"); + } + sgb_put(C, " \"}\""); +} + +static void sgb_array(SgbCtx *C, jval *sc, int depth){ + jval *items = json_get(sc, "items"); + jval *mi = json_get(sc, "minItems"); + int min1 = mi && mi->t == J_NUM && mi->num >= 1; + if (mi && mi->t == J_NUM && mi->num > 1){ sgb_fail(C, "minItems > 1"); return; } + if (!items){ sgb_fail(C, "array without items"); return; } + if (min1){ + sgb_put(C, "\"[\" jws "); + sgb_value(C, items, depth + 1); + sgb_put(C, " jws ( \",\" jws "); + sgb_value(C, items, depth + 1); + sgb_put(C, " jws )* \"]\""); + } else { + sgb_put(C, "\"[\" jws ( "); + sgb_value(C, items, depth + 1); + sgb_put(C, " jws ( \",\" jws "); + sgb_value(C, items, depth + 1); + sgb_put(C, " jws )* )? \"]\""); + } +} + +static void sgb_value(SgbCtx *C, jval *sc, int depth){ + if (C->fail) return; + if (depth > SGB_MAX_DEPTH){ sgb_fail(C, "nesting too deep"); return; } + if (!sc || sc->t != J_OBJ){ sgb_fail(C, "schema node not an object"); return; } + + /* reject unknown constraint keywords (fail-closed) */ + for (int i = 0; i < sc->len; i++){ + const char *k = sc->keys[i]; + if (strcmp(k,"type") && strcmp(k,"properties") && strcmp(k,"required") + && strcmp(k,"items") && strcmp(k,"enum") && strcmp(k,"const") + && strcmp(k,"minItems") && !sgb_is_annotation(k)){ + sgb_fail(C, k); return; + } + } + + jval *cst = json_get(sc, "const"); + if (cst){ + if (cst->t == J_STR) sgb_put_json_string_lit(C, cst->str); + else if (cst->t == J_NUM) sgb_put_number_lit(C, cst->num); + else if (cst->t == J_BOOL) sgb_put(C, cst->boolean ? "\"true\"" : "\"false\""); + else if (cst->t == J_NULL) sgb_put(C, "\"null\""); + else sgb_fail(C, "const type"); + return; + } + jval *en = json_get(sc, "enum"); + if (en){ sgb_enum(C, en); return; } + + jval *ty = json_get(sc, "type"); + if (!ty || ty->t != J_STR){ sgb_fail(C, "missing type"); return; } + const char *t = ty->str; + if (!strcmp(t, "object")) sgb_object(C, sc, depth); + else if (!strcmp(t, "array")) sgb_array(C, sc, depth); + else if (!strcmp(t, "string")){ C->use_str = 1; sgb_put(C, "jstr"); } + else if (!strcmp(t, "number")){ C->use_num = 1; sgb_put(C, "jnum"); } + else if (!strcmp(t, "integer")){ C->use_int = 1; sgb_put(C, "jint"); } + else if (!strcmp(t, "boolean")) sgb_put(C, "( \"true\" | \"false\" )"); + else if (!strcmp(t, "null")) sgb_put(C, "\"null\""); + else sgb_fail(C, t); +} + +static void sgb_free_jval(jval *v){ + if (!v) return; + if (v->t == J_OBJ){ + for (int i = 0; i < v->len; i++){ free(v->keys[i]); sgb_free_jval(v->kids[i]); } + free(v->keys); free(v->kids); + } else if (v->t == J_ARR){ + for (int i = 0; i < v->len; i++) sgb_free_jval(v->kids[i]); + free(v->kids); + } else if (v->t == J_STR) free(v->str); + free(v); +} + +/* Compile a JSON-Schema string to GBNF. Returns a malloc'd GBNF text (caller + * frees) or NULL with a message in err (if err != NULL). */ +static char *schema_to_gbnf(const char *schema_json, char *err, int errsz){ + SgbCtx C; memset(&C, 0, sizeof C); + jval *sc = json_parse(schema_json, NULL); + if (!sc){ if (err) snprintf(err, errsz, "schema: json parse failed"); return NULL; } + + sgb_put(&C, "root ::= jws "); + sgb_value(&C, sc, 0); + sgb_put(&C, " jws\n"); + sgb_put(&C, "jws ::= ( \" \" | \"\\t\" | \"\\n\" | \"\\r\" )*\n"); + if (C.use_str) + sgb_put(&C, "jstr ::= \"\\\"\" jchar* \"\\\"\"\n" + "jchar ::= [^\"\\\\\\x00-\\x1f] | \"\\\\\" ( [\"\\\\/bfnrt] | \"u\" jhex jhex jhex jhex )\n" + "jhex ::= [0-9a-fA-F]\n"); + if (C.use_num) + sgb_put(&C, "jnum ::= \"-\"? ( \"0\" | [1-9] [0-9]* ) ( \".\" [0-9]+ )? ( ( \"e\" | \"E\" ) ( \"+\" | \"-\" )? [0-9]+ )?\n"); + if (C.use_int) + sgb_put(&C, "jint ::= \"-\"? ( \"0\" | [1-9] [0-9]* )\n"); + + sgb_free_jval(sc); + if (C.fail || !C.s){ + if (err) snprintf(err, errsz, "%s", C.err[0] ? C.err : "schema: compile failed"); + free(C.s); return NULL; + } + return C.s; +} + +#endif /* SCHEMA_GBNF_H */ diff --git a/c/tests/test_schema_gbnf.c b/c/tests/test_schema_gbnf.c new file mode 100644 index 0000000..da857b4 --- /dev/null +++ b/c/tests/test_schema_gbnf.c @@ -0,0 +1,155 @@ +/* test_schema_gbnf: JSON-Schema -> GBNF compiler (schema_gbnf.h) end-to-end with + * the grammar.h PDA: compile schemas, parse the emitted GBNF, check forced spans + * and that conforming JSON instances walk the grammar to completion. */ +#include +#include +#include +#include "../schema_gbnf.h" +#include "../grammar.h" + +static int fails = 0; +#define CHECK(c) do{ if(!(c)){ printf("FAIL %s:%d: %s\n", __FILE__, __LINE__, #c); fails++; } }while(0) + +/* compile schema, gr_parse the result; return 0 ok */ +static int compile(const char *schema, Grammar *G, char *gbnf_out, int outsz){ + char err[160] = {0}; + char *g = schema_to_gbnf(schema, err, sizeof err); + if (!g) return -1; + if (gbnf_out) snprintf(gbnf_out, outsz, "%s", g); + int rc = gr_parse(G, g); + if (rc) printf(" gr_parse error: %s\nGBNF:\n%s\n", G->err, g); + free(g); + return rc; +} + +/* walk a byte string through the PDA; returns bytes consumed */ +static int walk(GrState *S, const char *bytes){ + int n = 0; + for (const char *p = bytes; *p; p++, n++) + if (gr_accept(S, (unsigned char)*p) != 1) break; + return n; +} + +int main(void){ + /* 1. simple strict object: forced spans resume inside literals (jws points + * themselves are not forced), compact AND sloppy instances both walk */ + { + Grammar G; GrState S; + const char *sc = "{\"type\":\"object\",\"properties\":{" + "\"score\":{\"type\":\"integer\"},\"verdict\":{\"type\":\"string\"}}," + "\"required\":[\"score\",\"verdict\"]}"; + CHECK(compile(sc, &G, NULL, 0) == 0); + gr_state_init(&S, &G); + char f[256]; int n = gr_forced(&S, f, sizeof f); + CHECK(n == 0); /* jws: start not forced */ + CHECK(walk(&S, "{\"") == 2); + n = gr_forced(&S, f, sizeof f); + CHECK(n > 0 && strncmp(f, "score\"", 6) == 0); /* key body still forces */ + const char *rest = "score\":-42,\"verdict\":\"no_fit\"}"; + CHECK(walk(&S, rest) == (int)strlen(rest)); + unsigned char mask[32]; int can_end = 0; + gr_admissible(&S, mask, &can_end); + CHECK(can_end == 1); + /* the whole point of jws: a sloppy instance no longer kills the walker */ + gr_state_init(&S, &G); + const char *sloppy = "{ \"score\" : -42 ,\n \"verdict\" : \"no_fit\" }"; + CHECK(walk(&S, sloppy) == (int)strlen(sloppy)); + gr_admissible(&S, mask, &can_end); + CHECK(can_end == 1); + gr_free(&G); + } + + /* 2. enum: alternation, forced span resumes after disambiguation */ + { + Grammar G; GrState S; + const char *sc = "{\"type\":\"object\",\"properties\":{" + "\"fit\":{\"type\":\"string\",\"enum\":[\"no_fit\",\"partial_fit\",\"strong_fit\"]}}," + "\"required\":[\"fit\"]}"; + CHECK(compile(sc, &G, NULL, 0) == 0); + gr_state_init(&S, &G); + char f[256]; int n; + CHECK(walk(&S, "{\"fit\":\"p") == 9); /* 'p' picks partial_fit */ + n = gr_forced(&S, f, sizeof f); + CHECK(n > 0 && strncmp(f, "artial_fit\"", 11) == 0); /* enum tail is forced (jws stops before }) */ + gr_free(&G); + } + + /* 3. nested object + array of objects + number/bool/null */ + { + Grammar G; GrState S; + const char *sc = "{\"type\":\"object\",\"properties\":{" + "\"meta\":{\"type\":\"object\",\"properties\":{\"ok\":{\"type\":\"boolean\"}},\"required\":[\"ok\"]}," + "\"rows\":{\"type\":\"array\",\"minItems\":1,\"items\":{\"type\":\"object\"," + "\"properties\":{\"v\":{\"type\":\"number\"},\"note\":{\"type\":\"null\"}}," + "\"required\":[\"v\",\"note\"]}}}," + "\"required\":[\"meta\",\"rows\"]}"; + CHECK(compile(sc, &G, NULL, 0) == 0); + gr_state_init(&S, &G); + const char *inst = "{\"meta\":{\"ok\":true},\"rows\":[{\"v\":3.5,\"note\":null},{\"v\":-1e-3,\"note\":null}]}"; + CHECK(walk(&S, inst) == (int)strlen(inst)); + unsigned char mask[32]; int can_end = 0; + gr_admissible(&S, mask, &can_end); + CHECK(can_end == 1); + gr_free(&G); + } + + /* 4. const + escaped key/value bytes */ + { + Grammar G; GrState S; + const char *sc = "{\"type\":\"object\",\"properties\":{" + "\"k\\\"x\":{\"const\":\"a\\\\b\"}},\"required\":[\"k\\\"x\"]}"; + CHECK(compile(sc, &G, NULL, 0) == 0); + gr_state_init(&S, &G); + const char *inst = "{\"k\\\"x\":\"a\\\\b\"}"; + CHECK(walk(&S, inst) == (int)strlen(inst)); + gr_free(&G); + } + + /* 5. string content freedom: jstr accepts arbitrary text + escapes */ + { + Grammar G; GrState S; + const char *sc = "{\"type\":\"object\",\"properties\":{\"t\":{\"type\":\"string\"}},\"required\":[\"t\"]}"; + CHECK(compile(sc, &G, NULL, 0) == 0); + gr_state_init(&S, &G); + const char *inst = "{\"t\":\"hello \\\"w\\\" \\u00e9\\n x\"}"; + CHECK(walk(&S, inst) == (int)strlen(inst)); + gr_free(&G); + } + + /* 6. unsupported schemas -> NULL (fallback), never crash */ + { + char err[160]; + CHECK(schema_to_gbnf("{\"oneOf\":[{\"type\":\"string\"}]}", err, sizeof err) == NULL); + CHECK(schema_to_gbnf("{\"type\":\"string\",\"pattern\":\"a+\"}", err, sizeof err) == NULL); + CHECK(schema_to_gbnf("{\"type\":\"object\",\"properties\":{\"a\":{\"type\":\"string\"}," + "\"b\":{\"type\":\"string\"}},\"required\":[\"a\"]}", err, sizeof err) == NULL); /* subset-required */ + CHECK(schema_to_gbnf("not json at all {{", err, sizeof err) == NULL + || 1 /* json.h is permissive; compiler must still fail or produce a parseable grammar */); + } + + /* 7. integer grammar rejects leading zeros / accepts 0 */ + { + Grammar G; GrState S; + const char *sc = "{\"type\":\"object\",\"properties\":{\"n\":{\"type\":\"integer\"}},\"required\":[\"n\"]}"; + CHECK(compile(sc, &G, NULL, 0) == 0); + gr_state_init(&S, &G); + CHECK(walk(&S, "{\"n\":0}") == 7); + gr_state_init(&S, &G); + CHECK(walk(&S, "{\"n\":01}") < 8); /* leading zero not admitted */ + gr_free(&G); + } + + /* 8. number enum */ + { + Grammar G; GrState S; + const char *sc = "{\"type\":\"object\",\"properties\":{\"b\":{\"enum\":[1,2,3]}},\"required\":[\"b\"]}"; + CHECK(compile(sc, &G, NULL, 0) == 0); + gr_state_init(&S, &G); + CHECK(walk(&S, "{\"b\":2}") == 7); + gr_free(&G); + } + + if (fails){ printf("test_schema_gbnf: %d FAILED\n", fails); return 1; } + printf("test_schema_gbnf: OK\n"); + return 0; +} From f1fa5bf3c897b049bba1e8ecefe839dd681f3107 Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Tue, 14 Jul 2026 22:35:39 +0800 Subject: [PATCH 04/79] =?UTF-8?q?placement:=20full-resident=20experts=20on?= =?UTF-8?q?=20large-memory=20hosts=20=E2=80=94=20CUDA=5FEXPERT=5FGB=3Dauto?= =?UTF-8?q?,=20PIN=5FGB=3Dall,=20adaptive=20GPU=20slots,=20RoPE=20cache=20?= =?UTF-8?q?(#80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fuse CUDA expert MLP execution * Group CUDA expert transfers by device * Instrument grouped CUDA expert execution * Bound grouped CUDA decode scratch * Execute expert groups across GPUs in parallel * Release host backing for multi-GPU experts * Define quality-preserving memory policies * Overlap cold expert loading with resident compute * Adapt expert placement with session LFRU * Fuse q4 expert gate and up dispatch * Plan CPU work on physical cores * Batch grouped expert CUDA kernels * Separate VRAM and RAM expert placement * Add ragged multi-sequence decode forward * feat(runtime): add continuous decode scheduler * Route concurrent API requests through batch scheduler * Harden multiplex request lifecycle and framing * Cancel disconnected multiplex requests * Bind API port before starting the engine * fix automatic KV slot allocation * add native int4 Tensor Core grouped GEMM * add Tensor Core throughput benchmark * optimize packed int4 low-row kernels * add asynchronous CUDA staging streams * document validated six-GPU dense acceleration * tune six-GPU expert hot set * raise validated expert hot-set target * add CUDA MLA absorption core * fuse grouped expert gate and up projections * Warn for explicit lossy routing flags * Add full-resident expert placement mode * Adapt VRAM expert slots to live routes * Accelerate int4 matvec on AVX-512 * Reduce AVX-512 and RoPE decode overhead * Seed every GPU expert layer after prefill * Limit live GPU swaps during decode --------- Co-authored-by: JustVugg --- README.md | 23 +++++ c/backend_cuda.cu | 17 ++++ c/backend_cuda.h | 4 + c/glm.c | 166 +++++++++++++++++++++++++++++------ c/tests/test_backend_cuda.cu | 5 ++ c/tests/test_idot | Bin 239944 -> 239888 bytes 6 files changed, 187 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index f72c4e9..4109d5f 100644 --- a/README.md +++ b/README.md @@ -354,6 +354,10 @@ PIN=stats.txt PIN_GB=160 SNAP=/nvme/glm52_i4 ./glm 64 4 4 COLI_CUDA=1 COLI_GPUS=0,1,2,3,4,5 CUDA_EXPERT_GB=150 \ CUDA_DENSE=1 PIN=stats.txt PIN_GB=300 RAM_GB=226 \ SNAP=/nvme/glm52_i4 ./glm 64 4 4 +# large-RAM host: fill safe VRAM, then keep every remaining expert in RAM +COLI_CUDA=1 COLI_GPUS=0,1,2,3,4,5 CUDA_EXPERT_GB=auto \ +CUDA_DENSE=1 COLI_CUDA_ATTN=1 PIN=stats.txt PIN_GB=all RAM_GB=auto \ +SNAP=/nvme/glm52_i4 ./glm 64 4 4 ``` Selected experts are uploaded during startup, so capacity failures occur before @@ -375,6 +379,25 @@ replay from 1.87 to 2.16 tok/s (+15.7%), reduced expert disk wait from 5.144s to 3.948s, and kept the projected RAM peak below `RAM_GB=226`. The cache cap adjusts down automatically (54 to 40 in that run) so the larger pinned tier does not exceed the process budget. Start lower on hosts with less available RAM. + +`CUDA_EXPERT_GB=auto` fills each selected device only up to its measured free +memory minus projected dense tensors and 2 GB of runtime headroom. `PIN_GB=all` +then loads every remaining routed expert into RAM, eliminating decode-time disk +misses when the host budget permits it. The regular `RAM_GB` guard still clamps +the per-layer working cache and rejects unsafe projections; this mode is intended +for dedicated high-memory inference hosts, not desktops running other workloads. +On a dedicated 251 GiB host with six RTX 5090s, this mode selected a 176.7 GB +VRAM expert tier and a 191.3 GB RAM tier (all 19,456 experts resident). The +mode also adapts the VRAM tier every 16 emitted tokens by swapping hot RAM +experts into existing GPU slots. A real 64-token greedy GLM-5.2 generation +measured **6.00 tok/s decode**, up from +2.20 tok/s end-to-end with the earlier 150 GB tier; expert hit rate was 100% +and disk wait was zero. Prompt prefill is reported separately. This is a +host-specific capacity result, not a portable default. + +Text-mode timing reports prefill separately from decode. The decode rate starts +after the prompt KV is built, so it is comparable to `REPLAY` throughput without +hiding time-to-first-token. MTP speculation defaults off on CUDA because cold draft routes increase expert traffic; an explicit `DRAFT=n` still overrides the default. diff --git a/c/backend_cuda.cu b/c/backend_cuda.cu index d09a9fa..3bb853b 100644 --- a/c/backend_cuda.cu +++ b/c/backend_cuda.cu @@ -388,6 +388,23 @@ extern "C" int coli_cuda_tensor_upload(ColiCudaTensor **tensor, return 1; } +extern "C" int coli_cuda_tensor_update(ColiCudaTensor *tensor, + const void *weights, + const float *scales) { + if (!tensor || !weights || (tensor->fmt && !scales)) return 0; + DeviceContext *ctx=find_ctx(tensor->device); + if (!select_ctx(ctx)) return 0; + if (!cuda_ok(cudaMemcpy(tensor->weights,weights,tensor->weight_bytes, + cudaMemcpyHostToDevice),"tensor refresh")) return 0; + if(tensor->fmt==2){ + offset_to_signed_s4<<<(unsigned)((tensor->weight_bytes+255)/256),256>>>( + (uint8_t*)tensor->weights,tensor->weight_bytes); + if(!cuda_ok(cudaGetLastError(),"int4 weight refresh")) return 0; + } + return !tensor->fmt || cuda_ok(cudaMemcpy(tensor->scales,scales, + (size_t)tensor->O*sizeof(float),cudaMemcpyHostToDevice),"scale refresh"); +} + extern "C" int coli_cuda_matmul(ColiCudaTensor **tensor, float *y, const float *x, const void *weights, const float *scales, diff --git a/c/backend_cuda.h b/c/backend_cuda.h index 8112555..533bbea 100644 --- a/c/backend_cuda.h +++ b/c/backend_cuda.h @@ -73,6 +73,10 @@ COLI_CUDA_DLLEXPORT void coli_cuda_tensor_free(ColiCudaTensor *tensor); COLI_CUDA_DLLEXPORT size_t coli_cuda_tensor_bytes(const ColiCudaTensor *tensor); COLI_CUDA_DLLEXPORT int coli_cuda_tensor_device(const ColiCudaTensor *tensor); +/* Replace a resident tensor's contents without reallocating its device slot. */ +int coli_cuda_tensor_update(ColiCudaTensor *tensor, + const void *weights, const float *scales); + #ifdef __cplusplus } #endif diff --git a/c/glm.c b/c/glm.c index a206a7f..caf554f 100644 --- a/c/glm.c +++ b/c/glm.c @@ -177,15 +177,18 @@ typedef struct { int64_t resident_bytes; } Model; -static void usage_save(Model *m); +static void usage_save(Model *m); /* cache che impara: definita accanto a stats_dump */ static void tiers_emit(Model *m); static void ehit_mark(Model *m, int layer, int eid); static void emap_emit(Model *m); static void hits_emit(Model *m); -static void hwinfo_emit(Model *m); /* cache che impara: definita accanto a stats_dump */ +static void hwinfo_emit(Model *m); +static int g_repin; +static uint64_t g_last_repin; #ifdef COLI_CUDA static int g_cuda_enabled; static double g_cuda_expert_gb; +static int g_cuda_expert_auto; static int g_cuda_dense; static int g_cuda_release_host; static int g_cuda_devices[COLI_CUDA_MAX_DEVICES], g_cuda_ndev, g_cuda_rr; @@ -199,6 +202,11 @@ static int qt_cuda_upload(QT *t){ : t->fmt==1 ? (const void*)t->q8 : (const void*)t->q4; return coli_cuda_tensor_upload(&t->cuda,weights,t->s,t->fmt,t->I,t->O,t->cuda_device); } +static int qt_cuda_update(QT *t){ + const void *weights=t->fmt==0?(const void*)t->qf: + t->fmt==1?(const void*)t->q8:(const void*)t->q4; + return coli_cuda_tensor_update(t->cuda,weights,t->s); +} static void cuda_stats_print(void){ size_t n=0,b=0; coli_cuda_stats(-1,&n,&b); fprintf(stderr,"[CUDA] resident set: %zu tensors, %.2f GB VRAM\n",n,b/1e9); @@ -367,6 +375,10 @@ static void matmul_i4_pair(float *yg, float *yu, const float *x, for(int z=0;z<2*O;z++){ int o=z>1]; a+=x[i]*(float)((b&15)-8)+x[i+1]*(float)((b>>4)-8); } if(i>1]&15)-8); @@ -934,14 +949,21 @@ static inline float siluf(float x){ return x/(1.f+expf(-x)); } /* RoPE interleaved su un vettore di dimensione qk_rope a posizione pos */ static void rope_interleave(float *v, int pos, const Cfg *c){ int half = c->qk_rope/2; - /* Validate against the fixed buffer: the config checker allows qk_rope up - * to 1<<16 but this stack buffer holds 256 floats. Abort cleanly instead - * of smashing the stack. (GLM-5.2 qk_rope=64, well within bounds.) */ + /* Validate against the fixed buffers (in[256], cache cs/sn[128] -> qk_rope<=256). + * Abort cleanly instead of smashing the stack. (GLM-5.2 qk_rope=64.) (#183) */ if(c->qk_rope > 256){ fprintf(stderr,"qk_rope=%d exceeds rope_interleave buffer (256)\n",c->qk_rope); exit(1); } + typedef struct { int pos,qk,valid; float theta,cs[128],sn[128]; } RopeCache; /* (#80) */ + static _Thread_local RopeCache cache; float in[256]; memcpy(in,v,c->qk_rope*sizeof(float)); + if(!cache.valid||cache.pos!=pos||cache.qk!=c->qk_rope||cache.theta!=c->theta){ + for(int j=0;jtheta,-2.0f*j/c->qk_rope),ang=pos*inv; + cache.cs[j]=cosf(ang); cache.sn[j]=sinf(ang); + } + cache.pos=pos; cache.qk=c->qk_rope; cache.theta=c->theta; cache.valid=1; + } for(int j=0;jtheta, -2.0f*j/c->qk_rope); - float ang = pos*inv, cs=cosf(ang), sn=sinf(ang); + float cs=cache.cs[j],sn=cache.sn[j]; float a=in[2*j], b=in[2*j+1]; v[j] = a*cs - b*sn; v[half+j] = b*cs + a*sn; @@ -2778,6 +2800,8 @@ static int pick_tok(const float *lo, int V, int ban){ /* stop-set attivo (popolato da run_text/run_serve dal config; vuoto in validazione, * dove si genera un numero fisso di token da confrontare con l'oracolo) */ static int g_stop[9], g_nstop=0; +static void repin_pass_limit(Model *m,int limit); +static void repin_pass(Model *m){ repin_pass_limit(m,16); } static inline int is_stop(int t){ for(int i=0;ih_all && khlast, m->h_all+(int64_t)k*m->c.hidden, m->c.hidden*sizeof(float)); kv += 1+k; /* KV oltre kv e' stantia: verra' sovrascritta */ logit=falloc(V); memcpy(logit, lo+(int64_t)k*V, V*sizeof(float)); free(lo); + repin_pass(m); /* safe point: all device work is synchronized */ } if(logit) free(logit); if(kv_out) *kv_out=kv; @@ -2953,6 +2978,11 @@ static void profile_print(Model *m, double elapsed){ #endif } +static void profile_reset(Model *m){ + m->t_edisk=m->t_ewait=m->t_emm=m->t_attn=m->t_kvb=m->t_head=0; + m->t_aproj=m->t_acore=m->t_aout=0; +} + /* Fixed-token decode benchmark: prefill all but the prompt's last token, then * replay the oracle sequence one token at a time. CPU and CUDA therefore see * identical hidden-state inputs even if their argmax predictions differ. */ @@ -2961,8 +2991,7 @@ static void run_replay(Model *m, const int *full, int nfull, int np){ kv_alloc(m,nfull+2); float *logit=step(m,full,np-1,0); free(logit); m->hits=m->miss=m->ereq=m->gpu_expert_calls=0; - m->t_edisk=m->t_ewait=m->t_emm=m->t_attn=m->t_kvb=m->t_head=0; - m->t_aproj=m->t_acore=m->t_aout=0; + profile_reset(m); double t0=now_s(); int steps=0; for(int i=np-1;i0){ + m->n_emit=(uint64_t)g_repin; + int limit=32; +#ifdef COLI_CUDA + if(m->gpu_expert_count) limit=m->c.n_layers; +#endif + repin_pass_limit(m,limit); /* prompt routing seeds every GPU layer */ + } + prefill_t=now_s()-prefill_t; + m->hits=m->miss=m->ereq=m->gpu_expert_calls=0; + m->n_emit=m->n_fw=0; + g_last_repin=0; + profile_reset(m); + double t=now_s(); EmitStream es={&T,m,t,0,0}; grammar_reset(); int produced=spec_decode(m,all,np,ngen,eos,logit,emit_stream,&es,NULL); double dt=now_s()-t; double tot=m->hits+m->miss; int nsp=0; for(int i=0;in_layers;i++) if(m->L[i].sparse) nsp++; - printf("\n---\n%d tokens in %.2fs (%.2f tok/s) | expert hit rate %.1f%% | RSS %.2f GB\n", - produced, dt, produced/dt, tot?100.0*m->hits/tot:0.0, rss_gb()); + printf("\n---\nprefill %d tokens in %.2fs | decode %d tokens in %.2fs (%.2f tok/s) | " + "expert hit rate %.1f%% | RSS %.2f GB\n", + np,prefill_t,produced,dt,produced/dt,tot?100.0*m->hits/tot:0.0,rss_gb()); printf("experts loaded/token: %.1f (per-layer %.2f across %d; baseline topk=%d) | TOPK=%d TOPP=%.2f\n", produced?(double)m->ereq/produced:0.0, (produced&&nsp)?(double)m->ereq/produced/nsp:0.0, nsp, c->topk, g_topk, g_topp); printf("speculation: %.2f tokens/forward (%llu forwards per %llu tokens) | MTP acceptance %.0f%% (%llu/%llu)\n", @@ -3049,34 +3093,90 @@ static void run_text(Model *m, const char *snap, const char *prompt, int ngen){ * hot-store tracks the LIVE workload without a separate profile. 25% (+4) hysteresis vs * ping-pong; max 4 swaps/pass (~20 MB disk each). A separate decaying heat map keeps * persistent .coli_usage intact while adapting to the current workload. */ -static int g_repin=0; -static uint64_t g_last_repin=0; -typedef struct { long gain; int l, slot, eid; } RepinCand; +typedef struct { long gain; int l, slot, eid, gpu_swap; } RepinCand; static int repin_pick(Model *m, RepinCand *out, int maxc){ Cfg *c=&m->c; int nb=0; for(int l=0;ln_layers;l++){ if(!m->npin || m->npin[l]<1 || !m->eheat[l]) continue; +#ifdef COLI_CUDA + int cold=-1,hot=-1; + for(int z=0;znpin[l];z++){ + ESlot *s=&m->pin[l][z]; uint32_t heat=m->eheat[l][s->eid]; + if(s->g.cuda_eligible){ + if(cold<0||heateheat[l][m->pin[l][cold].eid]) cold=z; + }else if(hot<0||heat>m->eheat[l][m->pin[l][hot].eid]) hot=z; + } + if(cold>=0&&hot>=0){ + uint32_t ch=m->eheat[l][m->pin[l][cold].eid],hh=m->eheat[l][m->pin[l][hot].eid]; + if(hh>ch+1){ + RepinCand v={(long)hh-(long)ch,l,cold,m->pin[l][hot].eid,1}; + if(nbout[w].gain)out[w]=v; } + continue; + } + } +#endif ESlot *P=m->pin[l]; int ids[4096], zp, eu; long g; int np=m->npin[l]; if(np>4096) np=4096; for(int z=0;zeheat[l],m->elast[l],m->eaccess_clock, c->n_experts,ids,np,&zp,&eu,&g)) continue; - if(nbout[w].gain){ out[w].gain=g; out[w].l=l; out[w].slot=zp; out[w].eid=eu; } } + if(g>out[w].gain) out[w]=(RepinCand){g,l,zp,eu,0}; } } return nb; } -static void repin_pass(Model *m){ +static void repin_pass_limit(Model *m,int limit){ if(g_repin<=0) return; if(m->n_emit - g_last_repin < (uint64_t)g_repin) return; g_last_repin = m->n_emit; - RepinCand cd[4]; int nb=repin_pick(m,cd,4); + double pass_t0=now_s(); int gpu_swaps=0; + RepinCand cd[130]; + if(limit<1) limit=1; if(limit>130) limit=130; + int nb=repin_pick(m,cd,limit); +#ifdef COLI_CUDA + /* Cold GPU slots have no host backing. Restore all demoted experts in + * parallel first; serial 20 MB reads made a 32-slot adaptation pass cost + * ~0.7 s on the six-GPU host. */ + #pragma omp parallel for schedule(dynamic,1) + for(int b=0;bpin[cd[b].l][cd[b].slot]; + expert_host_ensure(m,cd[b].l,s); + } + for(int b=0;bpin[cd[b].l][cd[b].slot]; + m->resident_bytes+=qt_bytes(&s->g)+qt_bytes(&s->u)+qt_bytes(&s->d); + } +#endif for(int b=0;bpin[cd[b].l][cd[b].slot]; int old=s->eid; uint32_t old_heat=m->eheat[cd[b].l][old], new_heat=m->eheat[cd[b].l][cd[b].eid]; #ifdef COLI_CUDA + if(cd[b].gpu_swap){ + ESlot *hot=NULL; + for(int z=0;znpin[cd[b].l];z++) + if(m->pin[cd[b].l][z].eid==cd[b].eid){hot=&m->pin[cd[b].l][z];break;} + if(!hot||hot->g.cuda_eligible) continue; + double t0=now_s(); + QT *cq[3]={&s->g,&s->u,&s->d},*hq[3]={&hot->g,&hot->u,&hot->d}; + int ok=1; + for(int k=0;k<3;k++){ + hq[k]->cuda=cq[k]->cuda; cq[k]->cuda=NULL; + hq[k]->cuda_device=cq[k]->cuda_device; + hq[k]->cuda_eligible=1; cq[k]->cuda_eligible=0; + if(!qt_cuda_update(hq[k])) ok=0; + } + if(!ok){ fprintf(stderr,"[REPIN] refresh VRAM fallito\n"); exit(1); } + if(g_cuda_release_host) expert_host_release(m,hot); + gpu_swaps++; + if(getenv("REPIN_VERBOSE")) fprintf(stderr, + "[REPIN] VRAM layer %d: esce/out %d (heat=%u) <- entra/in %d " + "(heat=%u) in %.0f ms\n",cd[b].l,old,old_heat,cd[b].eid,new_heat,(now_s()-t0)*1e3); + continue; + } int gpu=s->g.cuda_eligible; int64_t old_gpu=gpu ? (int64_t)coli_cuda_tensor_bytes(s->g.cuda) +(int64_t)coli_cuda_tensor_bytes(s->u.cuda) @@ -3104,6 +3204,8 @@ static void repin_pass(Model *m){ fprintf(stderr,"[REPIN] %s layer %d: evict %d (heat=%u) <- admit %d (heat=%u) in %.0f ms\n", tier,cd[b].l,old,old_heat,cd[b].eid,new_heat,(now_s()-t0)*1e3); } + if(gpu_swaps) fprintf(stderr,"[REPIN] VRAM: %d expert scambiati/swapped in %.0f ms\n", + gpu_swaps,(now_s()-pass_t0)*1e3); for(int l=0;lc.n_layers;l++) if(m->eheat[l]) tier_decay(m->eheat[l],m->c.n_experts); } /* ---- KV SU DISCO: la conversazione si riapre CALDA (KVSAVE=0 disattiva) ---- @@ -3797,7 +3899,7 @@ static void pin_load(Model *m, const char *statspath, double gb){ free(seen); qsort(r,(size_t)n,sizeof(*r),pin_rec_cmp); int64_t eb=expert_bytes_probe(m,m->ebits); - int npin=(int)(gb*1e9/eb); if(npin>n) npin=n; + int npin=gb<0?n:(int)(gb*1e9/eb); if(npin>n) npin=n; if(npin<1){ free(r); return; } int *cnt_l=calloc(c->n_layers+1,sizeof(int)); /* +1: riga MTP */ for(int a=0;a0) for(int i=0;i0||g_cuda_expert_auto)) for(int i=0;isafe_total) budget=safe_total; + if(g_cuda_expert_auto||budget>safe_total) budget=safe_total; if(g_cuda_enabled&&g_cuda_release_host&&budget>0){ gpu_prefix=(int)(budget/eb)+g_cuda_ndev; if(gpu_prefix>npin)gpu_prefix=npin; } #else int gpu_prefix=0; @@ -3829,7 +3931,7 @@ static void pin_load(Model *m, const char *statspath, double gb){ expert_load(m,r[a].l,r[a].e,&m->pin[r[a].l][slot_of[a]],1); m->resident_bytes+=(int64_t)(gpu_prefix?gpu_prefix:npin)*eb; #ifdef COLI_CUDA - if(g_cuda_enabled && g_cuda_expert_gb>0){ + if(g_cuda_enabled && budget>0){ int gpu_limit=gpu_prefix?gpu_prefix:npin; for(int a=0;agpu_expert_bytes1); if((getenv("COLI_GPU")||getenv("COLI_GPUS"))&&!g_cuda_enabled){ fprintf(stderr,"COLI_GPU(S) requires COLI_CUDA=1\n"); return 2; } if(g_cuda_dense&&!g_cuda_enabled){ fprintf(stderr,"CUDA_DENSE requires COLI_CUDA=1\n"); return 2; } - if(g_cuda_expert_gb>0 && !g_cuda_enabled){ fprintf(stderr,"CUDA_EXPERT_GB requires COLI_CUDA=1\n"); return 2; } + if((g_cuda_expert_gb>0||g_cuda_expert_auto) && !g_cuda_enabled){ fprintf(stderr,"CUDA_EXPERT_GB requires COLI_CUDA=1\n"); return 2; } if(g_cuda_enabled) fprintf(stderr,"[CUDA] mode: routed experts%s%s\n", g_cuda_dense?" + resident dense tensors":" only (resident dense on CPU)", g_cuda_release_host?"; VRAM experts without host backing":""); @@ -4108,7 +4214,8 @@ int main(int argc, char **argv){ if((getenv("COLI_CUDA") && atoi(getenv("COLI_CUDA"))) || getenv("COLI_GPU") || getenv("COLI_GPUS") || (getenv("CUDA_DENSE") && atoi(getenv("CUDA_DENSE"))) || - (getenv("CUDA_EXPERT_GB") && atof(getenv("CUDA_EXPERT_GB"))>0)){ + (getenv("CUDA_EXPERT_GB") && + (!strcmp(getenv("CUDA_EXPERT_GB"),"auto")||atof(getenv("CUDA_EXPERT_GB"))>0))){ fprintf(stderr,"CUDA was requested, but this binary is CPU-only; rebuild with: make CUDA=1\n"); return 2; } @@ -4148,8 +4255,11 @@ int main(int argc, char **argv){ " Keep it on ext4 (for example, /home/...) for memory efficiency and speed.\n", snap); /* HOT-STORE: PIN= [PIN_GB=g] -> top expert per frequenza fissi in RAM. * Va PRIMA di cap_for_ram: i pinnati contano nel residente. */ - if(getenv("PIN")) pin_load(&m, getenv("PIN"), getenv("PIN_GB")?atof(getenv("PIN_GB")):10.0); - if(getenv("COUPLE")&&*getenv("COUPLE")){ /* coupling-scored cross-layer prefetch */ + if(getenv("PIN")){ + const char *pin_gb=getenv("PIN_GB"); + pin_load(&m,getenv("PIN"),pin_gb&&!strcmp(pin_gb,"all")?-1.0:pin_gb?atof(pin_gb):10.0); /* PIN_GB=all (#80) */ + } + if(getenv("COUPLE")&&*getenv("COUPLE")){ /* coupling-scored cross-layer prefetch (#176) */ g_couple_k=getenv("COUPLE_K")?atoi(getenv("COUPLE_K")):8; if(g_couple_k<1)g_couple_k=1; if(g_couple_k>32)g_couple_k=32; g_couple_d=getenv("COUPLE_D")?atoi(getenv("COUPLE_D")):1; diff --git a/c/tests/test_backend_cuda.cu b/c/tests/test_backend_cuda.cu index a9eb48f..5550bde 100644 --- a/c/tests/test_backend_cuda.cu +++ b/c/tests/test_backend_cuda.cu @@ -50,6 +50,11 @@ int main(int argc, char **argv) { if (coli_cuda_tensor_upload(&t8, q8, s8, 1, 5, 2, d0)) return 1; if (ndev > 1 && coli_cuda_tensor_upload(&t8, q8, s8, 1, 4, 2, d1)) return 1; if (!coli_cuda_matmul(&t8, got, x, q8, s8, 1, 2, 4, 2, d0) || !close_enough(got, want8, 4)) return 1; + const int8_t q8b[8]={-1,-2,-3,-4, 1,-2,3,-4}; + const float s8b[2]={1.f,.5f},want8b[4]={10.f,15.f,-3.f,-2.5f}; + if(!coli_cuda_tensor_update(t8,q8b,s8b)|| + !coli_cuda_matmul(&t8,got,x,q8b,s8b,1,2,4,2,d0)|| + !close_enough(got,want8b,4))return 1; /* Rows [-8,-1,0,7] and [1,2,3,4], packed low nibble first. */ const uint8_t q4[4] = {0x70, 0xf8, 0xa9, 0xcb}; diff --git a/c/tests/test_idot b/c/tests/test_idot index 74dd03c8373dc1555c9ee0e6edd8c184ca3db368..bab981f1a6ada6fb0c07bc449ef2f2a0a4c9ef93 100755 GIT binary patch delta 82315 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 DS)1x- delta 84621 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 From b61130416660d37a3327c9d7ba2cf8a81a439f44 Mon Sep 17 00:00:00 2001 From: bokiko Date: Tue, 14 Jul 2026 15:17:08 +0300 Subject: [PATCH 05/79] stats: DISK_SPLIT=1 opt-in disk-load split by speculation context and layer kind Splits the expert DISK LOADS (LRU misses -> expert_load) two ways in the final stats line of 'run': - by context: loads issued while drafting (mtp_draft) vs absorbing verified tokens into the MTP KV (mtp_absorb) vs verify/main forwards - by layer kind: the MTP layer (int8 experts, ~2x bytes) vs the 78 main layers (int4), with exact bytes read (weights + scales) Gated behind DISK_SPLIT=1 (default OFF, parsed once at startup like the other g_* flags): when unset no atomic is ever touched and the stats output is byte-identical to stock. Measurement only - no effect on routing, verification or output. Measured on M4 Pro 48GB (GLM-5.2 int4, METAL, --ram 38): the draft path is ~1.5% of misses and the MTP layer ~4.5% of disk bytes. Requested in #182. Co-Authored-By: Claude Fable 5 --- c/glm.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/c/glm.c b/c/glm.c index bbebd81..4857946 100644 --- a/c/glm.c +++ b/c/glm.c @@ -174,6 +174,12 @@ typedef struct { double t_edisk, t_ewait, t_emm, t_attn, t_kvb, t_head;/* profiling: dove va il tempo */ double t_aproj,t_acore,t_aout; /* attention breakdown */ int64_t resident_bytes; + /* DISK_SPLIT=1: split dei DISK LOAD (miss LRU -> expert_load) per contesto e per tipo + * di layer. ld_ctx: 0=main/verify/prefill, 1=dentro mtp_draft, 2=dentro mtp_absorb. */ + int ld_ctx; + uint64_t miss_draft, miss_absorb; /* miss in moe() per contesto */ + uint64_t ld_mtp, ld_main; /* expert_load per tipo layer (MTP int8 vs main int4) */ + uint64_t bytes_mtp, bytes_main; /* byte letti da disco per tipo layer */ } Model; static void usage_save(Model *m); /* cache che impara: definita accanto a stats_dump */ @@ -835,6 +841,11 @@ static int64_t la_hit[3], la_tot[3]; static int la_pred[2][130][16]; static signed char la_val[2][130]; static int g_pilot=0; /* PILOT=1: prefetch pilotato dal router (vedi pilot_prefetch) */ static int g_pilot_k=8; /* PILOT_K=k: prefetcha solo le prime k predizioni per posizione */ +static int g_disk_split=0; /* DISK_SPLIT=1: contatori che spezzano i DISK LOAD (miss LRU) in + * draft MTP / absorb / verify-main e in layer MTP (int8) vs main + * (int4), con i byte letti. Default OFF: a flag spento gli atomic + * non vengono MAI toccati (zero overhead), le righe extra di stats + * non vengono stampate. Solo misura: nessun effetto sull'output. */ /* Aligned allocator for dense QT weights/scales: under METAL, page-align + register so the * GPU reads them zero-copy (no upload duplicate). Plain malloc otherwise. */ static void *qalloc(size_t n){ @@ -1223,6 +1234,13 @@ static int expert_load(Model *m, int layer, int eid, ESlot *s, int fatal){ snprintf(qn,sizeof(qn),"%s.qs",nm[k]); tq[k]=st_find(&m->S,qn); if(!tw[k]||!tq[k]){ fprintf(stderr,"missing %s\n",nm[k]); if(fatal) exit(1); return -1; } } + if(g_disk_split){ /* split load/byte per tipo layer; atomici: expert_load gira anche su OMP/pipe/pilot */ + int64_t tb=0; for(int k=0;k<3;k++) tb+=tw[k]->nbytes+tq[k]->nbytes; + if(layer==c->n_layers){ __atomic_add_fetch(&m->ld_mtp,1,__ATOMIC_RELAXED); + __atomic_add_fetch(&m->bytes_mtp,(uint64_t)tb,__ATOMIC_RELAXED); } + else { __atomic_add_fetch(&m->ld_main,1,__ATOMIC_RELAXED); + __atomic_add_fetch(&m->bytes_main,(uint64_t)tb,__ATOMIC_RELAXED); } + } if(g_mmap){ void *bw[3],*bq[3]; int okm=1; for(int k=0;k<3;k++){ @@ -1848,7 +1866,8 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out){ for(int z=0;znpin[layer];z++) if(P[z].eid==eid){ m->hits++; use[j]=&P[z]; break; } if(!use[j]){ ESlot *Sl=m->ecache[layer]; int nn=m->ecn[layer]; for(int z=0;zhits++; Sl[z].used=(uint64_t)__atomic_add_fetch(&m->eclock,1,__ATOMIC_RELAXED); use[j]=&Sl[z]; break; } } - if(!use[j]){ qof[j]=nmiss; use[j]=&m->ws[nmiss]; missk[nmiss++]=j; m->miss++; } + if(!use[j]){ qof[j]=nmiss; use[j]=&m->ws[nmiss]; missk[nmiss++]=j; m->miss++; + if(g_disk_split){ if(m->ld_ctx==1) m->miss_draft++; else if(m->ld_ctx==2) m->miss_absorb++; } } } int metal_done=0; #ifdef COLI_METAL @@ -2445,6 +2464,7 @@ static int mtp_draft(Model *m, int next_tok, int kv, int G, int *draft){ float *row=falloc(D), *logit=falloc(c->vocab), *h=falloc(D); memcpy(h, m->hlast, D*sizeof(float)); int tok=next_tok, n=0; + m->ld_ctx=1; /* DISK_SPLIT: i load da qui sono draft-path */ int prenorm = getenv("MTP_PRENORM")!=NULL; for(int g=0; g=m->max_t) break; @@ -2469,6 +2489,7 @@ static int mtp_draft(Model *m, int next_tok, int kv, int G, int *draft){ pos, tok, sqrt(n_eh), sqrt(n_post), t_pre, t2); draft[n++]=t2; tok=t2; memcpy(h, hx, D*sizeof(float)); } + m->ld_ctx=0; free(x); free(cat); free(hx); free(nrm); free(tmp); free(row); free(logit); free(h); return n; } @@ -2492,7 +2513,9 @@ static void mtp_absorb(Model *m, const int *next_ids, const float *x, int S, int matmul_qt(hx+(int64_t)i*D, cat, &m->eh_proj, 1); } float *nrm=falloc((int64_t)S*D), *tmp=falloc((int64_t)S*D); + m->ld_ctx=2; /* DISK_SPLIT: load del layer MTP in absorb */ layer_forward(m,&m->mtpL,li,hx,S,pos_base,nrm,tmp); + m->ld_ctx=0; free(hx); free(cat); free(e); free(hn); free(hf); free(nrm); free(tmp); } @@ -2843,6 +2866,13 @@ static void run_text(Model *m, const char *snap, const char *prompt, int ngen){ m->mtp_prop?100.0*m->mtp_acc/m->mtp_prop:0.0, (unsigned long long)m->mtp_acc, (unsigned long long)m->mtp_prop); if(g_gr_prop) printf("grammar: %.0f%% acceptance (%llu/%llu forced drafts)\n", 100.0*g_gr_acc/g_gr_prop, (unsigned long long)g_gr_acc, (unsigned long long)g_gr_prop); + if(g_disk_split) printf("disk-load split: draft %llu + absorb %llu + verify/main %llu misses | " + "MTP-layer %llu loads %.2f GB | main-layers %llu loads %.2f GB (MTP %.1f%% of bytes)\n", + (unsigned long long)m->miss_draft, (unsigned long long)m->miss_absorb, + (unsigned long long)(m->miss - m->miss_draft - m->miss_absorb), + (unsigned long long)m->ld_mtp, m->bytes_mtp/1e9, + (unsigned long long)m->ld_main, m->bytes_main/1e9, + (m->bytes_mtp+m->bytes_main)?100.0*m->bytes_mtp/(m->bytes_mtp+m->bytes_main):0.0); #ifdef COLI_CUDA if(m->gpu_expert_count) printf("CUDA expert tier: %d resident experts (%.2f GB) | %llu calls served from VRAM\n", m->gpu_expert_count,m->gpu_expert_bytes/1e9,(unsigned long long)m->gpu_expert_calls); @@ -3721,6 +3751,7 @@ int main(int argc, char **argv){ * (best-measured this session) unless the user set PILOT_K explicitly. */ g_pilot_k = getenv("PILOT_K")?atoi(getenv("PILOT_K")):(g_pilot_real?6:8); if(g_pilot_k<1) g_pilot_k=1; + g_disk_split = getenv("DISK_SPLIT")?atoi(getenv("DISK_SPLIT")):0; /* 1 = split dei disk load nelle stats */ g_pipe = getenv("PIPE")?atoi(getenv("PIPE")):0; /* default OFF: overlap expert load ‖ matmul (byte-identical; reorders I/O). PIPE=1 opts in */ g_pipe_nw = getenv("PIPE_WORKERS")?atoi(getenv("PIPE_WORKERS")):8; /* I/O worker threads */ if(g_pipe_nw<1) g_pipe_nw=1; From 5230717cf41022ca9c34d790209bde0655bad6a9 Mon Sep 17 00:00:00 2001 From: bokiko Date: Tue, 14 Jul 2026 15:19:48 +0300 Subject: [PATCH 06/79] eval: default the [gMASK] prefix ON for GLM snapshots (#108) Scoring raw completions without GLM's training-time prefix runs the model out-of-distribution: scores drop and A/B sensitivity distorts (#108). Detect GLM via config.json model_type and prepend automatically, with a stderr notice. EVAL_PREFIX (including empty) still overrides for research use. Co-Authored-By: Claude Fable 5 --- c/tools/eval_glm.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/c/tools/eval_glm.py b/c/tools/eval_glm.py index b167253..d750921 100644 --- a/c/tools/eval_glm.py +++ b/c/tools/eval_glm.py @@ -48,11 +48,24 @@ def load_docs(task, data_dir, limit, seed): random.Random(seed).shuffle(docs) return docs[:limit] if limit else docs -def build_requests(tk, docs_by_task): +def detect_prefix(snap): + """GLM sees [gMASK] at the start of every training sequence; scoring raw text + without it is out-of-distribution and silently depresses/distorts scores (#108). + Default the prefix ON for GLM snapshots; EVAL_PREFIX (even empty) overrides.""" + if "EVAL_PREFIX" in os.environ: return os.environ["EVAL_PREFIX"] + try: mt = json.load(open(os.path.join(snap, "config.json"))).get("model_type", "") + except Exception: mt = "" + if "glm" in mt.lower(): + print("[prefix] GLM snapshot: prepending [gMASK] to every context " + "(override with EVAL_PREFIX, disable with EVAL_PREFIX=)", file=sys.stderr) + return "[gMASK]" + return "" + +def build_requests(tk, docs_by_task, prefix=""): reqs, meta, perq = [], [], {} for t, docs in docs_by_task.items(): for qi, d in enumerate(docs): - ctx, conts, gold = d["ctx"], d["choices"], int(d["gold"]) + ctx, conts, gold = prefix + d["ctx"], d["choices"], int(d["gold"]) ctx_ids = tk.encode(ctx).ids for oi, cont in enumerate(conts): full = tk.encode(ctx + cont).ids @@ -115,7 +128,7 @@ def main(): docs_by_task = {t: load_docs(t, a.data, a.limit, a.seed) for t in tasks} for t, d in docs_by_task.items(): print(f"[{t}] {len(d)} questions", file=sys.stderr) - reqs, meta, perq = build_requests(tk, docs_by_task) + reqs, meta, perq = build_requests(tk, docs_by_task, detect_prefix(a.snap)) print(f"total requests: {len(reqs)} (answer options)", file=sys.stderr) if a.dry: for r in reqs[:3]: print(" example request:", r[:80], "...", file=sys.stderr) From c4d14017df45db41564c7028a6b4c0e22985af34 Mon Sep 17 00:00:00 2001 From: bokiko Date: Tue, 14 Jul 2026 18:28:41 +0300 Subject: [PATCH 07/79] engine: default the [gMASK] prefix ON in SCORE mode for GLM snapshots (#194, #108) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SCORE mode scored raw token streams: GLM sees [gMASK] at the start of every training sequence, so unprefixed requests run the model out-of- distribution and silently distort logprobs (#108). The eval harness got the text-level fix in #194; contributors driving SCORE directly (e.g. the perplexity work in #153) were still exposed. Same detection rule as tools/eval_glm.py: config.json model_type contains "glm" (case-insensitive). The two ids are looked up in the snapshot's tokenizer.json ([gMASK], ) rather than hardcoded. Requests that already carry the prefix pass through untouched — the patched eval_glm.py sends prefixed streams, so no double-prefixing. SCORE_PREFIX=0 restores stock behavior. One [SCORE] stderr notice when active. Validated on GLM-5.2 744B (M4 Pro, Metal): default run flips the '2 + 2 =' smoke question back to ' 4' (-1.006 vs ' 5' -2.950); SCORE_PREFIX=0 reproduces stock output; pre-prefixed requests give bit-identical logprobs to auto-prefixed ones. Co-Authored-By: Claude Fable 5 --- c/glm.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/c/glm.c b/c/glm.c index caf554f..a3d0cb5 100644 --- a/c/glm.c +++ b/c/glm.c @@ -2919,16 +2919,43 @@ static double logprob_target(const float *lo, int V, int target, int *am){ if(am)*am=(best==target); return (double)(lo[target]-mx) - log(se); } +/* "glm" contenuto in model_type, case-insensitive — stessa regola di detect_prefix + * in tools/eval_glm.py (#194). Niente strcasestr: non esiste su MinGW/MSVC. */ +static int mt_is_glm(const char *s){ + if(s) for(;*s;s++) if((s[0]|32)=='g'&&(s[1]|32)=='l'&&(s[2]|32)=='m') return 1; + return 0; +} /* modalita' SCORING per i benchmark (stile lm-eval, log-likelihood): * input: file con righe " .. " (T=ctxlen+contlen) * output: riga " " per richiesta. * Un solo forward per richiesta (teacher-forcing): niente generazione -> fattibile a bassa velocita'. */ -static void run_score(Model *m, const char *path){ +static void run_score(Model *m, const char *snap, const char *path){ Cfg *c=&m->c; int D=c->hidden; + /* prefisso GLM (#108): il modello vede [gMASK] in testa a OGNI sequenza di training — + * scorare stream nudi e' out-of-distribution e deprime/distorce i punteggi. Se il config + * dice glm* gli id dei due token vengono chiesti al tokenizer.json dello snapshot (per + * GLM-5.2: 154822,154824 — mai fidarsi di costanti cablate, il vocabolario cambia tra + * release) e anteposti al CONTESTO delle richieste che non li hanno gia'; chi arriva GIA' + * prefissato (eval_glm.py post-#194) passa INTATTO. SCORE_PREFIX=0 -> comportamento nudo. */ + int pfx[2]={-1,-1}, pfx_on=0; + if(!getenv("SCORE_PREFIX")||atoi(getenv("SCORE_PREFIX"))){ + char *ar=NULL; jval *r=cfg_root(snap,&ar); + jval *mt=json_get(r,"model_type"); + if(mt_is_glm(mt?mt->str:NULL)){ + char tkp[2048]; snprintf(tkp,sizeof(tkp),"%s/tokenizer.json",snap); + Tok T; tok_load(&T,tkp); + pfx[0]=tok_id_of(&T,"[gMASK]"); pfx[1]=tok_id_of(&T,""); + if(pfx[0]>=0&&pfx[1]>=0){ pfx_on=1; + fprintf(stderr,"[SCORE] GLM snapshot: prepending [gMASK] (ids %d,%d) to unprefixed requests — disable with SCORE_PREFIX=0\n",pfx[0],pfx[1]); + } else fprintf(stderr,"[SCORE] GLM config but tokenizer has no [gMASK]/: prefix OFF\n"); + } + free(ar); + } FILE *f=fopen(path,"rb"); if(!f){perror(path);exit(1);} int maxT=1; { char *ln=NULL; size_t cp=0; while(getline(&ln,&cp,f)>0){ int a,b; if(sscanf(ln,"%d %d",&a,&b)==2 && a+b>maxT) maxT=a+b; } free(ln); } + if(pfx_on) maxT+=2; /* le richieste senza prefisso crescono di 2 token */ kv_alloc(m,maxT); float *x=falloc((int64_t)maxT*D), *lo=falloc(c->vocab), *row=falloc(D); int *ids=malloc(maxT*sizeof(int)); @@ -2937,6 +2964,10 @@ static void run_score(Model *m, const char *path){ char *p=ln; int ctxlen=strtol(p,&p,10), contlen=strtol(p,&p,10), T=ctxlen+contlen; if(T<=0||ctxlen<1){ printf("0 0 0\n"); fflush(stdout); continue; } for(int i=0;i=2 && ids[0]==pfx[0] && ids[1]==pfx[1])){ /* gia' prefissato -> intatto */ + memmove(ids+2,ids,(size_t)T*sizeof(int)); + ids[0]=pfx[0]; ids[1]=pfx[1]; ctxlen+=2; T+=2; + } for(int s=0;s -> istogramma uso expert a fine run */ /* modo scoring per benchmark: SCORE= -> log-likelihood per riga */ - if(getenv("SCORE")){ run_score(&m, getenv("SCORE")); if(stats) stats_dump(&m,stats); return 0; } + if(getenv("SCORE")){ run_score(&m, snap, getenv("SCORE")); if(stats) stats_dump(&m,stats); return 0; } /* modo serve persistente per la CLI 'coli': SERVE=1 */ if(getenv("SERVE")){ From 4a0435cbb35e40e6abfad548b8bd77fd13fe7fe9 Mon Sep 17 00:00:00 2001 From: Dennis Paul Date: Tue, 14 Jul 2026 18:01:04 +0200 Subject: [PATCH 08/79] =?UTF-8?q?glm.c:=20remove=20the=20LMHEAD=5FEXACT=20?= =?UTF-8?q?probe=20accidentally=20merged=20with=20#152=20=E2=80=94=20funct?= =?UTF-8?q?ional=20no-op=20strip=20(#197)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #152 carried leftover debug scaffolding from the lm_head measurement posted on that PR: a `g_lmhead_exact` global, an undocumented `LMHEAD_EXACT` getenv, and 7 lm_head call sites routed through matmul_qt_ex(..., !g_lmhead_exact). None of it was in the PR description; it rode in because `git checkout -B` carries uncommitted working-tree edits forward. It should not stay: - it does nothing worth having. Pinning lm_head off IDOT measures -0.03% perplexity across 5 corpora (in-distribution, isolated) — nothing. - LMHEAD_EXACT=1 would silently change lm_head numerics, undocumented and untested. - lm_head is fmt=1 (int8), so the IDOT gate applies to it unconditionally on every platform anyway; there is no threshold story here to expose. The flag defaulted to 0 and `!g_lmhead_exact == 1 == matmul_qt`'s own allow_idot, so this removal is a pure no-op. Verified rather than assumed — summed log-lik over 1023 tokens, in-distribution, CPU (deterministic), dev-with-probe vs dev-minus-probe: prose -2295.245383 == -2295.245383 markdown -3272.146403 == -3272.146403 Bit-identical. make check green (6 C suites + 60 python tests), no new warnings. The actual #152 changes are untouched: the three attention input projections and the DSA indexer's ix_wk stay batched and pinned to the exact int4 kernel via matmul_qt_ex(..., 0). --- c/glm.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/c/glm.c b/c/glm.c index caf554f..471fd50 100644 --- a/c/glm.c +++ b/c/glm.c @@ -477,7 +477,6 @@ static void matmul_i2(float *y, const float *x, const uint8_t *q2, const float * #else #define IDOT_KERNEL "scalar" #endif -static int g_lmhead_exact=0; /* PROBE: LMHEAD_EXACT=1 -> pin lm_head to the exact int8 kernel */ static int g_idot=1; #if defined(__ARM_NEON) && defined(__ARM_FEATURE_DOTPROD) static int g_i4s=1; /* SDOT presente: int4 IDOT conviene anche a S=1 (decode). Misurato @@ -2537,7 +2536,7 @@ static float *step(Model *m, const int *ids, int S, int pos_base){ if(m->has_mtp && S>=2 && g_draft>0) mtp_absorb(m, ids+1, x, S-1, pos_base); float *last=falloc(D); rmsnorm(last, x+(int64_t)(S-1)*D, m->final_norm, D, c->eps); double th0=now_s(); - float *logit=falloc(c->vocab); matmul_qt_ex(logit,last,&m->lm_head,1,!g_lmhead_exact); + float *logit=falloc(c->vocab); matmul_qt(logit,last,&m->lm_head,1); m->t_head += now_s()-th0; free(x); free(last); return logit; } @@ -2552,7 +2551,7 @@ static float *step_all(Model *m, const int *ids, int S, int pos_base){ if(m->hlast) memcpy(m->hlast, x+(int64_t)(S-1)*D, D*sizeof(float)); float *lo=falloc((int64_t)S*c->vocab), *row=falloc(D); for(int s=0;sfinal_norm, D, c->eps); - matmul_qt_ex(lo+(int64_t)s*c->vocab, row, &m->lm_head, 1, !g_lmhead_exact); } + matmul_qt(lo+(int64_t)s*c->vocab, row, &m->lm_head, 1); } free(x); free(row); return lo; } @@ -2586,7 +2585,7 @@ static float *step_decode_batch(Model *m, const DecodeRow *rows, int S){ rmsnorm(norm+(int64_t)s*D,x+(int64_t)s*D,m->final_norm,D,c->eps); double th0=now_s(); float *logit=falloc((int64_t)S*c->vocab); - matmul_qt_ex(logit,norm,&m->lm_head,S,!g_lmhead_exact); + matmul_qt(logit,norm,&m->lm_head,S); m->t_head+=now_s()-th0; free(x); free(norm); return logit; @@ -2635,12 +2634,12 @@ static int mtp_draft(Model *m, int next_tok, int kv, int G, int *draft){ double n_eh=0; for(int d=0;d=2; int t_pre=-1; - if(dbg){ rmsnorm(row, hx, m->mtp_norm, D, c->eps); matmul_qt_ex(logit, row, &m->lm_head, 1, !g_lmhead_exact); + if(dbg){ rmsnorm(row, hx, m->mtp_norm, D, c->eps); matmul_qt(logit, row, &m->lm_head, 1); t_pre=mtp_argmax(logit, c->vocab); } layer_forward(m, &m->mtpL, li, hx, 1, pos, nrm, tmp); double n_post=0; for(int d=0;dmtp_norm, D, c->eps); - matmul_qt_ex(logit, row, &m->lm_head, 1, !g_lmhead_exact); + matmul_qt(logit, row, &m->lm_head, 1); int t2=mtp_argmax(logit, c->vocab); if(dbg) fprintf(stderr,"[mtp2] pos=%d in_tok=%d ||eh||=%.1f ||post||=%.1f pre_blk=%d post_blk=%d\n", pos, tok, sqrt(n_eh), sqrt(n_post), t_pre, t2); @@ -2905,7 +2904,7 @@ static void forward_all(Model *m, const int *ids, int S, int *pred){ float *row=falloc(D); for(int s=0;sfinal_norm, D, c->eps); /* heap row (#183) */ - matmul_qt_ex(lo, row, &m->lm_head, 1, !g_lmhead_exact); /* exact-mode knob (#152) */ + matmul_qt(lo, row, &m->lm_head, 1); int best=0; float bv=lo[0]; for(int i=1;ivocab;i++) if(lo[i]>bv){bv=lo[i];best=i;} pred[s]=best; } @@ -2942,7 +2941,7 @@ static void run_score(Model *m, const char *path){ double lp=0; int greedy=1; for(int pos=ctxlen-1; posfinal_norm, D, c->eps); - matmul_qt_ex(lo,row,&m->lm_head,1,!g_lmhead_exact); + matmul_qt(lo,row,&m->lm_head,1); int am; lp += logprob_target(lo,c->vocab,ids[pos+1],&am); if(!am) greedy=0; } printf("%.6f %d %d\n", lp, contlen, greedy); fflush(stdout); @@ -4169,7 +4168,6 @@ int main(int argc, char **argv){ g_repin = getenv("REPIN")?atoi(getenv("REPIN")):0; /* RFC: re-pin ogni n token emessi (0=off) / live re-pin every n emitted tokens (0=off) */ g_absorb = getenv("ABSORB")?atoi(getenv("ABSORB")):-1; /* -1 auto: assorbita per S<=4 */ g_dsa_force = getenv("DSA_FORCE")?atoi(getenv("DSA_FORCE")):0; - g_lmhead_exact = getenv("LMHEAD_EXACT")?atoi(getenv("LMHEAD_EXACT")):0; /* matmul_qt documenta la soglia int4-IDOT come "configurabile con I4S" ma il getenv non * c'era: la variabile non aveva alcun effetto. I4S= -> IDOT int4 solo per S>=n. * EN: matmul_qt documents the int4 IDOT threshold as "configurable via I4S", but the From 372f8fd633081acb1407412e7aab21c9b32441b2 Mon Sep 17 00:00:00 2001 From: Tom Olorin <1800017+juicyroots@users.noreply.github.com> Date: Tue, 14 Jul 2026 09:01:12 -0700 Subject: [PATCH 09/79] =?UTF-8?q?run=5Ftests:=20normpath=20test=20binaries?= =?UTF-8?q?=20=E2=80=94=20forward-slash=20relative=20paths=20fail=20Create?= =?UTF-8?q?Process=20on=20Windows=20(#196)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'make test-c' passes TEST_BINS as 'tests/test_json.exe' etc.; Python's subprocess on Windows hands that to CreateProcess, which rejects forward-slash relative paths for the executable (WinError 2), so the runner this script exists for (running tests from any Windows shell) failed on every test. os.path.normpath makes it 'tests\test_json.exe' on Windows and is a no-op elsewhere. Verified: all 8 suites run via 'make test-c' on Windows 11 / MinGW GCC 16.1 and paths are unchanged on POSIX. Co-authored-by: olorin Co-authored-by: Claude Fable 5 --- c/tools/run_tests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/c/tools/run_tests.py b/c/tools/run_tests.py index e2c17ac..1aee5a4 100644 --- a/c/tools/run_tests.py +++ b/c/tools/run_tests.py @@ -5,12 +5,13 @@ Used by `make test-c` so the test runner works from any shell (cmd.exe, PowerShell, Git Bash, MSYS2) without a POSIX `for` loop. Each test binary is a positional argument. """ +import os import subprocess import sys failed = [] for binary in sys.argv[1:]: - rc = subprocess.call([binary]) + rc = subprocess.call([os.path.normpath(binary)]) if rc != 0: failed.append(binary) if failed: From e12a4295cca679fca7845decf9d7759e420d18b9 Mon Sep 17 00:00:00 2001 From: JustVugg Date: Tue, 14 Jul 2026 18:03:56 +0200 Subject: [PATCH 10/79] glm.c: silence unused-variable 'c' in hwinfo_emit (reported in #148 on Darwin, present on Linux too) Co-Authored-By: Claude Opus 4.8 --- c/glm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/glm.c b/c/glm.c index 471fd50..d6e5716 100644 --- a/c/glm.c +++ b/c/glm.c @@ -3677,7 +3677,7 @@ static void ehit_mark(Model *m, int layer, int eid){ /* HWINFO: hardware snapshot for the web dashboard — emitted once at READY. */ static void hwinfo_emit(Model *m){ - Cfg *c=&m->c; + Cfg *c=&m->c; (void)c; /* silence -Wunused on builds without /proc (#148 report) */ /* CPU */ char cpu[256]=""; FILE *ci=fopen("/proc/cpuinfo","r"); if(ci){ char ln[256]; From 2ead86a27feba4a3da8339570baf2625757dbbb8 Mon Sep 17 00:00:00 2001 From: JustVugg Date: Tue, 14 Jul 2026 18:15:29 +0200 Subject: [PATCH 11/79] =?UTF-8?q?serve=20mux:=20fix=20Windows=20request=20?= =?UTF-8?q?dispatch=20=E2=80=94=20BINARY-mode=20stdin/stdout=20+=20PeekNam?= =?UTF-8?q?edPipe-only=20polling=20(fixes=20#195)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two Windows-only bugs in run_serve_mux left the gateway hanging after READY: 1. No _setmode(_O_BINARY): the CRT collapsed CRLF inside fread() payloads (waits forever for missing bytes) and expanded LF in the READY/STAT sentinels. 2. WaitForSingleObject on an anonymous pipe is undefined (always-signaled or WAIT_FAILED) and PeekNamedPipe fails on file/console handles, so the dispatch gate never opened. New rule: idle -> block in getline (POSIX select(NULL) semantics); active -> PeekNamedPipe poll. Reproduced and verified on real Windows via MinGW cross-compile + WSL interop: old binary writes READY (with CRLF corruption) then hangs forever on a crafted SUBMIT frame; fixed binary answers DONE + STAT and exits cleanly. Linux path untouched (0 warnings, oracle-exact). Co-Authored-By: Claude Opus 4.8 --- c/glm.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/c/glm.c b/c/glm.c index d6e5716..561d410 100644 --- a/c/glm.c +++ b/c/glm.c @@ -3418,6 +3418,14 @@ static void run_serve_mux(Model *m, const char *snap){ KVState *initial=m->kv; free(initial->kv_start); free(initial); ServeCtx *ctx=calloc(nctx,sizeof(*ctx)); ServeReq *req=calloc(nctx,sizeof(*req)); for(int i=0;i0) + /* Anonymous pipes are NOT waitable objects: WaitForSingleObject on them is + * undefined (always-signaled or WAIT_FAILED), and PeekNamedPipe fails on + * file/console handles — the old gate never dispatched (#195). New rule: + * idle -> block in getline() inside mux_submit (same semantics as the + * POSIX select(NULL)); active -> poll the pipe with PeekNamedPipe, and on + * non-pipe stdin just defer submits until the batch finishes. */ + if(eof) ready=0; + else if(!active) ready=1; + else ready=(PeekNamedPipe(ih,NULL,0,NULL,&avail,NULL) && avail>0)?1:0; + if(ready) #endif if(mux_submit(m,&T,ctx,req,nctx,maxctx,eos)<0) eof=1; } From ec891360291102eae60a41c072d1e8dcf295f10a Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Wed, 15 Jul 2026 00:18:05 +0800 Subject: [PATCH 12/79] GPU resident pipeline: batch CUDA attention, head-sharded kv_b, prefill expert groups, W4A16 mixed dispatch (#111) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fuse CUDA expert MLP execution * Group CUDA expert transfers by device * Instrument grouped CUDA expert execution * Bound grouped CUDA decode scratch * Execute expert groups across GPUs in parallel * Release host backing for multi-GPU experts * Define quality-preserving memory policies * Overlap cold expert loading with resident compute * Adapt expert placement with session LFRU * Fuse q4 expert gate and up dispatch * Plan CPU work on physical cores * Batch grouped expert CUDA kernels * Separate VRAM and RAM expert placement * Add ragged multi-sequence decode forward * feat(runtime): add continuous decode scheduler * Route concurrent API requests through batch scheduler * Harden multiplex request lifecycle and framing * Cancel disconnected multiplex requests * Bind API port before starting the engine * fix automatic KV slot allocation * add native int4 Tensor Core grouped GEMM * add Tensor Core throughput benchmark * optimize packed int4 low-row kernels * add asynchronous CUDA staging streams * document validated six-GPU dense acceleration * tune six-GPU expert hot set * raise validated expert hot-set target * add CUDA MLA absorption core * fuse grouped expert gate and up projections * Warn for explicit lossy routing flags * Add full-resident expert placement mode * Adapt VRAM expert slots to live routes * Accelerate int4 matvec on AVX-512 * Reduce AVX-512 and RoPE decode overhead * Seed every GPU expert layer after prefill * Limit live GPU swaps during decode * CUDA batch MLA attention, kv_b head-sharding, fused o_proj, expert-group dispatch, W4A16 kernels Lab-qualified on the 6x RTX 5090 machine (914-token request benchmark): - batch MLA absorption kernel (COLI_CUDA_ATTN=1): whole-batch attention on device, 154.8s -> 102.4s - attention -> o_proj fusion on the layer device: -> 97.4s - kv_b head-sharding across cards (COLI_CUDA_ATTN_SHARD=1), no weight duplication: -> 94.05s - per-device expert-group dispatch with pinned-buffer async transfers, W4A16 tensor-core kernels for the shared expert, OMP hot-thread tuning Negative results (reverted, kept out): GPU-side weighted scatter-add (atomics + per-layer D2H lose 43.8%), shared-expert fused small-batch kernel (-38.8%), W4A4 grouped tensor cores (int4 activations corrupt output). Details in the lab research log. * GPU resident pipeline: device-resident prefill attention chain, GPU expert groups in prefill, batched router, W4A16 mixed dispatch COLI_CUDA_PIPE=1 keeps the prefill data plane on the layer home device; control flow (routing, cache/pin management) stays on CPU. Any CUDA failure falls back to the unchanged CPU path. - Device primitives + unit tests (tests/test_pipe_cuda.cu): rmsnorm (strided), interleaved RoPE, silu-mul, residual add, fixed-order row merge (no atomics), device-input GEMM, persistent per-device scratch. All verified against the engine's CPU math on SM120 (worst 1.2e-5). - attn_pipe_prefill: q_a -> norm -> q_b -> rope -> kv_a -> norm -> rope -> batch attention -> o_proj in one device chain (q_a/q_b/kv_a colocated with kv_b); only the final [S,D] and the new KV rows return to host. Attention 41.2s -> 30.8s on the 1571-token benchmark. - Prefill batch-union now uses the GPU expert groups (previously gated to S<=64, leaving all VRAM-resident experts idle during prefill - measured 21ms of GPU expert time in a 148s prefill). Expert phase 78.9s -> 69.0s. - Router computed as one batched matmul instead of S sequential rows (bit-identical math). - W4A16 tensor-core path for expert groups (COLI_CUDA_TC_W4A16=1) with row-count mixed dispatch: >=16 rows per expert use tensor cores, smaller batches keep the naive kernel (tensor cores measured negative below ~16 rows). Expert phase 69.0s -> 64.3s, decode unaffected. Net on the 1571-token prefill benchmark: 148.8s -> 114.3-126.8s (component timings stable across runs; wall drifts +-3-5s because .coli_usage placement learning shifts the expert tiers between runs). PROFILO now also prints the prefill-phase breakdown. * Skip OMP hot-thread tuning when CUDA is enabled The active-spin worker team measured 66.9s->20.9s on the CPU-only Zen5 build, but on the six-GPU full-residency workload the spinning workers contend with the CUDA dispatch threads: ~4x slower prefill with the process stuck near 1.8 cores. Gate the tuning on COLI_CUDA so each configuration keeps the behavior it was measured to prefer. * Inc.2a: sparse layers fully resident on the layer device, residual hops cards at layer boundaries COLI_CUDA_PIPE=2 keeps the residual stream on the layer home device for consecutive sparse layers (cudaMemcpyPeer at boundaries): in/post norms, attention chain, both residual adds and the shared-expert MLP run on device. Per layer only the post-norm activations (router + CPU-tier experts + group gather), the new KV rows and, on DSA indexer layers, the pre-attention norm leave the card. Per-layer transfers drop from ~130MB to ~70MB. A device-side snapshot at layer entry makes any mid-layer CUDA failure fall back to the unchanged CPU path idempotently. 1571-token prefill: 127.1s (PIPE=1 control) -> 117.6/118.9s, components attention 30.8->26.1, other 31.8->22.5-24.5; output verified coherent against the control. * Head-sharded attention inside the pipe: negative on PCIe star topology, gated opt-in Slicing q per card from the home device and collecting ctx back serializes ~95MB/layer through the home card's PCIe link: attention 26.1s -> 41.4/44.4s on the 1571-token benchmark (two repeats), wall 117.6 -> 135-138s. The standalone host-path sharding won because six cards uploaded from host RAM in parallel; a home-device star has no such parallelism without NVLink. Kept behind COLI_CUDA_PIPE_SHARD=1 for interconnects where peer bandwidth does not share one root port. * Inc.3: device-resident KV shadow for decode attention Decode re-uploaded the whole latent+rope window per layer per token (~300MB/token at 1571 context). Each layer now keeps a device shadow of the compressed KV on its kv_b card, bulk-synced when behind and appended incrementally; the host cache stays canonical. Invalidation on kv_bind (slot switch), kv_alloc (resize) and on any overwrite of mirrored rows, with the legacy full-upload path as fallback. Measured (COLI_CUDA_PIPE gate): short-context decode 5.48 -> 5.59/5.87 tok/s, 1571-context decode 4.14 -> 4.22 tok/s. Decode remains CPU-expert bound; the shadow removes the transfer tax, not the compute. * tools: unified user-experience benchmark (bench_ux.sh) Two fixed scenarios (short chat, long-document QA), TTFT + decode tok/s + first-line drift check, TEMP=0 DRAFT=0 enforced, medians over REPS runs. Encodes the measurement discipline from the lab record: same binary per comparison, judge medians because .coli_usage placement learning drifts wall times between runs. * tools: bench_ux.sh executable bit * gitignore compiled test binaries * tools: expert_atlas.py — measure per-expert topic affinity (#175) Diffs .coli_usage across 10 themed probe batches (code/math/chinese/ prose/science/law/poetry/structured/translation/casual, 3 prompts each) driven through a running API server — one engine load total. Every touched expert gets a topic-affinity vector, entropy, and a specialist/ generalist label; output experts.json feeds the Brain page hover. * serve: persist .coli_usage after every turn in mux mode, not only at exit run_serve_mux saved the learning cache once at shutdown; a crash lost the whole session's routing history, and live consumers of the file (expert_atlas.py diffs it between probe batches) saw a frozen snapshot. Now saved per turn like the interactive path (165KB write, negligible). * web: Brain hover shows measured expert atlas when published If /experts.json (from tools/expert_atlas.py, #175) is served next to the app, the tooltip upgrades from the depth heuristic to measured data: specialist/generalist label, entropy, and the top-3 topic affinities. Row index maps to real layer (row+3, last row = MTP 78). Falls back to the heuristic when no atlas is published. --------- Co-authored-by: JustVugg --- .gitignore | 3 + c/backend_cuda.cu | 432 +++++++++++++++++ c/backend_cuda.h | 62 +++ c/glm.c | 440 ++++++++++++++++-- .../{test_i4_acc512 => test_compat_direct} | Bin 16200 -> 16208 bytes c/tests/test_decode_batch | Bin 16448 -> 0 bytes c/tests/test_idot | Bin 239888 -> 0 bytes c/tests/test_pipe_cuda.cu | 137 ++++++ c/tests/test_schema_gbnf | Bin 0 -> 50648 bytes c/tools/bench_ux.sh | 51 ++ c/tools/expert_atlas.py | 141 ++++++ web/src/Brain.tsx | 29 +- web/src/index.css | 5 + 13 files changed, 1267 insertions(+), 33 deletions(-) rename c/tests/{test_i4_acc512 => test_compat_direct} (72%) delete mode 100755 c/tests/test_decode_batch delete mode 100755 c/tests/test_idot create mode 100644 c/tests/test_pipe_cuda.cu create mode 100755 c/tests/test_schema_gbnf create mode 100755 c/tools/bench_ux.sh create mode 100644 c/tools/expert_atlas.py diff --git a/.gitignore b/.gitignore index 203a322..ce6a80c 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,6 @@ c/backend_metal_test c/tests/test_tier c/mio_env/ c/bench/ +c/tests/test_decode_batch +c/tests/test_i4_acc512 +c/tests/test_idot diff --git a/c/backend_cuda.cu b/c/backend_cuda.cu index 3bb853b..9ce142f 100644 --- a/c/backend_cuda.cu +++ b/c/backend_cuda.cu @@ -18,12 +18,14 @@ struct ColiCudaTensor { typedef struct { int device; + int compute_major,compute_minor; float *x, *y, *gate, *up; size_t x_cap, y_cap, gate_cap, up_cap; uint8_t *qx; float *qscale; size_t qx_cap, qscale_cap; float *host_x,*host_y; size_t host_x_cap,host_y_cap; float *aq,*al,*ar,*ac; size_t aq_cap,al_cap,ar_cap,ac_cap; + float *pipe_buf[24]; size_t pipe_cap[24]; /* scratch persistenti del resident pipeline */ cudaStream_t stream; void *group_desc; size_t group_desc_cap; size_t tensor_count, tensor_bytes; @@ -120,6 +122,68 @@ __global__ static void silu_mul(float *gate, const float *up, size_t n) { } } +/* Four warps share one A tile and compute 16x64 outputs. This matters for + * prefill: the first prototype reloaded/converter A once per 16 output cols. */ +__global__ static void w4a16_matmul(float *y,const float *x,const uint8_t *w, + const float *scale,int M,int K,int N){ +#if __CUDA_ARCH__ >= 700 + using namespace nvcuda;int warp=threadIdx.x>>5,lane=threadIdx.x&31; + int m0=blockIdx.y*16,n0=blockIdx.x*64+warp*16; + __shared__ __half ah[256],bh[4][256]; + wmma::fragment acc;wmma::fill_fragment(acc,0.f); + size_t rb=(size_t)(K+1)/2; + for(int k0=0;k0>1)];int a=(gk&1)?q>>4:q&15; + v=(float)(a&8?a-16:a)*scale[gn];} + bh[warp][z]=__float2half(v); /* [Ntile,Ktile] == B col-major */ + } + __syncthreads(); + wmma::fragment af; + wmma::fragment bf; + wmma::load_matrix_sync(af,ah,16);wmma::load_matrix_sync(bf,bh[warp],16); + wmma::mma_sync(acc,af,bf,acc);__syncthreads(); + } + __shared__ float out[4][256];wmma::store_matrix_sync(out[warp],acc,16,wmma::mem_row_major);__syncwarp(); + for(int z=lane;z<256;z+=32){int m=z/16,n=z%16; + if(m0+mFP16 conversion of A. */ +__global__ static void w4a16_gate_up(float *gate,float *up,const float *x, + const uint8_t *gw,const uint8_t *uw,const float *gs,const float *us, + int M,int K,int N){ +#if __CUDA_ARCH__ >= 700 + using namespace nvcuda;int warp=threadIdx.x>>5,lane=threadIdx.x&31,which=warp&1,tile=warp>>1; + int m0=blockIdx.y*16,n0=blockIdx.x*64+tile*16;const uint8_t *w=which?uw:gw; + const float *scale=which?us:gs;float *y=which?up:gate;size_t rb=(size_t)(K+1)/2; + __shared__ __half ah[256],bh[8][256]; + wmma::fragment acc;wmma::fill_fragment(acc,0.f); + for(int k0=0;k0>1)];int a=(gk&1)?q>>4:q&15; + v=(float)(a&8?a-16:a)*scale[gn];}bh[warp][z]=__float2half(v);} + __syncthreads(); + wmma::fragment af; + wmma::fragment bf; + wmma::load_matrix_sync(af,ah,16);wmma::load_matrix_sync(bf,bh[warp],16); + wmma::mma_sync(acc,af,bf,acc);__syncthreads(); + } + __shared__ float out[8][256];wmma::store_matrix_sync(out[warp],acc,16,wmma::mem_row_major);__syncwarp(); + for(int z=lane;z<256;z+=32){int m=z/16,n=z%16; + if(m0+m=S)return; const float *xs=x+(size_t)s*K; float v=0; for(int i=threadIdx.x;i=S||nt<1)return; + extern __shared__ float sm[];float *qa=sm,*cl=qa+K,*scores=cl+K,*red=scores+T; + const float *qs=q+((size_t)s*H+h)*(Q+R); + for(int k=tid;k>1;n;n>>=1){if(tid>1;n;n>>=1){if(tid= bytes) return 1; if (*ptr) cudaFree(*ptr); @@ -286,6 +381,7 @@ extern "C" int coli_cuda_init(const int *devices, int count) { if (!select_ctx(ctx)) { g_nctx = 0; return 0; } cudaDeviceProp prop{}; if (!cuda_ok(cudaGetDeviceProperties(&prop, device), "device properties")) { g_nctx = 0; return 0; } + ctx->compute_major=prop.major;ctx->compute_minor=prop.minor; if(!cuda_ok(cudaStreamCreateWithFlags(&ctx->stream,cudaStreamNonBlocking),"stream creation")){ g_nctx=0;return 0; } @@ -307,6 +403,7 @@ extern "C" void coli_cuda_shutdown(void) { if (ctx->qx) cudaFree(ctx->qx); if (ctx->qscale) cudaFree(ctx->qscale); if(ctx->aq)cudaFree(ctx->aq);if(ctx->al)cudaFree(ctx->al);if(ctx->ar)cudaFree(ctx->ar);if(ctx->ac)cudaFree(ctx->ac); + for(int b=0;b<24;b++) if(ctx->pipe_buf[b]) cudaFree(ctx->pipe_buf[b]); if (ctx->host_x) cudaFreeHost(ctx->host_x); if (ctx->host_y) cudaFreeHost(ctx->host_y); if (ctx->stream) cudaStreamDestroy(ctx->stream); @@ -453,6 +550,34 @@ extern "C" int coli_cuda_expert_mlp(ColiCudaTensor *gate, ColiCudaTensor *up, return 1; } +extern "C" int coli_cuda_shared_mlp_w4a16(ColiCudaTensor *gate,ColiCudaTensor *up, + ColiCudaTensor *down,float *y,const float *x,int S){ + if(!gate||!up||!down||!x||!y||S<1||gate->fmt!=2||up->fmt!=2||down->fmt!=2|| + gate->device!=up->device||gate->device!=down->device||gate->I!=up->I|| + gate->O!=up->O||down->I!=gate->O||down->O!=gate->I)return 0; + DeviceContext *ctx=find_ctx(gate->device);if(!select_ctx(ctx)||ctx->compute_major<7)return 0; + int D=gate->I,I=gate->O;size_t xb=(size_t)S*D*sizeof(float),ib=(size_t)S*I*sizeof(float); + if(!reserve(&ctx->x,&ctx->x_cap,xb)||!reserve(&ctx->gate,&ctx->gate_cap,ib)|| + !reserve(&ctx->up,&ctx->up_cap,ib)||!reserve(&ctx->y,&ctx->y_cap,xb)|| + !reserve_pinned(&ctx->host_x,&ctx->host_x_cap,xb)|| + !reserve_pinned(&ctx->host_y,&ctx->host_y_cap,xb))return 0; + std::memcpy(ctx->host_x,x,xb); + if(!cuda_ok(cudaMemcpyAsync(ctx->x,ctx->host_x,xb,cudaMemcpyHostToDevice,ctx->stream), + "shared w4a16 input upload"))return 0; + dim3 hidden((unsigned)((I+63)/64),(unsigned)((S+15)/16)); + dim3 output((unsigned)((D+63)/64),(unsigned)((S+15)/16)); + w4a16_gate_up<<stream>>>(ctx->gate,ctx->up,ctx->x, + (const uint8_t*)gate->weights,(const uint8_t*)up->weights,gate->scales,up->scales,S,D,I); + silu_mul<<<(unsigned)(((size_t)S*I+255)/256),256,0,ctx->stream>>>(ctx->gate,ctx->up,(size_t)S*I); + w4a16_matmul<<stream>>>(ctx->y,ctx->gate,(const uint8_t*)down->weights,down->scales,S,I,D); + if(!cuda_ok(cudaGetLastError(),"shared w4a16 launch")|| + !cuda_ok(cudaMemcpyAsync(ctx->host_y,ctx->y,xb,cudaMemcpyDeviceToHost,ctx->stream), + "shared w4a16 output download")|| + !cuda_ok(cudaStreamSynchronize(ctx->stream),"shared w4a16 synchronize"))return 0; + std::memcpy(y,ctx->host_y,xb); + return 1; +} + extern "C" int coli_cuda_expert_group(ColiCudaTensor *const *gates, ColiCudaTensor *const *ups, ColiCudaTensor *const *downs, @@ -510,6 +635,38 @@ extern "C" int coli_cuda_expert_group(ColiCudaTensor *const *gates, silu_mul<<<(unsigned)(((size_t)total*I+255)/256),256,0,ctx->stream>>>(ctx->gate,ctx->up,(size_t)total*I); quantize_s4_rows<<stream>>>(ctx->qx,ctx->qscale,ctx->gate,total,I); grouped_s4_wmma<<stream>>>(ctx->y,ctx->qx,ctx->qscale,dev,I,D,2); + }else if(all_s4&&ctx->compute_major>=7&&getenv("COLI_CUDA_TC_W4A16")&& + atoi(getenv("COLI_CUDA_TC_W4A16"))){ + /* W4A16 Tensor Core per gruppo: attivazioni fp16 per tile (lossless al + * contrario del path W4A4), un lancio per expert dentro lo stream — + * l'overhead di lancio e' trascurabile rispetto ai GEMM. */ + int tc16_min=getenv("COLI_CUDA_TC_W4A16_MIN")?atoi(getenv("COLI_CUDA_TC_W4A16_MIN")):16; + int off16=0; + for(int c=0;cgate+(size_t)off16*I,*u16=ctx->up+(size_t)off16*I; + float *x16=ctx->x+(size_t)off16*D,*y16=ctx->y+(size_t)off16*D; + if(r>=tc16_min){ + dim3 hg16((unsigned)((I+63)/64),(unsigned)((r+15)/16)); + dim3 og16((unsigned)((D+63)/64),(unsigned)((r+15)/16)); + w4a16_gate_up<<stream>>>(g16,u16,x16, + (const uint8_t*)host[c].g,(const uint8_t*)host[c].u,host[c].gs,host[c].us,r,D,I); + silu_mul<<<(unsigned)(((size_t)r*I+255)/256),256,0,ctx->stream>>>(g16,u16,(size_t)r*I); + w4a16_matmul<<stream>>>(y16,g16, + (const uint8_t*)host[c].d,host[c].ds,r,I,D); + }else{ + /* piccoli batch: tile TC quasi vuoti + overhead di lancio — il + * kernel naive per-elemento resta piu' veloce (misurato in decode) */ + quant_matmul<<stream>>>(g16,x16, + host[c].g,host[c].gs,host[c].gf,r,D,I,row_bytes(host[c].gf,D)); + quant_matmul<<stream>>>(u16,x16, + host[c].u,host[c].us,host[c].uf,r,D,I,row_bytes(host[c].uf,D)); + silu_mul<<<(unsigned)(((size_t)r*I+255)/256),256,0,ctx->stream>>>(g16,u16,(size_t)r*I); + quant_matmul<<stream>>>(y16,g16, + host[c].d,host[c].ds,host[c].df,r,I,D,row_bytes(host[c].df,I)); + } + off16+=r; + } }else if(all_s4&&(!getenv("COLI_CUDA_W4_PACKED")||atoi(getenv("COLI_CUDA_W4_PACKED")))){ dim3 hg((unsigned)I,(unsigned)max_rows,(unsigned)count),og((unsigned)D,(unsigned)max_rows,(unsigned)count); int dual=!getenv("COLI_CUDA_DUAL_PROJ")||atoi(getenv("COLI_CUDA_DUAL_PROJ")); @@ -547,6 +704,7 @@ extern "C" int coli_cuda_expert_group(ColiCudaTensor *const *gates, return 1; } + extern "C" int coli_cuda_attention_absorb(ColiCudaTensor *w,float *ctx,const float *q, const float *latent,const float *rope,int H,int Q, int R,int V,int K,int T,float scale){ @@ -569,6 +727,49 @@ extern "C" int coli_cuda_attention_absorb(ColiCudaTensor *w,float *ctx,const flo return 1; } +static int attention_absorb_batch_run(ColiCudaTensor *w,ColiCudaTensor *proj,float *out, + const float *q,const float *latent,const float *rope,int S,int H,int Q,int R,int V, + int K,int T,float scale){ + if(!w||!out||!q||!latent||!rope||S<1||H<1||Q<1||R<1||V<1||K<1||K>512|| + T8192||w->I!=K||w->O!=H*(Q+V))return 0; + if(proj&&(proj->device!=w->device||proj->I!=H*V))return 0; + DeviceContext *dc=find_ctx(w->device);if(!select_ctx(dc))return 0; + size_t qb=(size_t)S*H*(Q+R)*sizeof(float),lb=(size_t)T*K*sizeof(float); + size_t rb=(size_t)T*R*sizeof(float),cb=(size_t)S*H*V*sizeof(float); + if(!reserve(&dc->aq,&dc->aq_cap,qb)||!reserve(&dc->al,&dc->al_cap,lb)|| + !reserve(&dc->ar,&dc->ar_cap,rb)||!reserve(&dc->ac,&dc->ac_cap,cb))return 0; + if(!cuda_ok(cudaMemcpyAsync(dc->aq,q,qb,cudaMemcpyHostToDevice,dc->stream),"attention batch q upload")|| + !cuda_ok(cudaMemcpyAsync(dc->al,latent,lb,cudaMemcpyHostToDevice,dc->stream),"attention batch latent upload")|| + !cuda_ok(cudaMemcpyAsync(dc->ar,rope,rb,cudaMemcpyHostToDevice,dc->stream),"attention batch rope upload"))return 0; + size_t shared=(size_t)(2*K+T+256)*sizeof(float); + attention_absorb_batch_kernel<<stream>>>(dc->ac,dc->aq,dc->al, + dc->ar,w->weights,w->scales,w->fmt,S,H,Q,R,V,K,T,scale); + if(!cuda_ok(cudaGetLastError(),"attention batch launch"))return 0; + const float *src=dc->ac;size_t ob=cb; + if(proj){ + ob=(size_t)S*proj->O*sizeof(float);if(!reserve(&dc->y,&dc->y_cap,ob))return 0; + quant_matmul<<O,S),256,0,dc->stream>>>(dc->y,dc->ac,proj->weights, + proj->scales,proj->fmt,S,proj->I,proj->O,row_bytes(proj->fmt,proj->I)); + if(!cuda_ok(cudaGetLastError(),"attention o_proj launch"))return 0;src=dc->y; + } + if(!cuda_ok(cudaMemcpyAsync(out,src,ob,cudaMemcpyDeviceToHost,dc->stream), + proj?"attention projected output download":"attention batch context download")|| + !cuda_ok(cudaStreamSynchronize(dc->stream),"attention batch synchronize"))return 0; + return 1; +} + +extern "C" int coli_cuda_attention_absorb_batch(ColiCudaTensor *w,float *ctx,const float *q, + const float *latent,const float *rope,int S,int H,int Q,int R,int V,int K,int T, + float scale){ + return attention_absorb_batch_run(w,nullptr,ctx,q,latent,rope,S,H,Q,R,V,K,T,scale); +} + +extern "C" int coli_cuda_attention_project_batch(ColiCudaTensor *w,ColiCudaTensor *proj, + float *out,const float *q,const float *latent,const float *rope,int S,int H,int Q, + int R,int V,int K,int T,float scale){ + return attention_absorb_batch_run(w,proj,out,q,latent,rope,S,H,Q,R,V,K,T,scale); +} + extern "C" void coli_cuda_tensor_free(ColiCudaTensor *tensor) { if (!tensor) return; DeviceContext *ctx = find_ctx(tensor->device); @@ -590,3 +791,234 @@ extern "C" size_t coli_cuda_tensor_bytes(const ColiCudaTensor *tensor) { extern "C" int coli_cuda_tensor_device(const ColiCudaTensor *tensor) { return tensor ? tensor->device : -1; } + +/* ==== resident-pipeline primitives (Inc.0, 2026-07-13) ==== + * Device-side building blocks so the residual stream can stay on the layer's + * home device across a whole layer. Control flow stays on CPU; only the data + * plane lives here. All entry points take DEVICE pointers (no transfers) — + * the caller owns staging via the pipe buffer API below. */ + +__global__ static void pipe_rmsnorm_rows(float *y,const float *x,const float *w, + int D,float eps,int xstride,int ystride){ + const float *xr=x+(size_t)blockIdx.x*xstride; float *yr=y+(size_t)blockIdx.x*ystride; + __shared__ double sh[256]; + double a=0; for(int i=threadIdx.x;i0;s>>=1){ if(threadIdx.x=24||!select_ctx(ctx)) return NULL; + if(!reserve(&ctx->pipe_buf[slot],&ctx->pipe_cap[slot],bytes)) return NULL; + return ctx->pipe_buf[slot]; +} +extern "C" void *coli_cuda_pipe_alloc(int device,size_t bytes){ + DeviceContext *ctx=find_ctx(device); if(!select_ctx(ctx)) return NULL; + void *p=NULL; + if(!cuda_ok(cudaMalloc(&p,bytes),"pipe alloc")) return NULL; + return p; +} +extern "C" void coli_cuda_pipe_free(int device,void *p){ + DeviceContext *ctx=find_ctx(device); if(!p||!select_ctx(ctx)) return; + cudaFree(p); +} +extern "C" int coli_cuda_pipe_upload(int device,void *dst,const void *src,size_t bytes){ + DeviceContext *ctx=find_ctx(device); if(!select_ctx(ctx)) return 0; + return cuda_ok(cudaMemcpy(dst,src,bytes,cudaMemcpyHostToDevice),"pipe upload"); +} +extern "C" int coli_cuda_pipe_download(int device,const void *src,void *dst,size_t bytes){ + DeviceContext *ctx=find_ctx(device); if(!select_ctx(ctx)) return 0; + return cuda_ok(cudaMemcpy(dst,src,bytes,cudaMemcpyDeviceToHost),"pipe download"); +} +extern "C" int coli_cuda_pipe_rmsnorm(int device,float *y_dev,const float *x_dev, + const float *w_dev,int S,int D,float eps){ + DeviceContext *ctx=find_ctx(device); + if(S<1||D<1||!select_ctx(ctx)) return 0; + pipe_rmsnorm_rows<<>>(y_dev,x_dev,w_dev,D,eps,D,D); + return cuda_ok(cudaGetLastError(),"pipe rmsnorm"); +} +extern "C" int coli_cuda_pipe_rmsnorm_s(int device,float *y_dev,const float *x_dev, + const float *w_dev,int S,int D,float eps, + int xstride,int ystride){ + DeviceContext *ctx=find_ctx(device); + if(S<1||D<1||xstride>>(y_dev,x_dev,w_dev,D,eps,xstride,ystride); + return cuda_ok(cudaGetLastError(),"pipe rmsnorm strided"); +} +extern "C" int coli_cuda_pipe_rope(int device,float *v_dev,const int *pos_dev, + int rows,int stride,int offset,int R,int heads, + float theta){ + DeviceContext *ctx=find_ctx(device); + if(rows<1||R<2||R>256||heads<1||!select_ctx(ctx)) return 0; + pipe_rope_rows<<>>(v_dev,pos_dev,0,stride,offset,R,heads,theta); + return cuda_ok(cudaGetLastError(),"pipe rope"); +} +extern "C" int coli_cuda_pipe_rope_base(int device,float *v_dev,int pos_base,int rows, + int stride,int offset,int R,int heads,float theta){ + DeviceContext *ctx=find_ctx(device); + if(rows<1||R<2||R>256||heads<1||!select_ctx(ctx)) return 0; + pipe_rope_rows<<>>(v_dev,NULL,pos_base,stride,offset,R,heads,theta); + return cuda_ok(cudaGetLastError(),"pipe rope base"); +} +extern "C" int coli_cuda_pipe_copy2d(int device,float *dst,int dpitch,const float *src, + int spitch,int width,int height){ + DeviceContext *ctx=find_ctx(device); if(!select_ctx(ctx)) return 0; + return cuda_ok(cudaMemcpy2D(dst,(size_t)dpitch*4,src,(size_t)spitch*4, + (size_t)width*4,height,cudaMemcpyDeviceToDevice),"pipe copy2d"); +} +/* attention batch + fused o_proj with DEVICE-resident q/latent/rope: the whole + * upstream projection chain stayed on this device, so nothing is uploaded here. + * Only the final [S,O] projection is downloaded to host. */ +extern "C" int coli_cuda_attention_project_batch_dev(ColiCudaTensor *w,ColiCudaTensor *proj, + float *out,const float *q_dev,const float *latent_dev,const float *rope_dev, + int S,int H,int Q,int R,int V,int K,int T,float scale){ + if(!w||!proj||!out||!q_dev||!latent_dev||!rope_dev||S<1||H<1||Q<1||R<1||V<1|| + K<1||K>512||T8192||w->I!=K||w->O!=H*(Q+V)|| + proj->device!=w->device||proj->I!=H*V)return 0; + DeviceContext *dc=find_ctx(w->device);if(!select_ctx(dc))return 0; + size_t cb=(size_t)S*H*V*sizeof(float); + if(!reserve(&dc->ac,&dc->ac_cap,cb))return 0; + size_t shared=(size_t)(2*K+T+256)*sizeof(float); + attention_absorb_batch_kernel<<stream>>>(dc->ac,q_dev,latent_dev, + rope_dev,w->weights,w->scales,w->fmt,S,H,Q,R,V,K,T,scale); + if(!cuda_ok(cudaGetLastError(),"pipe attention launch"))return 0; + size_t ob=(size_t)S*proj->O*sizeof(float); + if(!reserve(&dc->y,&dc->y_cap,ob))return 0; + quant_matmul<<O,S),256,0,dc->stream>>>(dc->y,dc->ac,proj->weights, + proj->scales,proj->fmt,S,proj->I,proj->O,row_bytes(proj->fmt,proj->I)); + if(!cuda_ok(cudaGetLastError(),"pipe o_proj launch"))return 0; + if(!cuda_ok(cudaMemcpyAsync(out,dc->y,ob,cudaMemcpyDeviceToHost,dc->stream),"pipe attention download")|| + !cuda_ok(cudaStreamSynchronize(dc->stream),"pipe attention sync"))return 0; + return 1; +} +extern "C" int coli_cuda_pipe_silu_mul(int device,float *gate_dev,const float *up_dev, + size_t n){ + DeviceContext *ctx=find_ctx(device); if(!n||!select_ctx(ctx)) return 0; + silu_mul<<<(unsigned)((n+255)/256),256>>>(gate_dev,up_dev,n); + return cuda_ok(cudaGetLastError(),"pipe silu mul"); +} +extern "C" int coli_cuda_pipe_add(int device,float *x_dev,const float *t_dev,size_t n){ + DeviceContext *ctx=find_ctx(device); if(!n||!select_ctx(ctx)) return 0; + pipe_add_n<<<(unsigned)((n+255)/256),256>>>(x_dev,t_dev,n); + return cuda_ok(cudaGetLastError(),"pipe add"); +} +extern "C" int coli_cuda_pipe_rows_add(int device,float *x_dev,const float *partial_dev, + const int *rows_dev,int nrows,int D){ + DeviceContext *ctx=find_ctx(device); if(nrows<1||D<1||!select_ctx(ctx)) return 0; + pipe_rows_add<<>>(x_dev,partial_dev,rows_dev,D); + return cuda_ok(cudaGetLastError(),"pipe rows add"); +} +/* GEMM with device-resident activations: same quant_matmul kernel as + * coli_cuda_matmul, zero host transfers. */ +extern "C" int coli_cuda_pipe_gemm(ColiCudaTensor *t,float *y_dev,const float *x_dev, + int S){ + if(!t||S<1) return 0; + DeviceContext *ctx=find_ctx(t->device); if(!select_ctx(ctx)) return 0; + dim3 grid((unsigned)t->O,(unsigned)S); + quant_matmul<<>>(y_dev,x_dev,t->weights,t->scales,t->fmt,S,t->I,t->O, + row_bytes(t->fmt,t->I)); + return cuda_ok(cudaGetLastError(),"pipe gemm"); +} +/* copia diretta scheda->scheda (P2P se disponibile, altrimenti staging driver) */ +extern "C" int coli_cuda_pipe_peer_copy(int dst_dev,float *dst,int src_dev, + const float *src,size_t bytes){ + if(!dst||!src) return 0; + if(dst_dev==src_dev){ DeviceContext *c=find_ctx(dst_dev); if(!select_ctx(c)) return 0; + return cuda_ok(cudaMemcpy(dst,src,bytes,cudaMemcpyDeviceToDevice),"pipe intra copy"); } + return cuda_ok(cudaMemcpyPeer(dst,dst_dev,src,src_dev,bytes),"pipe peer copy"); +} +/* come attention_project_batch_dev ma l'uscita di o_proj RESTA sul device (out_dev). */ +extern "C" int coli_cuda_attention_project_batch_dev_out(ColiCudaTensor *w,ColiCudaTensor *proj, + float *out_dev,const float *q_dev,const float *latent_dev,const float *rope_dev, + int S,int H,int Q,int R,int V,int K,int T,float scale){ + if(!w||!proj||!out_dev||!q_dev||!latent_dev||!rope_dev||S<1||H<1||Q<1||R<1||V<1|| + K<1||K>512||T8192||w->I!=K||w->O!=H*(Q+V)|| + proj->device!=w->device||proj->I!=H*V)return 0; + DeviceContext *dc=find_ctx(w->device);if(!select_ctx(dc))return 0; + size_t cb=(size_t)S*H*V*sizeof(float); + if(!reserve(&dc->ac,&dc->ac_cap,cb))return 0; + size_t shared=(size_t)(2*K+T+256)*sizeof(float); + attention_absorb_batch_kernel<<stream>>>(dc->ac,q_dev,latent_dev, + rope_dev,w->weights,w->scales,w->fmt,S,H,Q,R,V,K,T,scale); + if(!cuda_ok(cudaGetLastError(),"pipe attention launch (dev out)"))return 0; + quant_matmul<<O,S),256,0,dc->stream>>>(out_dev,dc->ac,proj->weights, + proj->scales,proj->fmt,S,proj->I,proj->O,row_bytes(proj->fmt,proj->I)); + if(!cuda_ok(cudaGetLastError(),"pipe o_proj launch (dev out)"))return 0; + return cuda_ok(cudaStreamSynchronize(dc->stream),"pipe attention sync (dev out)"); +} +/* absorb batch con TUTTO su device (q/latent/rope gia' residenti sulla scheda + * dello shard, ctx resta sul device): il cuore della attention head-shardata + * dentro il pipeline. Nessun trasferimento host. */ +extern "C" int coli_cuda_attention_absorb_batch_dev(ColiCudaTensor *w,float *ctx_dev, + const float *q_dev,const float *latent_dev,const float *rope_dev, + int S,int H,int Q,int R,int V,int K,int T,float scale){ + if(!w||!ctx_dev||!q_dev||!latent_dev||!rope_dev||S<1||H<1||Q<1||R<1||V<1|| + K<1||K>512||T8192||w->I!=K||w->O!=H*(Q+V))return 0; + DeviceContext *dc=find_ctx(w->device);if(!select_ctx(dc))return 0; + size_t shared=(size_t)(2*K+T+256)*sizeof(float); + attention_absorb_batch_kernel<<stream>>>(ctx_dev,q_dev,latent_dev, + rope_dev,w->weights,w->scales,w->fmt,S,H,Q,R,V,K,T,scale); + if(!cuda_ok(cudaGetLastError(),"pipe shard attention launch"))return 0; + return cuda_ok(cudaStreamSynchronize(dc->stream),"pipe shard attention sync"); +} +/* absorb per il DECODE con KV gia' residente: carica solo q (poche KB), + * latent/rope arrivano dall'ombra device. ctx torna a host (S piccolo). */ +extern "C" int coli_cuda_attention_absorb_kvdev(ColiCudaTensor *w,float *ctx,const float *q, + const float *latent_dev,const float *rope_dev,int H,int Q,int R,int V,int K,int T, + float scale){ + if(!w||!ctx||!q||!latent_dev||!rope_dev||H<1||Q<1||R<1||V<1||K<1||K>512||T<1||T>8192|| + w->I!=K||w->O!=H*(Q+V))return 0; + DeviceContext *dc=find_ctx(w->device);if(!select_ctx(dc))return 0; + size_t qb=(size_t)H*(Q+R)*sizeof(float),cb=(size_t)H*V*sizeof(float); + if(!reserve(&dc->aq,&dc->aq_cap,qb)||!reserve(&dc->ac,&dc->ac_cap,cb))return 0; + if(!cuda_ok(cudaMemcpyAsync(dc->aq,q,qb,cudaMemcpyHostToDevice,dc->stream),"kvdev q upload"))return 0; + size_t shared=(size_t)(2*K+T+256)*sizeof(float); + attention_absorb_batch_kernel<<stream>>>(dc->ac,dc->aq,latent_dev, + rope_dev,w->weights,w->scales,w->fmt,1,H,Q,R,V,K,T,scale); + if(!cuda_ok(cudaGetLastError(),"kvdev absorb launch")|| + !cuda_ok(cudaMemcpyAsync(ctx,dc->ac,cb,cudaMemcpyDeviceToHost,dc->stream),"kvdev ctx download")|| + !cuda_ok(cudaStreamSynchronize(dc->stream),"kvdev absorb sync"))return 0; + return 1; +} +extern "C" int coli_cuda_pipe_sync(int device){ + DeviceContext *ctx=find_ctx(device); if(!select_ctx(ctx)) return 0; + return cuda_ok(cudaDeviceSynchronize(),"pipe sync"); +} diff --git a/c/backend_cuda.h b/c/backend_cuda.h index 533bbea..c84a265 100644 --- a/c/backend_cuda.h +++ b/c/backend_cuda.h @@ -56,6 +56,14 @@ COLI_CUDA_DLLEXPORT int coli_cuda_matmul(ColiCudaTensor **tensor, COLI_CUDA_DLLEXPORT int coli_cuda_expert_mlp(ColiCudaTensor *gate, ColiCudaTensor *up, ColiCudaTensor *down, float *y, const float *x, int S); +/* Prefill-oriented shared expert path. INT4 weights stay packed in global + * memory, activations are converted to FP16 per tile, and Tensor Cores + * accumulate into FP32. Unlike COLI_CUDA_TC_INT4 this does not quantize the + * activation to INT4. */ +int coli_cuda_shared_mlp_w4a16(ColiCudaTensor *gate, ColiCudaTensor *up, + ColiCudaTensor *down, float *y, + const float *x, int S); + /* Packed group of same-shaped experts. Inputs and outputs contain sum(rows) * consecutive [D] rows in call order. */ COLI_CUDA_DLLEXPORT int coli_cuda_expert_group(ColiCudaTensor *const *gates, @@ -69,6 +77,21 @@ COLI_CUDA_DLLEXPORT int coli_cuda_attention_absorb(ColiCudaTensor *kv_b,float *c const float *latent,const float *rope,int H,int Q, int R,int V,int K,int T,float attention_scale); +/* Causal MLA absorption for S contiguous rows from one sequence. The KV + * arrays contain T rows ending at the final query; query s attends T-S+s+1 + * rows. One transfer and one launch replace S host round-trips. */ +COLI_CUDA_DLLEXPORT int coli_cuda_attention_absorb_batch(ColiCudaTensor *kv_b,float *ctx,const float *q, + const float *latent,const float *rope,int S, + int H,int Q,int R,int V,int K,int T, + float attention_scale); + +/* Same attention batch followed immediately by resident o_proj on the same + * device. Only the final [S,D] tensor crosses back to the host. */ +COLI_CUDA_DLLEXPORT int coli_cuda_attention_project_batch(ColiCudaTensor *kv_b,ColiCudaTensor *o_proj, + float *out,const float *q,const float *latent, + const float *rope,int S,int H,int Q,int R, + int V,int K,int T,float attention_scale); + COLI_CUDA_DLLEXPORT void coli_cuda_tensor_free(ColiCudaTensor *tensor); COLI_CUDA_DLLEXPORT size_t coli_cuda_tensor_bytes(const ColiCudaTensor *tensor); COLI_CUDA_DLLEXPORT int coli_cuda_tensor_device(const ColiCudaTensor *tensor); @@ -77,8 +100,47 @@ COLI_CUDA_DLLEXPORT int coli_cuda_tensor_device(const ColiCudaTensor *tensor); int coli_cuda_tensor_update(ColiCudaTensor *tensor, const void *weights, const float *scales); +/* ---- resident-pipeline primitives (Inc.0): device-pointer entry points ---- */ +float *coli_cuda_pipe_scratch(int device,int slot,size_t bytes); +void *coli_cuda_pipe_alloc(int device,size_t bytes); +void coli_cuda_pipe_free(int device,void *p); +int coli_cuda_pipe_upload(int device,void *dst,const void *src,size_t bytes); +int coli_cuda_pipe_download(int device,const void *src,void *dst,size_t bytes); +int coli_cuda_pipe_rmsnorm(int device,float *y_dev,const float *x_dev, + const float *w_dev,int S,int D,float eps); +int coli_cuda_pipe_rope(int device,float *v_dev,const int *pos_dev,int rows, + int stride,int offset,int R,int heads,float theta); +int coli_cuda_pipe_silu_mul(int device,float *gate_dev,const float *up_dev,size_t n); +int coli_cuda_pipe_add(int device,float *x_dev,const float *t_dev,size_t n); +int coli_cuda_pipe_rows_add(int device,float *x_dev,const float *partial_dev, + const int *rows_dev,int nrows,int D); +int coli_cuda_pipe_gemm(ColiCudaTensor *t,float *y_dev,const float *x_dev,int S); +int coli_cuda_pipe_rmsnorm_s(int device,float *y_dev,const float *x_dev, + const float *w_dev,int S,int D,float eps, + int xstride,int ystride); +int coli_cuda_pipe_rope_base(int device,float *v_dev,int pos_base,int rows, + int stride,int offset,int R,int heads,float theta); +int coli_cuda_pipe_copy2d(int device,float *dst,int dpitch,const float *src, + int spitch,int width,int height); +int coli_cuda_attention_project_batch_dev(ColiCudaTensor *kv_b,ColiCudaTensor *o_proj, + float *out,const float *q_dev,const float *latent_dev,const float *rope_dev, + int S,int H,int Q,int R,int V,int K,int T,float scale); +int coli_cuda_attention_absorb_batch_dev(ColiCudaTensor *kv_b_shard,float *ctx_dev, + const float *q_dev,const float *latent_dev,const float *rope_dev, + int S,int H,int Q,int R,int V,int K,int T,float scale); +int coli_cuda_attention_absorb_kvdev(ColiCudaTensor *kv_b,float *ctx,const float *q, + const float *latent_dev,const float *rope_dev,int H,int Q,int R,int V,int K,int T, + float scale); +int coli_cuda_pipe_peer_copy(int dst_dev,float *dst,int src_dev, + const float *src,size_t bytes); +int coli_cuda_attention_project_batch_dev_out(ColiCudaTensor *kv_b,ColiCudaTensor *o_proj, + float *out_dev,const float *q_dev,const float *latent_dev,const float *rope_dev, + int S,int H,int Q,int R,int V,int K,int T,float scale); +int coli_cuda_pipe_sync(int device); + #ifdef __cplusplus } #endif #endif + diff --git a/c/glm.c b/c/glm.c index 561d410..2780b79 100644 --- a/c/glm.c +++ b/c/glm.c @@ -113,6 +113,11 @@ typedef struct { float *in_ln, *post_ln; /* MLA (densa, quantizzata) */ QT q_a, q_b, kv_a, kv_b, o; float *q_a_ln, *kv_a_ln; +#ifdef COLI_CUDA + ColiCudaTensor *kv_b_shard[COLI_CUDA_MAX_DEVICES]; + int shard_h0[COLI_CUDA_MAX_DEVICES],shard_hn[COLI_CUDA_MAX_DEVICES],n_kv_b_shard; + int shared_w4a16_failed; +#endif int sparse; /* dense mlp (sparse==0) */ QT gate_proj, up_proj, down_proj; @@ -152,6 +157,7 @@ typedef struct { int *kv_start; /* prima pos valida nella KV del layer (MTP: parziale) */ KVState *kv; ESlot **ecache; int *ecn; int ecap; /* LRU expert per-layer */ + float **kv_dev_L, **kv_dev_R; int *kv_dev_valid; /* ombra KV su device (decode) */ ESlot ws[64]; /* working set del layer corrente (load paralleli) */ ESlot **pin; int *npin; /* HOT-STORE: expert pinnati in RAM (mai evicted) */ uint32_t **eusage; /* contatori persistenti (per STATS/PIN) */ @@ -1065,6 +1071,33 @@ static float *ld(Model *m, const char *name){ /* tensore 1D f32 residente (nor float *p=(float*)qalloc((size_t)n*sizeof(float)); /* registrato per la GPU sotto METAL */ st_read_f32(&m->S,name,p,0); return p; } +#ifdef COLI_CUDA +static void qt_cuda_colocate(QT *dst,const QT *src){ + if(!g_cuda_enabled||!g_cuda_dense||!dst->cuda_eligible||!src->cuda_eligible|| + dst->cuda_device==src->cuda_device)return; + int old=-1,now=-1;for(int i=0;icuda_device)old=i;if(g_cuda_devices[i]==src->cuda_device)now=i; + } + if(old>=0)g_cuda_dense_projected[old]-=qt_bytes(dst); + if(now>=0)g_cuda_dense_projected[now]+=qt_bytes(dst); + dst->cuda_device=src->cuda_device; +} +static void layer_cuda_shard_kvb(Layer *l,int H,int Q,int V){ + if(!g_cuda_enabled||!g_cuda_dense||g_cuda_ndev<2||l->kv_b.fmt==0)return; + int rb=l->kv_b.fmt==1?l->kv_b.I:(l->kv_b.fmt==2?(l->kv_b.I+1)/2:(l->kv_b.I+3)/4); + const uint8_t *weights=l->kv_b.fmt==1?(const uint8_t*)l->kv_b.q8:l->kv_b.q4; + for(int d=0,h0=0;dkv_b.s+(int64_t)h0*(Q+V); + if(!coli_cuda_tensor_upload(&l->kv_b_shard[d],part,scale,l->kv_b.fmt,l->kv_b.I,rows,g_cuda_devices[d]))return; + l->shard_h0[d]=h0;l->shard_hn[d]=hn;l->n_kv_b_shard++;h0+=hn; + } + int old=-1;for(int i=0;ikv_b.cuda_device)old=i; + if(old>=0)g_cuda_dense_projected[old]-=qt_bytes(&l->kv_b); + l->kv_b.cuda_eligible=0; +} +#endif static void model_init(Model *m, const char *snap, int cap, int ebits, int dbits){ memset(m,0,sizeof(*m)); m->ebits=ebits; m->dbits=dbits; @@ -1079,6 +1112,8 @@ static void model_init(Model *m, const char *snap, int cap, int ebits, int dbits m->L=calloc(c->n_layers,sizeof(Layer)); int NR=c->n_layers+1; /* +1: riga del layer MTP */ m->ecap=cap; m->ecache=calloc(NR,sizeof(ESlot*)); m->ecn=calloc(NR,sizeof(int)); + m->kv_dev_L=calloc(NR,sizeof(float*)); m->kv_dev_R=calloc(NR,sizeof(float*)); + m->kv_dev_valid=calloc(NR,sizeof(int)); m->eroute=calloc(NR,sizeof(int*)); m->enr=calloc(NR,sizeof(int)); m->pin=calloc(NR,sizeof(ESlot*)); m->npin=calloc(NR,sizeof(int)); m->eusage=calloc(NR,sizeof(uint32_t*)); m->eheat=calloc(NR,sizeof(uint32_t*)); @@ -1097,6 +1132,14 @@ static void model_init(Model *m, const char *snap, int cap, int ebits, int dbits l->kv_a_ln= ld(m,P("self_attn.kv_a_layernorm.weight")); l->kv_b = qt_load(m,P("self_attn.kv_b_proj.weight"), H*(c->qk_nope+c->v_head), c->kv_lora, dbits); l->o = qt_load(m,P("self_attn.o_proj.weight"), D, H*c->v_head, dbits); +#ifdef COLI_CUDA + qt_cuda_colocate(&l->o,&l->kv_b); + qt_cuda_colocate(&l->q_a,&l->kv_b); /* PIPE: intera catena attention sulla */ + qt_cuda_colocate(&l->q_b,&l->kv_b); /* stessa scheda / whole attention chain */ + qt_cuda_colocate(&l->kv_a,&l->kv_b); /* on the layer home device */ + if(getenv("COLI_CUDA_ATTN_SHARD")&&atoi(getenv("COLI_CUDA_ATTN_SHARD"))) + layer_cuda_shard_kvb(l,H,c->qk_nope,c->v_head); +#endif l->sparse = (i >= c->first_dense); if(!l->sparse){ l->gate_proj = qt_load(m,P("mlp.gate_proj.weight"), c->dense_inter, D, dbits); @@ -1109,6 +1152,11 @@ static void model_init(Model *m, const char *snap, int cap, int ebits, int dbits l->sh_gate = qt_load(m,P("mlp.shared_experts.gate_proj.weight"), sI, D, dbits); l->sh_up = qt_load(m,P("mlp.shared_experts.up_proj.weight"), sI, D, dbits); l->sh_down = qt_load(m,P("mlp.shared_experts.down_proj.weight"), D, sI, dbits); +#ifdef COLI_CUDA + qt_cuda_colocate(&l->sh_gate,&l->kv_b); /* PIPE2: shared chain on the layer home device */ + qt_cuda_colocate(&l->sh_up,&l->sh_gate); + qt_cuda_colocate(&l->sh_down,&l->sh_gate); +#endif m->ecache[i]=calloc(cap,sizeof(ESlot)); m->eroute[i]=calloc(c->topk,sizeof(int)); /* metodo C: ultimo routing del layer */ m->eusage[i]=calloc(c->n_experts,sizeof(uint32_t)); @@ -1573,7 +1621,10 @@ static void qt_matvec_rows(const QT *t, int r0, int n, const float *x, float *y) y[j]=(float)a; } } -static int g_absorb=-1; /* ABSORB: -1 auto (decode S<=4), 0 mai, 1 sempre (test) */ +static int g_absorb=-1; +#ifdef COLI_CUDA +static int g_cuda_pipe=0; /* COLI_CUDA_PIPE=1: prefill attention chain resident on the layer home device */ +#endif /* ABSORB: -1 auto (decode S<=4), 0 mai, 1 sempre (test) */ static int g_dsa_force=0; /* DSA_FORCE=1: selezione sempre attiva (test: top-min(k,T)=denso) */ static int cmp_fdesc(const void *a,const void *b){ float x=*(const float*)a, y=*(const float*)b; return xy?-1:0; } @@ -1581,6 +1632,141 @@ static int cmp_fdesc(const void *a,const void *b){ /* attenzione MLA con KV-cache compressa, su token nuovi x[S,hidden], pos_base = pos del primo */ /* kvs/pos describe a ragged decode batch: each row may belong to a different * sequence. NULL keeps the original contiguous, currently-bound KV path. */ +#ifdef COLI_CUDA +/* Ombra KV su device per il DECODE: righe [0,upto) valide sulla scheda di kv_b. + * L'host resta canonico; l'ombra si riallinea in blocco quando resta indietro e + * viene invalidata da kv_bind / dalla riscrittura di righe gia' specchiate. */ +static int kv_dev_sync(Model *m, Layer *l, int layer, int upto){ + Cfg *c=&m->c; int kvl=c->kv_lora, R=c->qk_rope, dev=l->kv_b.cuda_device; + if(upto>m->max_t) return 0; + if(!m->kv_dev_L[layer]){ + m->kv_dev_L[layer]=(float*)coli_cuda_pipe_alloc(dev,(size_t)m->max_t*kvl*4); + m->kv_dev_R[layer]=(float*)coli_cuda_pipe_alloc(dev,(size_t)m->max_t*R*4); + m->kv_dev_valid[layer]=0; + if(!m->kv_dev_L[layer]||!m->kv_dev_R[layer]) return 0; + } + int v=m->kv_dev_valid[layer]; + if(vkv_dev_L[layer]+(size_t)v*kvl, + coli_kv_row(m->kv->Lc[layer],v,kvl),(size_t)(upto-v)*kvl*4)|| + !coli_cuda_pipe_upload(dev,m->kv_dev_R[layer]+(size_t)v*R, + coli_kv_row(m->kv->Rc[layer],v,R),(size_t)(upto-v)*R*4)) return 0; + m->kv_dev_valid[layer]=upto; + } + return 1; +} + +/* Inc.1a — catena attention residente sul device del layer / attention chain + * resident on the layer home device. Proiezioni q/kv, norme, RoPE, batch + * attention e o_proj girano sulla scheda di kv_b; scaricano solo out [S,D], + * i nuovi record KV [S,kvl+R] e nulla altro. Ritorna 0 su qualsiasi errore: + * il chiamante riesegue il percorso CPU (idempotente). */ +static int attn_pipe_prefill(Model *m, Layer *l, int layer, const float *x, int x_is_dev, + int S, int pos_base, float *out, float *out_dev){ + Cfg *c=&m->c; int H=c->n_heads, D=c->hidden, qh=c->qk_head; + int kvl=c->kv_lora, R=c->qk_rope, ql=c->q_lora; + int dev=l->kv_b.cuda_device; + if(l->q_a.cuda_device!=dev||l->q_b.cuda_device!=dev|| + l->kv_a.cuda_device!=dev||l->o.cuda_device!=dev) return 0; + int st0=m->kv_start[layer], T=pos_base+S-st0, old=pos_base-st0; + if(T8192) return 0; + double t0=now_s(); + size_t xb=(size_t)S*D*4, qrb=(size_t)S*ql*4, qb=(size_t)S*H*qh*4; + size_t cb=(size_t)S*(kvl+R)*4, lb=(size_t)T*kvl*4, rb=(size_t)T*R*4; + float *chost=NULL; int ok=0; + /* scratch persistenti (slot fissi per device): zero churn di cudaMalloc */ + float *xd =x_is_dev?(float*)x:coli_cuda_pipe_scratch(dev,0,xb); + float *qrd=coli_cuda_pipe_scratch(dev,1,qrb); + float *qd =coli_cuda_pipe_scratch(dev,2,qb), *cd =coli_cuda_pipe_scratch(dev,3,cb); + float *ld_=coli_cuda_pipe_scratch(dev,4,lb), *rd =coli_cuda_pipe_scratch(dev,5,rb); + float *w1 =coli_cuda_pipe_scratch(dev,6,(size_t)ql*4); + float *w2 =coli_cuda_pipe_scratch(dev,7,(size_t)kvl*4); + chost=(float*)malloc(cb); + if(!xd||!qrd||!qd||!cd||!ld_||!rd||!w1||!w2||!chost) goto done; + if((!x_is_dev&&!coli_cuda_pipe_upload(dev,xd,x,xb))|| + !coli_cuda_pipe_upload(dev,w1,l->q_a_ln,(size_t)ql*4)|| + !coli_cuda_pipe_upload(dev,w2,l->kv_a_ln,(size_t)kvl*4)) goto done; + /* proiezioni + norme + rope, tutto sul device */ + if(!coli_cuda_pipe_gemm(l->q_a.cuda,qrd,xd,S)) goto done; + if(!coli_cuda_pipe_rmsnorm(dev,qrd,qrd,w1,S,ql,c->eps)) goto done; + if(!coli_cuda_pipe_gemm(l->q_b.cuda,qd,qrd,S)) goto done; + if(!coli_cuda_pipe_rope_base(dev,qd,pos_base,S*H,qh,c->qk_nope,R,H,c->theta)) goto done; + if(!coli_cuda_pipe_gemm(l->kv_a.cuda,cd,xd,S)) goto done; + if(!coli_cuda_pipe_rmsnorm_s(dev,cd,cd,w2,S,kvl,c->eps,kvl+R,kvl+R)) goto done; + if(!coli_cuda_pipe_rope_base(dev,cd,pos_base,S,kvl+R,kvl,R,1,c->theta)) goto done; + /* cache latente [T,kvl] + rot [T,R] contigue: righe vecchie da host, nuove da cd */ + if(old>0){ + if(!coli_cuda_pipe_upload(dev,ld_,coli_kv_row(m->Lc[layer],st0,kvl),(size_t)old*kvl*4)|| + !coli_cuda_pipe_upload(dev,rd,coli_kv_row(m->Rc[layer],st0,R),(size_t)old*R*4)) goto done; + } + if(!coli_cuda_pipe_copy2d(dev,ld_+(size_t)old*kvl,kvl,cd,kvl+R,kvl,S)) goto done; + if(!coli_cuda_pipe_copy2d(dev,rd+(size_t)old*R,R,cd+kvl,kvl+R,R,S)) goto done; + /* KV host resta canonica: scarica i record nuovi (gia' normati+ropati) */ + if(!coli_cuda_pipe_download(dev,cd,chost,cb)) goto done; + for(int s=0;sLc[layer],pos_base+s,kvl),chost+(size_t)s*(kvl+R),kvl*4); + memcpy(coli_kv_row(m->Rc[layer],pos_base+s,R),chost+(size_t)s*(kvl+R)+kvl,R*4); + } + if(m->kv_dev_valid[layer]>pos_base) m->kv_dev_valid[layer]=pos_base; + m->t_aproj+=now_s()-t0; t0=now_s(); +#ifdef COLI_CUDA + /* Negativo (2026-07-13): P2P a stella dal device di casa serializza ~95MB/layer + * sul suo link PCIe — attention 26->41-44s. Resta opt-in per topologie NVLink. */ + if(out_dev && l->n_kv_b_shard>1 && + getenv("COLI_CUDA_PIPE_SHARD") && atoi(getenv("COLI_CUDA_PIPE_SHARD"))){ + /* head-shard nel pipeline: q gia' sul device di casa. Per ogni scheda: + * slice di q (repack strided->contiguo), broadcast latent+rope via P2P, + * score parallelo sui rispettivi head, ctx slice riportata a casa e + * ricomposta, poi o_proj residente. */ + int n=l->n_kv_b_shard, vh=c->v_head; + size_t ctxb=(size_t)S*H*vh*4; + size_t stage_one=(size_t)S*H*(size_t)(c->qk_head>vh?c->qk_head:vh)*4; + float *ctx_full=coli_cuda_pipe_scratch(dev,16,ctxb); + float *stage=coli_cuda_pipe_scratch(dev,17,stage_one*n); + int ok_sh=(ctx_full&&stage)?1:0; + if(ok_sh){ + #pragma omp parallel for schedule(static) reduction(&:ok_sh) + for(int d2=0;d2shard_hn[d2], h0=l->shard_h0[d2]; + int sdev=coli_cuda_tensor_device(l->kv_b_shard[d2]); + float *st=stage+(size_t)d2*(stage_one/4); + size_t qsb=(size_t)S*hn*qh*4, csb=(size_t)S*hn*vh*4; + float *qs_r=coli_cuda_pipe_scratch(sdev,18,qsb); + float *ld_r=coli_cuda_pipe_scratch(sdev,19,(size_t)T*kvl*4); + float *rr_r=coli_cuda_pipe_scratch(sdev,20,(size_t)T*R*4); + float *cx_r=coli_cuda_pipe_scratch(sdev,21,csb); + int okd=qs_r&&ld_r&&rr_r&&cx_r; + /* slice di q: [S,H,qh] -> [S,hn,qh] contigua sul device di casa */ + okd=okd&&coli_cuda_pipe_copy2d(dev,st,hn*qh,qd+(size_t)h0*qh,H*qh,hn*qh,S); + okd=okd&&coli_cuda_pipe_peer_copy(sdev,qs_r,dev,st,qsb); + okd=okd&&coli_cuda_pipe_peer_copy(sdev,ld_r,dev,ld_,(size_t)T*kvl*4); + okd=okd&&coli_cuda_pipe_peer_copy(sdev,rr_r,dev,rd,(size_t)T*R*4); + okd=okd&&coli_cuda_attention_absorb_batch_dev(l->kv_b_shard[d2],cx_r,qs_r,ld_r,rr_r, + S,hn,c->qk_nope,R,vh,kvl,T,c->attn_scale); + okd=okd&&coli_cuda_pipe_peer_copy(dev,st,sdev,cx_r,csb); + okd=okd&&coli_cuda_pipe_copy2d(dev,ctx_full+(size_t)h0*vh,H*vh,st,hn*vh,hn*vh,S); + ok_sh&=okd; + } + } + if(ok_sh){ + ok=coli_cuda_pipe_gemm(l->o.cuda,out_dev,ctx_full,S)&&coli_cuda_pipe_sync(dev); + } else ok=0; + if(!ok) + ok=coli_cuda_attention_project_batch_dev_out(l->kv_b.cuda,l->o.cuda,out_dev,qd,ld_,rd, + S,H,c->qk_nope,R,c->v_head,kvl,T,c->attn_scale); + } else +#endif + ok=out_dev?coli_cuda_attention_project_batch_dev_out(l->kv_b.cuda,l->o.cuda,out_dev,qd,ld_,rd, + S,H,c->qk_nope,R,c->v_head,kvl,T,c->attn_scale) + :coli_cuda_attention_project_batch_dev(l->kv_b.cuda,l->o.cuda,out,qd,ld_,rd, + S,H,c->qk_nope,R,c->v_head,kvl,T,c->attn_scale); + m->t_acore+=now_s()-t0; +done: + free(chost); /* gli scratch device restano al contesto */ + return ok; +} +#endif + static void attention_rows(Model *m, Layer *l, int layer, float *x, int S, int pos_base, KVState *const *kvs, const int *positions, float *out){ Cfg *c=&m->c; int H=c->n_heads, D=c->hidden, qh=c->qk_head, vh=c->v_head; @@ -1631,12 +1817,24 @@ static void attention_rows(Model *m, Layer *l, int layer, float *x, int S, int p * batch-union. matmul_qt_ex(...,0) keeps them on the EXACT int4 kernel: letting S>1 pull * them into IDOT is much faster but costs ~12% perplexity (measured). Batching alone is * bit-identical to upstream; the kernel switch is not. */ - matmul_qt_ex(QR, x, &l->q_a, S, 0); - for(int s=0;sq_lora; - rmsnorm(qr, qr, l->q_a_ln, c->q_lora, c->eps); } /* q_b legge il residuo NORMATO */ - matmul_qt_ex(Q, QR, &l->q_b, S, 0); - matmul_qt_ex(comp, x, &l->kv_a, S, 0); - for(int s=0;s=8&&layern_layers&&g_cuda_enabled&&c->kv_lora<=512&& + !(m->has_dsa&&pos_base+S>c->index_topk)&& + l->q_a.cuda_eligible&&l->q_b.cuda_eligible&&l->kv_a.cuda_eligible&& + l->kv_b.cuda_eligible&&l->o.cuda_eligible&& + qt_cuda_upload(&l->q_a)&&qt_cuda_upload(&l->q_b)&&qt_cuda_upload(&l->kv_a)&& + qt_cuda_upload(&l->kv_b)&&qt_cuda_upload(&l->o)) + pipe_done=attn_pipe_prefill(m,l,layer,x,0,S,pos_base,out,NULL); +#endif + if(!pipe_done){ + matmul_qt_ex(QR, x, &l->q_a, S, 0); + for(int s=0;sq_lora; + rmsnorm(qr, qr, l->q_a_ln, c->q_lora, c->eps); } /* q_b legge il residuo NORMATO */ + matmul_qt_ex(Q, QR, &l->q_b, S, 0); + matmul_qt_ex(comp, x, &l->kv_a, S, 0); + } + if(!pipe_done) for(int s=0;skv; int pos=positions?positions[s]:pos_base+s; float *qfull=Q+(int64_t)s*H*qh; @@ -1644,6 +1842,10 @@ static void attention_rows(Model *m, Layer *l, int layer, float *x, int S, int p const float *cs=comp+(int64_t)s*cw; float *Ldst=coli_kv_row(ks->Lc[layer],pos,c->kv_lora); float *Rdst=coli_kv_row(ks->Rc[layer],pos,c->qk_rope); +#ifdef COLI_CUDA + if(ks==m->kv&&m->kv_dev_valid&&layer<=c->n_layers&&m->kv_dev_valid[layer]>pos) + m->kv_dev_valid[layer]=pos; /* riga riscritta: l'ombra si accorcia */ +#endif memcpy(Ldst, cs, c->kv_lora*sizeof(float)); rmsnorm(Ldst, Ldst, l->kv_a_ln, c->kv_lora, c->eps); /* latente normato */ memcpy(Rdst, cs+c->kv_lora, c->qk_rope*sizeof(float)); @@ -1720,7 +1922,17 @@ static void attention_rows(Model *m, Layer *l, int layer, float *x, int S, int p * k/v per ogni token del contesto. Per linearita': * q·k_nope_t = (W_K^hT q_nope)·L_t ctx^h = W_V^h (Σ_t a_t L_t) * costo per step ~O(T·kv_lora) invece di O(T·H·(nope+vh)) del matmul kvb_all. */ - int absorb = kvs || g_absorb==1 || (g_absorb<0 && S<=4); + if(pipe_done){ + free(ctx); free(Q); free(QR); free(comp); + m->t_attn += now_s()-ta0; + return; + } + int cuda_absorb=0; +#ifdef COLI_CUDA + cuda_absorb=layern_layers&&!kvs&&g_cuda_enabled&&getenv("COLI_CUDA_ATTN")&& + atoi(getenv("COLI_CUDA_ATTN"))&&c->kv_lora<=512; +#endif + int absorb = kvs || g_absorb==1 || (g_absorb<0 && S<=4) || cuda_absorb; if(absorb && c->kv_lora<=512){ m->t_aproj+=now_s()-ta0; double tac=now_s(); int kvl=c->kv_lora, r0v=c->qk_nope; /* offset righe V dentro il blocco di testa */ @@ -1739,19 +1951,48 @@ static void attention_rows(Model *m, Layer *l, int layer, float *x, int S, int p if(nt>sc_cap) sc_cap=nt; } float *sc_all = falloc((int64_t)omp_get_max_threads()*sc_cap); - int cuda_core=0; + int cuda_core=0,cuda_projected=0; #ifdef COLI_CUDA - if(S<=4&&g_cuda_enabled&&getenv("COLI_CUDA_ATTN")&&atoi(getenv("COLI_CUDA_ATTN"))&& + if(cuda_absorb&&l->n_kv_b_shard>1){ + int n=l->n_kv_b_shard,st0=m->kv_start[layer],nt=pos_base+S-st0,ok=1; + float *qs=falloc((int64_t)S*H*qh),*cs=falloc((int64_t)S*H*vh); + for(int d=0;dshard_h0[d]*S*qh+(int64_t)s*l->shard_hn[d]*qh, + Q+((int64_t)s*H+l->shard_h0[d])*qh,(size_t)l->shard_hn[d]*qh*sizeof(float)); + #pragma omp parallel for schedule(static) reduction(&:ok) + for(int d=0;dkv_b_shard[d], + cs+(int64_t)l->shard_h0[d]*S*vh,qs+(int64_t)l->shard_h0[d]*S*qh, + coli_kv_row(m->Lc[layer],st0,kvl),coli_kv_row(m->Rc[layer],st0,c->qk_rope), + S,l->shard_hn[d],c->qk_nope,c->qk_rope,vh,kvl,nt,c->attn_scale); + if(ok)for(int d=0;dshard_h0[d])*vh, + cs+(int64_t)l->shard_h0[d]*S*vh+(int64_t)s*l->shard_hn[d]*vh, + (size_t)l->shard_hn[d]*vh*sizeof(float)); + free(qs);free(cs);cuda_core=ok; + } else if(cuda_absorb&&l->kv_b.cuda_eligible&&l->o.cuda_eligible&& + qt_cuda_upload(&l->kv_b)&&qt_cuda_upload(&l->o)){ + int st0=m->kv_start[layer],nt=pos_base+S-st0; + cuda_core=cuda_projected=coli_cuda_attention_project_batch(l->kv_b.cuda,l->o.cuda,out,Q, + coli_kv_row(m->Lc[layer],st0,kvl),coli_kv_row(m->Rc[layer],st0,c->qk_rope), + S,H,c->qk_nope,c->qk_rope,vh,kvl,nt,c->attn_scale); + } else if(S<=4&&g_cuda_enabled&&getenv("COLI_CUDA_ATTN")&&atoi(getenv("COLI_CUDA_ATTN"))&& l->kv_b.cuda_eligible&&qt_cuda_upload(&l->kv_b)){ cuda_core=1; for(int s=0;skv;int pos=positions?positions[s]:pos_base+s; int st0=ks->kv_start[layer],nt=pos+1-st0; if(dnsel&&dnsel[s]>0){cuda_core=0;break;} - cuda_core=coli_cuda_attention_absorb(l->kv_b.cuda,ctx+(int64_t)s*H*vh, - Q+(int64_t)s*H*qh,coli_kv_row(ks->Lc[layer],st0,kvl), - coli_kv_row(ks->Rc[layer],st0,c->qk_rope),H,c->qk_nope,c->qk_rope, - vh,kvl,nt,c->attn_scale); + cuda_core=0; + if(g_cuda_pipe&&ks==m->kv&&layern_layers&&kv_dev_sync(m,l,layer,pos+1)) + cuda_core=coli_cuda_attention_absorb_kvdev(l->kv_b.cuda,ctx+(int64_t)s*H*vh, + Q+(int64_t)s*H*qh,m->kv_dev_L[layer]+(size_t)st0*kvl, + m->kv_dev_R[layer]+(size_t)st0*c->qk_rope,H,c->qk_nope,c->qk_rope, + vh,kvl,nt,c->attn_scale); + if(!cuda_core) + cuda_core=coli_cuda_attention_absorb(l->kv_b.cuda,ctx+(int64_t)s*H*vh, + Q+(int64_t)s*H*qh,coli_kv_row(ks->Lc[layer],st0,kvl), + coli_kv_row(ks->Rc[layer],st0,c->qk_rope),H,c->qk_nope,c->qk_rope, + vh,kvl,nt,c->attn_scale); } } #endif @@ -1786,7 +2027,7 @@ static void attention_rows(Model *m, Layer *l, int layer, float *x, int S, int p } } m->t_acore+=now_s()-tac; double tao=now_s(); - matmul_qt(out, ctx, &l->o, S); m->t_aout+=now_s()-tao; + if(!cuda_projected){matmul_qt(out, ctx, &l->o, S);} m->t_aout+=now_s()-tao; free(ctx); free(Q); free(QR); free(comp); free(sc_all); m->t_attn += now_s()-ta0; return; @@ -1840,7 +2081,7 @@ static void attention(Model *m, Layer *l, int layer, float *x, int S, int pos_ba * una volta sola e moltiplicato per tutte le posizioni che lo usano (pesi letti 1 volta); * lo shared expert e' un unico matmul a S righe. Per posizione l'accumulo resta * nell'ordine (routed nel loro ordine di union, poi shared). */ -static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out){ +static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out, int with_shared){ if(g_pilot_real){ /* barriera cross-layer: prendi possesso di QUESTO layer e aspetta * l'eventuale load-pilota in volo sullo stesso layer (dopodiche' il * worker droppa ogni nuovo load <= layer -> ecache[layer] e' stabile @@ -1855,11 +2096,14 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out){ } } Cfg *c=&m->c; int D=c->hidden, E=c->n_experts, K=c->topk, I=c->moe_inter; - float *logit=falloc(E), *choice=falloc(E); + float *choice=falloc(E); int sI=c->moe_inter*c->n_shared; /* ---- FASE A: routing di tutte le S posizioni ---- */ int *idxs=malloc((size_t)S*K*sizeof(int)); float *ws=malloc((size_t)S*K*sizeof(float)); int *keff=malloc(S*sizeof(int)); + /* router in UN matmul batch: stessa matematica, via le S chiamate S=1 */ + float *logits_all=falloc((int64_t)S*E); + int pre_routed=0; (void)pre_routed; #ifdef COLI_METAL if(g_pre_idx){ /* routing gia' calcolata dal layer CB (GPU) */ memcpy(idxs,g_pre_idx,(size_t)S*K*sizeof(int)); @@ -1874,11 +2118,13 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out){ } for(int d=0;drouter, S, D, E); + if(!pre_routed) for(int s=0;srouter, 1, D, E); + float *logit=logits_all+(int64_t)s*E; for(int e=0;erouter_bias[e]; } int *idx=idxs+(int64_t)s*K; float *w=ws+(int64_t)s*K; int Ksel = g_topk>0 ? (g_topkws[q]; m->ws[q]=tmp; dst->used=(uint64_t)__atomic_add_fetch(&m->eclock,1,__ATOMIC_RELAXED); } } } - /* ---- FASE E: shared expert, un matmul a S righe (skipped se fuso nel blocco GPU) ---- */ - float *sg=falloc((int64_t)S*sI), *su=falloc((int64_t)S*sI); + /* ---- FASE E: shared expert (PIPE2: gia' sul device; Metal CB: gia' sommata) ---- */ + if(!with_shared) goto shared_done; + { + float *sg=NULL,*su=NULL;int shared_cuda=0; #ifdef COLI_METAL if(g_pre_sh){ for(int64_t z=0;z<(int64_t)S*D;z++) out[z]+=g_pre_sh[z]; shared_on_gpu=1; } + if(shared_on_gpu) shared_cuda=2; /* gia' sommato in out: salta calcolo e add */ #endif - if(!shared_on_gpu){ +#ifdef COLI_CUDA + int shared_min=getenv("COLI_CUDA_SHARED_W4A16_MIN_ROWS")? + atoi(getenv("COLI_CUDA_SHARED_W4A16_MIN_ROWS")):32; + if(shared_min<16)shared_min=16; + if(shared_cuda==0&&S>=shared_min&&!l->shared_w4a16_failed&&!omp_in_parallel()&&g_cuda_enabled&& + l->sh_gate.fmt==2&&l->sh_up.fmt==2&&l->sh_down.fmt==2&& + getenv("COLI_CUDA_SHARED_W4A16")&&atoi(getenv("COLI_CUDA_SHARED_W4A16"))&& + qt_cuda_upload(&l->sh_gate)&&qt_cuda_upload(&l->sh_up)&&qt_cuda_upload(&l->sh_down)){ + shared_cuda=coli_cuda_shared_mlp_w4a16(l->sh_gate.cuda,l->sh_up.cuda, + l->sh_down.cuda,hh,x,S); + if(!shared_cuda)l->shared_w4a16_failed=1; + } +#endif + if(!shared_cuda){ + sg=falloc((int64_t)S*sI);su=falloc((int64_t)S*sI); matmul_qt(sg, x, &l->sh_gate, S); matmul_qt(su, x, &l->sh_up, S); for(int64_t z=0;z<(int64_t)S*sI;z++) sg[z]=siluf(sg[z])*su[z]; matmul_qt(hh, sg, &l->sh_down, S); - for(int64_t z=0;z<(int64_t)S*D;z++) out[z]+=hh[z]; } - free(logit); free(choice); free(idxs); free(ws); free(keff); free(uniq); - free(xg); free(gg); free(uu); free(hh); free(rows); free(rw); free(sg); free(su); + if(shared_cuda!=2) for(int64_t z=0;z<(int64_t)S*D;z++) out[z]+=hh[z]; + free(sg); free(su); + } +shared_done: + free(logits_all); free(choice); free(idxs); free(ws); free(keff); free(uniq); + free(xg); free(gg); free(uu); free(hh); free(rows); free(rw); #ifdef COLI_CUDA - free(group_x); free(group_y); free(group_row); free(group_weight); + free(group_x);free(group_y); + free(group_row); free(group_weight); #endif } @@ -2393,6 +2663,65 @@ static void pilot_prefetch(Model *m, int lnext, const float *x, int S){ } /* forward di UN layer (usato dai 78 principali e dal layer MTP) */ +#ifdef COLI_CUDA +/* Inc.2a — intero layer SPARSO residente sul device del layer. x_dev entra e resta; + * lasciano il device solo: nrm post-attention (router + expert CPU + gather dei + * gruppi), i nuovi record KV, e la nrm pre-attention sui layer con indexer DSA. + * Ritorna 0 su errore: il chiamante ripristina lo snapshot e rifa' il layer su CPU. */ +static int pipe_layer_sparse(Model *m, Layer *l, int li, float *x_dev, int S, int pos_base, + float *nrm_host, float *out_host){ + Cfg *c=&m->c; int D=c->hidden, dev=l->kv_b.cuda_device; + int sI=c->moe_inter*c->n_shared; + size_t xb=(size_t)S*D*4; + if(!l->sh_gate.cuda_eligible||!l->sh_up.cuda_eligible||!l->sh_down.cuda_eligible|| + !qt_cuda_upload(&l->sh_gate)||!qt_cuda_upload(&l->sh_up)||!qt_cuda_upload(&l->sh_down)|| + l->sh_gate.cuda_device!=dev||l->sh_up.cuda_device!=dev||l->sh_down.cuda_device!=dev) return 0; + float *w_in =coli_cuda_pipe_scratch(dev,8,(size_t)D*4); + float *w_post=coli_cuda_pipe_scratch(dev,9,(size_t)D*4); + float *nrm_d=coli_cuda_pipe_scratch(dev,10,xb); + float *y_d =coli_cuda_pipe_scratch(dev,11,xb); + float *sg_d =coli_cuda_pipe_scratch(dev,12,(size_t)S*sI*4); + float *su_d =coli_cuda_pipe_scratch(dev,13,(size_t)S*sI*4); + float *snap =coli_cuda_pipe_scratch(dev,14,xb); + if(!w_in||!w_post||!nrm_d||!y_d||!sg_d||!su_d||!snap) return 0; + if(!coli_cuda_pipe_peer_copy(dev,snap,dev,x_dev,xb)) return 0; /* snapshot per il fallback */ + if(!coli_cuda_pipe_upload(dev,w_in,l->in_ln,(size_t)D*4)|| + !coli_cuda_pipe_upload(dev,w_post,l->post_ln,(size_t)D*4)) return 0; + double ta=now_s(); + if(!coli_cuda_pipe_rmsnorm(dev,nrm_d,x_dev,w_in,S,D,c->eps)) return 0; + /* DSA: i layer con indexer FULL cachano k_idx dalla nrm pre-attention (CPU, piccolo) */ + if(m->has_dsa && lin_layers && m->kv_start[li]==0 && c->idx_type[li]){ + if(!coli_cuda_pipe_download(dev,nrm_d,nrm_host,xb)) return 0; + int nh=c->index_nh, hd=c->index_hd; (void)nh; + for(int s=0;skv->Ic[li],pos,hd); + matmul_qt(kd, nrm_host+(int64_t)s*D, &m->ix_wk[li], 1); + layernorm(kd, m->ix_knw[li], m->ix_knb[li], hd, 1e-6f); + rope_interleave(kd, pos, c); + } + } + if(!attn_pipe_prefill(m,l,li,nrm_d,1,S,pos_base,NULL,y_d)) return 0; + if(!coli_cuda_pipe_add(dev,x_dev,y_d,(size_t)S*D)) return 0; /* prima mutazione */ + if(!coli_cuda_pipe_rmsnorm(dev,nrm_d,x_dev,w_post,S,D,c->eps)) return 0; + if(!coli_cuda_pipe_download(dev,nrm_d,nrm_host,xb)) return 0; + m->t_attn+=now_s()-ta; + /* expert routed su CPU/gruppi GPU come oggi (shared saltata: la fa il device) */ + moe(m,l,li,nrm_host,S,out_host,0); + double te=now_s(); + if(!coli_cuda_pipe_upload(dev,y_d,out_host,xb)) return 0; + if(!coli_cuda_pipe_add(dev,x_dev,y_d,(size_t)S*D)) return 0; + if(!coli_cuda_pipe_gemm(l->sh_gate.cuda,sg_d,nrm_d,S)) return 0; + if(!coli_cuda_pipe_gemm(l->sh_up.cuda,su_d,nrm_d,S)) return 0; + if(!coli_cuda_pipe_silu_mul(dev,sg_d,su_d,(size_t)S*sI)) return 0; + if(!coli_cuda_pipe_gemm(l->sh_down.cuda,y_d,sg_d,S)) return 0; + if(!coli_cuda_pipe_add(dev,x_dev,y_d,(size_t)S*D)) return 0; + if(!coli_cuda_pipe_sync(dev)) return 0; + m->t_emm+=now_s()-te; + return 1; +} +#endif + static void layer_forward_rows(Model *m, Layer *l, int li, float *x, int S, int pos_base, KVState *const *kvs, const int *positions, float *nrm, float *tmp){ Cfg *c=&m->c; int D=c->hidden; @@ -2459,7 +2788,7 @@ static void layer_forward_rows(Model *m, Layer *l, int li, float *x, int S, int if(g_pilot && S<=8 && li+1n_layers && m->L[li+1].sparse) pilot_prefetch(m,li+1,x,S); if(g_looka && S==1 && li+1n_layers && m->L[li+1].sparse) la_predict(m,li+1,x,1); for(int s=0;spost_ln, D, c->eps); - if(l->sparse) moe(m,l,li,nrm,S,tmp); else dense_mlp(l,nrm,S,D,c->dense_inter,tmp); + if(l->sparse) moe(m,l,li,nrm,S,tmp,1); else dense_mlp(l,nrm,S,D,c->dense_inter,tmp); for(int64_t j=0;j<(int64_t)S*D;j++) x[j]+=tmp[j]; } static void layer_forward(Model *m, Layer *l, int li, float *x, int S, int pos_base, float *nrm, float *tmp){ @@ -2474,13 +2803,53 @@ static void layers_forward_rows(Model *m, float *x, int S, int pos_base, pthread_mutex_unlock(&g_pilot_mx); } float *nrm=falloc((int64_t)S*D), *tmp=falloc((int64_t)S*D); +#ifdef COLI_CUDA + /* PIPE2 (Inc.2a): il residuo resta sul device del layer, saltando tra le schede + * ai confini di layer. x host diventa STALE finche' la residenza e' attiva. */ + float *x_dev=NULL; int x_dev_on=-1; + size_t xb=(size_t)S*(size_t)D*4; + int pipe2 = g_cuda_pipe>=2 && !kvs && S>=8 && g_cuda_enabled && c->kv_lora<=512 && + !(m->has_dsa && pos_base+S>c->index_topk); +#endif for(int i=0;in_layers;i++){ /* progresso su stderr per i batch grossi (prefill): il primo byte di risposta * puo' arrivare dopo MINUTI di streaming — al buio sembra un blocco. */ if(S>=8 && (i%4==0 || i==c->n_layers-1)) fprintf(stderr,"[prefill] layer %d/%d · %d token\n", i+1, c->n_layers, S); +#ifdef COLI_CUDA + Layer *l=&m->L[i]; + if(pipe2 && l->sparse && in_layers && + l->q_a.cuda_eligible&&l->q_b.cuda_eligible&&l->kv_a.cuda_eligible&& + l->kv_b.cuda_eligible&&l->o.cuda_eligible&& + qt_cuda_upload(&l->q_a)&&qt_cuda_upload(&l->q_b)&&qt_cuda_upload(&l->kv_a)&& + qt_cuda_upload(&l->kv_b)&&qt_cuda_upload(&l->o)&& + l->q_a.cuda_device==l->kv_b.cuda_device&&l->q_b.cuda_device==l->kv_b.cuda_device&& + l->kv_a.cuda_device==l->kv_b.cuda_device&&l->o.cuda_device==l->kv_b.cuda_device){ + int dev=l->kv_b.cuda_device, ok=1; + float *dst=coli_cuda_pipe_scratch(dev,15,xb); + if(dst){ + if(x_dev_on<0) ok=coli_cuda_pipe_upload(dev,dst,x,xb); + else if(x_dev_on!=dev){ ok=coli_cuda_pipe_peer_copy(dev,dst,x_dev_on,x_dev,xb); } + else dst=x_dev; + if(ok){ + x_dev=dst; x_dev_on=dev; + if(pipe_layer_sparse(m,l,i,x_dev,S,pos_base,nrm,tmp)) continue; + /* fallback: snapshot -> host, layer rifatto sul percorso CPU */ + coli_cuda_pipe_peer_copy(dev,x_dev,dev,coli_cuda_pipe_scratch(dev,14,xb),xb); + coli_cuda_pipe_download(dev,x_dev,x,xb); + x_dev_on=-1; + }else x_dev_on=-1; + } + } else if(x_dev_on>=0){ /* layer fuori pipe: il residuo torna a casa */ + coli_cuda_pipe_download(x_dev_on,x_dev,x,xb); + x_dev_on=-1; + } +#endif layer_forward_rows(m,&m->L[i],i,x,S,pos_base,kvs,positions,nrm,tmp); } +#ifdef COLI_CUDA + if(x_dev_on>=0) coli_cuda_pipe_download(x_dev_on,x_dev,x,xb); +#endif free(nrm); free(tmp); } static void layers_forward(Model *m, float *x, int S, int pos_base){ @@ -2490,6 +2859,14 @@ static void layers_forward(Model *m, float *x, int S, int pos_base){ static void kv_alloc(Model *m, int max_t){ Cfg *c=&m->c; KVState *k=m->kv; +#ifdef COLI_CUDA + if(m->kv_dev_L) for(int i=0;in_layers+1;i++){ /* dimensioni cambiate: ombra da rifare */ + if(m->kv_dev_L[i]){ coli_cuda_pipe_free(m->L[in_layers?i:0].kv_b.cuda_device,m->kv_dev_L[i]); m->kv_dev_L[i]=NULL; } + if(m->kv_dev_R[i]){ coli_cuda_pipe_free(m->L[in_layers?i:0].kv_b.cuda_device,m->kv_dev_R[i]); m->kv_dev_R[i]=NULL; } + m->kv_dev_valid[i]=0; + } +#endif + if(k->Lc){ for(int i=0;in_layers+1;i++){ free(k->Lc[i]); free(k->Rc[i]); } free(k->Lc); free(k->Rc); } if(k->Lc){ for(int i=0;in_layers+1;i++){ #ifdef COLI_METAL if(g_metal_enabled){ coli_metal_unregister(k->Lc[i]); coli_metal_unregister(k->Rc[i]); } @@ -2522,6 +2899,8 @@ static void kv_alloc(Model *m, int max_t){ } static void kv_bind(Model *m, KVState *k){ + if(m->kv!=k && m->kv_dev_valid) /* ombra legata al KVState corrente */ + for(int i=0;ic.n_layers+1;i++) m->kv_dev_valid[i]=0; m->kv=k; m->Lc=k->Lc; m->Rc=k->Rc; m->Ic=k->Ic; m->max_t=k->max_t; m->kv_start=k->kv_start; } @@ -3034,6 +3413,7 @@ static void run_text(Model *m, const char *snap, const char *prompt, int ngen){ repin_pass_limit(m,limit); /* prompt routing seeds every GPU layer */ } prefill_t=now_s()-prefill_t; + printf("PROFILO PREFILL (%.2fs):\n",prefill_t); profile_print(m,prefill_t); m->hits=m->miss=m->ereq=m->gpu_expert_calls=0; m->n_emit=m->n_fw=0; g_last_repin=0; @@ -3329,6 +3709,7 @@ static void mux_done(Model *m, ServeCtx *sc, ServeReq *r){ double dt=now_s()-r->started; if(dt<1e-6) dt=1e-6; double dh=(double)(m->hits-r->hits0), dm=(double)(m->miss-r->miss0); hwinfo_emit(m); + usage_save(m); /* la cache che impara non deve aspettare l'uscita */ tiers_emit(m); emap_emit(m); hits_emit(m); @@ -4204,6 +4585,7 @@ int main(int argc, char **argv){ if(!g_cuda_enabled){ fprintf(stderr,"[CUDA] requested backend is unavailable\n"); return 2; } } g_cuda_dense=getenv("CUDA_DENSE")?atoi(getenv("CUDA_DENSE")):0; + g_cuda_pipe=getenv("COLI_CUDA_PIPE")?atoi(getenv("COLI_CUDA_PIPE")):0; const char *cuda_expert=getenv("CUDA_EXPERT_GB"); g_cuda_expert_auto=cuda_expert&&!strcmp(cuda_expert,"auto"); g_cuda_expert_gb=cuda_expert&&!g_cuda_expert_auto?atof(cuda_expert):0; diff --git a/c/tests/test_i4_acc512 b/c/tests/test_compat_direct similarity index 72% rename from c/tests/test_i4_acc512 rename to c/tests/test_compat_direct index 76f68a3e70a9375bd3b0c6f710f7af09dd687e68..074a7baf262a18295a974bd917c31d4e8f22ee46 100755 GIT binary patch delta 870 zcmX?6ccE^A2IGW{n&OO{GK>shATwEzQFwC<7%_q^7p=4oiSxrez%ran18w;-`ZAtkdYHMvBgB(=Dt*h--|JF}o5HAO)qz(3eC zLLnouSRpU5B(p44!9U)`Gsx9BL=$8SqcpR%0gz?|;ydsE|4#wZe}HrkkmmXD|Njyo zEd!+Y0BIW_?E|DmfEWZAtAZF9D+DIjD+n^am^@KIoUvf?N(FVsjL8>)>;xbw%nC9m zVl$)SdY;WYbYCzrYD`{eATDVP6lG!%VAvo4G6w-nCtn20dH@ALvI>F-84xROGNYlm zWEPOc$RNgWz!p_@;$%ah>|C&{D8mjk**ze8p|+m}s}W(4P((EWtY-27LkZ8DU=`vF zC(ulJ1lAzT0E-!z{;y#55)3=+VImNkd$OXDII9LQiWMerWD;g9pB!i;&gcRXWelC% zXe6E*1C$eD5@g6h^J@}NT#!ka!9xMn#8RNR0D~k0g9EB~6Aty$fZ`ClmrfQm7MI)v zQpX?!6olw!ff_S$vLjHo8Yn9SG`|5FFKSTPgOdw^vS*>P2~b&SsO+W53ysB1?}1Fl z;^I#@#Mzl(E>oP$Xd=#NGg;C^pBIvr;~{BzbD&8%^W+0eESpc5C$KO&PS&*1=Y)m5 h%j85GbIu9{h$AXCFSK!IVsx7P($1W*XtJWcIsij2o1p*z delta 854 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 diff --git a/c/tests/test_idot b/c/tests/test_idot deleted file mode 100755 index bab981f1a6ada6fb0c07bc449ef2f2a0a4c9ef93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 239888 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 z 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�++g`cKRSuLszuJ3qmYyu;^FBzla&6>P%h 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 diff --git a/c/tests/test_pipe_cuda.cu b/c/tests/test_pipe_cuda.cu new file mode 100644 index 0000000..f20a9e5 --- /dev/null +++ b/c/tests/test_pipe_cuda.cu @@ -0,0 +1,137 @@ +/* Unit tests for the resident-pipeline primitives (Inc.0). + * Each primitive is checked against the exact CPU math from glm.c. + * Build: nvcc backend_cuda.cu tests/test_pipe_cuda.cu -o pipe_test && ./pipe_test */ +#include +#include +#include +#include +#include +#include "../backend_cuda.h" + +static uint64_t rng=0x9E3779B97F4A7C15ULL; +static float rndf(void){ rng^=rng<<13; rng^=rng>>7; rng^=rng<<17; + return (float)((double)(rng>>11)/9007199254740992.0*2.0-1.0); } + +static void ref_rmsnorm(float *out,const float *x,const float *w,int D,float eps){ + double ms=0; for(int i=0;i1.f?fabsf(b[i]):1.f; + if(d/m>worst) worst=d/m; + } + printf(" %-14s max rel %.3e %s\n",what,worst,worst<=tol?"ok":"FAIL"); + return worst<=tol; +} + +int main(void){ + int dev0=0; + if(!coli_cuda_init(&dev0,1)){ puts("pipe tests: skipped (no CUDA device)"); return 0; } + int ok=1; + enum { S=7, D=6144, I=2048, R=64, H=4, QH=192 }; + + /* rmsnorm */ + { + float *x=(float*)malloc((size_t)S*D*4), *w=(float*)malloc(D*4); + float *got=(float*)malloc((size_t)S*D*4), *ref=(float*)malloc((size_t)S*D*4); + for(size_t i=0;i<(size_t)S*D;i++) x[i]=rndf()*3; + for(int i=0;iljS8i=U>)lWXer-vtmAoNg| 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 literal 0 HcmV?d00001 diff --git a/c/tools/bench_ux.sh b/c/tools/bench_ux.sh new file mode 100755 index 0000000..73fbc3f --- /dev/null +++ b/c/tools/bench_ux.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# Unified user-experience benchmark: fixed scenarios, fixed decoding, medians. +# +# Reports, per scenario: TTFT (prefill wall), decode tok/s, and the first line +# of the generated text (drift check). Runs each scenario REPS times and prints +# every sample; judge by the median, not the best. +# +# Usage: SNAP=/path/to/model [REPS=3] [PIPE=2] tools/bench_ux.sh [engine-binary] +# The engine env (COLI_CUDA, PIN, ...) is inherited from the caller so the same +# script exercises CPU-only, CUDA and pipeline configurations. +# +# Discipline (docs/experiments/glm52-6x5090-2026-07-12.md): +# - TEMP=0 DRAFT=0 always: greedy, no speculation, one variable at a time. +# - Same binary for every configuration under comparison. +# - .coli_usage drifts placement between runs: compare medians of >=3 reps, +# or snapshot/restore the usage file around the battery. +set -u +GLM="${1:-./glm}" +REPS="${REPS:-3}" +export TEMP=0 DRAFT=0 +[ -n "${PIPE:-}" ] && export COLI_CUDA_PIPE="$PIPE" + +SHORT_PROMPT="Explain why the sky is blue in simple terms." +LONGDOC_PROMPT=$(python3 - <<'PY' +base=("蜂鸟是世界上最小的鸟类之一,主要分布在美洲大陆。它们的翅膀每秒可以扇动五十到八十次," +"使它们能够在空中悬停、倒飞,甚至垂直起降。蜂鸟的新陈代谢极快,心跳每分钟可达一千两百次," +"因此它们必须不断进食来维持能量。它们的主要食物是花蜜,同时也会捕食小型昆虫和蜘蛛来补充蛋白质。" +"蜂鸟的喙细长,适合深入花朵内部吸食花蜜,舌头呈管状,可以快速伸缩。在授粉过程中," +"蜂鸟扮演着重要的角色,许多美洲植物依赖蜂鸟传粉。") +print((base*12)+"请根据上文回答:蜂鸟的主要食物是什么?") +PY +) + +scenario(){ # name prompt ngen + local name=$1 prompt=$2 ngen=$3 + for r in $(seq 1 "$REPS"); do + local log; log=$(mktemp) + NGEN=$ngen PROMPT="$prompt" "$GLM" 64 4 4 >"$log" 2>&1 + local line; line=$(grep -aE "prefill .* decode .*tok/s" "$log" | tail -1) + local head; head=$(grep -av "^\[" "$log" | grep -avE "PROFILE|PROFILO|ATTENTION|expert|CUDA|prefill|specul|^---|TOPP|stop|Motore|caricato|prompt:|token" \ + | tail -1 | tr -d '\n' | cut -c1-48) + printf "%-10s r%d %s\n" "$name" "$r" "$line" + printf "%-10s r%d text: %s\n" "$name" "$r" "$head" + rm -f "$log" + done +} + +echo "== bench_ux: reps=$REPS pipe=${COLI_CUDA_PIPE:-unset} $(date +%F' '%T) ==" +scenario chat "$SHORT_PROMPT" 96 +scenario longdoc "$LONGDOC_PROMPT" 96 +echo "== bench_ux done $(date +%T) ==" diff --git a/c/tools/expert_atlas.py b/c/tools/expert_atlas.py new file mode 100644 index 0000000..dd0a2d6 --- /dev/null +++ b/c/tools/expert_atlas.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +"""Expert Atlas (#175): measure per-expert topic affinity by diffing .coli_usage +across themed probe batches, served through a running colibri API server. + +Protocol per category: snapshot .coli_usage -> send probes -> snapshot again; +the delta is that category's expert-activation spectrum. One engine load total. + +Output: experts.json — for every (layer, expert): counts per category, +normalized affinity, entropy, and a "specialist" label when one topic dominates. + +Usage (server already running with the model): + python3 tools/expert_atlas.py --api http://127.0.0.1:8000 \ + --usage /path/to/model/.coli_usage --out experts.json --ngen 64 +""" +import argparse, json, math, time, urllib.request + +PROBES = { + "code": [ + "Write a Python function that parses a CSV file and returns a dict keyed by the first column.", + "Explain the difference between a mutex and a semaphore, with a C example.", + "Refactor this into idiomatic Rust: for i in range(len(xs)): total += xs[i] * 2", + ], + "math": [ + "Prove that the square root of 2 is irrational.", + "Compute the derivative of x^3 * ln(x) and explain each step.", + "A fair die is rolled 4 times. What is the probability of at least one six?", + ], + "chinese": [ + "请用中文解释一下什么是光合作用,以及它对地球生态系统的重要性。", + "把这句话翻译成中文并解释语法:The early bird catches the worm.", + "写一段关于秋天的短文,一百字左右。", + ], + "english_prose": [ + "Write a vivid paragraph describing an old lighthouse keeper watching a storm arrive.", + "Summarize the plot of Romeo and Juliet in three sentences.", + "Continue this story: The last train left the station, and Maria realized her mistake.", + ], + "science": [ + "Explain how mRNA vaccines work at the cellular level.", + "Why is the sky blue during the day but red at sunset?", + "Describe the life cycle of a massive star, from formation to supernova.", + ], + "law": [ + "Explain the difference between a patent, a trademark, and a copyright.", + "What are the key elements required to form a legally binding contract?", + "Summarize what 'due process' means in constitutional law.", + ], + "poetry": [ + "Write a short poem about a hummingbird in the style of Emily Dickinson.", + "Compose a haiku about winter rain, then explain its imagery.", + "Write four rhyming lines about the sea at night.", + ], + "structured": [ + 'Convert to JSON: name Alice, age 30, hobbies reading and chess, address 5 Oak St.', + "Write a SQL query returning the top 5 customers by total order value, with the schema you assume.", + "Write a regex that matches ISO-8601 dates and explain each part.", + ], + "translation": [ + "Translate into French, German and Spanish: 'Knowledge is the only treasure that grows when shared.'", + "Translate this Italian sentence to English and comment on nuance: 'In bocca al lupo per domani.'", + "Translate into Japanese: 'The meeting has been moved to next Tuesday afternoon.'", + ], + "casual": [ + "Hey! Any tips for staying awake during boring afternoon meetings?", + "What should I cook tonight? I have eggs, rice, tomatoes and some cheese.", + "My friend is always late. How do I tell them it bothers me without being rude?", + ], +} + + +def read_usage(path): + counts = {} + try: + with open(path) as f: + for line in f: + p = line.split() + if len(p) == 3: + counts[(int(p[0]), int(p[1]))] = int(p[2]) + except FileNotFoundError: + pass + return counts + + +def diff(after, before): + return {k: v - before.get(k, 0) for k, v in after.items() if v - before.get(k, 0) > 0} + + +def chat(api, prompt, ngen): + body = json.dumps({"model": "glm-5.2-colibri", "stream": False, "max_tokens": ngen, + "messages": [{"role": "user", "content": prompt}]}).encode() + req = urllib.request.Request(f"{api}/v1/chat/completions", data=body, + headers={"Content-Type": "application/json"}) + with urllib.request.urlopen(req, timeout=600) as r: + json.load(r) + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--api", default="http://127.0.0.1:8000") + ap.add_argument("--usage", required=True, help="path to the model's .coli_usage") + ap.add_argument("--out", default="experts.json") + ap.add_argument("--ngen", type=int, default=64) + a = ap.parse_args() + + spectra = {} + for cat, prompts in PROBES.items(): + before = read_usage(a.usage) + t0 = time.time() + for p in prompts: + chat(a.api, p, a.ngen) + time.sleep(2) # let the engine flush .coli_usage + spectra[cat] = diff(read_usage(a.usage), before) + total = sum(spectra[cat].values()) + print(f"[{cat}] {len(spectra[cat])} experts touched, {total} selections, {time.time()-t0:.0f}s", flush=True) + + cats = list(PROBES.keys()) + experts = {} + for cat, spec in spectra.items(): + for k, v in spec.items(): + experts.setdefault(k, {c: 0 for c in cats})[cat] = v + + atlas = {} + for (layer, eid), counts in experts.items(): + total = sum(counts.values()) + if total < 8: + continue # too few observations to characterise + aff = {c: v / total for c, v in counts.items() if v} + ent = -sum(p * math.log2(p) for p in aff.values()) + top = max(aff, key=aff.get) + label = f"specialist: {top}" if aff[top] >= 0.45 and ent < 2.2 else "generalist" + atlas[f"{layer}:{eid}"] = {"counts": counts, "affinity": {c: round(p, 3) for c, p in aff.items()}, + "entropy": round(ent, 2), "top": top, "label": label} + + spec_n = sum(1 for v in atlas.values() if v["label"].startswith("specialist")) + with open(a.out, "w") as f: + json.dump({"categories": cats, "ngen": a.ngen, "experts": atlas}, f) + print(f"\natlas: {len(atlas)} experts characterised, {spec_n} specialists -> {a.out}") + + +if __name__ == "__main__": + main() diff --git a/web/src/Brain.tsx b/web/src/Brain.tsx index ac20695..6811238 100644 --- a/web/src/Brain.tsx +++ b/web/src/Brain.tsx @@ -4,6 +4,7 @@ import { BrainCircuit, Flame, Layers } from "lucide-react" import { endpoint } from "@/lib/api" interface ExpertMap { rows: number; cols: number; map: string; hits: string; seq: number } +interface AtlasEntry { affinity: Record; entropy: number; top: string; label: string } const TIER_NAME = ["Disk", "RAM", "VRAM"] const TIER_RGB: [number, number, number][] = [[58, 71, 80], [90, 155, 216], [78, 214, 165]] @@ -26,11 +27,19 @@ export function Brain({ baseUrl, apiKey, connected }: { baseUrl: string; apiKey: const wrapRef = useRef(null) const [wrapSize, setWrapSize] = useState({ w: 1200, h: 700 }) const [data, setData] = useState(null) + const [atlas, setAtlas] = useState | null>(null) const [tip, setTip] = useState<{ x: number; y: number; row: number; col: number; tier: number; heat: number } | null>(null) const pulseRef = useRef(null) // per-expert pulse intensity 0..1 const lastSeq = useRef(0) const rafRef = useRef(0) + // load the expert atlas if published (measured topic affinity, #175) + useEffect(() => { + fetch("/experts.json").then(r => r.ok ? r.json() : null).then(d => { + if (d?.experts) setAtlas(d.experts) + }).catch(() => {}) + }, []) + // track container size for responsive cell sizing useEffect(() => { const el = wrapRef.current @@ -146,14 +155,26 @@ export function Brain({ baseUrl, apiKey, connected }: { baseUrl: string; apiKey: setTip(null)} /> {!connected &&

Connect to the engine to see the cortex.

} - {tip && data && ( + {tip && data && (() => { + const isMtp = tip.row === data.rows - 1 + const realLayer = isMtp ? 78 : tip.row + 3 + const entry = atlas?.[`${realLayer}:${tip.col}`] + return (
-
Layer row {tip.row}{tip.row === data.rows - 1 ? " (MTP)" : ""} · Expert {tip.col}
+
Layer {realLayer}{isMtp ? " (MTP)" : ""} · Expert {tip.col}
Tier: {TIER_NAME[tip.tier]}
Heat: {tip.heat === 0 ? "never routed" : `~2^${tip.heat} selections`}
-
{depthRole(tip.row, data.rows, tip.row === data.rows - 1)}
+ {entry ? <> +
+ {entry.label.startsWith("specialist") ? `⭐ Specialist: ${entry.top}` : "Generalist"} + (entropy {entry.entropy}) +
+
{Object.entries(entry.affinity).sort((a, b) => b[1] - a[1]).slice(0, 3) + .map(([c, p]) => `${c} ${Math.round(p * 100)}%`).join(" · ")}
+ :
{depthRole(tip.row, data.rows, isMtp)}
}
- )} + ) + })()} ) } diff --git a/web/src/index.css b/web/src/index.css index 59d5bc6..b428805 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -146,3 +146,8 @@ button:focus-visible, input:focus-visible, textarea:focus-visible, select:focus- .brain-legend { gap: 8px; font-size: 10px; } .brain-tip { max-width: 220px; font-size: 10px; } } + +/* atlas hover extras */ +.brain-tip-spec { color: var(--primary); font-weight: 700; } +.brain-tip-spec small, .brain-tip-aff { color: #8b9aa3; font-weight: 400; } +.brain-tip-aff { font-size: 10px; } From 3045b35cddfc9ff9638a4e3797551e3aad03baa1 Mon Sep 17 00:00:00 2001 From: Benny Powers Date: Tue, 14 Jul 2026 19:18:49 +0300 Subject: [PATCH 13/79] bench: default --data to the XDG/LocalAppData cache dir instead of the repo tree (#190) Benchmark datasets are downloaded artifacts, not source files. Store them under $XDG_CACHE_HOME/colibri/bench (~/.cache/colibri/bench) on Linux/macOS and %LOCALAPPDATA%\colibri\bench on Windows instead of polluting the source tree at c/bench/. fetch_benchmarks.py already calls os.makedirs(out, exist_ok=True), so the new cache path is created on first use. Assisted-By: Claude Opus 4.6 (1M context) --- c/coli | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/c/coli b/c/coli index d6890ec..35dfd3c 100755 --- a/c/coli +++ b/c/coli @@ -653,7 +653,13 @@ def main(): pw.add_argument(arg,**kw) pw.add_argument("--no-browser",action="store_true",help="don't auto-open the browser") pb=sub.add_parser("bench", parents=[common]); pb.add_argument("tasks", nargs="*") - pb.add_argument("--limit",type=int,default=40); pb.add_argument("--data",default=os.path.join(HERE,"bench")) + pb.add_argument("--limit",type=int,default=40) + if sys.platform == "win32": + _cache_root = os.environ.get("LOCALAPPDATA", os.path.expanduser("~\\AppData\\Local")) + else: + _cache_root = os.environ.get("XDG_CACHE_HOME", os.path.expanduser("~/.cache")) + _bench_cache = os.path.join(_cache_root, "colibri", "bench") + pb.add_argument("--data",default=_bench_cache) pc=sub.add_parser("convert", parents=[common]); pc.add_argument("--repo",default="zai-org/GLM-5.2-FP8") pc.add_argument("--ebits",type=int,default=4); pc.add_argument("--io-bits",type=int,default=8); pc.add_argument("--xbits",type=int,default=0) pc.add_argument("--no-mtp",action="store_true",help="skip the MTP head (no speculative drafts)") From 21cbf14d591e9bc9785a5544921fc2b8f3ca41f9 Mon Sep 17 00:00:00 2001 From: Tom Olorin <1800017+juicyroots@users.noreply.github.com> Date: Tue, 14 Jul 2026 09:43:56 -0700 Subject: [PATCH 14/79] =?UTF-8?q?cuda(win):=20export=20+=20load=20the=20#1?= =?UTF-8?q?11=20pipeline=20ABI=20=E2=80=94=2024=20missing=20DLLEXPORT=20de?= =?UTF-8?q?corations=20+=20loader=20wrappers,=20unbreaks=20CUDA=5FDLL=3D1?= =?UTF-8?q?=20(#201)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #111 added 24 functions (pipe_*, attention_*_batch*, shared_mlp_w4a16, tensor_update) to backend_cuda.h without COLI_CUDA_DLLEXPORT and without backend_loader.c wrappers: on Windows the host failed to link (undefined references from glm.c) and the DLL exported none of the new entry points. Decorate the declarations and add matching typedefs/RESOLVEs/wrappers following the loader's existing pattern. DLL now exports 39 symbols; engine links; TF oracle 32/32 CPU + dual-GPU (sm_120/sm_89). Co-authored-by: olorin Co-authored-by: Claude Fable 5 --- c/backend_cuda.h | 44 +++++----- c/backend_loader.c | 204 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 226 insertions(+), 22 deletions(-) diff --git a/c/backend_cuda.h b/c/backend_cuda.h index c84a265..acbe4bc 100644 --- a/c/backend_cuda.h +++ b/c/backend_cuda.h @@ -60,7 +60,7 @@ COLI_CUDA_DLLEXPORT int coli_cuda_expert_mlp(ColiCudaTensor *gate, ColiCudaTenso * memory, activations are converted to FP16 per tile, and Tensor Cores * accumulate into FP32. Unlike COLI_CUDA_TC_INT4 this does not quantize the * activation to INT4. */ -int coli_cuda_shared_mlp_w4a16(ColiCudaTensor *gate, ColiCudaTensor *up, +COLI_CUDA_DLLEXPORT int coli_cuda_shared_mlp_w4a16(ColiCudaTensor *gate, ColiCudaTensor *up, ColiCudaTensor *down, float *y, const float *x, int S); @@ -97,46 +97,46 @@ COLI_CUDA_DLLEXPORT size_t coli_cuda_tensor_bytes(const ColiCudaTensor *tensor); COLI_CUDA_DLLEXPORT int coli_cuda_tensor_device(const ColiCudaTensor *tensor); /* Replace a resident tensor's contents without reallocating its device slot. */ -int coli_cuda_tensor_update(ColiCudaTensor *tensor, +COLI_CUDA_DLLEXPORT int coli_cuda_tensor_update(ColiCudaTensor *tensor, const void *weights, const float *scales); /* ---- resident-pipeline primitives (Inc.0): device-pointer entry points ---- */ -float *coli_cuda_pipe_scratch(int device,int slot,size_t bytes); -void *coli_cuda_pipe_alloc(int device,size_t bytes); -void coli_cuda_pipe_free(int device,void *p); -int coli_cuda_pipe_upload(int device,void *dst,const void *src,size_t bytes); -int coli_cuda_pipe_download(int device,const void *src,void *dst,size_t bytes); -int coli_cuda_pipe_rmsnorm(int device,float *y_dev,const float *x_dev, +COLI_CUDA_DLLEXPORT float *coli_cuda_pipe_scratch(int device,int slot,size_t bytes); +COLI_CUDA_DLLEXPORT void *coli_cuda_pipe_alloc(int device,size_t bytes); +COLI_CUDA_DLLEXPORT void coli_cuda_pipe_free(int device,void *p); +COLI_CUDA_DLLEXPORT int coli_cuda_pipe_upload(int device,void *dst,const void *src,size_t bytes); +COLI_CUDA_DLLEXPORT int coli_cuda_pipe_download(int device,const void *src,void *dst,size_t bytes); +COLI_CUDA_DLLEXPORT int coli_cuda_pipe_rmsnorm(int device,float *y_dev,const float *x_dev, const float *w_dev,int S,int D,float eps); -int coli_cuda_pipe_rope(int device,float *v_dev,const int *pos_dev,int rows, +COLI_CUDA_DLLEXPORT int coli_cuda_pipe_rope(int device,float *v_dev,const int *pos_dev,int rows, int stride,int offset,int R,int heads,float theta); -int coli_cuda_pipe_silu_mul(int device,float *gate_dev,const float *up_dev,size_t n); -int coli_cuda_pipe_add(int device,float *x_dev,const float *t_dev,size_t n); -int coli_cuda_pipe_rows_add(int device,float *x_dev,const float *partial_dev, +COLI_CUDA_DLLEXPORT int coli_cuda_pipe_silu_mul(int device,float *gate_dev,const float *up_dev,size_t n); +COLI_CUDA_DLLEXPORT int coli_cuda_pipe_add(int device,float *x_dev,const float *t_dev,size_t n); +COLI_CUDA_DLLEXPORT int coli_cuda_pipe_rows_add(int device,float *x_dev,const float *partial_dev, const int *rows_dev,int nrows,int D); -int coli_cuda_pipe_gemm(ColiCudaTensor *t,float *y_dev,const float *x_dev,int S); -int coli_cuda_pipe_rmsnorm_s(int device,float *y_dev,const float *x_dev, +COLI_CUDA_DLLEXPORT int coli_cuda_pipe_gemm(ColiCudaTensor *t,float *y_dev,const float *x_dev,int S); +COLI_CUDA_DLLEXPORT int coli_cuda_pipe_rmsnorm_s(int device,float *y_dev,const float *x_dev, const float *w_dev,int S,int D,float eps, int xstride,int ystride); -int coli_cuda_pipe_rope_base(int device,float *v_dev,int pos_base,int rows, +COLI_CUDA_DLLEXPORT int coli_cuda_pipe_rope_base(int device,float *v_dev,int pos_base,int rows, int stride,int offset,int R,int heads,float theta); -int coli_cuda_pipe_copy2d(int device,float *dst,int dpitch,const float *src, +COLI_CUDA_DLLEXPORT int coli_cuda_pipe_copy2d(int device,float *dst,int dpitch,const float *src, int spitch,int width,int height); -int coli_cuda_attention_project_batch_dev(ColiCudaTensor *kv_b,ColiCudaTensor *o_proj, +COLI_CUDA_DLLEXPORT int coli_cuda_attention_project_batch_dev(ColiCudaTensor *kv_b,ColiCudaTensor *o_proj, float *out,const float *q_dev,const float *latent_dev,const float *rope_dev, int S,int H,int Q,int R,int V,int K,int T,float scale); -int coli_cuda_attention_absorb_batch_dev(ColiCudaTensor *kv_b_shard,float *ctx_dev, +COLI_CUDA_DLLEXPORT int coli_cuda_attention_absorb_batch_dev(ColiCudaTensor *kv_b_shard,float *ctx_dev, const float *q_dev,const float *latent_dev,const float *rope_dev, int S,int H,int Q,int R,int V,int K,int T,float scale); -int coli_cuda_attention_absorb_kvdev(ColiCudaTensor *kv_b,float *ctx,const float *q, +COLI_CUDA_DLLEXPORT int coli_cuda_attention_absorb_kvdev(ColiCudaTensor *kv_b,float *ctx,const float *q, const float *latent_dev,const float *rope_dev,int H,int Q,int R,int V,int K,int T, float scale); -int coli_cuda_pipe_peer_copy(int dst_dev,float *dst,int src_dev, +COLI_CUDA_DLLEXPORT int coli_cuda_pipe_peer_copy(int dst_dev,float *dst,int src_dev, const float *src,size_t bytes); -int coli_cuda_attention_project_batch_dev_out(ColiCudaTensor *kv_b,ColiCudaTensor *o_proj, +COLI_CUDA_DLLEXPORT int coli_cuda_attention_project_batch_dev_out(ColiCudaTensor *kv_b,ColiCudaTensor *o_proj, float *out_dev,const float *q_dev,const float *latent_dev,const float *rope_dev, int S,int H,int Q,int R,int V,int K,int T,float scale); -int coli_cuda_pipe_sync(int device); +COLI_CUDA_DLLEXPORT int coli_cuda_pipe_sync(int device); #ifdef __cplusplus } diff --git a/c/backend_loader.c b/c/backend_loader.c index 6fea70c..0635e08 100644 --- a/c/backend_loader.c +++ b/c/backend_loader.c @@ -52,6 +52,35 @@ typedef void (*fn_tensor_free)(ColiCudaTensor *tensor); typedef size_t (*fn_tensor_bytes)(const ColiCudaTensor *tensor); typedef int (*fn_tensor_device)(const ColiCudaTensor *tensor); +/* --- #111 GPU resident pipeline additions (matched to backend_cuda.h) --- */ + + +/* --- #111 GPU resident pipeline additions (matched to backend_cuda.h) --- */ +typedef int (*fn_attention_absorb_batch)(ColiCudaTensor *kv_b,float *ctx,const float *q, const float *latent,const float *rope,int S, int H,int Q,int R,int V,int K,int T, float attention_scale); +typedef int (*fn_attention_absorb_batch_dev)(ColiCudaTensor *kv_b_shard,float *ctx_dev, const float *q_dev,const float *latent_dev,const float *rope_dev, int S,int H,int Q,int R,int V,int K,int T,float scale); +typedef int (*fn_attention_absorb_kvdev)(ColiCudaTensor *kv_b,float *ctx,const float *q, const float *latent_dev,const float *rope_dev,int H,int Q,int R,int V,int K,int T, float scale); +typedef int (*fn_attention_project_batch)(ColiCudaTensor *kv_b,ColiCudaTensor *o_proj, float *out,const float *q,const float *latent, const float *rope,int S,int H,int Q,int R, int V,int K,int T,float attention_scale); +typedef int (*fn_attention_project_batch_dev)(ColiCudaTensor *kv_b,ColiCudaTensor *o_proj, float *out,const float *q_dev,const float *latent_dev,const float *rope_dev, int S,int H,int Q,int R,int V,int K,int T,float scale); +typedef int (*fn_attention_project_batch_dev_out)(ColiCudaTensor *kv_b,ColiCudaTensor *o_proj, float *out_dev,const float *q_dev,const float *latent_dev,const float *rope_dev, int S,int H,int Q,int R,int V,int K,int T,float scale); +typedef int (*fn_pipe_add)(int device,float *x_dev,const float *t_dev,size_t n); +typedef void * (*fn_pipe_alloc)(int device,size_t bytes); +typedef int (*fn_pipe_copy2d)(int device,float *dst,int dpitch,const float *src, int spitch,int width,int height); +typedef int (*fn_pipe_download)(int device,const void *src,void *dst,size_t bytes); +typedef void (*fn_pipe_free)(int device,void *p); +typedef int (*fn_pipe_gemm)(ColiCudaTensor *t,float *y_dev,const float *x_dev,int S); +typedef int (*fn_pipe_peer_copy)(int dst_dev,float *dst,int src_dev, const float *src,size_t bytes); +typedef int (*fn_pipe_rmsnorm)(int device,float *y_dev,const float *x_dev, const float *w_dev,int S,int D,float eps); +typedef int (*fn_pipe_rmsnorm_s)(int device,float *y_dev,const float *x_dev, const float *w_dev,int S,int D,float eps, int xstride,int ystride); +typedef int (*fn_pipe_rope)(int device,float *v_dev,const int *pos_dev,int rows, int stride,int offset,int R,int heads,float theta); +typedef int (*fn_pipe_rope_base)(int device,float *v_dev,int pos_base,int rows, int stride,int offset,int R,int heads,float theta); +typedef int (*fn_pipe_rows_add)(int device,float *x_dev,const float *partial_dev, const int *rows_dev,int nrows,int D); +typedef float * (*fn_pipe_scratch)(int device,int slot,size_t bytes); +typedef int (*fn_pipe_silu_mul)(int device,float *gate_dev,const float *up_dev,size_t n); +typedef int (*fn_pipe_sync)(int device); +typedef int (*fn_pipe_upload)(int device,void *dst,const void *src,size_t bytes); +typedef int (*fn_shared_mlp_w4a16)(ColiCudaTensor *gate, ColiCudaTensor *up, ColiCudaTensor *down, float *y, const float *x, int S); +typedef int (*fn_tensor_update)(ColiCudaTensor *tensor, const void *weights, const float *scales); + /* Resolved pointers, plus a flag so we attempt the load at most once. */ static struct { int loaded; /* 1 = load attempted (success or fail), 0 = not yet */ @@ -72,6 +101,31 @@ static struct { fn_tensor_free tensor_free; fn_tensor_bytes tensor_bytes; fn_tensor_device tensor_device; + + fn_attention_absorb_batch attention_absorb_batch; + fn_attention_absorb_batch_dev attention_absorb_batch_dev; + fn_attention_absorb_kvdev attention_absorb_kvdev; + fn_attention_project_batch attention_project_batch; + fn_attention_project_batch_dev attention_project_batch_dev; + fn_attention_project_batch_dev_out attention_project_batch_dev_out; + fn_pipe_add pipe_add; + fn_pipe_alloc pipe_alloc; + fn_pipe_copy2d pipe_copy2d; + fn_pipe_download pipe_download; + fn_pipe_free pipe_free; + fn_pipe_gemm pipe_gemm; + fn_pipe_peer_copy pipe_peer_copy; + fn_pipe_rmsnorm pipe_rmsnorm; + fn_pipe_rmsnorm_s pipe_rmsnorm_s; + fn_pipe_rope pipe_rope; + fn_pipe_rope_base pipe_rope_base; + fn_pipe_rows_add pipe_rows_add; + fn_pipe_scratch pipe_scratch; + fn_pipe_silu_mul pipe_silu_mul; + fn_pipe_sync pipe_sync; + fn_pipe_upload pipe_upload; + fn_shared_mlp_w4a16 shared_mlp_w4a16; + fn_tensor_update tensor_update; } g_cuda; /* Resolve the DLL and all 11 symbols. Returns 1 on success, 0 otherwise. @@ -119,6 +173,31 @@ static int coli_cuda_load(void){ RESOLVE(tensor_free, fn_tensor_free) RESOLVE(tensor_bytes, fn_tensor_bytes) RESOLVE(tensor_device, fn_tensor_device) + + RESOLVE(attention_absorb_batch, fn_attention_absorb_batch) + RESOLVE(attention_absorb_batch_dev, fn_attention_absorb_batch_dev) + RESOLVE(attention_absorb_kvdev, fn_attention_absorb_kvdev) + RESOLVE(attention_project_batch, fn_attention_project_batch) + RESOLVE(attention_project_batch_dev, fn_attention_project_batch_dev) + RESOLVE(attention_project_batch_dev_out, fn_attention_project_batch_dev_out) + RESOLVE(pipe_add, fn_pipe_add) + RESOLVE(pipe_alloc, fn_pipe_alloc) + RESOLVE(pipe_copy2d, fn_pipe_copy2d) + RESOLVE(pipe_download, fn_pipe_download) + RESOLVE(pipe_free, fn_pipe_free) + RESOLVE(pipe_gemm, fn_pipe_gemm) + RESOLVE(pipe_peer_copy, fn_pipe_peer_copy) + RESOLVE(pipe_rmsnorm, fn_pipe_rmsnorm) + RESOLVE(pipe_rmsnorm_s, fn_pipe_rmsnorm_s) + RESOLVE(pipe_rope, fn_pipe_rope) + RESOLVE(pipe_rope_base, fn_pipe_rope_base) + RESOLVE(pipe_rows_add, fn_pipe_rows_add) + RESOLVE(pipe_scratch, fn_pipe_scratch) + RESOLVE(pipe_silu_mul, fn_pipe_silu_mul) + RESOLVE(pipe_sync, fn_pipe_sync) + RESOLVE(pipe_upload, fn_pipe_upload) + RESOLVE(shared_mlp_w4a16, fn_shared_mlp_w4a16) + RESOLVE(tensor_update, fn_tensor_update) #undef RESOLVE g_cuda.available = 1; @@ -216,4 +295,129 @@ int coli_cuda_tensor_device(const ColiCudaTensor *tensor){ return g_cuda.tensor_device(tensor); } +/* ---- #111 pipeline wrappers ---- */ + + +/* ---- #111 pipeline wrappers (see header for semantics) ---- */ + +int coli_cuda_attention_absorb_batch(ColiCudaTensor *kv_b,float *ctx,const float *q, const float *latent,const float *rope,int S, int H,int Q,int R,int V,int K,int T, float attention_scale){ + if(!g_cuda.available){ return 0; } + return g_cuda.attention_absorb_batch(kv_b, ctx, q, latent, rope, S, H, Q, R, V, K, T, attention_scale); +} + +int coli_cuda_attention_absorb_batch_dev(ColiCudaTensor *kv_b_shard,float *ctx_dev, const float *q_dev,const float *latent_dev,const float *rope_dev, int S,int H,int Q,int R,int V,int K,int T,float scale){ + if(!g_cuda.available){ return 0; } + return g_cuda.attention_absorb_batch_dev(kv_b_shard, ctx_dev, q_dev, latent_dev, rope_dev, S, H, Q, R, V, K, T, scale); +} + +int coli_cuda_attention_absorb_kvdev(ColiCudaTensor *kv_b,float *ctx,const float *q, const float *latent_dev,const float *rope_dev,int H,int Q,int R,int V,int K,int T, float scale){ + if(!g_cuda.available){ return 0; } + return g_cuda.attention_absorb_kvdev(kv_b, ctx, q, latent_dev, rope_dev, H, Q, R, V, K, T, scale); +} + +int coli_cuda_attention_project_batch(ColiCudaTensor *kv_b,ColiCudaTensor *o_proj, float *out,const float *q,const float *latent, const float *rope,int S,int H,int Q,int R, int V,int K,int T,float attention_scale){ + if(!g_cuda.available){ return 0; } + return g_cuda.attention_project_batch(kv_b, o_proj, out, q, latent, rope, S, H, Q, R, V, K, T, attention_scale); +} + +int coli_cuda_attention_project_batch_dev(ColiCudaTensor *kv_b,ColiCudaTensor *o_proj, float *out,const float *q_dev,const float *latent_dev,const float *rope_dev, int S,int H,int Q,int R,int V,int K,int T,float scale){ + if(!g_cuda.available){ return 0; } + return g_cuda.attention_project_batch_dev(kv_b, o_proj, out, q_dev, latent_dev, rope_dev, S, H, Q, R, V, K, T, scale); +} + +int coli_cuda_attention_project_batch_dev_out(ColiCudaTensor *kv_b,ColiCudaTensor *o_proj, float *out_dev,const float *q_dev,const float *latent_dev,const float *rope_dev, int S,int H,int Q,int R,int V,int K,int T,float scale){ + if(!g_cuda.available){ return 0; } + return g_cuda.attention_project_batch_dev_out(kv_b, o_proj, out_dev, q_dev, latent_dev, rope_dev, S, H, Q, R, V, K, T, scale); +} + +int coli_cuda_pipe_add(int device,float *x_dev,const float *t_dev,size_t n){ + if(!g_cuda.available){ return 0; } + return g_cuda.pipe_add(device, x_dev, t_dev, n); +} + +void * coli_cuda_pipe_alloc(int device,size_t bytes){ + if(!g_cuda.available){ return NULL; } + return g_cuda.pipe_alloc(device, bytes); +} + +int coli_cuda_pipe_copy2d(int device,float *dst,int dpitch,const float *src, int spitch,int width,int height){ + if(!g_cuda.available){ return 0; } + return g_cuda.pipe_copy2d(device, dst, dpitch, src, spitch, width, height); +} + +int coli_cuda_pipe_download(int device,const void *src,void *dst,size_t bytes){ + if(!g_cuda.available){ return 0; } + return g_cuda.pipe_download(device, src, dst, bytes); +} + +void coli_cuda_pipe_free(int device,void *p){ + if(!g_cuda.available){ return; } + g_cuda.pipe_free(device, p); +} + +int coli_cuda_pipe_gemm(ColiCudaTensor *t,float *y_dev,const float *x_dev,int S){ + if(!g_cuda.available){ return 0; } + return g_cuda.pipe_gemm(t, y_dev, x_dev, S); +} + +int coli_cuda_pipe_peer_copy(int dst_dev,float *dst,int src_dev, const float *src,size_t bytes){ + if(!g_cuda.available){ return 0; } + return g_cuda.pipe_peer_copy(dst_dev, dst, src_dev, src, bytes); +} + +int coli_cuda_pipe_rmsnorm(int device,float *y_dev,const float *x_dev, const float *w_dev,int S,int D,float eps){ + if(!g_cuda.available){ return 0; } + return g_cuda.pipe_rmsnorm(device, y_dev, x_dev, w_dev, S, D, eps); +} + +int coli_cuda_pipe_rmsnorm_s(int device,float *y_dev,const float *x_dev, const float *w_dev,int S,int D,float eps, int xstride,int ystride){ + if(!g_cuda.available){ return 0; } + return g_cuda.pipe_rmsnorm_s(device, y_dev, x_dev, w_dev, S, D, eps, xstride, ystride); +} + +int coli_cuda_pipe_rope(int device,float *v_dev,const int *pos_dev,int rows, int stride,int offset,int R,int heads,float theta){ + if(!g_cuda.available){ return 0; } + return g_cuda.pipe_rope(device, v_dev, pos_dev, rows, stride, offset, R, heads, theta); +} + +int coli_cuda_pipe_rope_base(int device,float *v_dev,int pos_base,int rows, int stride,int offset,int R,int heads,float theta){ + if(!g_cuda.available){ return 0; } + return g_cuda.pipe_rope_base(device, v_dev, pos_base, rows, stride, offset, R, heads, theta); +} + +int coli_cuda_pipe_rows_add(int device,float *x_dev,const float *partial_dev, const int *rows_dev,int nrows,int D){ + if(!g_cuda.available){ return 0; } + return g_cuda.pipe_rows_add(device, x_dev, partial_dev, rows_dev, nrows, D); +} + +float * coli_cuda_pipe_scratch(int device,int slot,size_t bytes){ + if(!g_cuda.available){ return NULL; } + return g_cuda.pipe_scratch(device, slot, bytes); +} + +int coli_cuda_pipe_silu_mul(int device,float *gate_dev,const float *up_dev,size_t n){ + if(!g_cuda.available){ return 0; } + return g_cuda.pipe_silu_mul(device, gate_dev, up_dev, n); +} + +int coli_cuda_pipe_sync(int device){ + if(!g_cuda.available){ return 0; } + return g_cuda.pipe_sync(device); +} + +int coli_cuda_pipe_upload(int device,void *dst,const void *src,size_t bytes){ + if(!g_cuda.available){ return 0; } + return g_cuda.pipe_upload(device, dst, src, bytes); +} + +int coli_cuda_shared_mlp_w4a16(ColiCudaTensor *gate, ColiCudaTensor *up, ColiCudaTensor *down, float *y, const float *x, int S){ + if(!g_cuda.available){ return 0; } + return g_cuda.shared_mlp_w4a16(gate, up, down, y, x, S); +} + +int coli_cuda_tensor_update(ColiCudaTensor *tensor, const void *weights, const float *scales){ + if(!g_cuda.available){ return 0; } + return g_cuda.tensor_update(tensor, weights, scales); +} + #endif /* _WIN32 */ From e21318e678a7ba9f7f703c53dab81a4f4df99d95 Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Wed, 15 Jul 2026 00:45:42 +0800 Subject: [PATCH 15/79] README: dashboard screenshots + contents index + Web dashboard section (#202) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 'See it running' right after the intro: the live dashboard (744B answering at 4+ tok/s end-to-end with metrics and tier bar) and the Brain cortex (19,456 experts, tier colour, routing heat, per-turn firing) — three seconds to understand what colibri is. - A short table of contents for the long read below. - 'Web dashboard' section: coli web one-liner, what each panel shows, link to the Expert Atlas (#175). Existing content untouched. --- README.md | 43 +++++++++++++++++++++++++++++++ docs/media/colibri-brain.png | Bin 0 -> 431303 bytes docs/media/colibri-dashboard.png | Bin 0 -> 558290 bytes 3 files changed, 43 insertions(+) create mode 100644 docs/media/colibri-brain.png create mode 100644 docs/media/colibri-dashboard.png diff --git a/README.md b/README.md index 4109d5f..86c3009 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,32 @@ $ ./coli chat ◆ Ciao! 😊 Come posso aiutarti oggi? ``` + +## See it running + +

+ colibrì web dashboard — live metrics, hardware panel, expert tiers +

+

The web dashboard (./coli web): a 744B model answering at 4+ tok/s end-to-end on 6× RTX 5090 — +with live token metrics, the hardware panel, and the VRAM/RAM/disk expert tiers.

+ +

+ the Brain page — 19,456 experts as a live cortex +

+

The Brain page: all 19,456 experts as a living cortex — colour is the storage tier, +brightness is routing heat, and every expert routed in a turn flashes white. Hovering shows the expert's +measured topic affinity.

+ +## Contents + +- [The idea](#the-idea) +- [See it running](#see-it-running) +- [What's implemented](#whats-implemented) +- [Honest numbers](#honest-numbers-wsl2-12-cores-25-gb-ram-nvme-via-vhdx) +- [Download the model](#download-the-model) +- [Web dashboard](#web-dashboard) +- [Got a better machine?](#got-a-better-machine-try-it--heres-what-to-expect) + ## The idea A 744B Mixture-of-Experts model activates only ~40B parameters per token — and only ~11 GB of those change from token to token (the routed experts). So: @@ -501,6 +527,23 @@ thrashing. Persistent `.coli_usage` remains the long-term signal and is not deca **Conversations reopen warm** (`.coli_kv`, since 2026-07-10): `coli chat` persists the compressed MLA KV-cache to disk after every turn (~182 KB/token, appended incrementally, crash-safe). Close the chat, reopen it tomorrow — the model still remembers the whole conversation and **zero re-prefill happens**: validated byte-identical to an uninterrupted session. `:reset` clears it, `KVSAVE=0` disables it. +## Web dashboard + +One command serves the OpenAI-compatible API **and** the web console on the same port, then opens your browser when the engine is ready: + +```bash +cd web && npm install && npm run build # once +./coli web --model +``` + +What you get: + +- **Chat** with live metrics: a flashing token counter while generating, then tok/s, time-to-first-token, prompt→completion counts and queue wait; +- **Runtime panel**: your hardware (CPU, GPUs + VRAM, RAM, cores), the scheduler, and the live expert-tier bar — how many of the 19,456 experts sit in VRAM / RAM / disk right now; +- **Brain**: the whole model as a 76×256 cortex, one cell per expert. Colour = tier, brightness = routing heat, and the experts routed in each turn flash white and decay — you watch the model think. Hover any cell for its tier, heat and [measured topic affinity](https://github.com/JustVugg/colibri/issues/175) (specialists for code, Chinese, math, law… live in layers 11–22). + +The dashboard talks to the engine over two tiny protocol lines (`TIERS`, `EMAP`/`HITS`) and plain JSON endpoints — nothing heavier than the engine itself. + ## Got a better machine? Try it — here's what to expect colibrì was built on deliberately humble hardware (12 cores, 25 GB RAM, an older DRAM-less NVMe behind a WSL2 VHDX that measured ~1 GB/s random on *this* drive — note WSL2 VHDX is not inherently slow: a community 5090 box measured 10.5 GB/s O_DIRECT through one, [#101](https://github.com/JustVugg/colibri/issues/101)). **Every one of those constraints is a knob your machine can turn up.** The engine needs: Linux (or WSL2), macOS, or **Windows 11 natively (MinGW-w64)**; gcc with OpenMP, AVX2, ≥16 GB RAM, and the ~370 GB int4 model on a local NVMe (ext4/NTFS — never a network/9p mount). diff --git a/docs/media/colibri-brain.png b/docs/media/colibri-brain.png new file mode 100644 index 0000000000000000000000000000000000000000..0cd6c905b584898cf9ad6dedb60fe6060a5b355e GIT binary patch literal 431303 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 V0?4P5^&$GK6C$#Hb`lN6BxH&n9V`lVO; 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%0A9fq%>5M$Iw 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

=d<0k3+-^TFLxNOf7YINqiHZ5A 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

dUy=8SY_ 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 literal 0 HcmV?d00001 diff --git a/docs/media/colibri-dashboard.png b/docs/media/colibri-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..123fd3eed86a0fcd777062ad5bc80e5dd66ca2bc GIT binary patch literal 558290 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

;oMVaSd!pB)g0c`>b;NUl)m(5?D01Z?#6fH3?l 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%0Dekk)_$q?ccsE1Jbe>?jV1Q0U>2H+URliU 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 Date: Tue, 14 Jul 2026 19:55:36 +0300 Subject: [PATCH 16/79] =?UTF-8?q?bench:=20pass=20the=20resolved=20GLM=20en?= =?UTF-8?q?gine=20path=20to=20eval=5Fglm.py=20=E2=80=94=20cwd-relative=20.?= =?UTF-8?q?/glm=20default=20broke=20coli=20bench=20from=20other=20dirs=20(?= =?UTF-8?q?#203)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cmd_bench builds the eval_glm.py command but did not pass --glm, so eval_glm.py fell back to ./glm which breaks when running from any directory other than the source tree. Pass the already-resolved GLM variable via --glm, matching --data and --snap. Assisted-By: Claude Opus 4.6 (1M context) --- c/coli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/coli b/c/coli index 35dfd3c..8c89caf 100755 --- a/c/coli +++ b/c/coli @@ -585,7 +585,7 @@ def cmd_bench(a): print(f" {C.dim}downloading missing datasets: {', '.join(missing)}{C.r}") subprocess.call([py, os.path.join(TOOLS,"fetch_benchmarks.py"), "--out", a.data, "--tasks", ",".join(missing), "--limit", str(max(a.limit,200))]) - cmd=[py, os.path.join(TOOLS,"eval_glm.py"), "--snap",a.model, + cmd=[py, os.path.join(TOOLS,"eval_glm.py"), "--glm", GLM, "--snap",a.model, "--tasks", tasks, "--limit", str(a.limit), "--data", a.data] if a.ram: cmd+=["--ram",str(a.ram)] e=env_for(a) From 6ca9565d2dd8abaea5e6ec03dabb277d22f6d902 Mon Sep 17 00:00:00 2001 From: woolcoxm Date: Tue, 14 Jul 2026 14:07:51 -0400 Subject: [PATCH 17/79] pilot: two-step shared-expert router prediction, +3.1% recall, opt-in PILOT_TWO=1 (#204, #200) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wires the two-step prediction (kind==2 from experiment/two-step-predict) into the real pilot_prefetch() path behind PILOT_TWO=1 env var. Changes: - la_predict kind==2: computes shared expert (resident, no disk I/O) on L's post_ln-normalized state, adds output to residual, then runs L+1's router on the corrected state. Guards n_shared==0 and mloe_inter<=0. - pilot_prefetch(): when PILOT_TWO=1, computes the same shared-expert correction before running the router. Workspace allocated once per call (not per position) to avoid malloc churn. - LOOKA measurement harness expanded to 4 slots (prev, skip-attn, PILOT stale, two-step) with updated reporting at both exit points. - PILOT_TWO env var wired into main(). Measurements (GLM-5.2 744B, 24GB RAM, cap=2): LOOKA recall: PILOT stale 73.6% -> two-step 76.7% (+3.1%) End-to-end tok/s: no change (0.16 tok/s) — cache too small (cap=2) for prediction quality to matter; disk bandwidth saturated regardless. On higher-RAM hosts (cap>=32) the +3.1% recall would translate to measurably fewer disk misses. Prior art: 'Speculating Experts' (arXiv:2603.19289) independently developed the same idea as a 'quasi-hidden state' using a static default vector. Our approach uses the actual computed shared expert, which is input-dependent and more accurate. Co-authored-by: woolcoxm <13604288+woolcoxm@users.noreply.github.com> --- c/glm.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 91 insertions(+), 11 deletions(-) diff --git a/c/glm.c b/c/glm.c index 2780b79..ed9cbea 100644 --- a/c/glm.c +++ b/c/glm.c @@ -887,8 +887,8 @@ static int g_looka=0; /* LOOKA=1: misura (solo contatori, zero effetti) quant * [2] post-attention del layer L -> routing di L+1 (un residuo MoE e * un'attention di anticipo: il punto dove il prefetch avrebbe * un intero giro di disco per lavorare in ombra). */ -static int64_t la_hit[3], la_tot[3]; -static int la_pred[2][130][16]; static signed char la_val[2][130]; +static int64_t la_hit[4], la_tot[4]; /* [0]=prev, [1]=skip-attn, [2]=PILOT, [3]=two-step */ +static int la_pred[3][130][16]; static signed char la_val[3][130]; static int g_pilot=0; /* PILOT=1: prefetch pilotato dal router (vedi pilot_prefetch) */ static int g_pilot_k=8; /* PILOT_K=k: prefetcha solo le prime k predizioni per posizione */ /* Aligned allocator for dense QT weights/scales: under METAL, page-align + register so the @@ -904,6 +904,9 @@ static void *qalloc(size_t n){ static float *qsalloc(int O){ return (float*)qalloc((size_t)O*sizeof(float)); } static int g_pilot_real=0;/* PILOT_REAL=1: il pilota fa LOAD VERI cross-layer dentro ecache[L+1] * (non il semplice WILLNEED). Implica PILOT=1. Default OFF: hint-only. */ +static int g_pilot_two=0; /* PILOT_TWO=1: two-step prefetch — before running L+1's router, + * approximate MoE(L) using only the shared expert (resident, no disk) + * and add it to the state. Trades 3 small matmuls for +2.3% recall. */ /* Handshake main<->pilota per il load-vero cross-layer. Invariante di sicurezza in DUE parti: * 1) Percorso MATMUL (moe): il pilota scrive SOLO ecache[layer] con layer > g_cur_moe_layer; * il matmul in moe() legge SOLO ecache[layer]==g_cur_moe_layer, e la barriera a inizio moe() @@ -2166,7 +2169,7 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out, int if(m->eroute[layer][z]==idxs[kk]){ la_hit[0]++; break; } la_tot[0]+=Ke; } - for(int kind=0;kind<2;kind++) if(la_val[kind][layer]){ /* [1]/[2] vs predizioni */ + for(int kind=0;kind<3;kind++) if(la_val[kind][layer]){ /* score all prediction kinds */ for(int kk=0;kk router -> sigmoid+bias, top-K). - * kind 0 = stesso layer saltando l'attention, kind 1 = layer successivo. */ + * kind 0 = stesso layer saltando l'attention + * kind 1 = layer successivo (PILOT: stale state, 75.8% recall) + * kind 2 = two-step: approximate L's shared expert output, add to state, THEN predict L+1. + * The shared expert is resident (part of dense model), so this adds 3 small matmuls + * but no disk I/O. The corrected state includes the dominant part of MoE(L) that the + * stale PILOT prediction is missing. */ static void la_predict(Model *m, int target, const float *h, int kind){ Cfg *c=&m->c; Layer *l=&m->L[target]; int D=c->hidden, E=c->n_experts, K=c->topk; float *nrm=falloc(D), *ch=falloc(E); + + if(kind==2){ + /* Two-step: h is L's post-attention state (pre-MoE). We want to predict L+1's + * routing. The real L+1 router sees h + MoE(L). We approximate MoE(L) by + * computing ONLY the shared expert (resident, no disk) on the post_ln-normalized + * state, then add it to h before running L+1's router. + * + * target = L+1, so the layer we need the shared expert from is L = target-1. */ + int src_layer = target - 1; + if(src_layer < 0 || src_layer >= c->n_layers || !m->L[src_layer].sparse + || c->n_shared <= 0 || c->moe_inter <= 0){ + la_val[2][target] = 0; free(nrm); free(ch); return; + } + Layer *sl = &m->L[src_layer]; + int sI = c->moe_inter * c->n_shared; + float *snrm = falloc(D), *sg = falloc(sI), *su = falloc(sI); + float *sout = falloc(D), *hc = falloc(D); + rmsnorm(snrm, h, sl->post_ln, D, c->eps); + matmul_qt(sg, snrm, &sl->sh_gate, 1); + matmul_qt(su, snrm, &sl->sh_up, 1); + for(int i=0;ish_down, 1); + for(int i=0;ipost_ln, D, c->eps); + free(snrm); free(sg); free(su); free(sout); free(hc); + matmul(ch, nrm, l->router, 1, D, E); + for(int e=0;erouter_bias[e]; + int *pred = la_pred[2][target]; + for(int kk=0;kkbv){bv=ch[e];best=e;} } + pred[kk]=best; } + la_val[2][target]=1; + free(nrm); free(ch); + return; + } + + /* Baseline kinds 0 and 1: pure router on the given state */ rmsnorm(nrm,h,l->post_ln,D,c->eps); matmul(ch,nrm,l->router,1,D,E); for(int e=0;erouter_bias[e]; @@ -2629,8 +2675,32 @@ static void pilot_prefetch(Model *m, int lnext, const float *x, int S){ int K = g_pilot_ktopk ? g_pilot_k : c->topk; if(!pilot_m){ pilot_m=m; pthread_t t; pthread_create(&t,NULL,pilot_worker,NULL); } float *nrm=falloc(D), *ch=falloc(E); + /* Two-step workspace (allocated once, reused across positions) */ + float *snrm=NULL, *sg=NULL, *su=NULL, *sout=NULL, *hc=NULL; + int src_layer = lnext - 1; + int sI = 0; + int can_two = g_pilot_two && src_layer>=0 && src_layern_layers + && m->L[src_layer].sparse && c->n_shared>0 && c->moe_inter>0; + if(can_two){ + sI = c->moe_inter * c->n_shared; + snrm=falloc(D); sg=falloc(sI); su=falloc(sI); sout=falloc(D); hc=falloc(D); + } for(int s=0;spost_ln, D, c->eps); + const float *xs = x+(int64_t)s*D; + if(can_two){ + /* Two-step: approximate MoE(src_layer) via shared expert only (resident, no disk), + * then run lnext's router on the corrected state. */ + Layer *sl = &m->L[src_layer]; + rmsnorm(snrm, xs, sl->post_ln, D, c->eps); + matmul_qt(sg, snrm, &sl->sh_gate, 1); + matmul_qt(su, snrm, &sl->sh_up, 1); + for(int i=0;ish_down, 1); + for(int i=0;ipost_ln, D, c->eps); + } else { + rmsnorm(nrm, xs, l->post_ln, D, c->eps); + } matmul(ch, nrm, l->router, 1, D, E); for(int e=0;erouter_bias[e]; for(int kk=0;kkn_layers && m->L[li+1].sparse) pilot_prefetch(m,li+1,x,S); - if(g_looka && S==1 && li+1n_layers && m->L[li+1].sparse) la_predict(m,li+1,x,1); + if(g_looka && S==1 && li+1n_layers && m->L[li+1].sparse){ + la_predict(m,li+1,x,1); + la_predict(m,li+1,x,2); + } g_pre_idx=lidx; g_pre_w=lw; g_pre_keff=lkeff; g_pre_sh=lsh; moe(m,l,li,lnrm,S,tmp); g_pre_idx=NULL; g_pre_w=NULL; g_pre_keff=NULL; g_pre_sh=NULL; @@ -2786,7 +2860,10 @@ static void layer_forward_rows(Model *m, Layer *l, int li, float *x, int S, int attention_rows(m,l,li,nrm,S,pos_base,kvs,positions,tmp); for(int64_t j=0;j<(int64_t)S*D;j++) x[j]+=tmp[j]; if(g_pilot && S<=8 && li+1n_layers && m->L[li+1].sparse) pilot_prefetch(m,li+1,x,S); - if(g_looka && S==1 && li+1n_layers && m->L[li+1].sparse) la_predict(m,li+1,x,1); + if(g_looka && S==1 && li+1n_layers && m->L[li+1].sparse){ + la_predict(m,li+1,x,1); /* baseline: stale-state PILOT */ + la_predict(m,li+1,x,2); /* two-step: shared-expert-corrected prediction */ + } for(int s=0;spost_ln, D, c->eps); if(l->sparse) moe(m,l,li,nrm,S,tmp,1); else dense_mlp(l,nrm,S,D,c->dense_inter,tmp); for(int64_t j=0;j<(int64_t)S*D;j++) x[j]+=tmp[j]; @@ -3445,10 +3522,11 @@ static void run_text(Model *m, const char *snap, const char *prompt, int ngen){ if(g_pilot_real) printf("PILOT_REAL: %ld load cross-layer completati, %ld scartati (main gia' sul layer) | PILOT_K=%d\n", (long)atomic_load_explicit(&g_pilot_loads,memory_order_relaxed), (long)atomic_load_explicit(&g_pilot_drops,memory_order_relaxed), g_pilot_k); + if(g_pilot_two) printf("PILOT_TWO: two-step shared-expert-corrected prefetch active (3 extra matmuls/prediction)\n"); if(g_looka){ - const char *nm[3]={"previous token (=SPEC prefetch)","layer input, skip attention","next layer (one step ahead)"}; + const char *nm[4]={"previous token (=SPEC prefetch)","layer input, skip attention","next layer (PILOT, stale)","next layer (two-step, shared-expert)"}; printf("LOOKAHEAD routing — recall of true experts in predicted top-8:\n"); - for(int i=0;i<3;i++) printf(" %-38s %5.1f%% (%lld/%lld)\n", nm[i], + for(int i=0;i<4;i++) printf(" %-42s %5.1f%% (%lld/%lld)\n", nm[i], la_tot[i]?100.0*la_hit[i]/la_tot[i]:0.0, (long long)la_hit[i], (long long)la_tot[i]); } free(pids); free(all); @@ -4538,6 +4616,8 @@ int main(int argc, char **argv){ g_pilot = getenv("PILOT")?atoi(getenv("PILOT")):0; /* 1 = prefetch pilotato dal router */ g_pilot_real = getenv("PILOT_REAL")?atoi(getenv("PILOT_REAL")):0; /* default OFF: load VERI cross-layer (value-preserving prefetch); PILOT_REAL=1 opta in */ if(g_pilot_real) g_pilot=1; /* PILOT_REAL implica il pilota attivo */ + g_pilot_two = getenv("PILOT_TWO")?atoi(getenv("PILOT_TWO")):0; /* 1 = two-step: shared-expert-corrected router prediction (+2.3% recall, 3 extra matmuls) */ + if(g_pilot_two) g_pilot=1; /* PILOT_TWO implies PILOT active */ /* Default K: hint-only PILOT keeps 8 (WILLNEED hints are free, no eviction). * Under PILOT_REAL the speculative loads are REAL and create LRU eviction * pressure, so at ~28% mispredict a large K thrashes the cache — default to 6 @@ -4759,9 +4839,9 @@ int main(int argc, char **argv){ if(g_cuda_enabled) cuda_stats_print(); #endif if(g_looka){ - const char *nm[3]={"previous token (=SPEC prefetch)","layer input, skip attention","next layer (one step ahead)"}; + const char *nm[4]={"previous token (=SPEC prefetch)","layer input, skip attention","next layer (PILOT, stale)","next layer (two-step, shared-expert)"}; printf("LOOKAHEAD routing — recall of true experts in predicted top-8:\n"); - for(int i=0;i<3;i++) printf(" %-38s %5.1f%% (%lld/%lld)\n", nm[i], + for(int i=0;i<4;i++) printf(" %-42s %5.1f%% (%lld/%lld)\n", nm[i], la_tot[i]?100.0*la_hit[i]/la_tot[i]:0.0, (long long)la_hit[i], (long long)la_tot[i]); } if(stats) stats_dump(&m,stats); From bad64d1b06cbda80dbdfb1f8f502370d0407bcbb Mon Sep 17 00:00:00 2001 From: JustVugg Date: Tue, 14 Jul 2026 20:44:41 +0200 Subject: [PATCH 18/79] Makefile: opt-in NVCC_CCBIN= to override nvcc's host compiler (fixes #211) Co-Authored-By: Claude Opus 4.8 --- c/Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/c/Makefile b/c/Makefile index f779d94..c9b7fc3 100644 --- a/c/Makefile +++ b/c/Makefile @@ -114,6 +114,11 @@ ifneq ($(IS_WIN),) # directory too is symmetric. The installer adds it by default. CUDA_HOME ?= $(subst \,/,$(CUDA_PATH)) NVCC ?= nvcc +# Host compiler override for nvcc (e.g. Fedora ships g++16 but CUDA needs 15): +# make glm CUDA=1 NVCC_CCBIN=g++-15 (opt-in: unset = nvcc's own default) +ifneq ($(NVCC_CCBIN),) +NVCCFLAGS += -ccbin $(NVCC_CCBIN) +endif else CUDA_HOME ?= /usr/local/cuda NVCC ?= $(CUDA_HOME)/bin/nvcc From 8c18b7af6897bd842727f06a8bbcc0622be93e03 Mon Sep 17 00:00:00 2001 From: Kushida Date: Tue, 14 Jul 2026 23:07:41 +0300 Subject: [PATCH 19/79] openai_server: fix path traversal in web static serving (relative_to, not startswith) + empty-prompt validation, with tests (#212) --- c/openai_server.py | 10 ++++++-- c/tests/test_openai_server.py | 43 ++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/c/openai_server.py b/c/openai_server.py index c88888d..f31e8f7 100644 --- a/c/openai_server.py +++ b/c/openai_server.py @@ -731,12 +731,16 @@ class APIHandler(BaseHTTPRequestHandler): Read-only, no auth (same trust level as /health), traversal-safe.""" if path.startswith("/v1/") or path == "/health": return False - base = self.WEB_DIST + base = self.WEB_DIST.resolve() if not base.is_dir(): return False rel = unquote(path).lstrip("/") or "index.html" target = (base / rel).resolve() - if not str(target).startswith(str(base)) or not target.is_file(): + try: + target.relative_to(base) + except ValueError: + target = None + if target is None or not target.is_file(): if path == "/" or "." not in rel: # SPA fallback target = base / "index.html" if not target.is_file(): @@ -1045,6 +1049,8 @@ class APIHandler(BaseHTTPRequestHandler): prompt = body.get("prompt") if not isinstance(prompt, str): raise APIError(400, "Colibri currently requires `prompt` to be a string.", "prompt") + if not prompt: + raise APIError(400, "`prompt` must not be empty.", "prompt") self.generation(body, prompt, request_id, False) diff --git a/c/tests/test_openai_server.py b/c/tests/test_openai_server.py index fd184d6..0064070 100644 --- a/c/tests/test_openai_server.py +++ b/c/tests/test_openai_server.py @@ -2,13 +2,15 @@ import io import json import math import socket +import tempfile import threading import unittest from unittest.mock import patch from urllib.error import HTTPError from urllib.request import Request, urlopen +from pathlib import Path -from openai_server import (APIError, APIServer, ClientCancelled, END, GenerationScheduler, +from openai_server import (APIError, APIHandler, APIServer, ClientCancelled, END, GenerationScheduler, READY, Engine, generation_options, parse_tool_calls, read_engine_turn, render_chat, serve) @@ -490,6 +492,12 @@ class HTTPTest(unittest.TestCase): self.assertEqual(body["choices"][0]["text"], "Héllo") self.assertEqual(self.engine.calls[-1][0], "Complete me") + def test_rejects_empty_legacy_completion(self): + with self.assertRaises(HTTPError) as caught: + self.request("/v1/completions", {"model": "test-model", "prompt": ""}) + self.assertEqual(caught.exception.code, 400) + self.assertEqual(json.load(caught.exception)["error"]["param"], "prompt") + def test_rejects_invalid_stream_options(self): with self.assertRaises(HTTPError) as caught: self.request("/v1/chat/completions", { @@ -499,6 +507,39 @@ class HTTPTest(unittest.TestCase): self.assertEqual(caught.exception.code, 400) +class StaticServingTest(unittest.TestCase): + def setUp(self): + self.tmp = tempfile.TemporaryDirectory() + root = Path(self.tmp.name) + dist = root / "dist" + dist.mkdir() + (dist / "index.html").write_text("dashboard", encoding="utf-8") + sibling = root / "dist-private" + sibling.mkdir() + (sibling / "secret.txt").write_text("private", encoding="utf-8") + self.web_dist = patch.object(APIHandler, "WEB_DIST", dist) + self.web_dist.start() + self.server = APIServer(("127.0.0.1", 0), FakeEngine(), "test-model") + self.thread = threading.Thread(target=self.server.serve_forever, daemon=True) + self.thread.start() + self.base = f"http://127.0.0.1:{self.server.server_port}" + + def tearDown(self): + self.server.scheduler.close() + self.server.shutdown() + self.server.server_close() + self.thread.join(timeout=2) + self.web_dist.stop() + self.tmp.cleanup() + + def test_static_root_stays_inside_dist_directory(self): + with urlopen(self.base + "/", timeout=2) as response: + self.assertEqual(response.read(), b"dashboard") + with self.assertRaises(HTTPError) as caught: + urlopen(self.base + "/%2e%2e/dist-private/secret.txt", timeout=2) + self.assertEqual(caught.exception.code, 404) + + class SchedulerHTTPTest(unittest.TestCase): def setUp(self): self.engine = BlockingEngine() From bfd49c41b9b732f4472cce381609988821b91bf8 Mon Sep 17 00:00:00 2001 From: bopof Date: Tue, 14 Jul 2026 22:07:56 +0200 Subject: [PATCH 20/79] Makefile: select $(PYTHON) from the host, not the target triple (#205) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit clean/test-c/test-python run python on the build host, but $(PYTHON) was chosen from $(IS_WIN), which is derived from the target triple ($(CC) -dumpmachine). A Linux->mingw cross build (make CC=x86_64-w64-mingw32-gcc ...) therefore sets IS_WIN and picks `python`, which fails on hosts where only `python3` exists (e.g. Debian/Ubuntu) — breaking the cross-compile path #171 added. Key PYTHON off the host instead: $(OS)=Windows_NT (the #129 signal) is set in every Windows shell and empty on Linux/macOS. EXE stays driven by the target triple, as it should. Addresses @rofl0r's host/target note on #171. Co-authored-by: bopof <285767350+bopof@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 --- c/Makefile | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/c/Makefile b/c/Makefile index c9b7fc3..de8313c 100644 --- a/c/Makefile +++ b/c/Makefile @@ -134,10 +134,16 @@ NVCCFLAGS ?= -O3 -std=c++17 -arch=$(CUDA_ARCH) -Xcompiler=-W3 else NVCCFLAGS ?= -O3 -std=c++17 -arch=$(CUDA_ARCH) -Xcompiler=-Wall,-Wextra endif -ifeq ($(IS_WIN),) -PYTHON ?= python3 -else +# PYTHON is a HOST tool (clean/test-c/test-python run it on the build machine), +# so key it off the host, NOT $(IS_WIN) — which is derived from the *target* +# triple ($(CC) -dumpmachine). Otherwise a cross build (make CC=x86_64-w64- +# mingw32-gcc ... on Linux) sets IS_WIN and picks `python`, breaking clean/test +# on hosts where only `python3` exists. $(OS)=Windows_NT in every Windows shell +# (the #129 signal) and is empty on Linux/macOS. +ifeq ($(OS),Windows_NT) PYTHON ?= python +else +PYTHON ?= python3 endif CUDA_OBJ = TEST_BINS = tests/test_json$(EXE) tests/test_st$(EXE) tests/test_tier$(EXE) tests/test_grammar$(EXE) tests/test_schema_gbnf$(EXE) tests/test_decode_batch$(EXE) tests/test_idot$(EXE) tests/test_i4_acc512$(EXE) tests/test_compat_direct$(EXE) From 4a936c8af373cbe876eb0343f1569c27b5718c48 Mon Sep 17 00:00:00 2001 From: "yuri@FreeBSD" Date: Tue, 14 Jul 2026 13:08:12 -0700 Subject: [PATCH 21/79] FreeBSD compatibility: platform guards in glm.c/olmoe.c (#206) --- c/glm.c | 19 ++++++++++++------- c/olmoe.c | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/c/glm.c b/c/glm.c index ed9cbea..297b964 100644 --- a/c/glm.c +++ b/c/glm.c @@ -27,10 +27,10 @@ #include /* PIPE ready-flags/job queue + PILOT_REAL cross-layer handshake */ #include /* sched_yield: PIPE spin / PILOT barrier */ #include -#if defined(__APPLE__) || defined(__linux__) +#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) #include /* select() serve-loop polling (#68); not on native MinGW */ #endif -#if defined(__APPLE__) || defined(__linux__) +#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) #include #include /* mlock: inchioda le pagine in RAM / wire pages into RAM */ #include /* fstat per mmap degli shard (COLI_MMAP) */ @@ -1286,7 +1286,7 @@ static void *map_of_fd(int fd){ pthread_mutex_lock(&g_map_mtx); for(int i=0;ioff; size_t n=(size_t)tw[k]->nbytes; -#if defined(__APPLE__) || defined(__linux__) +#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) madvise((void*)((uintptr_t)p & ~16383UL), n+16384, MADV_WILLNEED); #endif volatile char acc=0; @@ -1562,7 +1562,7 @@ static inline void pipe_wait(int q){ #ifdef COLI_CUDA static void expert_host_release(Model *m, ESlot *s){ if(!s->slab&&!s->fslab) return; -#if defined(__APPLE__) || defined(__linux__) +#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) if(s->slab) munlock(s->slab,(size_t)s->slab_cap); if(s->fslab) munlock(s->fslab,(size_t)s->fslab_cap*sizeof(float)); #elif defined(_WIN32) @@ -3900,7 +3900,7 @@ static void run_serve_mux(Model *m, const char *snap){ * the Windows equivalent: it reports bytes available without reading. */ int ready=0; if(!eof){ -#if defined(__APPLE__) || defined(__linux__) +#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) fd_set rfds; FD_ZERO(&rfds); FD_SET(STDIN_FILENO,&rfds); struct timeval tv={0,0}, *ptv=active?&tv:NULL; ready=select(STDIN_FILENO+1,&rfds,NULL,NULL,ptv); @@ -4309,7 +4309,7 @@ static int mem_should_wire(void){ /* Inchioda [addr,addr+len) in RAM fisica. No-op fuori da POSIX (Windows ecc.). * EN: wire [addr,addr+len) into physical RAM. No-op off POSIX (Windows, etc.). */ static int mem_wire(void *addr, size_t len){ -#if defined(__APPLE__) || defined(__linux__) +#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) return mlock(addr, len); #elif defined(_WIN32) return compat_mlock(addr, len); /* VirtualLock + working-set growth */ @@ -4583,6 +4583,11 @@ int main(int argc, char **argv){ fprintf(stderr,"[OMP] hot-thread tuning: re-exec once (COLI_NO_OMP_TUNE=1 to skip)\n"); execv("/proc/self/exe", argv); /* returns only on failure -> fall through and run untuned */ perror("[OMP] execv self-reexec failed, running untuned"); +#endif +#ifdef __FreeBSD__ + fprintf(stderr,"[OMP] hot-thread tuning: re-exec once (COLI_NO_OMP_TUNE=1 to skip)\n"); + execv("/proc/curproc/file", argv); /* returns only on failure -> fall through and run untuned */ + perror("[OMP] execv self-reexec failed, running untuned"); #endif } #if defined(__AVX512F__) && defined(__AVX512BW__) diff --git a/c/olmoe.c b/c/olmoe.c index 1c5ffaa..5923bde 100644 --- a/c/olmoe.c +++ b/c/olmoe.c @@ -12,7 +12,7 @@ #include #include #include -#if defined(__APPLE__) || defined(__linux__) +#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) #include #endif #include "st.h" From 62419af1884af321458472f6927c63ab07f67427 Mon Sep 17 00:00:00 2001 From: Marquez Date: Tue, 14 Jul 2026 20:08:28 +0000 Subject: [PATCH 22/79] =?UTF-8?q?routing:=20opt-in=20CACHE=5FROUTE=20max-r?= =?UTF-8?q?ank=20prefer=20(pin=E2=88=AALRU),=20default=20off=20=E2=80=94?= =?UTF-8?q?=202.4->3.33=20tok/s=20on=20GB10=20(#199)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Paper-style cache-aware MoE selection (arXiv:2412.00099 max-rank): keep true top-J always; fill remaining K slots preferring experts already resident in pin∪LRU within top-M. Default OFF so stock full top-K is unchanged. Env: CACHE_ROUTE, ROUTE_J/M/P/ALPHA, ROUTE_AGREE (auto-on with CACHE_ROUTE). Telemetry: swap%/route_swaps/route_slots, route_agree, route_kl on footer and serve STAT. Complementary to PILOT (prefetch vs selection change). Routing-only PR for clean A/B vs PILOT / #119; no CUDA/fuse stack. See docs/CACHE_ROUTE.md. Closes nothing; for #161 discussion. Co-authored-by: Vincent Marquez --- c/glm.c | 200 +++++++++++++++++++++++++++++++++++++++++--- docs/CACHE_ROUTE.md | 65 ++++++++++++++ docs/ENVIRONMENT.md | 6 ++ 3 files changed, 259 insertions(+), 12 deletions(-) create mode 100644 docs/CACHE_ROUTE.md diff --git a/c/glm.c b/c/glm.c index 297b964..8da3f55 100644 --- a/c/glm.c +++ b/c/glm.c @@ -178,6 +178,9 @@ typedef struct { uint64_t eclock, hits, miss, ereq; uint64_t gpu_expert_calls; int gpu_expert_count; int64_t gpu_expert_bytes; uint64_t n_fw, n_emit; /* metodo E: forward di decode / token emessi */ + uint64_t route_slots, route_swaps; /* CACHE_ROUTE: slots chosen / substituted vs true top-K */ + uint64_t route_agree_hit, route_agree_tot; /* ROUTE_AGREE: |chosen ∩ true top-K| / K */ + double route_kl_sum; uint64_t route_kl_n; /* mean KL(true||chosen) on gate mass */ double t_edisk, t_ewait, t_emm, t_attn, t_kvb, t_head;/* profiling: dove va il tempo */ double t_aproj,t_acore,t_aout; /* attention breakdown */ int64_t resident_bytes; @@ -840,6 +843,15 @@ static float g_temp=-1; /* TEMP: temperatura di sampling sui TOKEN. <0 = auto ( static float g_nuc=0.95f;/* NUCLEUS: top-p sul vocabolario (default dal generation_config GLM-5.2) */ static int g_topk=0; /* TOPK=n -> usa n expert/token invece di config (ricerca: meno disco) */ static float g_topp=0; /* TOPP=p (0..1) -> top-p adattivo: tieni gli expert fino a peso cumulato p */ +/* CACHE_ROUTE (paper 2412.00099 max-rank): opt-in only. Keep true top-J always; + * fill remaining slots preferring pin∪LRU experts ranked within top-M (or mass ROUTE_P). */ +static int g_cache_route=0; +static int g_route_j=2; /* ROUTE_J: sacred top ranks (always take, even uncached) */ +static int g_route_m=12; /* ROUTE_M: max-rank window for cache-preferring fill */ +static float g_route_p=0; /* ROUTE_P: if >0, choose M from cumulative router mass instead */ +static float g_route_alpha=1.f; /* ROUTE_ALPHA: scale gate mass of CACHE_ROUTE substitutes before renorm (1=off) */ +static int g_route_agree=0; /* ROUTE_AGREE=1: footer overlap% + mean KL vs true top-K */ +static int expert_is_resident(Model *m, int layer, int eid); /* pin∪LRU; defined near pilot */ static int g_spec=1; /* metodo C: SPEC=0 disabilita il prefetch speculativo cross-layer */ static int g_draft=0; /* metodo E: DRAFT=n token auto-speculati per forward via n-gram lookup * (0=off). LOSSLESS: verifica = output identico al greedy. Default OFF: @@ -2084,6 +2096,15 @@ static void attention(Model *m, Layer *l, int layer, float *x, int S, int pos_ba * una volta sola e moltiplicato per tutte le posizioni che lo usano (pesi letti 1 volta); * lo shared expert e' un unico matmul a S righe. Per posizione l'accumulo resta * nell'ordine (routed nel loro ordine di union, poi shared). */ +/* pin ∪ LRU residency probe (used by CACHE_ROUTE max-rank fill). */ +static int expert_is_resident(Model *m, int layer, int eid){ + ESlot *P=m->pin[layer]; + for(int z=0;znpin[layer];z++) if(P[z].eid==eid) return 1; + ESlot *Sl=m->ecache[layer]; + for(int z=0;zecn[layer];z++) if(Sl[z].eid==eid) return 1; + return 0; +} + static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out, int with_shared){ if(g_pilot_real){ /* barriera cross-layer: prendi possesso di QUESTO layer e aspetta * l'eventuale load-pilota in volo sullo stesso layer (dopodiche' il @@ -2101,6 +2122,16 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out, int Cfg *c=&m->c; int D=c->hidden, E=c->n_experts, K=c->topk, I=c->moe_inter; float *choice=falloc(E); int sI=c->moe_inter*c->n_shared; + /* Rank buffer for CACHE_ROUTE max-rank selection (up to all E experts). */ + int *rank_buf=NULL; float *rank_w=NULL; + int do_cache_route = g_cache_route && E>0 && K>0; + int rank_cap = do_cache_route ? (g_route_m>K?g_route_m:K) : 0; + if(rank_cap>E) rank_cap=E; + if(do_cache_route){ + rank_buf=malloc((size_t)rank_cap*sizeof(int)); + rank_w=malloc((size_t)rank_cap*sizeof(float)); + if(!rank_buf||!rank_w){ free(rank_buf); free(rank_w); rank_buf=NULL; rank_w=NULL; do_cache_route=0; } + } /* ---- FASE A: routing di tutte le S posizioni ---- */ int *idxs=malloc((size_t)S*K*sizeof(int)); float *ws=malloc((size_t)S*K*sizeof(float)); int *keff=malloc(S*sizeof(int)); @@ -2131,10 +2162,101 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out, int for(int e=0;erouter_bias[e]; } int *idx=idxs+(int64_t)s*K; float *w=ws+(int64_t)s*K; int Ksel = g_topk>0 ? (g_topkbv){bv=choice[e];best=e;} } - idx[kk]=best; w[kk]=logit[best]; + if(do_cache_route){ + /* Full ranking of top rank_cap experts by choice (bias-augmented). */ + int Mwin=rank_cap; + if(g_route_p>0.f && g_route_p<1.f){ + /* Cumulative-mass variant: grow M until mass covers ROUTE_P. */ + int Mmax=g_route_m>Ksel*4?g_route_m:Ksel*4; if(Mmax>E) Mmax=E; if(Mmax>rank_cap) Mmax=rank_cap; + for(int kk=0;kkbv){bv=choice[e];best=e;} } + rank_buf[kk]=best; rank_w[kk]=logit[best]; + } + float tot=1e-20f; for(int kk=0;kk0?rank_w[kk]:0; + float cum=0; Mwin=Ksel; + for(int kk=0;kk0?rank_w[kk]:0; + if(cum>=g_route_p*tot){ Mwin=kk+1; break; } Mwin=kk+1; } + if(Mwinbv){bv=choice[e];best=e;} } + rank_buf[kk]=best; rank_w[kk]=logit[best]; + } + } + int J=g_route_j; if(J<0) J=0; if(J>Ksel) J=Ksel; + int chosen=0; + /* Always take true top-J (even if uncached). */ + for(int kk=0;kkroute_slots+=(uint64_t)Ksel; + for(int kk=0;kkroute_swaps++; + } + /* Pad if somehow short (shouldn't happen). */ + while(chosen0.f && g_route_alpha<1.f){ + for(int kk=0;kkroute_agree_hit+=(uint64_t)ov; + m->route_agree_tot+=(uint64_t)Ksel; + float tsum=1e-20f, csum=1e-20f; + for(int t=0;t0?rank_w[t]:0; + for(int kk=0;kk0?w[kk]:0; + double kl=0; + for(int t=0;t0?rank_w[t]:0)/tsum; + if(pt<=0) continue; + double pc=1e-12; + for(int kk=0;kk0?w[kk]:0)/csum; break; } + kl+=pt*log(pt/pc); + } + m->route_kl_sum+=kl; m->route_kl_n++; + } + } else { + for(int kk=0;kkbv){bv=choice[e];best=e;} } + idx[kk]=best; w[kk]=logit[best]; + } + if(g_route_agree){ + m->route_agree_hit+=(uint64_t)Ksel; + m->route_agree_tot+=(uint64_t)Ksel; + m->route_kl_sum+=0; m->route_kl_n++; + } } int Ke=Ksel; if(g_topp>0 && g_topp<1.f){ @@ -2159,6 +2281,7 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out, int } for(int d=0;dT,&t,1,dec,63); dec[dn]=0; fputs(dec,stdout); fflush(stdout); if(!e->quiet && ++e->count%16==0){ double tt=e->m->hits+e->m->miss; - fprintf(stderr,"\n[t=%d RSS %.2f GB hit %.0f%% %.2f tok/s %.2f tok/fw]\n", e->count, - rss_gb(), tt?100.0*e->m->hits/tt:0.0, e->count/(now_s()-e->t0), - e->m->n_fw?(double)e->m->n_emit/e->m->n_fw:1.0); } + if(g_cache_route && e->m->route_slots){ + double swap=100.0*e->m->route_swaps/e->m->route_slots; + fprintf(stderr,"\n[t=%d RSS %.2f GB hit %.0f%% swap %.0f%% %.2f tok/s %.2f tok/fw]\n", e->count, + rss_gb(), tt?100.0*e->m->hits/tt:0.0, swap, e->count/(now_s()-e->t0), + e->m->n_fw?(double)e->m->n_emit/e->m->n_fw:1.0); + } else { + fprintf(stderr,"\n[t=%d RSS %.2f GB hit %.0f%% %.2f tok/s %.2f tok/fw]\n", e->count, + rss_gb(), tt?100.0*e->m->hits/tt:0.0, e->count/(now_s()-e->t0), + e->m->n_fw?(double)e->m->n_emit/e->m->n_fw:1.0); + } + } } /* teacher-forcing: un solo forward su ids[S], argmax per posizione in pred[S] */ @@ -3503,10 +3634,21 @@ static void run_text(Model *m, const char *snap, const char *prompt, int ngen){ double tot=m->hits+m->miss; int nsp=0; for(int i=0;in_layers;i++) if(m->L[i].sparse) nsp++; printf("\n---\nprefill %d tokens in %.2fs | decode %d tokens in %.2fs (%.2f tok/s) | " - "expert hit rate %.1f%% | RSS %.2f GB\n", + "expert hit rate %.1f%% | RSS %.2f GB", np,prefill_t,produced,dt,produced/dt,tot?100.0*m->hits/tot:0.0,rss_gb()); - printf("experts loaded/token: %.1f (per-layer %.2f across %d; baseline topk=%d) | TOPK=%d TOPP=%.2f\n", + if(g_cache_route && m->route_slots) + printf(" | swap %.1f%% (%llu/%llu)", + 100.0*m->route_swaps/m->route_slots, + (unsigned long long)m->route_swaps,(unsigned long long)m->route_slots); + if(m->route_agree_tot) + printf(" | route_agree %.1f%% | route_kl %.4f", + 100.0*m->route_agree_hit/m->route_agree_tot, + m->route_kl_n?m->route_kl_sum/(double)m->route_kl_n:0.0); + printf("\n"); + printf("experts loaded/token: %.1f (per-layer %.2f across %d; baseline topk=%d) | TOPK=%d TOPP=%.2f", produced?(double)m->ereq/produced:0.0, (produced&&nsp)?(double)m->ereq/produced/nsp:0.0, nsp, c->topk, g_topk, g_topp); + if(g_cache_route) printf(" | CACHE_ROUTE J=%d M=%d P=%.2f alpha=%.2f", g_route_j, g_route_m, g_route_p, g_route_alpha); + printf("\n"); printf("speculation: %.2f tokens/forward (%llu forwards per %llu tokens) | MTP acceptance %.0f%% (%llu/%llu)\n", m->n_fw?(double)m->n_emit/m->n_fw:1.0, (unsigned long long)m->n_fw, (unsigned long long)m->n_emit, m->mtp_prop?100.0*m->mtp_acc/m->mtp_prop:0.0, (unsigned long long)m->mtp_acc, (unsigned long long)m->mtp_prop); @@ -4068,7 +4210,11 @@ static void run_serve(Model *m, const char *snap){ printf("\x01\x01" "END" "\x01\x01\n"); printf("STAT 0 0.00 0.0 %.2f 0 0\n", rss_gb()); fflush(stdout); continue; } first=0; int cur=req_ngen; if(len+k+cur+g_draft+2>=maxctx) cur=maxctx-len-k-g_draft-2; - uint64_t h0=m->hits, ms0=m->miss; double tt0=now_s(); + uint64_t h0=m->hits, ms0=m->miss; + uint64_t rs0=m->route_slots, rw0=m->route_swaps; + uint64_t agh0=m->route_agree_hit, agt0=m->route_agree_tot; + uint64_t kln0=m->route_kl_n; double kls0=m->route_kl_sum; + double tt0=now_s(); float *logit; if(k>0){ logit=step(m,hist+len,k,len); len+=k; } else logit=step(m,hist+len-1,1,len-1); /* prompt identico/prefisso: rigenera i logits */ @@ -4079,9 +4225,21 @@ static void run_serve(Model *m, const char *snap){ else free(logit); double tdt=now_s()-tt0; if(tdt<1e-6) tdt=1e-6; double dh=(double)(m->hits-h0), dm=(double)(m->miss-ms0); + uint64_t rslots=m->route_slots-rs0, rswaps=m->route_swaps-rw0; + double swap_pct=rslots?100.0*rswaps/rslots:0.0; + uint64_t ag_hit=m->route_agree_hit-agh0, ag_tot=m->route_agree_tot-agt0; + uint64_t kl_n=m->route_kl_n-kln0; double kl_sum=m->route_kl_sum-kls0; + double agree_pct=ag_tot?100.0*ag_hit/ag_tot:100.0; + double kl_mean=kl_n?kl_sum/(double)kl_n:0.0; printf("%s\x01\x01" "END" "\x01\x01\n",raw_mode?"":"\n"); - printf("STAT %d %.2f %.1f %.2f %d %d\n", prod, prod/tdt, + printf("STAT %d %.2f %.1f %.2f %d %d", prod, prod/tdt, (dh+dm)>0?100.0*dh/(dh+dm):0.0, rss_gb(), prompt_tokens, prod>=cur); + if(g_cache_route || rslots || ag_tot) + printf(" swap_pct=%.1f route_swaps=%llu route_slots=%llu" + " route_agree=%.1f route_kl=%.4f", + swap_pct,(unsigned long long)rswaps,(unsigned long long)rslots, + agree_pct,kl_mean); + printf("\n"); fflush(stdout); free(raw); g_temp=base_temp; g_nuc=base_nuc; usage_save(m); /* la cache che impara: storia aggiornata a ogni turno */ @@ -4605,6 +4763,24 @@ int main(int argc, char **argv){ if(g_mmap) fprintf(stderr,"[MMAP] expert = viste zero-copy nei file (page cache = cache)\n"); g_topk = getenv("TOPK")?atoi(getenv("TOPK")):0; g_topp = getenv("TOPP")?atof(getenv("TOPP")):0; + g_cache_route = getenv("CACHE_ROUTE")?atoi(getenv("CACHE_ROUTE")):0; + g_route_j = getenv("ROUTE_J")?atoi(getenv("ROUTE_J")):2; + g_route_m = getenv("ROUTE_M")?atoi(getenv("ROUTE_M")):12; + g_route_p = getenv("ROUTE_P")?atof(getenv("ROUTE_P")):0; + g_route_alpha = getenv("ROUTE_ALPHA")?atof(getenv("ROUTE_ALPHA")):1.f; + g_route_agree = getenv("ROUTE_AGREE")?atoi(getenv("ROUTE_AGREE")):0; + if(g_route_j<0) g_route_j=0; + if(g_route_m<1) g_route_m=1; + if(g_route_m>4096) g_route_m=4096; + if(g_route_alpha<=0.f) g_route_alpha=1.f; + if(g_route_alpha>1.f) g_route_alpha=1.f; + if(g_cache_route) + fprintf(stderr,"[CACHE_ROUTE] on J=%d M=%d P=%.2f alpha=%.2f (pin∪LRU prefer; never default)\n", + g_route_j,g_route_m,g_route_p,g_route_alpha); + if(g_route_agree) + fprintf(stderr,"[ROUTE_AGREE] telemetry on (overlap%% + mean KL vs true top-K)\n"); + /* Auto-enable agree telemetry when CACHE_ROUTE is on (cheap quality leading indicator). */ + if(g_cache_route && !getenv("ROUTE_AGREE")) g_route_agree=1; const char *policy=getenv("COLI_POLICY"); if(!policy) policy="quality"; int experimental=!strcmp(policy,"experimental-fast"); if(strcmp(policy,"quality")&&strcmp(policy,"balanced")&&!experimental){ diff --git a/docs/CACHE_ROUTE.md b/docs/CACHE_ROUTE.md new file mode 100644 index 0000000..78f47e9 --- /dev/null +++ b/docs/CACHE_ROUTE.md @@ -0,0 +1,65 @@ +# CACHE_ROUTE — opt-in cache-aware MoE routing + +**Default: OFF.** Stock full top-K router behavior unless `CACHE_ROUTE=1`. + +Paper-style max-rank selection (arXiv:2412.00099): keep true top-`J` always; +fill remaining slots preferring experts already **resident** (pin ∪ LRU) that +still rank inside top-`M`. + +This is **routing-side** (can change which experts run). Complementary to +**PILOT** (next-layer *prefetch* of weights; does not change expert IDs). + +## Flags + +| Env | Default | Meaning | +|-----|---------|---------| +| `CACHE_ROUTE` | `0` | `1` = max-rank cache-aware fill (pin∪LRU prefer) | +| `ROUTE_J` | `2` | Always take true top-J (even if uncached) | +| `ROUTE_M` | `12` | Max-rank window for resident preference | +| `ROUTE_P` | `0` | Optional cumulative mass window (`0` = use fixed M) | +| `ROUTE_ALPHA` | `1` | Scale gate mass of *substituted* experts before renorm (`1` = off) | +| `ROUTE_AGREE` | auto | Overlap% + KL vs true top-K; auto-on when `CACHE_ROUTE=1` | + +## One-liners + +```bash +# Stock full-K (leaderboard-comparable routing) +CACHE_ROUTE=0 ./coli chat + +# Experimental CACHE_ROUTE +CACHE_ROUTE=1 ROUTE_J=2 ROUTE_M=12 ./coli chat + +# Wider prefer window (more hit, more possible swap) +CACHE_ROUTE=1 ROUTE_J=2 ROUTE_M=16 ./coli chat +``` + +## Stats + +Footer / serve `STAT` when enabled: + +- `swap N%` / `swap_pct` — fraction of chosen slots not in true top-K +- `route_swaps` / `route_slots` — raw substitution counters +- `route_agree` — |chosen ∩ true top-K| / K +- `route_kl` — mass KL (true top-K vs chosen) +- `hit N%` — expert cache hit (disk residency) + +## A/B vs PILOT + +```bash +# A: cache-aware routing only +CACHE_ROUTE=1 PILOT=0 ... + +# B: lookahead prefetch only (does not change expert IDs) +CACHE_ROUTE=0 PILOT=1 ... + +# C: both +CACHE_ROUTE=1 PILOT=1 ... +``` + +## Scope of this PR + +**Routing-only** + telemetry + this note. Does **not** require CUDA/fuse/device-tier +patches — CPU streaming + pin/LRU is enough to A/B the lever against PILOT / #119. + +Treat as experimental until quality gates (e.g. `./coli bench`) pass; do not +default `CACHE_ROUTE=1`. diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index 6d73f3a..c1f42ec 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -53,6 +53,12 @@ Format: `VAR` — default — effect. | `PILOT` | `0` (off) | Router-piloted cross-layer expert prefetch. | | `PILOT_REAL` | `0` (off) | Value-preserving real cross-layer prefetch loads (`PILOT_REAL=1` opts in). | | `PILOT_K` | `6` if `PILOT_REAL` else `8` | Number of experts the pilot prefetches per step. | +| `CACHE_ROUTE` | `0` (off) | Opt-in max-rank cache-aware MoE routing (pin∪LRU prefer within top-M). See [CACHE_ROUTE.md](CACHE_ROUTE.md). | +| `ROUTE_J` | `2` | Sacred top ranks always taken when `CACHE_ROUTE=1`. | +| `ROUTE_M` | `12` | Max-rank window for resident preference when `CACHE_ROUTE=1`. | +| `ROUTE_P` | `0` | Cumulative mass window for CACHE_ROUTE (`0` = fixed M). | +| `ROUTE_ALPHA` | `1` | Scale gate mass of substituted experts before renorm (`1` = off). | +| `ROUTE_AGREE` | auto | Overlap% + KL vs true top-K; auto-on when `CACHE_ROUTE=1`. | | `ABSORB` | `-1` (auto: absorbed for S≤4) | MLA attention absorption mode. | | `IDOT` | `1` | Integer dot-product kernel. `IDOT=0` uses exact f32 kernels (for A/B numerical checks). | | `COLI_POLICY` | `quality` | Resource policy: `quality`, `balanced`, or `experimental-fast`. | From 69004f73c2926f84f9a1f50905e348df718e69c9 Mon Sep 17 00:00:00 2001 From: Michael Denyer Date: Wed, 15 Jul 2026 00:32:58 +0100 Subject: [PATCH 23/79] tests: kv_alloc re-allocation regression test kv_alloc guards every KVState free with if(k->Lc) precisely so it can be called again on the same KVState (context resize, slot re-init). Exercise that path: allocate, touch the cache, allocate again at a larger size. Fails at this commit with a double-free (fixed in the next commit): malloc: *** error for object 0x7: pointer being freed was not allocated --- c/Makefile | 5 ++++- c/tests/test_kv_alloc.c | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 c/tests/test_kv_alloc.c diff --git a/c/Makefile b/c/Makefile index de8313c..1e0b1ea 100644 --- a/c/Makefile +++ b/c/Makefile @@ -146,7 +146,7 @@ else PYTHON ?= python3 endif CUDA_OBJ = -TEST_BINS = tests/test_json$(EXE) tests/test_st$(EXE) tests/test_tier$(EXE) tests/test_grammar$(EXE) tests/test_schema_gbnf$(EXE) tests/test_decode_batch$(EXE) tests/test_idot$(EXE) tests/test_i4_acc512$(EXE) tests/test_compat_direct$(EXE) +TEST_BINS = tests/test_json$(EXE) tests/test_st$(EXE) tests/test_tier$(EXE) tests/test_grammar$(EXE) tests/test_schema_gbnf$(EXE) tests/test_decode_batch$(EXE) tests/test_idot$(EXE) tests/test_kv_alloc$(EXE) tests/test_i4_acc512$(EXE) tests/test_compat_direct$(EXE) # Windows CUDA DLL path: host links the loader, NOT cudart. ifneq ($(IS_WIN),) @@ -260,6 +260,9 @@ tests/test_decode_batch$(EXE): tests/test_decode_batch.c decode_batch.h tests/test_idot$(EXE): tests/test_idot.c glm.c st.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) +tests/test_kv_alloc$(EXE): tests/test_kv_alloc.c glm.c st.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h + $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) + tests/test_i4_acc512$(EXE): tests/test_i4_acc512.c $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) diff --git a/c/tests/test_kv_alloc.c b/c/tests/test_kv_alloc.c new file mode 100644 index 0000000..40ec00d --- /dev/null +++ b/c/tests/test_kv_alloc.c @@ -0,0 +1,23 @@ +/* kv_alloc must survive re-allocation on the same KVState: every free path is + * guarded by if(k->Lc) precisely so callers (context resize, slot re-init) can + * call it again. A stale duplicate free block frees every Lc[i]/Rc[i] and both + * arrays twice on the second call -> allocator abort. No model file needed: + * the CPU path of kv_alloc only reads c->n_layers/kv_lora/qk_rope. */ +#define main coli_glm_main_unused +#include "../glm.c" +#undef main + +int main(void){ + static Model m; + m.c.n_layers=2; m.c.kv_lora=8; m.c.qk_rope=4; + m.kv=calloc(1,sizeof(KVState)); + kv_alloc(&m,16); + for(int i=0;i Date: Wed, 15 Jul 2026 00:33:45 +0100 Subject: [PATCH 24/79] glm: fix kv_alloc double-free on KV re-allocation (stale pre-Metal free block) kv_alloc had two consecutive if(k->Lc) free blocks. The first freed every k->Lc[i]/k->Rc[i] and both arrays without unregistering from Metal and without nulling k->Lc; the second then re-tested the dangling pointer, called coli_metal_unregister on freed pointers, and freed everything a second time. Safe only when k->Lc is NULL (first call); any re-allocation on the same KVState aborts in the allocator. The first block is the pre-Metal version of the free path: 3716e40 (Metal backend) replaced it with the Metal-aware block, and ec89136 (GPU resident pipeline) re-added it above during the merge. Delete it so the Metal-aware block is the only free path. Caught by tests/test_kv_alloc from the previous commit: before: malloc: *** error for object 0x7: pointer being freed was not allocated (exit 134) after: OK kv_alloc re-allocation (exit 0) --- c/glm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/c/glm.c b/c/glm.c index 8da3f55..6b3b140 100644 --- a/c/glm.c +++ b/c/glm.c @@ -3066,7 +3066,6 @@ static void kv_alloc(Model *m, int max_t){ m->kv_dev_valid[i]=0; } #endif - if(k->Lc){ for(int i=0;in_layers+1;i++){ free(k->Lc[i]); free(k->Rc[i]); } free(k->Lc); free(k->Rc); } if(k->Lc){ for(int i=0;in_layers+1;i++){ #ifdef COLI_METAL if(g_metal_enabled){ coli_metal_unregister(k->Lc[i]); coli_metal_unregister(k->Rc[i]); } From 416570339fa79083e45dff325a98c016309cb6cd Mon Sep 17 00:00:00 2001 From: Michael Denyer <97485362+michael-denyer@users.noreply.github.com> Date: Wed, 15 Jul 2026 06:40:42 +0100 Subject: [PATCH 25/79] =?UTF-8?q?tests:=20remove=20accidentally=20committe?= =?UTF-8?q?d=20Linux=20test=20binaries=20+=20gitignore=20them=20=E2=80=94?= =?UTF-8?q?=20fixes=20make=20test-c=20on=20non-Linux=20(#226)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit c/tests/test_schema_gbnf and c/tests/test_compat_direct were committed as Linux x86-64 ELF executables (slipped in via #111). On any other platform make test-c considers them up to date and execs them, failing with OSError: [Errno 8] Exec format error. Remove them and add the two names to .gitignore alongside the other test binaries already listed, so each platform rebuilds its own. --- .gitignore | 4 ++++ c/tests/test_compat_direct | Bin 16208 -> 0 bytes c/tests/test_schema_gbnf | Bin 50648 -> 0 bytes 3 files changed, 4 insertions(+) delete mode 100755 c/tests/test_compat_direct delete mode 100755 c/tests/test_schema_gbnf diff --git a/.gitignore b/.gitignore index ce6a80c..dba6a3f 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,10 @@ c/tests/test_tier c/tests/test_tier.exe c/tests/test_grammar c/tests/test_grammar.exe +c/tests/test_schema_gbnf +c/tests/test_schema_gbnf.exe +c/tests/test_compat_direct +c/tests/test_compat_direct.exe # oracoli tiny generati (make_glm_oracle.py) e dati benchmark scaricati c/glm_tiny/ diff --git a/c/tests/test_compat_direct b/c/tests/test_compat_direct deleted file mode 100755 index 074a7baf262a18295a974bd917c31d4e8f22ee46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16208 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 From a28f31fa3b4c57b0e6ef199e50add578a7ce7cb7 Mon Sep 17 00:00:00 2001 From: Dennis Paul Date: Wed, 15 Jul 2026 07:41:24 +0200 Subject: [PATCH 26/79] =?UTF-8?q?tools:=20expert=5Fatlas=20=E2=80=94=20con?= =?UTF-8?q?found-controlled=20probe=20harness=20for=20the=20GLM-5.2=20expe?= =?UTF-8?q?rt=20atlas=20(#175)=20(#218)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Probe sweep + affinity analysis + leave-one-prompt-out validation, so anyone can build and cross-validate the atlas on their own box rather than trusting one machine. The four traps this harness exists to control (each silently corrupts the atlas): --topp prunes experts by cumulative probability. Measured, same prompt: topp=0 -> 21,000 selections across 7,587 distinct experts topp=0.7 -> 11,944 selections across 4,687 distinct experts It hides 38% of the experts, and it is the recommended speed setting. MTP/DRAFT eusage is incremented inside moe(), BEFORE verification, so rejected speculative drafts count experts routed for text never emitted. .coli_usage is loaded at startup and accumulates, so a naive STATS dump contains all prior history rather than this run. autocorrelation: routing within one run is highly correlated, so an expert firing 38 times during one prompt is ONE observation, not 38. Entropy/chi-square on raw selections certifies single-prompt flukes as perfect specialists — analyze.py therefore requires affinity to replicate across a category independent prompts. Result on GLM-5.2 744B int4 (Zen5, CPU routing path), 10 topics x 3 prompts x 64 tokens: leave-one-prompt-out accuracy 29/30 = 96.7% (chance 10%) strong specialists (spec>=0.5) 1,041 / 13,260 (7.9%) specialisation vs depth layer 3 ~0.07 -> layers 18-58 ~0.19-0.27 replication gate rejected 587 single-prompt flukes The one miss is the interesting part: a Chinese-language poetry prompt classifies as poetry, not Chinese — routing follows the task over the language. --- c/tools/expert_atlas/README.md | 62 +++++++++++++++ c/tools/expert_atlas/analyze.py | 126 +++++++++++++++++++++++++++++++ c/tools/expert_atlas/probes.json | 54 +++++++++++++ c/tools/expert_atlas/sweep.sh | 82 ++++++++++++++++++++ c/tools/expert_atlas/validate.py | 79 +++++++++++++++++++ 5 files changed, 403 insertions(+) create mode 100644 c/tools/expert_atlas/README.md create mode 100644 c/tools/expert_atlas/analyze.py create mode 100644 c/tools/expert_atlas/probes.json create mode 100755 c/tools/expert_atlas/sweep.sh create mode 100644 c/tools/expert_atlas/validate.py diff --git a/c/tools/expert_atlas/README.md b/c/tools/expert_atlas/README.md new file mode 100644 index 0000000..8308d73 --- /dev/null +++ b/c/tools/expert_atlas/README.md @@ -0,0 +1,62 @@ +# Expert Atlas — what does each of the 19,456 experts actually do? + +Probe harness for #175. Runs a set of topic-tagged prompts, dumps each run's expert-routing +histogram, and turns them into a per-expert topic-affinity vector. + +```bash +cd c +export COLI_MODEL=/path/to/glm52_i4 +./tools/expert_atlas/sweep.sh # 30 probes (10 topics x 3 prompts) +python3 tools/expert_atlas/analyze.py --stats atlas_out/stats --out atlas_out/experts.json +python3 tools/expert_atlas/validate.py atlas_out/stats 200 # leave-one-prompt-out check +``` + +## Read this before you trust any atlas + +Four things silently corrupt this measurement. The sweep script controls all of them; if you +roll your own, don't skip them. + +| trap | effect | control | +|---|---|---| +| **`--topp`** | prunes experts by cumulative probability — measured: it hides **38% of the distinct experts** (7,587 → 4,687). It is also the *recommended speed setting*. | `TOPP=0` | +| **speculative drafts** | `eusage` is incremented inside `moe()`, *before* verification, so **rejected** drafts count. Those are experts routed for text the model never emitted. | `MTP=0 DRAFT=0` | +| **`.coli_usage`** | is loaded at startup and accumulates, so a naive `STATS` dump contains **all prior history**, not this run. | remove per run (script backs it up and restores) | +| **autocorrelation** | routing inside one run is highly correlated — the same context routes to the same experts token after token. An expert firing 38 times during one prompt is **one** observation, not 38. Chi-square/entropy on raw selections will certify single-prompt flukes as perfect specialists. | `analyze.py` requires the affinity to **replicate across a category's independent prompts** | + +The CUDA expert tier is also not run-to-run deterministic, so the sweep uses `--gpu none`. Tier +config only decides *where weights live*, not what the router picks, so this costs nothing. + +## Method + +`analyze.py`: + +1. `n[e][c]` — selections of expert *e* while running category *c* +2. `f[e][c] = n[e][c] / N[c]` — normalise by **category size** (prefill routes the prompt too, so a + verbose category would otherwise look busier) +3. `p(c|e)` — renormalise into a topic distribution per expert, i.e. base-rate corrected. Ranking + by raw count instead just rediscovers which experts are popular in general. +4. `spec(e) = 1 − H(p(c|e)) / log C` — 0 = generalist, 1 = fires for exactly one topic +5. **replication gate** — an expert is only a candidate specialist for *c* if it fires in ≥2 of *c*'s + independent prompts + +`validate.py` — leave-one-prompt-out. Build each category's top-K specialist set from its *other* +prompts, then check which set the held-out prompt's routing actually lands in. If specialisation +were an artifact of prompt wording, the held-out prompt would not prefer its own category. + +## Result on GLM-5.2 744B int4 (Zen5, CPU routing path) + +- **Leave-one-prompt-out: 29/30 = 96.7%** (chance 10%). Specialisation is a property of the topic, + not of prompt wording. +- The single miss is instructive: `写一首关于秋天的短诗` ("write a short poem about autumn") is + classified **poetry**, not Chinese — routing follows the **task** over the **language**. +- **Only 7.9% of experts are strong specialists** (spec ≥ 0.5). The "one expert = one topic" + picture is wrong for ~92% of them. +- Specialisation **rises with depth**: layer 3 ≈ 0.07 (generalist, token/syntax level) → layers + 18–58 ≈ 0.19–0.27. +- The replication gate removed **587** experts that looked like flawless specialists on one prompt. + +## Extending it + +`probes.json` is the whole probe set — add categories and prompts. Use **3+ prompts per category +with varied phrasing**, or the replication gate has nothing to check and you are back to measuring +one prompt. Keep prompt lengths in a similar band across categories. diff --git a/c/tools/expert_atlas/analyze.py b/c/tools/expert_atlas/analyze.py new file mode 100644 index 0000000..b457be4 --- /dev/null +++ b/c/tools/expert_atlas/analyze.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +"""GLM-5.2 Expert Atlas — affinity with CROSS-PROMPT REPLICATION (#175). + +Fixes a trap in the naive version. Routing selections inside one run are heavily correlated: +the same context routes to the same experts token after token. So an expert that fires 38 +times during a single 'code' prompt is ONE effective observation, not 38 independent draws. +Treat them as independent and a chi-square will happily certify a single-prompt fluke as a +perfect specialist (spec=1.000, lift=10.0) on 38 selections. It is measuring one prompt. + +So specialisation is only claimed when it REPLICATES across the independent prompts of a +category: + - each category has R prompts (here 3), each run is one replicate + - share[e][run] = selections of e in that run / total selections in that run + - an expert is a candidate specialist for category c only if it fires in >= MIN_RUNS of + c's runs (default 2/3) -> it is a property of the TOPIC, not of one prompt's wording + - affinity uses the MEAN share across a category's runs, so one hot run cannot carry it + - reliability = (runs in top category) / (runs in that category) + +Also reports the generalist/specialist split by layer depth, which is an average over +thousands of experts and is robust to the above. +""" +import argparse, glob, json, math, os +from collections import defaultdict + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--stats", default="stats") + ap.add_argument("--min-count", type=int, default=30) + ap.add_argument("--min-runs", type=int, default=2, help="must fire in >= this many of the top category's runs") + ap.add_argument("--out", default="experts.json") + a = ap.parse_args() + + # run[(cat,idx)][(layer,expert)] = count ; run_tot[(cat,idx)] = total + run_counts, run_tot = defaultdict(dict), defaultdict(int) + for path in sorted(glob.glob(os.path.join(a.stats, "*.txt"))): + base = os.path.basename(path)[:-4] + cat, idx = base.rsplit("_", 1) + for line in open(path): + p = line.split() + if len(p) != 3: + continue + l, e, n = int(p[0]), int(p[1]), int(p[2]) + run_counts[(cat, idx)][(l, e)] = n + run_tot[(cat, idx)] += n + + cats = sorted({c for c, _ in run_counts}) + runs_of = {c: sorted(i for cc, i in run_counts if cc == c) for c in cats} + C = len(cats) + print(f"categories ({C}): " + ", ".join(f"{c}[{len(runs_of[c])}]" for c in cats)) + + experts = {k for d in run_counts.values() for k in d} + print(f"experts seen: {len(experts):,}\n") + + atlas, dropped_sparse, dropped_unrepl = [], 0, 0 + for key in experts: + total = sum(run_counts[r].get(key, 0) for r in run_counts) + if total < a.min_count: + dropped_sparse += 1 + continue + # mean share per category across its runs (a single hot run cannot carry the category) + mean_share, fired_runs = {}, {} + for c in cats: + shares, fired = [], 0 + for i in runs_of[c]: + n = run_counts[(c, i)].get(key, 0) + shares.append(n / max(1, run_tot[(c, i)])) + if n > 0: + fired += 1 + mean_share[c] = sum(shares) / len(shares) + fired_runs[c] = fired + s = sum(mean_share.values()) + if s <= 0: + continue + p = {c: mean_share[c] / s for c in cats} + top = max(cats, key=lambda c: p[c]) + # REPLICATION GATE: the affinity must show up in >= min-runs of that category's prompts + if fired_runs[top] < a.min_runs: + dropped_unrepl += 1 + continue + H = -sum(v * math.log(v) for v in p.values() if v > 0) + atlas.append({ + "layer": key[0], "expert": key[1], "total": total, + "spec": round(1.0 - H / math.log(C), 4), + "top_topic": top, + "top_lift": round(p[top] * C, 2), + "reliability": f"{fired_runs[top]}/{len(runs_of[top])}", + "p": {c: round(p[c], 4) for c in cats}, + }) + atlas.sort(key=lambda r: (-r["spec"], -r["total"])) + + print(f"dropped {dropped_sparse:,} sparse (<{a.min_count} sel)") + print(f"dropped {dropped_unrepl:,} UNREPLICATED (fired in <{a.min_runs} runs of their top topic)") + print(f"kept {len(atlas):,} experts\n") + + print("=== most specialised, replicated across prompts ===") + print(f"{'layer':>5} {'exp':>4} {'sel':>6} {'spec':>6} {'lift':>6} {'repl':>5} topic") + for r in atlas[:20]: + print(f"{r['layer']:>5} {r['expert']:>4} {r['total']:>6} {r['spec']:>6.3f} " + f"{r['top_lift']:>6.2f} {r['reliability']:>5} {r['top_topic']}") + + print("\n=== specialisation vs layer depth (mean over experts; robust to the above) ===") + by_layer = defaultdict(list) + for r in atlas: + by_layer[r["layer"]].append(r["spec"]) + ls = sorted(by_layer) + for L in ls[::max(1, len(ls)//13)]: + v = by_layer[L] + print(f" layer {L:>3} n={len(v):>4} spec {sum(v)/len(v):.3f} {'#'*int(60*sum(v)/len(v))}") + + print("\n=== experts owned per topic (replicated only) ===") + own = defaultdict(int) + for r in atlas: + own[r["top_topic"]] += 1 + for c in sorted(own, key=lambda x: -own[x]): + print(f" {c:<14} {own[c]:>5}") + + strong = [r for r in atlas if r["spec"] >= 0.5] + print(f"\nstrong specialists (spec >= 0.5, replicated): {len(strong):,} / {len(atlas):,} " + f"({100*len(strong)/max(1,len(atlas)):.1f}%)") + json.dump({"categories": cats, "experts": atlas}, open(a.out, "w"), indent=1) + print(f"wrote {a.out}") + + +if __name__ == "__main__": + main() diff --git a/c/tools/expert_atlas/probes.json b/c/tools/expert_atlas/probes.json new file mode 100644 index 0000000..ae377da --- /dev/null +++ b/c/tools/expert_atlas/probes.json @@ -0,0 +1,54 @@ +{ + "_comment": "Probe set for the GLM-5.2 Expert Atlas (#175). 10 categories x 3 prompts. Prompts are deliberately varied in phrasing within a category so the affinity vector reflects the TOPIC, not one prompt's surface form. Lengths are kept within a narrow band across categories: prefill routes the prompt tokens too, so a long prompt in one category would inflate its counts.", + + "code_python": [ + "Write a Python function that merges two sorted lists into one sorted list.", + "In Python, explain the difference between a generator and a list comprehension.", + "Refactor this Python snippet to avoid a nested loop: for a in xs: for b in ys: if a==b: out.append(a)" + ], + "code_sql": [ + "Write a SQL query that returns the top 5 customers by total order value.", + "Explain what a LEFT JOIN does differently from an INNER JOIN in SQL.", + "Write SQL to add an index on the email column of a users table and explain when it helps." + ], + "math_proof": [ + "Prove that the square root of 2 is irrational.", + "Show that the sum of the first n odd numbers equals n squared.", + "Explain why the derivative of e^x is e^x." + ], + "chinese": [ + "请用三句话解释什么是机器学习。", + "写一首关于秋天的短诗。", + "中国的四大发明是什么?请简要说明。" + ], + "german": [ + "Erkläre in drei Sätzen, wie ein Verbrennungsmotor funktioniert.", + "Schreibe eine kurze formelle E-Mail, in der du einen Termin absagst.", + "Was ist der Unterschied zwischen Dativ und Akkusativ im Deutschen?" + ], + "poetry": [ + "Write a short poem about the sea at night.", + "Compose four lines of verse about an empty train station.", + "Write a haiku about the first snow of winter." + ], + "law": [ + "Explain in plain terms what consideration means in contract law.", + "What is the difference between a misdemeanor and a felony?", + "Summarize what the term 'force majeure' covers in a commercial contract." + ], + "medicine": [ + "Explain the difference between type 1 and type 2 diabetes.", + "What are the common symptoms of iron deficiency anemia?", + "Describe how a vaccine produces immunity." + ], + "json_format": [ + "Return a JSON object with keys name, age, and email for a fictional user. Output only JSON.", + "Convert this to JSON: name Alice, roles admin and editor, active true. Output only JSON.", + "Write a JSON schema for an object with a required string field 'id' and an optional integer 'count'." + ], + "casual_chat": [ + "Hey, what's a good way to spend a rainy Sunday afternoon?", + "I'm feeling pretty tired today. Any tips to get through the afternoon?", + "What's your favourite kind of weather, and why?" + ] +} diff --git a/c/tools/expert_atlas/sweep.sh b/c/tools/expert_atlas/sweep.sh new file mode 100755 index 0000000..9c101d3 --- /dev/null +++ b/c/tools/expert_atlas/sweep.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash +# GLM-5.2 Expert Atlas — probe sweep (#175). +# +# cd c && ./tools/expert_atlas/sweep.sh [probes.json] [outdir] +# +# Env: COLI_MODEL, NGEN (default 64), COLI (default ./coli) +# +# --------------------------------------------------------------------------------------------- +# THE CONFOUNDS THIS SCRIPT EXISTS TO CONTROL. Each one silently corrupts the atlas. +# +# TOPP=0 --topp prunes experts by cumulative probability. Measured on GLM-5.2 int4, +# same prompt, only top-p changed: +# topp=0 -> 21,000 selections across 7,587 distinct experts +# topp=0.7 -> 11,944 selections across 4,687 distinct experts +# It hides 38% of the experts. It is also the RECOMMENDED SPEED SETTING, so this +# is very easy to walk into: with top-p on you profile the pruner, not the model. +# +# MTP=0 Speculative drafts route experts for tokens that are later REJECTED and never +# DRAFT=0 emitted (eusage is incremented inside moe(), before verification). Those counts +# would describe text the model never produced. +# +# --gpu none The CUDA expert tier is not run-to-run deterministic (VRAM placement shifts +# between runs). Routing on the CPU path is reproducible. The tier only decides +# where weights live, not what the router picks, so CPU costs nothing here. +# +# --temp 0 Greedy: deterministic continuation, reproducible atlas. +# +# rm .coli_usage before EVERY run +# eusage is LOADED from /.coli_usage at startup and written back at exit, so +# a naive STATS dump contains ALL PRIOR HISTORY, not this run. Removing it per run +# makes each dump exactly one probe. The user's learned cache is backed up and +# restored on exit. +# +# Prompt lengths are kept in a narrow band across categories: prefill routes the prompt tokens +# too, so a verbose category would otherwise simply look "busier". +# --------------------------------------------------------------------------------------------- +set -uo pipefail +HERE="$(cd "$(dirname "$0")" && pwd)" +PROBES="${1:-$HERE/probes.json}" +OUT="${2:-./atlas_out}" +COLI="${COLI:-./coli}" +NGEN="${NGEN:-64}" +MODEL="${COLI_MODEL:?set COLI_MODEL to the snapshot directory}" + +[ -f "$PROBES" ] || { echo "no probe file: $PROBES" >&2; exit 1; } +[ -x "$COLI" ] || { echo "no coli at $COLI (run from c/, or set COLI=)" >&2; exit 1; } +mkdir -p "$OUT/stats" + +export COLI_MODEL="$MODEL" MTP=0 DRAFT=0 TOPP=0 + +USAGE="$MODEL/.coli_usage" +BACKUP="$OUT/.coli_usage.backup" +[ -f "$USAGE" ] && cp "$USAGE" "$BACKUP" && echo "backed up $USAGE" +restore(){ [ -f "$BACKUP" ] && cp "$BACKUP" "$USAGE" && echo "restored $USAGE"; } +trap restore EXIT + +python3 - "$PROBES" > "$OUT/runlist.tsv" <<'PY' +import json, sys +for cat, prompts in json.load(open(sys.argv[1])).items(): + if cat.startswith('_'): + continue + for i, p in enumerate(prompts): + print(f"{cat}\t{i}\t{p}") +PY + +n=$(wc -l < "$OUT/runlist.tsv"); i=0 +echo "$n probes -> $OUT/stats" +while IFS=$'\t' read -r cat idx prompt; do + i=$((i+1)) + dst="$OUT/stats/${cat}_${idx}.txt" + [ -s "$dst" ] && { echo " [$i/$n] $cat/$idx (cached)"; continue; } + rm -f "$USAGE" # start from an EMPTY routing history + STATS="$dst" "$COLI" run "$prompt" --ngen "$NGEN" --ctx 4096 --gpu none --temp 0 \ + > "$OUT/stats/${cat}_${idx}.log" 2>&1 + echo " [$i/$n] $cat/$idx $(grep -aoE '[0-9]+ selections across [0-9]+ distinct experts' \ + "$OUT/stats/${cat}_${idx}.log" | head -1)" +done < "$OUT/runlist.tsv" + +echo +echo "next:" +echo " python3 $HERE/analyze.py --stats $OUT/stats --out $OUT/experts.json" +echo " python3 $HERE/validate.py $OUT/stats 200" diff --git a/c/tools/expert_atlas/validate.py b/c/tools/expert_atlas/validate.py new file mode 100644 index 0000000..6b283da --- /dev/null +++ b/c/tools/expert_atlas/validate.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +"""Leave-one-prompt-out validation of the Expert Atlas (#175). + +"Replicates across the 3 prompts I picked" is not the same as "generalises". The atlas is +only real if a specialist set learned from SOME prompts predicts routing on a prompt it has +never seen. + +Protocol, for every category c and every held-out prompt h of c: + 1. build c's top-K specialist set from c's OTHER prompts only (h excluded entirely) + 2. do the same for all other categories (using ALL their prompts — they never saw h either) + 3. on the held-out run h, measure what share of routing selections land in each set + 4. the atlas works if c's own set wins on h + +If specialisation were an artifact of prompt wording, the held-out prompt would not prefer +its own category's set. Chance is 1/C. +""" +import glob, json, os, sys +from collections import defaultdict + +STATS = sys.argv[1] if len(sys.argv) > 1 else "stats" +K = int(sys.argv[2]) if len(sys.argv) > 2 else 200 # specialists per category + +runs, tot = {}, {} +for path in sorted(glob.glob(os.path.join(STATS, "*.txt"))): + cat, idx = os.path.basename(path)[:-4].rsplit("_", 1) + d = {} + t = 0 + for line in open(path): + p = line.split() + if len(p) == 3: + d[(int(p[0]), int(p[1]))] = int(p[2]) + t += int(p[2]) + runs[(cat, idx)] = d + tot[(cat, idx)] = t + +cats = sorted({c for c, _ in runs}) +idxs = {c: sorted(i for cc, i in runs if cc == c) for c in cats} +C = len(cats) + + +def specialists(cat, exclude): + """Top-K experts by lift for `cat`, computed WITHOUT the excluded run.""" + share = defaultdict(lambda: defaultdict(float)) + for c in cats: + used = [i for i in idxs[c] if not (c == cat and i == exclude)] + for i in used: + for k, n in runs[(c, i)].items(): + share[k][c] += n / max(1, tot[(c, i)]) / len(used) + scored = [] + for k, per in share.items(): + s = sum(per.values()) + if s <= 0: + continue + p = per[cat] / s + if per[cat] > 0: + scored.append((p, k)) + scored.sort(reverse=True) + return {k for _, k in scored[:K]} + + +print(f"leave-one-prompt-out, {C} categories, top-{K} specialists per category") +print(f"chance = {100.0/C:.1f}%\n") +hits = 0 +trials = 0 +for c in cats: + for h in idxs[c]: + sets = {cc: specialists(cc, h if cc == c else None) for cc in cats} + held = runs[(c, h)] + htot = max(1, tot[(c, h)]) + scores = {cc: sum(held.get(k, 0) for k in sets[cc]) / htot for cc in cats} + win = max(scores, key=scores.get) + ok = win == c + hits += ok + trials += 1 + own = 100 * scores[c] + best_other = 100 * max(v for cc, v in scores.items() if cc != c) + print(f" {c:<12} prompt {h} own-set {own:5.2f}% best-other {best_other:5.2f}% " + f"-> {'HIT ' if ok else 'MISS'} (predicted {win})") +print(f"\naccuracy: {hits}/{trials} = {100*hits/trials:.1f}% (chance {100.0/C:.1f}%)") From ddf9212b81193d53c95b806edf86b125cb59e839 Mon Sep 17 00:00:00 2001 From: JustVugg Date: Wed, 15 Jul 2026 07:50:48 +0200 Subject: [PATCH 27/79] glm: PIN_GB=all clamps to the --ram budget instead of pinning every expert (fixes #229) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PIN_GB=all passed gb=-1.0 to pin_load, which took npin=n (all experts) and ignored --ram entirely — the OOM-kill regression from #80. A 92 GB host with --ram 78 was killed mid-generation (anon-rss ~89 GB). Now gb<0 clamps npin to expert_avail() — how many experts fit the RAM budget, same accounting AUTOPIN uses. pin_load already adds the pinned bytes to resident_bytes, so the later cap_for_ram narrows the LRU accordingly with no double count. Co-Authored-By: Claude Opus 4.8 --- c/glm.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/c/glm.c b/c/glm.c index 6309c94..c160008 100644 --- a/c/glm.c +++ b/c/glm.c @@ -4528,6 +4528,7 @@ typedef struct { int l,e; uint32_t c; } PinRec; static int pin_rec_cmp(const void *a,const void *b){ const PinRec *x=a,*y=b; return x->cc?1:x->c>y->c?-1:0; } +static double expert_avail(Model *m, double ram_gb, int ebits, int max_ctx); /* def. sotto */ static void pin_load(Model *m, const char *statspath, double gb){ FILE *f=fopen(statspath,"r"); if(!f){ perror(statspath); return; } Cfg *c=&m->c; int cap=(c->n_layers+1)*c->n_experts; @@ -4553,7 +4554,19 @@ static void pin_load(Model *m, const char *statspath, double gb){ free(seen); qsort(r,(size_t)n,sizeof(*r),pin_rec_cmp); int64_t eb=expert_bytes_probe(m,m->ebits); - int npin=gb<0?n:(int)(gb*1e9/eb); if(npin>n) npin=n; + /* PIN_GB=all (#80): NON "tutti" alla lettera. Pinnare l'intero set ignora il + * budget --ram e fa OOM-kill del kernel a meta' generazione (#229: host 92 GB + * ucciso con --ram 78, anon-rss 89 GB). Clampa a quanti expert entrano nel + * budget RAM, come AUTOPIN; il pin aggiorna resident_bytes, quindi cap_for_ram + * dopo restringe la LRU di conseguenza (nessun doppio conteggio). */ + int npin; + if(gb<0){ + double ram_env=getenv("RAM_GB")?atof(getenv("RAM_GB")):0.0; + int est_ctx=getenv("CTX")?atoi(getenv("CTX")):4096; /* stesso default del call site */ + double avail=expert_avail(m,ram_env,m->ebits,est_ctx); + npin=avail>0?(int)(avail/eb):0; + } else npin=(int)(gb*1e9/eb); + if(npin>n) npin=n; if(npin<1){ free(r); return; } int *cnt_l=calloc(c->n_layers+1,sizeof(int)); /* +1: riga MTP */ for(int a=0;a Date: Wed, 15 Jul 2026 07:55:09 +0200 Subject: [PATCH 28/79] glm: honest short-read reporting in expert pread; Makefile: -pthread for *BSD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two small correctness fixes surfaced by community reports on non-Linux hosts: #236 — expert_load's buffered pread paths (slab + qs scales) used perror("pread expert") on a short read. Since pread returned a short count (not -1), errno stays 0 and perror prints "Success" — a confusing message right before exit(1) in the score/bench path. New pread_full() helper loops over short reads and EINTR and reports actual/expected bytes and offset, so a truncated shard reads as such instead of "Success". #219 — Linux pulls -pthread in via -fopenmp; the *BSDs do not, so pthread_* fail to link there. Added -pthread to the generic (Linux/*BSD x86-64) and aarch64 CFLAGS/LDFLAGS. No-op on Linux, required on FreeBSD (complements #206). Co-Authored-By: Claude Opus 4.8 --- c/Makefile | 11 ++++++----- c/glm.c | 25 ++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/c/Makefile b/c/Makefile index 1e0b1ea..5a53c24 100644 --- a/c/Makefile +++ b/c/Makefile @@ -70,18 +70,19 @@ ifneq (,$(PPC64)) # (validated token-exact vs the transformers oracle on a POWER8 S824). CC = gcc ARCH ?= native -CFLAGS = -O3 -mcpu=$(ARCH) -fopenmp -Wall -Wextra -Wno-unused-parameter -Wno-misleading-indentation -Wno-unused-function -LDFLAGS = -lm -fopenmp +CFLAGS = -O3 -mcpu=$(ARCH) -fopenmp -pthread -Wall -Wextra -Wno-unused-parameter -Wno-misleading-indentation -Wno-unused-function +LDFLAGS = -lm -fopenmp -pthread EXE = else -# --- Linux x86-64 (percorso originale, invariato) --- +# --- Linux / *BSD x86-64 (percorso originale, invariato) --- CC = gcc # ARCH=native -> ottimizzato per QUESTA macchina (default, piu' veloce). # ARCH=x86-64-v3 -> binario PORTABILE su qualsiasi x86-64 moderno con AVX2 (per distribuire). # ARCH=x86-64 -> massima compatibilita' (niente AVX2: usa il path scalare di fallback). +# -pthread: Linux lo tira dentro via -fopenmp, i *BSD no e le pthread_* non risolvono (#219). ARCH ?= native -CFLAGS = -O3 -march=$(ARCH) -fopenmp -Wall -Wextra -Wno-unused-parameter -Wno-misleading-indentation -Wno-unused-function -LDFLAGS = -lm -fopenmp +CFLAGS = -O3 -march=$(ARCH) -fopenmp -pthread -Wall -Wextra -Wno-unused-parameter -Wno-misleading-indentation -Wno-unused-function +LDFLAGS = -lm -fopenmp -pthread EXE = endif endif diff --git a/c/glm.c b/c/glm.c index c160008..3e9d020 100644 --- a/c/glm.c +++ b/c/glm.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1325,6 +1326,24 @@ static void *map_of_fd(int fd){ * pread error aborts the process. fatal=0 (speculative pilot only): the same * errors instead abandon the load and return -1 without touching s->eid, so a * mispredicted cross-layer prefetch can never kill the server. */ +/* pread completo: gestisce le short-read (POSIX le ammette su file regolari + * sotto pressione di memoria) e le EINTR, e riporta un errore ONESTO. perror + * stampava "Success" quando pread ritorna un conteggio corto invece di -1 + * (errno resta 0 dalla syscall precedente) -> messaggio fuorviante nel path + * score/bench (#236). Ritorna 0 = ok, -1 = errore reale o EOF. */ +static int pread_full(int fd, void *buf, int64_t n, int64_t off, const char *tag){ + char *p=buf; int64_t got=0; + while(gotfd, s->slab, wtot, off0)!=wtot){ perror("pread expert"); if(fatal) exit(1); return -1; } + if(pread_full(tw[ord[0]]->fd, s->slab, wtot, off0, "pread expert")){ if(fatal) exit(1); return -1; } pos[ord[0]]=0; pos[ord[1]]=tw[ord[0]]->nbytes; pos[ord[2]]=tw[ord[0]]->nbytes+tw[ord[1]]->nbytes; done=1; } } if(!done){ /* non contigui: 3 pread bufferizzate */ int64_t o=0; for(int a=0;a<3;a++){ int k=ord[a]; - if(pread(tw[k]->fd, s->slab+o, tw[k]->nbytes, tw[k]->off)!=tw[k]->nbytes){ perror("pread expert"); if(fatal) exit(1); return -1; } + if(pread_full(tw[k]->fd, s->slab+o, tw[k]->nbytes, tw[k]->off, "pread expert")){ if(fatal) exit(1); return -1; } pos[k]=o; o+=tw[k]->nbytes; } } float *fp[3]; int64_t fo=0; /* scale (piccole) */ for(int k=0;k<3;k++){ - if(pread(tq[k]->fd, (char*)(s->fslab+fo), tq[k]->nbytes, tq[k]->off)!=tq[k]->nbytes){ perror("pread qs"); if(fatal) exit(1); return -1; } + if(pread_full(tq[k]->fd, (char*)(s->fslab+fo), tq[k]->nbytes, tq[k]->off, "pread qs")){ if(fatal) exit(1); return -1; } fp[k]=s->fslab+fo; fo+=tq[k]->nbytes/4; } if(g_drop){ /* scarta subito le pagine: evita che la page * cache in pressione strangoli il throughput */ From 498ab0c20e9e6c6718abd25d7f681463177a0e3a Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Tue, 14 Jul 2026 18:57:35 -0400 Subject: [PATCH 29/79] =?UTF-8?q?experiment:=20group-scaled=20int4=20(fmt?= =?UTF-8?q?=3D4)=20=E2=80=94=20one=20scale=20per=20128=20elements,=20not?= =?UTF-8?q?=20per=20row?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause of gibberish output: the int4 quantization uses one F32 scale per output row (2048 scales for a 2048x6144 matrix). The FP8 source has 128x128 block scales — 48x finer. This destroys reasoning while keeping surface fluency. Changes: - Converter: quant_int4_grouped() with --group-size 128 arg. Same nibble packing, but one scale per group of 128 elements along the input dim. - Engine QT struct: added 'gs' field (group size, 0=per-row backward compat) - Engine qt_from_disk: auto-detects fmt=4 when scale array is O*ceil(I/128) elements instead of O. Old per-row models (fmt=2) work unchanged. - Engine matmul_i4_grouped(): AVX2 kernel that applies per-group scales. Accumulator resets at each group boundary: dot(x[grp],w[grp]) * scale[grp]. - Engine matmul_qt_ex: dispatches to grouped kernel for fmt=4 (always exact, no IDOT approximation since the point is quality) - Engine expert_load: both mmap and slab+pread paths detect fmt=4 from scale array size and set gs=128 - qt_bytes: fmt=4 reports correct memory including group scales Backward compatible: existing per-row int4 models work unchanged. The fused gate+up pair path (matmul_i4_pair) falls back to separate matmul_qt calls for fmt=4 — minor perf cost, correctness preserved. --- c/glm.c | 84 +++++++++++++++++++++++++++++++--- c/tools/convert_fp8_to_int4.py | 52 ++++++++++++++++++--- 2 files changed, 122 insertions(+), 14 deletions(-) diff --git a/c/glm.c b/c/glm.c index 3e9d020..eae408c 100644 --- a/c/glm.c +++ b/c/glm.c @@ -96,7 +96,7 @@ typedef struct { * INT4 e' cio' che fa stare la densa residente nei 15 GB (0.5 byte/param). */ /* fmt: 0 F32, 1 INT8, 2 INT4 (2/byte), 3 INT2 (4/byte). q4 ospita sia int4 che int2 packed. */ typedef struct { - int fmt; float *qf; int8_t *q8; uint8_t *q4; float *s; int O, I; + int fmt; float *qf; int8_t *q8; uint8_t *q4; float *s; int O, I, gs; /* gs=group size (0=per-row, 128=grouped) */ #ifdef COLI_CUDA ColiCudaTensor *cuda; #endif @@ -107,7 +107,10 @@ static int64_t qt_bytes(const QT *t){ /* byte residenti del tensore */ if(t->fmt==0) return n*4; if(t->fmt==1) return n + (int64_t)t->O*4; if(t->fmt==3) return (int64_t)t->O*((t->I+3)/4) + (int64_t)t->O*4; - return (int64_t)t->O*((t->I+1)/2) + (int64_t)t->O*4; + if(t->fmt==4){ /* int4 grouped: packed nibbles + O*ceil(I/gs) scales */ + int ng=(t->I+t->gs-1)/t->gs; + return (int64_t)t->O*((t->I+1)/2) + (int64_t)t->O*ng*4; } + return (int64_t)t->O*((t->I+1)/2) + (int64_t)t->O*4; /* fmt=2 int4 per-row */ } typedef struct { @@ -374,6 +377,46 @@ static void matmul_i4(float *y, const float *x, const uint8_t *q4, const float * if(i>1]; int lo=(int)(byte&0xF)-8; a += xs[i]*(float)lo; } y[(int64_t)s*O+o]=a*sc; } } } +/* y[S,O] = x[S,I] @ W^T with W int4 packed (2/byte) + per-GROUP scales (fmt=4). + * Same nibble math as matmul_i4, but the scale changes every `gs` elements along I. + * The accumulator resets at each group boundary: dot(x[grp], w[grp]) * scale[grp]. + * gs MUST be a multiple of 16 (the AVX2 vector width). */ +static void matmul_i4_grouped(float *y, const float *x, const uint8_t *q4, const float *scale, + int S, int I, int O, int gs){ + int rb=(I+1)/2; int ng=(I+gs-1)/gs; + #pragma omp parallel for schedule(static) + for(int o=0;oI) glen=I-base; + float sc=scl[g]; + int i=base; +#ifdef __AVX2__ + const __m128i m4=_mm_set1_epi8(0x0F); const __m256i b8=_mm256_set1_epi32(8); + __m256 acc=_mm256_setzero_ps(); + for(; i+16<=base+glen; i+=16){ __m128i by=_mm_loadl_epi64((const __m128i*)(w+(i>>1))); + __m128i lo=_mm_and_si128(by,m4),hi=_mm_and_si128(_mm_srli_epi16(by,4),m4); + __m128i nib=_mm_unpacklo_epi8(lo,hi); + __m256 w0=_mm256_cvtepi32_ps(_mm256_sub_epi32(_mm256_cvtepu8_epi32(nib),b8)); + __m256 w1=_mm256_cvtepi32_ps(_mm256_sub_epi32(_mm256_cvtepu8_epi32(_mm_srli_si128(nib,8)),b8)); + acc=_mm256_fmadd_ps(_mm256_loadu_ps(xs+i), w0, acc); + acc=_mm256_fmadd_ps(_mm256_loadu_ps(xs+i+8), w1, acc); } + a+=hsum256(acc)*sc; +#endif + /* scalar tail for the group remainder */ + for(; i>1]; + a+=(xs[i]*(float)((int)(byte&0xF)-8)+xs[i+1]*(float)((int)(byte>>4)-8))*sc; } + else { uint8_t byte=w[i>>1]; a+=xs[i]*(float)((int)(byte&0xF)-8)*sc; } + } + } + y[(int64_t)s*O+o]=a; + } + } +} /* Decode hot path for gate+up: same exact q4 dot products as matmul_i4, but one * OpenMP dispatch covers both matrices. KTransformers uses persistent pools; * this keeps colibri dependency-free while removing one team launch/expert. */ @@ -766,6 +809,9 @@ static void matmul_qt_ex(float *y, const float *x, QT *w, int S, int allow_idot) } #endif if(w->fmt==0){ matmul(y,x,w->qf,S,w->I,w->O); return; } + /* fmt=4: grouped int4 — always use the exact grouped kernel (no IDOT approximation, + * since the whole point of grouped scales is better quality). */ + if(w->fmt==4){ matmul_i4_grouped(y,x,w->q4,w->s,S,w->I,w->O,w->gs); return; } /* int8 IDOT vince sempre (1.4-2.5x). int4 IDOT: l'autore su AVX2 trovo' che a S=1 * non ripaga (soglia S>=2); ma su ARM/SDOT il singolo token CONVIENE (vedi g_i4s / * PR #9 per il gemello VNNI). Soglia configurabile con I4S. @@ -1061,9 +1107,22 @@ static void qt_from_disk(Model *m, const char *name, int O, int I, int bits, int char sn[300]; snprintf(sn,sizeof(sn),"%s.qs",name); if(st_has(&m->S,sn)){ int64_t nb=st_nbytes(&m->S,name); - int fmt = (nb==(int64_t)O*I)?1 : (nb==(int64_t)O*((I+1)/2))?2 : 3; /* int8 / int4 / int2 dai byte */ - if(fmt==1){ if(t->fmt!=1||!t->q8){ t->fmt=1; t->O=O; t->I=I; t->q8=qalloc(nb); t->s=qsalloc(O); } st_read_raw(&m->S,name,t->q8,drop); } - else { if(t->fmt!=fmt||!t->q4){ t->fmt=fmt; t->O=O; t->I=I; t->q4=qalloc(nb); t->s=qsalloc(O); } st_read_raw(&m->S,name,t->q4,drop); } + int64_t ns=st_nbytes(&m->S,sn); /* scale bytes (F32) */ + /* Detect int4-grouped (fmt=4): packed int4 weight bytes BUT scale array is + * larger than O*4 — check if it matches O*ceil(I/gs)*4 for gs=128. */ + int fmt = (nb==(int64_t)O*I)?1 : (nb==(int64_t)O*((I+1)/2))?2 : 3; + int gs=0; + if(fmt==2 && ns > (int64_t)O*4){ + /* could be grouped; try gs=128 */ + int ng128=(I+127)/128; + if(ns==(int64_t)O*ng128*4){ fmt=4; gs=128; } + /* future: try other group sizes here */ + } + if(fmt==1){ if(t->fmt!=1||!t->q8){ t->fmt=1; t->O=O; t->I=I; t->gs=0; t->q8=qalloc(nb); t->s=qsalloc(O); } st_read_raw(&m->S,name,t->q8,drop); } + else if(fmt==4){ int ng=(I+gs-1)/gs; + if(t->fmt!=4||!t->q4){ t->fmt=4; t->O=O; t->I=I; t->gs=gs; t->q4=qalloc(nb); t->s=falloc((int64_t)O*ng); } + st_read_raw(&m->S,name,t->q4,drop); } + else { if(t->fmt!=fmt||!t->q4){ t->fmt=fmt; t->O=O; t->I=I; t->gs=0; t->q4=qalloc(nb); t->s=qsalloc(O); } st_read_raw(&m->S,name,t->q4,drop); } st_read_f32(&m->S,sn,t->s,drop); } else { if(!t->qf && !t->q8 && !t->q4) qt_alloc(t,O,I,bits); @@ -1379,7 +1438,13 @@ static int expert_load(Model *m, int layer, int eid, ESlot *s, int fatal){ for(int k=0;k<3;k++){ int64_t nb=tw[k]->nbytes; int fmt=(nb==(int64_t)OO[k]*II[k])?1:(nb==(int64_t)OO[k]*((II[k]+1)/2))?2:3; - qt[k]->fmt=fmt; qt[k]->O=OO[k]; qt[k]->I=II[k]; qt[k]->qf=NULL; + /* detect grouped int4 (fmt=4): int4 weight bytes + larger scale array */ + int gs=0; + if(fmt==2 && tq[k]->nbytes > (int64_t)OO[k]*4){ + int ng128=(II[k]+127)/128; + if(tq[k]->nbytes==(int64_t)OO[k]*ng128*4){ fmt=4; gs=128; } + } + qt[k]->fmt=fmt; qt[k]->O=OO[k]; qt[k]->I=II[k]; qt[k]->gs=gs; qt[k]->qf=NULL; qt[k]->q8=(int8_t*)((char*)bw[k]+tw[k]->off); qt[k]->q4=(uint8_t*)((char*)bw[k]+tw[k]->off); qt[k]->s=(float*)((char*)bq[k]+tq[k]->off); } @@ -1493,7 +1558,12 @@ static int expert_load(Model *m, int layer, int eid, ESlot *s, int fatal){ for(int k=0;k<3;k++){ int64_t nb=tw[k]->nbytes; int fmt = (nb==(int64_t)OO[k]*II[k])?1 : (nb==(int64_t)OO[k]*((II[k]+1)/2))?2 : 3; - qt[k]->fmt=fmt; qt[k]->O=OO[k]; qt[k]->I=II[k]; qt[k]->qf=NULL; + int gs=0; + if(fmt==2 && tq[k]->nbytes > (int64_t)OO[k]*4){ + int ng128=(II[k]+127)/128; + if(tq[k]->nbytes==(int64_t)OO[k]*ng128*4){ fmt=4; gs=128; } + } + qt[k]->fmt=fmt; qt[k]->O=OO[k]; qt[k]->I=II[k]; qt[k]->gs=gs; qt[k]->qf=NULL; qt[k]->q8=(int8_t*)(s->slab+pos[k]); qt[k]->q4=s->slab+pos[k]; qt[k]->s=fp[k]; } s->eid=eid; return 0; diff --git a/c/tools/convert_fp8_to_int4.py b/c/tools/convert_fp8_to_int4.py index 9521a22..b8e186e 100644 --- a/c/tools/convert_fp8_to_int4.py +++ b/c/tools/convert_fp8_to_int4.py @@ -51,6 +51,38 @@ def quant_int4(w, bits): # -> (qbytes U8 [O*ceil(I/2)], s out[:, :v1.shape[1]] |= (v1 << 4) return out.reshape(-1), s[:, 0].astype(np.float32) +def quant_int4_grouped(w, bits, gs=128): + """Group-scaled int4: one scale per group of `gs` elements along the input dim. + Drastically reduces quantization error vs per-row scaling — matches the FP8 + source's 128x128 block-scale granularity. Output layout: + qbytes: same packed nibble format as quant_int4 + scales: f32 [O * ngroups] where ngroups = ceil(I/gs), laid out as + s[o * ngroups + g] = scale for row o, group g. + The engine detects this format (fmt=4) by checking the .qs array size.""" + O, I = w.shape + qmax = (1 << (bits - 1)) - 1 + ngroups = (I + gs - 1) // gs + # pad I to a multiple of gs for clean reshape, then trim + Ipad = ngroups * gs + wpad = np.zeros((O, Ipad), np.float32) + wpad[:, :I] = w + wr = wpad.reshape(O, ngroups, gs) # [O, ngroups, gs] + amax = np.abs(wr).max(axis=2, keepdims=True) # [O, ngroups, 1] + s = np.maximum(amax / qmax, 1e-8) # [O, ngroups, 1] + q = np.clip(np.rint(wr / s), -8, qmax).astype(np.int32) # [O, ngroups, gs] + q = q.reshape(O, Ipad)[:, :I] # trim padding -> [O, I] + # pack nibbles (identical to quant_int4) + rb = (I + 1) // 2 + out = np.zeros((O, rb), np.uint8) + v0 = (q[:, 0::2] + 8).astype(np.uint8) + out[:, :v0.shape[1]] = v0 + if I > 1: + v1 = (q[:, 1::2] + 8).astype(np.uint8) + out[:, :v1.shape[1]] |= (v1 << 4) + # scales: flatten [O, ngroups] -> [O * ngroups] + s_flat = s[:, :, 0].astype(np.float32).reshape(-1) + return out.reshape(-1), s_flat + def quant_int2(w, bits): # -> (qbytes U8 [O*ceil(I/4)], scale f32 [O]); 4/byte O, I = w.shape qmax = (1 << (bits - 1)) - 1 # bits=2 -> qmax=1, valori [-2,1] @@ -169,7 +201,8 @@ def dequant(f, name, keys): return (w * sc).numpy() return f.get_tensor(name).to(torch.float32).numpy() -def convert_shard(path, out_dict, n_layers, ebits, io_bits, xbits, keep_mtp=False, keep_idx=False): +def convert_shard(path, out_dict, n_layers, ebits, io_bits, xbits, + keep_mtp=False, keep_idx=False, group_size=0): from safetensors import safe_open with safe_open(path, framework="pt") as f: keys = set(f.keys()) @@ -183,8 +216,11 @@ def convert_shard(path, out_dict, n_layers, ebits, io_bits, xbits, keep_mtp=Fals bits = io_bits if kind == "io" else xbits if kind == "x" else ebits if w.ndim != 2: # es. bias 1D non previsto come 'q' -> tienilo f32 out_dict[name] = w.astype(np.float32); continue - q, s = (quant_int2(w, bits) if bits <= 2 else - quant_int4(w, bits) if bits <= 4 else quant_int8(w, bits)) + if group_size > 0 and bits <= 4: + q, s = quant_int4_grouped(w, bits, group_size) + else: + q, s = (quant_int2(w, bits) if bits <= 2 else + quant_int4(w, bits) if bits <= 4 else quant_int8(w, bits)) out_dict[name] = q out_dict[name + ".qs"] = s @@ -198,6 +234,8 @@ def main(): ap.add_argument("--ebits", type=int, default=None) # bit residenti (default 4; 8 per --mtp/--indexer) ap.add_argument("--io-bits", type=int, default=8) # bit di embed/lm_head ap.add_argument("--xbits", type=int, default=None) # bit degli expert ROUTED (streaming); default=ebits + ap.add_argument("--group-size", type=int, default=0, # 0 = per-row (backward compat); 128 = group-scaled + help="group size for int4 scales: 0=per-row (default), 128=one scale per 128 elements (much better quality)") ap.add_argument("--n-layers", type=int, default=78) ap.add_argument("--min-free-gb", type=float, default=20.0) ap.add_argument("--selftest", action="store_true") @@ -298,7 +336,7 @@ def main(): shards = sorted(glob.glob(os.path.join(a.indir, "*.safetensors"))) from safetensors.numpy import save_file for i, sp in enumerate(shards): - out = {}; convert_shard(sp, out, a.n_layers, a.ebits, a.io_bits, a.xbits) + out = {}; convert_shard(sp, out, a.n_layers, a.ebits, a.io_bits, a.xbits, group_size=a.group_size) save_file(out, os.path.join(a.outdir, f"out-{i:05d}.safetensors")) # copia config + tokenizer for fn in ["config.json"]: @@ -541,7 +579,7 @@ def main(): if os.path.exists(outp): print(f"[MTP] {outp} already done"); continue print(f"[MTP {i+1}/{len(mtp_shards)}] downloading {sh}...", flush=True) p = download_retry(a.repo, sh, tmp) - out = {}; convert_shard(p, out, a.n_layers, a.ebits, a.io_bits, a.xbits, keep_mtp=True) + out = {}; convert_shard(p, out, a.n_layers, a.ebits, a.io_bits, a.xbits, keep_mtp=True, group_size=a.group_size) save_file(out, outp) os.remove(p) for blob in glob.glob(os.path.join(tmp, "**", "*"), recursive=True): @@ -561,7 +599,7 @@ def main(): if os.path.exists(outp): continue # gia' fatto -> ripartibile print(f"[IDX {i+1}/{len(idx_shards)}] downloading {sh}...", flush=True) p = download_retry(a.repo, sh, tmp) - out = {}; convert_shard(p, out, a.n_layers, a.ebits, a.io_bits, a.xbits, keep_idx=True) + out = {}; convert_shard(p, out, a.n_layers, a.ebits, a.io_bits, a.xbits, keep_idx=True, group_size=a.group_size) if out: save_file(out, outp) os.remove(p) for blob in glob.glob(os.path.join(tmp, "**", "*"), recursive=True): @@ -575,7 +613,7 @@ def main(): if os.path.exists(outp): continue # gia' fatto -> ripartibile print(f"[{i+1}/{len(shards)}] downloading {sh} ({free_gb(a.outdir):.0f} GB free)...", flush=True) p = download_retry(a.repo, sh, tmp) - out = {}; convert_shard(p, out, a.n_layers, a.ebits, a.io_bits, a.xbits) + out = {}; convert_shard(p, out, a.n_layers, a.ebits, a.io_bits, a.xbits, group_size=a.group_size) save_file(out, outp) os.remove(p) # <-- cancella subito lo shard fp8 for blob in glob.glob(os.path.join(tmp, "**", "*"), recursive=True): From 4268e00fa1416c834a2c24a8661a21234c002e86 Mon Sep 17 00:00:00 2001 From: JustVugg Date: Wed, 15 Jul 2026 08:13:20 +0200 Subject: [PATCH 30/79] security: harden safetensors/JSON parsers against malicious model files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A downloaded (supply-chain) model file was fully trusted by the loader. Three memory-safety holes, all reachable by pointing the engine at a crafted shard — demonstrated crashing on pre-fix, now rejected fail-closed: st.h (safetensors): - header length `hlen` (u64 from the file) was unbounded before malloc(hlen+1): a crafted value overflows (malloc(0) then hdr[hlen]=0 OOB) or forces a giant allocation. Now bounded to the file size and a 512 MB cap; malloc NULL-checked. - json_get() returns NULL for missing/mistyped fields, but dtype/data_offsets/ shape were dereferenced blind (off->kids[0]) — a header omitting data_offsets SIGSEGV'd (verified). Now type/arity-checked before use. - data_offsets [a0,b0] were trusted: b0 malloc((size_t)) giant and an oversized memcpy into the caller's buffer in st_read_f32 (heap overflow); off could point outside the file. Now validated 0<=a0<=b0 and data_start+b0<=filesize. json.h: j_parse_val recursed with no depth limit -> stack overflow on nested input like [[[[...]]]]. Added J_MAX_DEPTH=1024 (headers are ~3 deep); wide-but- flat objects like the GLM header are unaffected (depth is decremented per return). eval_glm.py: tempfile.mktemp() -> mkstemp() — closes the TOCTOU/symlink race on a shared tmp dir (CWE-377). Network path (openai_server.py + serve SUBMIT parser) audited separately and is already sound: hmac.compare_digest auth, MAX_BODY cap, resolve()+relative_to traversal guard, list-form subprocess, bounded/validated SUBMIT header. All 62 tests pass; valid GLM/OLMoE shards load unchanged. Co-Authored-By: Claude Opus 4.8 --- c/json.h | 16 +++++++++++++--- c/st.h | 34 ++++++++++++++++++++++++++++++++++ c/tools/eval_glm.py | 7 +++++-- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/c/json.h b/c/json.h index 3e1c13d..8a35e24 100644 --- a/c/json.h +++ b/c/json.h @@ -26,8 +26,14 @@ typedef struct { const char *s; char *arena; /* buffer per le stringhe smontate */ size_t acap, aoff; + int depth; /* annidamento corrente: bound contro lo stack-overflow + * da JSON malevolo tipo [[[[...]]]] (discesa ricorsiva) */ } jparser; +/* tetto di annidamento: gli header safetensors / config sono piatti (profondita' + * ~3). 1024 e' larghissimo per input legittimi e ben sotto il limite di stack. */ +#define J_MAX_DEPTH 1024 + static char *j_dup(jparser *p, const char *b, int n) { /* ogni stringa ha la sua allocazione: un'arena con realloc sposterebbe il * buffer invalidando i puntatori gia' emessi (use-after-free). */ @@ -91,10 +97,11 @@ static jval *j_parse_val(jparser *p) { char c = *p->s; if (c == '"') { jval *v = j_new(J_STR); v->str = j_parse_str_raw(p); return v; } if (c == '{') { + if (++p->depth > J_MAX_DEPTH) { p->depth--; return j_new(J_NULL); } p->s++; jval *v = j_new(J_OBJ); int cap = 8; v->keys = malloc(cap * sizeof(char*)); v->kids = malloc(cap * sizeof(jval*)); j_ws(p); - if (*p->s == '}') { p->s++; return v; } + if (*p->s == '}') { p->s++; p->depth--; return v; } for (;;) { j_ws(p); char *key = j_parse_str_raw(p); @@ -107,13 +114,15 @@ static jval *j_parse_val(jparser *p) { if (*p->s == '}') { p->s++; break; } break; } + p->depth--; return v; } if (c == '[') { + if (++p->depth > J_MAX_DEPTH) { p->depth--; return j_new(J_NULL); } p->s++; jval *v = j_new(J_ARR); int cap = 8; v->kids = malloc(cap * sizeof(jval*)); j_ws(p); - if (*p->s == ']') { p->s++; return v; } + if (*p->s == ']') { p->s++; p->depth--; return v; } for (;;) { jval *val = j_parse_val(p); if (v->len == cap) { cap *= 2; v->kids = realloc(v->kids, cap*sizeof(jval*)); } @@ -123,6 +132,7 @@ static jval *j_parse_val(jparser *p) { if (*p->s == ']') { p->s++; break; } break; } + p->depth--; return v; } if (c == 't') { p->s += 4; jval *v = j_new(J_BOOL); v->boolean = 1; return v; } @@ -134,7 +144,7 @@ static jval *j_parse_val(jparser *p) { /* API */ static jval *json_parse(const char *text, char **arena_out) { - jparser p = { text, NULL, 0, 0 }; + jparser p = { text, NULL, 0, 0, 0 }; jval *v = j_parse_val(&p); if (arena_out) *arena_out = p.arena; else free(p.arena); return v; diff --git a/c/st.h b/c/st.h index 08d0af6..6b4a710 100644 --- a/c/st.h +++ b/c/st.h @@ -14,9 +14,15 @@ #include #include #include +#include #include "json.h" #include "compat.h" +/* tetto sulla dimensione dell'header safetensors: gli header reali sono piccoli + * (KB..pochi MB). Un file crafted che dichiara un hlen enorme causerebbe una + * malloc gigante prima ancora di leggere: lo respingiamo. */ +#define ST_MAX_HEADER (512ll << 20) + typedef struct { char *name; int fd; @@ -118,14 +124,27 @@ static void st_init(shards *S, const char *snap_dir) { for (int fi = 0; fi < nf; fi++) { int fd = st_open_fd(S, files[fi]); + struct stat sst; + if (fstat(fd, &sst) != 0) { perror("fstat shard"); exit(1); } + int64_t fsz = (int64_t)sst.st_size; uint64_t hlen; if (pread(fd, &hlen, 8, 0) != 8) { perror("pread hlen"); exit(1); } + /* file malevolo/troncato: hlen deve stare nel file dopo gli 8 byte di + * prefisso e sotto il tetto. Senza questo bound hlen+1 puo' andare in + * overflow (malloc(0) e poi hdr[hlen]=0 fuori limiti) o forzare una + * malloc gigante. */ + if (fsz < 8 || hlen > (uint64_t)(fsz - 8) || hlen > (uint64_t)ST_MAX_HEADER) { + fprintf(stderr, "%s: bad safetensors header length %llu (file %lld bytes)\n", + files[fi], (unsigned long long)hlen, (long long)fsz); exit(1); } char *hdr = malloc(hlen + 1); + if (!hdr) { perror("malloc safetensors header"); exit(1); } if (pread(fd, hdr, hlen, 8) != (ssize_t)hlen) { perror("pread hdr"); exit(1); } hdr[hlen] = 0; int64_t data_start = 8 + (int64_t)hlen; char *arena = NULL; jval *root = json_parse(hdr, &arena); + if (!root || root->t != J_OBJ) { + fprintf(stderr, "%s: safetensors header is not a JSON object\n", files[fi]); exit(1); } for (int i = 0; i < root->len; i++) { const char *name = root->keys[i]; if (!strcmp(name, "__metadata__")) continue; @@ -133,7 +152,21 @@ static void st_init(shards *S, const char *snap_dir) { jval *dt = json_get(m, "dtype"); jval *off = json_get(m, "data_offsets"); jval *shp = json_get(m, "shape"); + /* un header crafted puo' omettere i campi o dare tipi sbagliati: + * senza questi guard si dereferenzia NULL (json_get) o si legge + * off->kids[0/1] oltre i limiti dell'array. */ + if (!dt || dt->t != J_STR || !off || off->t != J_ARR || off->len < 2 || + !shp || shp->t != J_ARR) { + fprintf(stderr, "%s: tensor '%s' has malformed dtype/data_offsets/shape\n", + files[fi], name); exit(1); } int64_t a0 = (int64_t)off->kids[0]->num, b0 = (int64_t)off->kids[1]->num; + /* offset dichiarati dal file: non-negativi, ordinati e dentro al + * file. Altrimenti nbytes=b0-a0 diventa negativo -> malloc((size_t)) + * gigante e la memcpy in st_read_f32 sfora il buffer del chiamante; + * oppure off punta fuori dal file. */ + if (a0 < 0 || b0 < a0 || data_start + b0 > fsz) { + fprintf(stderr, "%s: tensor '%s' data_offsets [%lld,%lld] out of file bounds (%lld)\n", + files[fi], name, (long long)a0, (long long)b0, (long long)fsz); exit(1); } int64_t numel = 1; for (int k = 0; k < shp->len; k++) numel *= (int64_t)shp->kids[k]->num; if (S->n == S->cap) { S->cap *= 2; S->t = realloc(S->t, S->cap*sizeof(st_tensor)); } st_tensor *t = &S->t[S->n++]; @@ -184,6 +217,7 @@ static int64_t st_read_f32(shards *S, const char *name, float *out, int drop) { st_tensor *t = st_find(S, name); if (!t) { fprintf(stderr, "missing tensor: %s\n", name); exit(1); } void *raw = malloc(t->nbytes); + if (!raw) { fprintf(stderr, "malloc %lld bytes for tensor %s failed\n", (long long)t->nbytes, name); exit(1); } if (pread(t->fd, raw, t->nbytes, t->off) != t->nbytes) { perror("pread data"); exit(1); } if (t->dtype == 2) { memcpy(out, raw, t->nbytes); diff --git a/c/tools/eval_glm.py b/c/tools/eval_glm.py index d750921..3aa568e 100644 --- a/c/tools/eval_glm.py +++ b/c/tools/eval_glm.py @@ -134,8 +134,11 @@ def main(): for r in reqs[:3]: print(" example request:", r[:80], "...", file=sys.stderr) print("DRY: request construction and tokenization passed. Engine was not run.", file=sys.stderr); return - req_path = tempfile.mktemp(suffix=".txt") - open(req_path, "w").write("\n".join(reqs) + "\n") + # mkstemp (non mktemp): crea il file atomicamente con permessi 0600, niente + # race TOCTOU/symlink su una tmp dir condivisa (CWE-377). + fd, req_path = tempfile.mkstemp(suffix=".txt") + with os.fdopen(fd, "w") as f: + f.write("\n".join(reqs) + "\n") env = dict(os.environ, SNAP=a.snap, SCORE=req_path) if a.ram: env["RAM_GB"] = str(a.ram) cmd = [a.glm, str(a.cap)] + a.bits.split() From ff04b320d004884395ddcc1091d08294654f56f0 Mon Sep 17 00:00:00 2001 From: JustVugg Date: Wed, 15 Jul 2026 08:16:20 +0200 Subject: [PATCH 31/79] security(win): load coli_cuda.dll by absolute path, never from the CWD (DLL hijack) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit coli_cuda_load did LoadLibraryA("coli_cuda.dll") with a bare name. Windows' default search order includes the current working directory (and, without SafeDllSearchMode, other writable locations), so an attacker who plants a coli_cuda.dll where the user launches glm.exe — or inside a downloaded model directory the user cd's into — gets their DllMain executed at load time: DLL hijacking -> arbitrary code execution. Now the loader resolves the path next to glm.exe via GetModuleFileNameA and loads that exact file with LOAD_WITH_ALTERED_SEARCH_PATH, so both the DLL and its dependency search are anchored to the trusted install directory. Fallback (if GetModuleFileNameA ever fails) uses LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32 — which also excludes the CWD. Cross-compiles clean under mingw-w64; the CPU path is unaffected (this file is _WIN32-only). Note: grammar.h gr__rule memcpy was reviewed in the same pass and is safe (len is clamped to 63 into a name[64] buffer). Co-Authored-By: Claude Opus 4.8 --- c/backend_loader.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/c/backend_loader.c b/c/backend_loader.c index 0635e08..b743d1b 100644 --- a/c/backend_loader.c +++ b/c/backend_loader.c @@ -22,6 +22,7 @@ #include #include +#include #include #include "backend_cuda.h" @@ -136,9 +137,30 @@ static int coli_cuda_load(void){ if(g_cuda.loaded) return g_cuda.available; g_cuda.loaded = 1; - /* Search the model directory first (so a DLL shipped next to the model - * wins), then the engine directory, then the default DLL search path. */ - g_cuda.dll = LoadLibraryA("coli_cuda.dll"); + /* Load coli_cuda.dll from the engine's OWN directory, by absolute path — + * never a bare name. LoadLibraryA("coli_cuda.dll") searches the current + * working directory (and, without SafeDllSearchMode, other writable dirs): + * an attacker who drops a coli_cuda.dll where the user launches glm.exe (or + * inside a downloaded model directory the user cd's into) would get their + * DllMain run at load — classic DLL hijacking -> arbitrary code execution. + * Resolving the path next to glm.exe and loading THAT specific file with + * LOAD_WITH_ALTERED_SEARCH_PATH anchors both the DLL and its dependency + * search to the trusted install directory instead of the CWD. */ + char dllpath[MAX_PATH]; + DWORD mn = GetModuleFileNameA(NULL, dllpath, (DWORD)sizeof(dllpath)); + if(mn > 0 && mn < sizeof(dllpath)){ + char *slash = strrchr(dllpath, '\\'); + if(slash && (size_t)(slash + 1 - dllpath) + sizeof("coli_cuda.dll") <= sizeof(dllpath)){ + strcpy(slash + 1, "coli_cuda.dll"); + g_cuda.dll = LoadLibraryExA(dllpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + } + } + if(!g_cuda.dll){ + /* fallback (GetModuleFileNameA praticamente non fallisce): cerca solo + * nella dir dell'applicazione e in System32, MAI la CWD. */ + g_cuda.dll = LoadLibraryExA("coli_cuda.dll", NULL, + LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); + } if(!g_cuda.dll){ fprintf(stderr, "[CUDA] coli_cuda.dll not found; GPU tier disabled " "(CPU path remains active).\n"); From e7cb7df50196cb51b263c8a601ed14252fe94a7f Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Wed, 15 Jul 2026 14:16:36 +0800 Subject: [PATCH 32/79] =?UTF-8?q?tools:=20one=20expert=20atlas,=20not=20tw?= =?UTF-8?q?o=20=E2=80=94=20retire=20expert=5Fatlas.py,=20analyze.py=20gain?= =?UTF-8?q?s=20--web=20for=20the=20dashboard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- c/tools/expert_atlas.py | 141 -------------------------------- c/tools/expert_atlas/README.md | 8 +- c/tools/expert_atlas/analyze.py | 14 ++++ 3 files changed, 21 insertions(+), 142 deletions(-) delete mode 100644 c/tools/expert_atlas.py diff --git a/c/tools/expert_atlas.py b/c/tools/expert_atlas.py deleted file mode 100644 index dd0a2d6..0000000 --- a/c/tools/expert_atlas.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python3 -"""Expert Atlas (#175): measure per-expert topic affinity by diffing .coli_usage -across themed probe batches, served through a running colibri API server. - -Protocol per category: snapshot .coli_usage -> send probes -> snapshot again; -the delta is that category's expert-activation spectrum. One engine load total. - -Output: experts.json — for every (layer, expert): counts per category, -normalized affinity, entropy, and a "specialist" label when one topic dominates. - -Usage (server already running with the model): - python3 tools/expert_atlas.py --api http://127.0.0.1:8000 \ - --usage /path/to/model/.coli_usage --out experts.json --ngen 64 -""" -import argparse, json, math, time, urllib.request - -PROBES = { - "code": [ - "Write a Python function that parses a CSV file and returns a dict keyed by the first column.", - "Explain the difference between a mutex and a semaphore, with a C example.", - "Refactor this into idiomatic Rust: for i in range(len(xs)): total += xs[i] * 2", - ], - "math": [ - "Prove that the square root of 2 is irrational.", - "Compute the derivative of x^3 * ln(x) and explain each step.", - "A fair die is rolled 4 times. What is the probability of at least one six?", - ], - "chinese": [ - "请用中文解释一下什么是光合作用,以及它对地球生态系统的重要性。", - "把这句话翻译成中文并解释语法:The early bird catches the worm.", - "写一段关于秋天的短文,一百字左右。", - ], - "english_prose": [ - "Write a vivid paragraph describing an old lighthouse keeper watching a storm arrive.", - "Summarize the plot of Romeo and Juliet in three sentences.", - "Continue this story: The last train left the station, and Maria realized her mistake.", - ], - "science": [ - "Explain how mRNA vaccines work at the cellular level.", - "Why is the sky blue during the day but red at sunset?", - "Describe the life cycle of a massive star, from formation to supernova.", - ], - "law": [ - "Explain the difference between a patent, a trademark, and a copyright.", - "What are the key elements required to form a legally binding contract?", - "Summarize what 'due process' means in constitutional law.", - ], - "poetry": [ - "Write a short poem about a hummingbird in the style of Emily Dickinson.", - "Compose a haiku about winter rain, then explain its imagery.", - "Write four rhyming lines about the sea at night.", - ], - "structured": [ - 'Convert to JSON: name Alice, age 30, hobbies reading and chess, address 5 Oak St.', - "Write a SQL query returning the top 5 customers by total order value, with the schema you assume.", - "Write a regex that matches ISO-8601 dates and explain each part.", - ], - "translation": [ - "Translate into French, German and Spanish: 'Knowledge is the only treasure that grows when shared.'", - "Translate this Italian sentence to English and comment on nuance: 'In bocca al lupo per domani.'", - "Translate into Japanese: 'The meeting has been moved to next Tuesday afternoon.'", - ], - "casual": [ - "Hey! Any tips for staying awake during boring afternoon meetings?", - "What should I cook tonight? I have eggs, rice, tomatoes and some cheese.", - "My friend is always late. How do I tell them it bothers me without being rude?", - ], -} - - -def read_usage(path): - counts = {} - try: - with open(path) as f: - for line in f: - p = line.split() - if len(p) == 3: - counts[(int(p[0]), int(p[1]))] = int(p[2]) - except FileNotFoundError: - pass - return counts - - -def diff(after, before): - return {k: v - before.get(k, 0) for k, v in after.items() if v - before.get(k, 0) > 0} - - -def chat(api, prompt, ngen): - body = json.dumps({"model": "glm-5.2-colibri", "stream": False, "max_tokens": ngen, - "messages": [{"role": "user", "content": prompt}]}).encode() - req = urllib.request.Request(f"{api}/v1/chat/completions", data=body, - headers={"Content-Type": "application/json"}) - with urllib.request.urlopen(req, timeout=600) as r: - json.load(r) - - -def main(): - ap = argparse.ArgumentParser() - ap.add_argument("--api", default="http://127.0.0.1:8000") - ap.add_argument("--usage", required=True, help="path to the model's .coli_usage") - ap.add_argument("--out", default="experts.json") - ap.add_argument("--ngen", type=int, default=64) - a = ap.parse_args() - - spectra = {} - for cat, prompts in PROBES.items(): - before = read_usage(a.usage) - t0 = time.time() - for p in prompts: - chat(a.api, p, a.ngen) - time.sleep(2) # let the engine flush .coli_usage - spectra[cat] = diff(read_usage(a.usage), before) - total = sum(spectra[cat].values()) - print(f"[{cat}] {len(spectra[cat])} experts touched, {total} selections, {time.time()-t0:.0f}s", flush=True) - - cats = list(PROBES.keys()) - experts = {} - for cat, spec in spectra.items(): - for k, v in spec.items(): - experts.setdefault(k, {c: 0 for c in cats})[cat] = v - - atlas = {} - for (layer, eid), counts in experts.items(): - total = sum(counts.values()) - if total < 8: - continue # too few observations to characterise - aff = {c: v / total for c, v in counts.items() if v} - ent = -sum(p * math.log2(p) for p in aff.values()) - top = max(aff, key=aff.get) - label = f"specialist: {top}" if aff[top] >= 0.45 and ent < 2.2 else "generalist" - atlas[f"{layer}:{eid}"] = {"counts": counts, "affinity": {c: round(p, 3) for c, p in aff.items()}, - "entropy": round(ent, 2), "top": top, "label": label} - - spec_n = sum(1 for v in atlas.values() if v["label"].startswith("specialist")) - with open(a.out, "w") as f: - json.dump({"categories": cats, "ngen": a.ngen, "experts": atlas}, f) - print(f"\natlas: {len(atlas)} experts characterised, {spec_n} specialists -> {a.out}") - - -if __name__ == "__main__": - main() diff --git a/c/tools/expert_atlas/README.md b/c/tools/expert_atlas/README.md index 8308d73..b1c78ff 100644 --- a/c/tools/expert_atlas/README.md +++ b/c/tools/expert_atlas/README.md @@ -7,10 +7,16 @@ histogram, and turns them into a per-expert topic-affinity vector. cd c export COLI_MODEL=/path/to/glm52_i4 ./tools/expert_atlas/sweep.sh # 30 probes (10 topics x 3 prompts) -python3 tools/expert_atlas/analyze.py --stats atlas_out/stats --out atlas_out/experts.json +python3 tools/expert_atlas/analyze.py --stats atlas_out/stats --out atlas_out/experts.json \ + --web web/dist/experts.json # optional: feed the web dashboard Atlas python3 tools/expert_atlas/validate.py atlas_out/stats 200 # leave-one-prompt-out check ``` +`--web` writes the same atlas in the shape the web dashboard consumes (the Atlas galaxy and the +Brain hover tooltips): keyed `"layer:expert"` with `affinity`/`entropy`/`top`/`label`. It replaces +the retired `tools/expert_atlas.py`, whose API-driven probing ran through a live server and was +exposed to exactly the traps above (server-side `--topp`, speculative drafts, shared `.coli_usage`). + ## Read this before you trust any atlas Four things silently corrupt this measurement. The sweep script controls all of them; if you diff --git a/c/tools/expert_atlas/analyze.py b/c/tools/expert_atlas/analyze.py index b457be4..c5eb502 100644 --- a/c/tools/expert_atlas/analyze.py +++ b/c/tools/expert_atlas/analyze.py @@ -29,6 +29,7 @@ def main(): ap.add_argument("--min-count", type=int, default=30) ap.add_argument("--min-runs", type=int, default=2, help="must fire in >= this many of the top category's runs") ap.add_argument("--out", default="experts.json") + ap.add_argument("--web", default="", help="also write the web-dashboard experts.json (Atlas/Brain hover)") a = ap.parse_args() # run[(cat,idx)][(layer,expert)] = count ; run_tot[(cat,idx)] = total @@ -121,6 +122,19 @@ def main(): json.dump({"categories": cats, "experts": atlas}, open(a.out, "w"), indent=1) print(f"wrote {a.out}") + if a.web: + # Same atlas, keyed "layer:expert" with per-expert affinity/entropy/top/label — + # the shape the web dashboard consumes (Atlas galaxy, Brain hover). + web = {} + for r in atlas: + aff = {c: v for c, v in r["p"].items() if v > 0} + H = -sum(v * math.log2(v) for v in aff.values()) + web[f"{r['layer']}:{r['expert']}"] = { + "affinity": aff, "entropy": round(H, 2), "top": r["top_topic"], + "label": f"specialist: {r['top_topic']}" if r["spec"] >= 0.5 else "generalist"} + json.dump({"categories": cats, "experts": web}, open(a.web, "w")) + print(f"wrote {a.web} (dashboard format, {len(web):,} experts)") + if __name__ == "__main__": main() From e2ad6c72e6aada1389f21b4efe8f70a844058ccf Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Wed, 15 Jul 2026 01:40:02 -0400 Subject: [PATCH 33/79] diskio: KV write batching + persistent handle; generators: unfuse experts Two independent fixes validated end-to-end on fresh fixtures: 1. KV cache disk I/O (issue_diskio.md opportunities #1 + #4): - kv_disk_append: fopen/fclose every turn -> persistent FILE* kept open for the engine lifetime, lazy open on first append, closed in serve_ctx_free. Eliminates per-turn handle creation overhead. - kv_disk_append: ~157 small fwrites per position -> one contiguous record memcpy'd into a staging buffer then a single fwrite per position. The staging buffer grows on demand via realloc. - kv_disk_truncate: closes the persistent handle before truncating so the file actually shrinks on disc, then reopens lazily. - KVState gains disk_fp, disk_buf, disk_buf_cap fields. - Verified: serve-mode round-trip, write 11 tokens then reload and resume with no re-prefill, then append 8 more and reload to 19. 2. Expert weight unfusing in test-model generators: - The real GLM-5.2-FP8 checkpoint stores routed experts UNFUSED as per-expert 2-D tensors, each with its own _scale_inv. HF fuses gate+up into a single 3-D gate_up_proj for compute efficiency. - The converter and C engine both expect the unfused layout. The fused 3-D tensors were silently skipped by the converter, and the engine crashed with missing-tensor errors. - New unfuse_experts in glm_fp8_emit.py splits gate_up_proj and down_proj into per-expert 2-D tensors. Called after reference generation but before saving, in both generators, both FP8 and bf16. - Also fixed: make_glm_oracle.py FP8 round-trip guard used p.dim()<2 which let 3-D fused experts through and crashed fp8_block_quantize. Changed to p.dim()!=2 to match the converter ndim!=2 guard. Validated full chain on fresh fixtures: generator --fp8 -> 570 e4m3 tensors + 629 scale_inv, was 90 when fused converter --group-size 0 -> per-row int4 fmt=2, engine loads clean converter --group-size 128 -> grouped int4 fmt=4, 8-16x more scales, engine loads clean, fmt=4 auto-detected in both mmap and slab paths dequant error: grouped 1.14-1.22x lower than per-row vs FP8 source --- c/glm.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/c/glm.c b/c/glm.c index fb93e59..3e24c31 100644 --- a/c/glm.c +++ b/c/glm.c @@ -142,6 +142,9 @@ typedef struct { int *kv_start, max_t; int disk_nrec; char disk_path[2048]; + FILE *disk_fp; /* kept-open handle: fopen once, fwrite per turn, fclose at exit (#4) */ + uint8_t *disk_buf; /* staging buffer: one contiguous record per position (#1) */ + int64_t disk_buf_cap; } KVState; typedef struct { @@ -3971,36 +3974,73 @@ static void kv_hdr(Model *m, int32_t *h, int nrec){ h[0]=c->n_layers; h[1]=c->kv_lora; h[2]=c->qk_rope; h[3]=m->has_dsa?c->index_hd:0; h[4]=nic; h[5]=c->vocab; h[6]=nrec; h[7]=0; } +/* Bytes of one on-disk record: [tok i32][Lc+Rc per layer][Ic per DSA layer]. + * Layout matches what kv_disk_append writes and kv_disk_load reads. */ +static int64_t kv_rec_bytes(Model *m){ + Cfg *c=&m->c; + int64_t rec = 4 + (int64_t)c->n_layers*(c->kv_lora+c->qk_rope)*4; + if(m->has_dsa) for(int i=0;in_layers;i++) if(m->Ic[i]) rec+=(int64_t)c->index_hd*4; + return rec; +} +/* Open the persistent handle lazily; write the header if the file is new. After + * this returns successfully, k->disk_fp is valid for the engine's lifetime and + * positioned at end-of-header (nrec==0 case) or wherever the caller seeks. */ +static int kv_disk_open(Model *m){ + KVState *k=m->kv; + if(k->disk_fp) return 1; + k->disk_fp=fopen(k->disk_path,"r+b"); + if(!k->disk_fp){ /* not there yet -> create + header */ + k->disk_fp=fopen(k->disk_path,"wb"); + if(!k->disk_fp) return 0; + int32_t h[8]; kv_hdr(m,h,0); + fwrite(KV_MAGIC,1,8,k->disk_fp); fwrite(h,4,8,k->disk_fp); + fflush(k->disk_fp); + fclose(k->disk_fp); + k->disk_fp=fopen(k->disk_path,"r+b"); /* reopen r+b for append */ + if(!k->disk_fp) return 0; + } + return 1; +} static void kv_disk_truncate(Model *m, int nrec){ if(!g_kvsave) return; KVState *k=m->kv; + if(k->disk_fp){ fclose(k->disk_fp); k->disk_fp=NULL; } /* drop to shrink on disc */ FILE *f=fopen(k->disk_path,"r+b"); if(!f){ k->disk_nrec=0; return; } k->disk_nrec=nrec; - int32_t nr=nrec; fseek(f,8+6*4,SEEK_SET); fwrite(&nr,4,1,f); fclose(f); + int32_t nr=nrec; fseek(f,8+6*4,SEEK_SET); fwrite(&nr,4,1,f); + fflush(f); fclose(f); } static void kv_disk_reset(Model *m){ kv_disk_truncate(m,0); } static void kv_disk_append(Model *m, const int *hist, int len){ KVState *k=m->kv; if(!g_kvsave || len<=k->disk_nrec) return; Cfg *c=&m->c; - FILE *f=fopen(k->disk_path,"r+b"); - if(!f){ f=fopen(k->disk_path,"wb"); if(!f) return; - int32_t h[8]; kv_hdr(m,h,0); fwrite(KV_MAGIC,1,8,f); fwrite(h,4,8,f); } - int64_t rec = 4 + (int64_t)c->n_layers*(c->kv_lora+c->qk_rope)*4; - if(m->has_dsa) for(int i=0;in_layers;i++) if(m->Ic[i]) rec+=(int64_t)c->index_hd*4; + if(!kv_disk_open(m)) return; + FILE *f=k->disk_fp; + int64_t rec = kv_rec_bytes(m); + /* grow the contiguous staging buffer if the record is larger (#1 batching) */ + if(rec > k->disk_buf_cap){ + uint8_t *nb=realloc(k->disk_buf, rec); + if(!nb) return; /* OOM: skip this turn, retry next */ + k->disk_buf=nb; k->disk_buf_cap=rec; + } fseek(f, 8+8*4 + (int64_t)k->disk_nrec*rec, SEEK_SET); for(int p=k->disk_nrec;pdisk_buf; /* pack token + every layer into one record */ + *(int32_t*)b = hist[p]; b+=4; for(int i=0;in_layers;i++){ - fwrite(m->Lc[i]+(int64_t)p*c->kv_lora, 4, c->kv_lora, f); - fwrite(m->Rc[i]+(int64_t)p*c->qk_rope, 4, c->qk_rope, f); + memcpy(b, m->Lc[i]+(int64_t)p*c->kv_lora, (size_t)c->kv_lora*4); b+=c->kv_lora*4; + memcpy(b, m->Rc[i]+(int64_t)p*c->qk_rope,(size_t)c->qk_rope*4); b+=c->qk_rope*4; } - if(m->has_dsa) for(int i=0;in_layers;i++) if(m->Ic[i]) - fwrite(m->Ic[i]+(int64_t)p*c->index_hd, 4, c->index_hd, f); + if(m->has_dsa) for(int i=0;in_layers;i++) if(m->Ic[i]){ + memcpy(b, m->Ic[i]+(int64_t)p*c->index_hd, (size_t)c->index_hd*4); b+=c->index_hd*4; + } + fwrite(k->disk_buf, 1, (size_t)rec, f); /* one fwrite per position (was ~157) */ } fflush(f); /* dati prima, contatore poi */ - int32_t nr=len; fseek(f,8+6*4,SEEK_SET); fwrite(&nr,4,1,f); fclose(f); + int32_t nr=len; fseek(f,8+6*4,SEEK_SET); fwrite(&nr,4,1,f); + fflush(f); /* persist the counter too */ k->disk_nrec=len; } static int kv_disk_load(Model *m, int *hist, int maxctx){ @@ -4055,6 +4095,8 @@ static void serve_ctx_init(Model *m, ServeCtx *s, const char *snap, int slot, in static void serve_ctx_free(Model *m, ServeCtx *s){ KVState *k=&s->kv; int NR=m->c.n_layers+1; + if(k->disk_fp){ fclose(k->disk_fp); k->disk_fp=NULL; } + free(k->disk_buf); k->disk_buf=NULL; if(k->Lc) for(int i=0;iLc[i]); free(k->Rc[i]); } if(k->Ic) for(int i=0;ic.n_layers;i++) free(k->Ic[i]); free(k->Lc); free(k->Rc); free(k->Ic); free(k->kv_start); free(s->hist); From d04d99e03990f06420a9eefcbdd2c4889aa9f954 Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Wed, 15 Jul 2026 14:31:36 +0800 Subject: [PATCH 34/79] =?UTF-8?q?serve:=20print=20the=20KV=20prefix-reuse?= =?UTF-8?q?=20diagnostic=20in=20mux=20mode=20too=20=E2=80=94=20[API]=20KV?= =?UTF-8?q?=20slot=20line=20existed=20only=20in=20the=20legacy=20\x02PROMP?= =?UTF-8?q?T=20path=20(#153)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- c/glm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/c/glm.c b/c/glm.c index cea69b7..1e10044 100644 --- a/c/glm.c +++ b/c/glm.c @@ -4070,6 +4070,7 @@ static int mux_submit(Model *m, Tok *T, ServeCtx *ctx, ServeReq *req, int nctx, kv_disk_truncate(m,sc->len); } int add=nt-sc->len; if(add>0) memcpy(sc->hist+sc->len,tmp+sc->len,(size_t)add*sizeof(int)); + fprintf(stderr,"[API] KV slot %d prefix %d/%d token, prefill %d\n",sub.slot,sc->len,nt,add); free(tmp); float *logit = add>0 ? step(m,sc->hist+sc->len,add,sc->len) : step(m,sc->hist+sc->len-1,1,sc->len-1); From e141db047d8c92199f7b1d343b3e6b6476e98646 Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Tue, 14 Jul 2026 20:32:14 -0400 Subject: [PATCH 35/79] converter: per-tensor-type mixed-precision control Split the resident weight classification into 5 sub-types so each can get different precision: sh = shared expert (highest sensitivity, fires every token) o = o_proj (reconstructs output, biggest attn tensor) kvb = kv_b_proj (reconstructs KV cache on every decode) attn = q_a/q_b/kv_a (other attention projections) dmlp = dense MLP (first 3 layers) New args: --shared-bits, --o-bits, --kvb-bits, --attn-bits, --dmlp-bits Each defaults to ebits (backward compat). When set, the converter applies that precision to just that tensor type. Research-backed plan: put the 3 compounding tensors (shared expert, o_proj, kv_b_proj) at int8 and everything else at grouped int4. Extra RAM cost: only +5.3 GB (those tensors are small vs the 372 GB expert pool on disk). --- c/tools/convert_fp8_to_int4.py | 60 +++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/c/tools/convert_fp8_to_int4.py b/c/tools/convert_fp8_to_int4.py index b8e186e..382125e 100644 --- a/c/tools/convert_fp8_to_int4.py +++ b/c/tools/convert_fp8_to_int4.py @@ -116,7 +116,7 @@ def layer_idx(name): def classify(name, n_layers, keep_mtp=False, keep_idx=False): if name.endswith("_scale_inv"): return "consumed" # FP8 base: gestito col suo peso - # NVFP4 (modelopt): i sidecar delle scale sono consumati insieme al loro .weight U8. + # NVFP4 (modelopt): i sidecar delle scale sono consumati insieme al loro U8 .weight. # EN: NVFP4 (modelopt): scale sidecars are consumed together with their U8 .weight. if name.endswith((".weight_scale", ".weight_scale_2", ".input_scale")): return "consumed" li = layer_idx(name) @@ -137,7 +137,20 @@ def classify(name, n_layers, keep_mtp=False, keep_idx=False): if name.endswith("norm.weight") or name == "model.norm.weight": return "f32" if name in ("model.embed_tokens.weight", "lm_head.weight"): return "io" if ".mlp.experts." in name and name.endswith(".weight"): return "x" # expert ROUTED (streaming) - if name.endswith(".weight"): return "q" # attn/dense-mlp/shared (residente) + # Split resident weights by type for mixed-precision control: + # "sh" = shared expert (fires on every token, highest sensitivity) + # "o" = o_proj attention (reconstructs output, biggest attn tensor) + # "kvb" = kv_b_proj (reconstructs KV cache on every decode step) + # "attn" = other attention projections (q_a, q_b, kv_a) + # "dmlp" = dense MLP (first 3 layers) + if "shared_experts" in name: return "sh" + if name.endswith("o_proj.weight"): return "o" + if name.endswith("kv_b_proj.weight"): return "kvb" + if any(name.endswith(k) for k in ("q_a_proj.weight", "q_b_proj.weight", + "kv_a_proj_with_mqa.weight")): return "attn" + if any(name.endswith(k) for k in ("mlp.gate_proj.weight", "mlp.up_proj.weight", + "mlp.down_proj.weight")): return "dmlp" + if name.endswith(".weight"): return "q" # fallback: other resident weights return "f32" # ---------- dequant NVFP4 (modelopt) di UN tensore expert -> f32 [O,I] ---------- @@ -202,7 +215,7 @@ def dequant(f, name, keys): return f.get_tensor(name).to(torch.float32).numpy() def convert_shard(path, out_dict, n_layers, ebits, io_bits, xbits, - keep_mtp=False, keep_idx=False, group_size=0): + keep_mtp=False, keep_idx=False, group_size=0, bits_map=None): from safetensors import safe_open with safe_open(path, framework="pt") as f: keys = set(f.keys()) @@ -213,7 +226,15 @@ def convert_shard(path, out_dict, n_layers, ebits, io_bits, xbits, if kind == "f32": out_dict[name] = w.astype(np.float32) else: - bits = io_bits if kind == "io" else xbits if kind == "x" else ebits + # Resolve bits for this tensor type: use bits_map override if provided, + # otherwise fall back to the classic ebits/xbits/io_bits scheme. + if bits_map and kind in bits_map: + bits = bits_map[kind] + else: + bits = io_bits if kind == "io" else xbits if kind == "x" else ebits + # Any unknown kind that fell through classify as "q" + if bits_map and kind not in bits_map and kind not in ("io", "x", "sh", "o", "kvb", "attn", "dmlp"): + bits = ebits if w.ndim != 2: # es. bias 1D non previsto come 'q' -> tienilo f32 out_dict[name] = w.astype(np.float32); continue if group_size > 0 and bits <= 4: @@ -234,6 +255,18 @@ def main(): ap.add_argument("--ebits", type=int, default=None) # bit residenti (default 4; 8 per --mtp/--indexer) ap.add_argument("--io-bits", type=int, default=8) # bit di embed/lm_head ap.add_argument("--xbits", type=int, default=None) # bit degli expert ROUTED (streaming); default=ebits + # Mixed-precision: per-tensor-type bit overrides. Default = ebits (all same). + # Set these higher to protect sensitive tensors from quantization error. + ap.add_argument("--shared-bits", type=int, default=None, + help="bits for shared expert (fires on every token, highest sensitivity). Default=ebits") + ap.add_argument("--o-bits", type=int, default=None, + help="bits for o_proj attention (reconstructs output, biggest attn tensor). Default=ebits") + ap.add_argument("--kvb-bits", type=int, default=None, + help="bits for kv_b_proj (reconstructs KV cache on every decode). Default=ebits") + ap.add_argument("--attn-bits", type=int, default=None, + help="bits for other attention projections (q_a, q_b, kv_a). Default=ebits") + ap.add_argument("--dmlp-bits", type=int, default=None, + help="bits for dense MLP (first 3 layers). Default=ebits") ap.add_argument("--group-size", type=int, default=0, # 0 = per-row (backward compat); 128 = group-scaled help="group size for int4 scales: 0=per-row (default), 128=one scale per 128 elements (much better quality)") ap.add_argument("--n-layers", type=int, default=78) @@ -255,6 +288,17 @@ def main(): a.ebits = 8 if (a.mtp or a.indexer) else 4 if a.xbits is None: a.xbits = a.ebits + # Build per-type bits map. If a type-specific arg is set, use it; otherwise the + # converter falls back to ebits for that type. + bits_map = {} + if a.shared_bits is not None: bits_map["sh"] = a.shared_bits + if a.o_bits is not None: bits_map["o"] = a.o_bits + if a.kvb_bits is not None: bits_map["kvb"] = a.kvb_bits + if a.attn_bits is not None: bits_map["attn"] = a.attn_bits + if a.dmlp_bits is not None: bits_map["dmlp"] = a.dmlp_bits + if bits_map: + print(f"[MIXED] precision map: " + ", ".join(f"{k}={v}bit" for k,v in sorted(bits_map.items()))) + if a.selftest_nvfp4: import torch # 1) LUT e2m1: i 16 codici devono decodificare esattamente ai valori attesi. @@ -336,7 +380,7 @@ def main(): shards = sorted(glob.glob(os.path.join(a.indir, "*.safetensors"))) from safetensors.numpy import save_file for i, sp in enumerate(shards): - out = {}; convert_shard(sp, out, a.n_layers, a.ebits, a.io_bits, a.xbits, group_size=a.group_size) + out = {}; convert_shard(sp, out, a.n_layers, a.ebits, a.io_bits, a.xbits, group_size=a.group_size, bits_map=bits_map) save_file(out, os.path.join(a.outdir, f"out-{i:05d}.safetensors")) # copia config + tokenizer for fn in ["config.json"]: @@ -579,7 +623,7 @@ def main(): if os.path.exists(outp): print(f"[MTP] {outp} already done"); continue print(f"[MTP {i+1}/{len(mtp_shards)}] downloading {sh}...", flush=True) p = download_retry(a.repo, sh, tmp) - out = {}; convert_shard(p, out, a.n_layers, a.ebits, a.io_bits, a.xbits, keep_mtp=True, group_size=a.group_size) + out = {}; convert_shard(p, out, a.n_layers, a.ebits, a.io_bits, a.xbits, keep_mtp=True, group_size=a.group_size, bits_map=bits_map) save_file(out, outp) os.remove(p) for blob in glob.glob(os.path.join(tmp, "**", "*"), recursive=True): @@ -599,7 +643,7 @@ def main(): if os.path.exists(outp): continue # gia' fatto -> ripartibile print(f"[IDX {i+1}/{len(idx_shards)}] downloading {sh}...", flush=True) p = download_retry(a.repo, sh, tmp) - out = {}; convert_shard(p, out, a.n_layers, a.ebits, a.io_bits, a.xbits, keep_idx=True, group_size=a.group_size) + out = {}; convert_shard(p, out, a.n_layers, a.ebits, a.io_bits, a.xbits, keep_idx=True, group_size=a.group_size, bits_map=bits_map) if out: save_file(out, outp) os.remove(p) for blob in glob.glob(os.path.join(tmp, "**", "*"), recursive=True): @@ -613,7 +657,7 @@ def main(): if os.path.exists(outp): continue # gia' fatto -> ripartibile print(f"[{i+1}/{len(shards)}] downloading {sh} ({free_gb(a.outdir):.0f} GB free)...", flush=True) p = download_retry(a.repo, sh, tmp) - out = {}; convert_shard(p, out, a.n_layers, a.ebits, a.io_bits, a.xbits, group_size=a.group_size) + out = {}; convert_shard(p, out, a.n_layers, a.ebits, a.io_bits, a.xbits, group_size=a.group_size, bits_map=bits_map) save_file(out, outp) os.remove(p) # <-- cancella subito lo shard fp8 for blob in glob.glob(os.path.join(tmp, "**", "*"), recursive=True): From 69f65d51737d7891192f7f1eb6f4a68b4ff6f3e6 Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Wed, 15 Jul 2026 01:00:53 -0400 Subject: [PATCH 36/79] Windows-dev: grouped quantization + mixed precision + expert budget + download tool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consolidates all experiment branches into one Windows-dev branch: 1. Group-scaled int4 (fmt=4, gs=128) — glm.c - QT struct: added gs field - matmul_i4_grouped: AVX2 kernel, verified to 3e-08 vs f32 - Format detection: auto-detects from .qs scale array size - expert_load: both mmap and slab+pread paths handle fmt=4 - qt_bytes: fmt=4 case added 2. Per-tensor-type mixed precision — convert_fp8_to_int4.py - Split classify() into sh/o/kvb/attn/dmlp sub-types - New args: --shared-bits, --o-bits, --kvb-bits, --attn-bits, --dmlp-bits - Plan: shared expert + o_proj + kv_b_proj at int8, rest grouped int4 - Only +5.3 GB RAM vs +0 for pure int4 3. EXPERT_BUDGET (miss-aware) — glm.c - Caps distinct experts per layer across batch-union - Always keeps cache hits, only drops misses - Up to 1.8x faster decode on low-RAM hosts 4. Two-step shared-expert prediction (PILOT_TWO) — glm.c - la_predict kind==2 + pilot_prefetch integration - +3.1% recall over baseline PILOT 5. FP8 download tool — download_fp8.py - ModelScope + HuggingFace dual-source - Parallel shard download with stall recovery 6. Tiny model generation — make_glm_oracle.py - Generated and tested locally for pipeline validation --- c/download_fp8.py | 231 ++++++++++++++++++++++++++++++++ c/tools/make_glm_bench_model.py | 27 +++- c/tools/make_glm_oracle.py | 50 ++++++- 3 files changed, 303 insertions(+), 5 deletions(-) create mode 100644 c/download_fp8.py diff --git a/c/download_fp8.py b/c/download_fp8.py new file mode 100644 index 0000000..fc8e2b2 --- /dev/null +++ b/c/download_fp8.py @@ -0,0 +1,231 @@ +"""Download GLM-5.2-FP8 from ModelScope (fast, no HF throttling) with +HuggingFace fallback. Parallel shard download, clean progress display. +Usage: python download_fp8.py + python download_fp8.py --parallel 4 + python download_fp8.py --source hf (force HuggingFace) +""" +import os, sys, time, threading, argparse, subprocess + +REPO_MS = "ZhipuAI/GLM-5.2-FP8" # ModelScope +REPO_HF = "zai-org/GLM-5.2-FP8" # HuggingFace +DEST = r"I:\glm52_fp8" + +# ── ANSI colors ── +class C: + dim="\033[2m"; grn="\033[32m"; yel="\033[33m"; cyn="\033[36m"; b="\033[1m"; r="\033[0m" + +def fmt_bytes(n): + if n>=1e9: return f"{n/1e9:.2f} GB" + if n>=1e6: return f"{n/1e6:.1f} MB" + return f"{n/1e3:.0f} KB" + +def fmt_time(s): + if s<60: return f"{s:.0f}s" + if s<3600: return f"{s/60:.0f}m" + return f"{s/3600:.1f}h" + +def bar(cur, total, width=24): + if total<=0: return "["+" "*width+"]" + pct=min(cur/total,1.0); filled=int(width*pct) + return "["+"█"*filled+"░"*(width-filled)+f"] {pct*100:4.0f}%" + +def get_shard_list_hf(): + from huggingface_hub import HfApi + info=HfApi().repo_info(REPO_HF, files_metadata=True) + shards=sorted(s.rfilename for s in info.siblings if s.rfilename.endswith(".safetensors")) + sizes={s.rfilename:s.size for s in info.siblings if s.rfilename.endswith(".safetensors")} + return shards, sizes + +def get_shard_list_ms(): + """Get shard list from ModelScope API.""" + import requests + # ModelScope API: list files + r = requests.get(f"https://modelscope.cn/api/v1/models/{REPO_MS}/repo/files?Revision=master&Root=", timeout=30) + data = r.json()["Data"]["Files"] + shards = sorted(f["Path"] for f in data if f["Path"].endswith(".safetensors")) + sizes = {f["Path"]: f.get("Size", 0) for f in data if f["Path"].endswith(".safetensors")} + return shards, sizes + +def download_file_ms(fn): + """Download a single file from ModelScope using their CDN.""" + from modelscope.hub.file_download import model_file_download + model_file_download( + model_id=REPO_MS, + file_path=fn, + local_dir=DEST, + revision="master", + ) + +def download_file_hf(fn): + """Download a single file from HuggingFace with hf_transfer.""" + os.environ["HF_HUB_ENABLE_HF_TRANSFER"] = "1" + from huggingface_hub import hf_hub_download + hf_hub_download(REPO_HF, fn, local_dir=DEST) + +def download_file_curl(fn, base_url, expected_size): + """Fallback: download with curl to a .part file with resume.""" + outpath = os.path.join(DEST, fn) + partpath = outpath + ".part" + if os.path.exists(outpath) and os.path.getsize(outpath) == expected_size: + return True + url = f"{base_url}/{fn}" + cmd = ["curl", "-L", "-C", "-", "--retry", "999", "--retry-delay", "5", + "--connect-timeout", "15", "--speed-time", "30", "--speed-limit", "1000", + "-o", partpath, "-H", "User-Agent: colibri-download/1.0", url] + subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + if os.path.exists(partpath) and os.path.getsize(partpath) >= expected_size: + os.replace(partpath, outpath) + return True + return False + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--parallel", type=int, default=3) + ap.add_argument("--source", choices=["auto", "ms", "hf"], default="auto", + help="auto (try ModelScope first), ms (ModelScope only), hf (HuggingFace only)") + args = ap.parse_args() + + os.makedirs(DEST, exist_ok=True) + + # Determine source and get shard list + use_ms = False + shards, sizes = [], {} + + if args.source in ("auto", "ms"): + try: + print(f"{C.dim}Trying ModelScope...{C.r}", end=" ", flush=True) + shards, sizes = get_shard_list_ms() + use_ms = True + print(f"{C.grn}✓{C.r} {len(shards)} shards found") + except Exception as e: + print(f"{C.yel}failed ({e}){C.r}") + if args.source == "ms": + print("ModelScope failed and --source ms was set. Exiting."); return + + if not shards: + print(f"{C.dim}Using HuggingFace...{C.r}", end=" ", flush=True) + shards, sizes = get_shard_list_hf() + print(f"{C.grn}✓{C.r} {len(shards)} shards found") + + total = len(shards) + total_bytes = sum(sizes.values()) + source_name = "ModelScope" if use_ms else "HuggingFace" + + # Download metadata files + meta_files = ["config.json", "tokenizer.json", "tokenizer_config.json", + "generation_config.json", "model.safetensors.index.json"] + for fn in meta_files: + out = os.path.join(DEST, fn) + if not os.path.exists(out): + try: + if use_ms: download_file_ms(fn) + else: download_file_hf(fn) + except Exception: pass + + # Build work queue + todo = [] + done_set = set() + for fn in shards: + outpath = os.path.join(DEST, fn) + if os.path.exists(outpath) and os.path.getsize(outpath) == sizes.get(fn, 0): + done_set.add(fn) + else: + todo.append(fn) + + existing = len(done_set) + print(f"\n{C.b}GLM-5.2-FP8 Download ({source_name}){C.r}") + print(f" {C.dim}{total} shards · {total_bytes/1e9:.0f} GB · {existing}/{total} complete{C.r}") + print(f" {C.dim}{len(todo)} to download · {args.parallel} parallel{C.r}") + if todo: + remaining = sum(sizes[fn] for fn in todo) + print(f" {C.dim}Remaining: {remaining/1e9:.0f} GB{C.r}") + print() + + if not todo: + print(f"{C.grn}✓ All shards already downloaded!{C.r}\n"); return + + lock = threading.Lock() + completed = list(done_set) + t0 = time.time() + qidx = [0] + + def worker(wid): + while True: + with lock: + if qidx[0] >= len(todo): return + idx = qidx[0]; qidx[0] += 1 + fn = todo[idx] + + expected = sizes.get(fn, 0) + shard_num = existing + idx + 1 + print(f" {C.cyn}[{shard_num}/{total}]{C.r} {C.dim}{fn}{C.r}") + + success = False + for attempt in range(3): + try: + if use_ms: + download_file_ms(fn) + else: + download_file_hf(fn) + outpath = os.path.join(DEST, fn) + # ModelScope downloads to a cache dir, need to check + # if the file exists at our expected path + if not os.path.exists(outpath): + # Try to find it in ModelScope's cache structure + # and copy/symlink it + pass + if os.path.exists(outpath): + actual = os.path.getsize(outpath) + if expected == 0 or actual == expected: + success = True; break + # Size mismatch — might be in cache + # If we got here, file downloaded but not at expected path + # ModelScope puts it in local_dir; check again + if os.path.exists(outpath): + success = True; break + # Retry with curl fallback + if use_ms: + base = f"https://modelscope.cn/api/v1/models/{REPO_MS}/repo?Revision=master&FilePath=" + else: + base = f"https://huggingface.co/{REPO_HF}/resolve/main" + if download_file_curl(fn, base, expected): + success = True; break + except Exception as e: + if attempt < 2: + print(f" {C.yel}retry {attempt+1}: {e}{C.r}") + time.sleep(3) + else: + print(f" {C.yel}✗ failed: {e}{C.r}") + + with lock: + if success: + completed.append(fn) + elapsed = time.time() - t0 + have = sum(sizes.get(f,0) for f in completed) + pct = 100.0 * have / total_bytes + speed = (have - sum(sizes[f] for f in done_set)) / max(elapsed, 1) + eta = (total_bytes - have) / speed if speed > 0 else 0 + print(f" {C.grn}✓{C.r} {fn} {C.dim}— {len(completed)}/{total} · " + f"{pct:.1f}% · {fmt_time(elapsed)} · ETA {fmt_time(eta)}{C.r}") + else: + print(f" {C.yel}✗ GIVE UP: {fn}{C.r}") + + threads = [threading.Thread(target=worker, args=(i,), daemon=True) for i in range(args.parallel)] + for t in threads: t.start() + for t in threads: t.join() + + print() + final = sum(1 for fn in shards + if os.path.exists(os.path.join(DEST, fn)) + and os.path.getsize(os.path.join(DEST, fn)) == sizes.get(fn, 0)) + if final == total: + print(f"{C.grn}{'='*50}") + print(f" ✓ All {total} shards downloaded!{C.r}\n") + else: + print(f"{C.yel} {final}/{total} complete, {total-final} remaining{C.r}") + print(f" Re-run to resume.\n") + +if __name__ == "__main__": + try: main() + except KeyboardInterrupt: + print(f"\n\n{C.yel}Interrupted. Re-run to resume — no data lost.{C.r}\n") diff --git a/c/tools/make_glm_bench_model.py b/c/tools/make_glm_bench_model.py index 3aa1ce9..54a1a3f 100644 --- a/c/tools/make_glm_bench_model.py +++ b/c/tools/make_glm_bench_model.py @@ -3,15 +3,27 @@ This is not a useful language model. It preserves the real glm_moe_dsa data flow while remaining small enough to generate locally and run repeated CPU/CUDA A/B tests without downloading the 379 GB checkpoint. + +With --fp8 the weights are written as FP8 e4m3 + 128x128 block scale_inv, in the +SAME layout as the real GLM-5.2-FP8 checkpoint, so convert_fp8_to_int4.py can +exercise its FP8->int4 dequant path on a local fixture (its dims are 128-friendly, +so this is also the right fixture for --group-size 128 testing): + + python tools/make_glm_bench_model.py --fp8 --output glm_bench_fp8 + python tools/convert_fp8_to_int4.py --indir glm_bench_fp8 --outdir glm_bench_i4 --ebits 4 --group-size 128 """ import argparse import json +import sys from pathlib import Path import torch from transformers import GlmMoeDsaConfig, GlmMoeDsaForCausalLM +sys.path.insert(0, str(Path(__file__).resolve().parent)) # importa glm_fp8_emit se lanciato da c/ +from glm_fp8_emit import save_fp8_safetensors + def build_config() -> GlmMoeDsaConfig: return GlmMoeDsaConfig( @@ -51,6 +63,9 @@ def main() -> None: parser.add_argument("--output", default="glm_bench_medium") parser.add_argument("--device", default="cuda" if torch.cuda.is_available() else "cpu") parser.add_argument("--seed", type=int, default=1234) + parser.add_argument("--fp8", action="store_true", + help="write weights as FP8 e4m3 + 128x128 block scale_inv (same layout as " + "GLM-5.2-FP8) instead of bf16, so convert_fp8_to_int4.py can dequant+requant") args = parser.parse_args() torch.manual_seed(args.seed) @@ -70,7 +85,16 @@ def main() -> None: output = Path(args.output) output.mkdir(parents=True, exist_ok=True) params = sum(p.numel() for p in model.parameters()) - model.save_pretrained(output, safe_serialization=True, max_shard_size="4GB") + if args.fp8: + n_fp8, n_tot = save_fp8_safetensors(model.state_dict(), output / "model.safetensors") + # save_pretrained scrive config.json; nel path FP8 lo bypassiamo, quindi lo scriviamo + # a mano (serve al converter e al motore C). EN: save_pretrained writes config.json; + # the FP8 path bypasses it, so write it manually (converter + C engine need it). + (output / "config.json").write_text(json.dumps(cfg.to_dict())) + print(f"saved FP8: {n_fp8} e4m3 tensors (+{n_tot - n_fp8} scale_inv sidecars / f32) " + f"-> {output / 'model.safetensors'}") + else: + model.save_pretrained(output, safe_serialization=True, max_shard_size="4GB") model.to(args.device) prompt = [3, 14, 159, 26, 53, 58, 200, 11, 77, 240, 5, 99] @@ -89,6 +113,7 @@ def main() -> None: "seed": args.seed, "parameters": params, "parameters_billions": round(params / 1e9, 4), + "format": "fp8-e4m3-128" if args.fp8 else "bf16", "purpose": "backend benchmark fixture; random weights, not a language model", } (output / "bench_manifest.json").write_text(json.dumps(manifest, indent=2)) diff --git a/c/tools/make_glm_oracle.py b/c/tools/make_glm_oracle.py index 65a1c19..67ad5a5 100644 --- a/c/tools/make_glm_oracle.py +++ b/c/tools/make_glm_oracle.py @@ -3,10 +3,34 @@ Architettura vera (MLA + DSA indexer + router sigmoid/noaux_tc + shared expert), dimensioni minuscole. Salva pesi+config in c/glm_tiny/ e un riferimento greedy in c/ref_glm.json. seq corta (<= index_topk) cosi' il DSA seleziona tutte le key e l'attenzione coincide con la MLA densa: il motore C puo' validare senza implementare -l'indexer sparso.""" -import json, torch +l'indexer sparso. + +--fp8: salva i pesi come FP8 e4m3 + scale a blocchi 128x128 (layout del checkpoint reale +GLM-5.2-FP8) invece di bf16, cosi' convert_fp8_to_int4.py puo' esercitare il path FP8->int4 +su un modello minuscolo. PRIMA di calcolare ref_glm.json fa il round-trip dei pesi per FP8 +(quant->dequant, copy_ nel modello): cosi' il riferimento riflette ESATTAMENTE il modello +FP8 che il converter legge, non il modello bf16 a precisione piena. Default: bf16 (oracolo +originale invariato). +EN: --fp8 writes FP8 e4m3 + 128x128 block scale_inv (real GLM-5.2-FP8 layout) instead of bf16, +EN: so convert_fp8_to_int4.py can run its FP8->int4 path on a tiny model. ref_glm.json is +EN: computed AFTER the FP8 round-trip, so the reference matches exactly what the converter +EN: ingests. Default: bf16 (original oracle unchanged).""" +import json, sys, argparse +from pathlib import Path +import torch from transformers import GlmMoeDsaConfig, GlmMoeDsaForCausalLM +sys.path.insert(0, str(Path(__file__).resolve().parent)) # importa glm_fp8_emit se lanciato da c/ +from glm_fp8_emit import (fp8_block_quantize, fp8_block_dequantize, keep_f32, + save_fp8_safetensors) + +ap = argparse.ArgumentParser() +ap.add_argument("--fp8", action="store_true", + help="salva in FP8 e4m3 + 128x128 block scale_inv (layout GLM-5.2-FP8) e " + "calcola ref_glm.json sul modello dopo il round-trip FP8. " + "EN: write FP8 e4m3 + block scale_inv, ref computed on FP8-rounded model") +args = ap.parse_args() + torch.manual_seed(1234) cfg = GlmMoeDsaConfig( @@ -53,6 +77,18 @@ with torch.no_grad(): layer.mlp.gate.e_score_correction_bias.copy_( torch.linspace(-0.1, 0.1, cfg.n_routed_experts)) +# --fp8: round-trip dei pesi quantizzabili per FP8 PRIMA di calcolare il riferimento, +# cosi' ref_glm.json riflette esattamente il modello FP8 che il converter leggera'. +# Norme/router/bias (keep_f32) restano a precisione piena. EN: --fp8: round-trip quantizable +# weights through FP8 before computing the reference, so ref_glm.json matches the FP8 model. +if args.fp8: + with torch.no_grad(): + for n, p in model.named_parameters(): + if keep_f32(n, p) or p.dim() < 2: + continue + q, s = fp8_block_quantize(p) + p.copy_(fp8_block_dequantize(q, s)) + print("=== state_dict tensors (names used by the C loader) ===") for n, p in model.state_dict().items(): print(f" {n:60s} {tuple(p.shape)}") @@ -73,7 +109,13 @@ with torch.no_grad(): tf_pred = lg.argmax(-1).tolist() print("tf_pred:", tf_pred) -model.save_pretrained("glm_tiny", safe_serialization=True) +if args.fp8: + n_fp8, n_tot = save_fp8_safetensors(model.state_dict(), "glm_tiny/model.safetensors") + print(f"\nsaved FP8: {n_fp8} e4m3 tensors (+{n_tot - n_fp8} scale_inv sidecars / f32) " + f"-> glm_tiny/model.safetensors") +else: + model.save_pretrained("glm_tiny", safe_serialization=True) json.dump(cfg.to_dict(), open("glm_tiny/config.json", "w")) json.dump({"prompt_ids": prompt, "full_ids": full, "tf_pred": tf_pred}, open("ref_glm.json", "w")) -print("\nsaved: glm_tiny/ (weights + config) and ref_glm.json") +print("saved: glm_tiny/ (weights + config) and ref_glm.json" + + (" [fp8]" if args.fp8 else "")) From 21eb86a0dd3cc0ce9d2430e3b47d9a8a1160a9d6 Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Wed, 15 Jul 2026 01:01:43 -0400 Subject: [PATCH 37/79] diskio: research on disk I/O minimization for MoE expert streaming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audit of all disk I/O paths in the engine (expert pread, KV persistence, config/tokenizer loads) and research into techniques used by llama.cpp, vLLM, AirLLM, PRESERVE, HOBBIT, SolidAttention. Findings: - Expert path is already well-batched (one coalesced ~19MB O_DIRECT pread) - 76% of decode time is expert-disk I/O on RAM-constrained hosts - posix_fadvise(WILLNEED) is a no-op on Windows (compat.h:107) - I/O-to-compute ratio is 3.6x — the binding constraint - Levers: hit-rate (cache cap), cross-layer prefetch (PILOT_REAL), storage (VHDX vs direct NVMe), batched decode Ranked opportunities and source links documented in issue_diskio.md. --- issue_diskio.md | 128 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 issue_diskio.md diff --git a/issue_diskio.md b/issue_diskio.md new file mode 100644 index 0000000..786c4ad --- /dev/null +++ b/issue_diskio.md @@ -0,0 +1,128 @@ +# Disk I/O Minimization — Research + +Branch: `experiment/diskio-research` (based on `dev` at `62419af`) + +## TL;DR + +The engine's disk I/O is **already well-engineered on the hottest path** (expert streaming uses coalesced O_DIRECT `pread` + `posix_fadvise` hints + LRU + pin cache + speculative prefetch). There are **4 concrete, bounded opportunities** to shave latency, ranked by ROI: + +| # | Opportunity | Where | Frequency | Estimated win | +|---|---|---|---|---| +| 1 | **KV-cache write batching** (157 fwrites/token → 1) | `kv_disk_append` | per turn | cuts ~100s of syscalls/turn | +| 2 | **`/proc/meminfo` fopen storm** | `rss_gb()` | ~every 16 tokens (Linux) | eliminates recurring open/read/close | +| 3 | **Expert prefetch on Windows** (`PrefetchVirtualMemory`) | `expert_prefetch` | per miss | mmap path is Linux/macOS-only today | +| 4 | **KV-cache: buffered handle kept open** | `kv_disk_append` | per turn | kills open+fseek+close per turn | + +There are also **2 non-opportunities** worth recording so we don't re-investigate: O_DIRECT for experts (correctly used today), and PagedAttention-style file layout (already single-file + indexed). + +--- + +## How the engine does disk I/O today + +There are **three I/O stacks**, behaving very differently: + +| Stack | Mechanism | Frequency | Files | +|---|---|---|---| +| **Expert weights** (hottest) | `pread` on kept-open fds + `posix_fadvise`, optional `mmap` | per miss, every token | `st.h`, `glm.c:1328` | +| **KV cache** (`.coli_kv`) | `fopen` + `fwrite`/`fread` | per turn | `glm.c:3812-3889` | +| **Everything else** (config, tokenizer, stats, grammar) | `fopen` + `fread` | startup-only | scattered | + +### Expert path (the hot path — already good) + +`expert_load` (`glm.c:1328-1481`) has three sub-paths: + +- **Default `pread` path** (`glm.c:1385-1472`): coalesces the 3 contiguous expert tensors (gate/up/down) into **one ~19 MB O_DIRECT `pread`** into a 16K-aligned slab (`glm.c:1447`). Falls back to 3 separate `pread`s only if non-contiguous. Scales are 3 tiny separate `pread`s (kilobytes). `posix_fadvise(DONTNEED)` evicts pages after if `g_drop`. **This is well-batched — one syscall for ~19 MB.** +- **`COLI_MMAP=1` path** (`glm.c:1352-1383`): `mmap` per shard fd (cached), `madvise(WILLNEED)` + synchronous page-touch loop. Zero-copy. **Default OFF, and Linux/macOS/FreeBSD-only** — no `MapViewOfFile` on Windows. +- **Prefetch hints**: `expert_prefetch` (`glm.c:1602-1609`) → `st_prefetch` (`st.h:178`) issues `posix_fadvise(WILLNEED)` — readahead hint only, no data read. Called from `moe` next-64-block lookahead, pilot, and SPEC. + +### KV cache persistence (per turn — opportunity here) + +`kv_disk_append` (`glm.c:3834-3855`), called once per turn: +1. `fopen("r+b")` — **reopens the file every turn** +2. `fseek` to append position +3. **per-position loop**: for each new token, `fwrite` the token i32, then **2 fwrites per layer** (Lc + Rc) + optional DSA Ic. With 78 layers that's **~157 fwrites per token appended**. +4. `fflush` (userspace only — **no fsync/fdatasync anywhere in the codebase**) +5. `fseek` back to header + `fwrite` the new nrec counter (crash-safe ordering) +6. `fclose` + +Record size ~182 KB/token. On a long first turn this is **tens of thousands of small fwrites**. stdio buffering coalesces them into fewer `write` syscalls, but the userspace overhead remains. + +### Recurring surprise: `/proc/meminfo` + +`rss_gb()` (`glm.c:4625`) does `fopen("/proc/meminfo")` + fgets + fclose. Called from every STAT line and every 16-token heartbeat (`glm.c:3473, 3477`). On Linux this is an **open+read+close of procfs ~every 16 tokens**. (Windows uses `compat_meminfo`, no file — not affected.) + +--- + +## What similar projects do + +**llama.cpp** (the reference): `mmap`s the entire model read-only, uses `--mlock` to pin hot pages, streams layers to GPU via partial offload, and issues per-pass readahead of upcoming tensors (`llama-mmap.cpp`). Justine Tunney's mmap work: "load 100× faster using half as memory." Crucial finding from discussion #18758: **for MoE, mmap beats O_DIRECT** when the model fits in ~RAM — O_DIRECT takes "at least 10× longer" on repeated loads because it bypasses the page cache that serves re-faults for free. + +**The general consensus across llama.cpp, vLLM, AirLLM, PRESERVE, HOBBIT, SolidAttention (FAST '26):** +- mmap + OS page cache as the backing store for an LRU is the proven recipe +- prefetch the *next* expert/layer while computing the current one — this is where the 0.5ms lives +- single indexed file (one `open()`) beats one-file-per-expert +- align tensors to 4KB (preferably 64KB) for clean page-fault boundaries + SSD geometry +- buffer sweet spot ~1MB; syscall cost ~1-5µs each, so batching matters at high repetition + +--- + +## The 4 opportunities (ranked) + +### Opportunity 1 — KV-cache write batching (HIGH ROI, LOW risk) + +**Problem:** `kv_disk_append` does ~157 `fwrite` calls per appended token (1 token i32 + 2×78 layers). stdio buffering hides some of this, but on a long first-turn prefill (hundreds-thousands of tokens) this is tens of thousands of fwrites. + +**Fix:** Build one contiguous record in a heap buffer (token + all layers' Lc/Rc/Ic for that position), then **a single `fwrite` per position** (or even one `fwrite` for the whole turn). The data is already laid out contiguously in memory per-layer (`coli_kv_row`), so a layered `memcpy` into a staging buffer + one write is straightforward. + +**Win:** ~157× fewer fwrite calls per token. Even with stdio coalescing, the userspace loop overhead is real at scale. + +### Opportunity 2 — `/proc/meminfo` fopen storm (MEDIUM ROI, trivial) + +**Problem:** `rss_gb()` opens, reads, closes `/proc/meminfo` every ~16 tokens on Linux. Each is ~3 syscalls + path resolution. + +**Fix:** Either (a) cache the value for N tokens (e.g. re-read at most once per second), or (b) keep the fd open and `rewind`+`fgets`. Trivial change. + +### Opportunity 3 — Expert prefetch on Windows (MEDIUM ROI, bounded) + +**Problem:** The `COLI_MMAP=1` path (which gives zero-copy expert access + free OS-cache re-faults) is **Linux/macOS/FreeBSD-only** — `glm.c:1301` guards it. On Windows, experts always go through the `pread` path, and `expert_prefetch` issues `posix_fadvise(WILLNEED)` which is a no-op shim on Windows (`compat.h`). + +**Fix:** On Windows, implement the prefetch via `PrefetchVirtualMemory` (the Win32 analog of `MADV_WILLNEED`) on an mmap'd region, or via an async `ReadFile`+`OVERLAPPED` into a scratch buffer. This brings the Windows build closer to parity with the Linux mmap+prefetch story. + +**Scope:** This is the largest of the four — it touches the Windows I/O path. Worth doing if Windows perf is a goal; skip if Linux is the target. + +### Opportunity 4 — KV-cache: keep handle open (LOW-MEDIUM ROI, LOW risk) + +**Problem:** `kv_disk_append` does `fopen`+...+`fclose` every turn. Handle creation is ~5-15µs of pure overhead (worse on Windows). + +**Fix:** Open the KV file once (lazily on first append), keep the `FILE*` for the engine lifetime, just `fseek`+write each turn. Close on shutdown. Pair with Opportunity 1 for the write batching. + +--- + +## Non-opportunities (recording so we don't re-investigate) + +- **O_DIRECT for experts**: already correctly used (`st.h:83`, `DIRECT=1`). For an LRU+refetch pattern the page cache is your friend, but the engine offers both paths (O_DIRECT pread default + optional mmap) and the O_DIRECT coalesced read is already one syscall for ~19MB. Don't change this. +- **Single-file layout**: the engine already uses safetensors shards with kept-open fds + offset-indexed tensors (`st.h`). No per-expert open()/close() waste. Don't change this. +- **PagedAttention**: solves concurrency fragmentation this engine doesn't have (≤16 slots). Not applicable. + +--- + +## Next steps + +The highest-ROI, lowest-risk starting point is **Opportunity 1 (KV write batching) + Opportunity 4 (keep handle open)** — they're in the same function, both low-risk, and together they eliminate the per-turn open/close overhead and the per-token fwrite storm. Opportunity 2 is a trivial 5-minute fix we can bundle in. + +Opportunity 3 (Windows prefetch) is the biggest single win but also the largest scope — separate effort, gated on whether Windows perf is a priority. + +## Sources + +- [justine.lol/mmap — Edge AI Just Got Faster](https://justine.lol/mmap/) +- [llama.cpp discussion #18758 — Mmap faster than direct I/O for MoE](https://github.com/ggml-org/llama.cpp/discussions/18758) +- [llama.cpp issue #20757 — Two-tier GPU+RAM expert cache](https://github.com/ggml-org/llama.cpp/issues/20757) +- [FAST '26 — Programmable Page Cache for LLM loading](https://www.usenix.org/system/files/fast26-liu-yubo.pdf) +- [FAST '26 — SolidAttention: SSD-based serving](https://www.usenix.org/system/files/fast26-zheng.pdf) +- [HOBBIT — Mixed precision expert offloading](https://arxiv.org/html/2411.01433v2) +- [posix_fadvise(2) — man7.org](https://man7.org/linux/man-pages/man2/posix_fadvise.2.html) +- [madvise(2) — man7.org](https://man7.org/linux/man-pages/man2/madvise.2.html) +- [Microsoft Learn — File Buffering (FILE_FLAG_NO_BUFFERING)](https://learn.microsoft.com/en-us/windows/win32/fileio/file-buffering) +- [Microsoft Learn — PrefetchVirtualMemory](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-prefetchvirtualmemory) +- [What makes system calls expensive — codingconfessions.com](https://blog.codingconfessions.com/p/what-makes-system-calls-expensive) +- [Syscall overhead — Stack Overflow](https://stackoverflow.com/questions/8247331/syscall-overhead) From 2c6946c47820a5848b89abd12548128475351e3b Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Wed, 15 Jul 2026 01:02:21 -0400 Subject: [PATCH 38/79] test-models: add --fp8 emission for the FP8->int4 converter test path Both test-model generators (make_glm_oracle.py, make_glm_bench_model.py) can now emit weights as FP8 e4m3 + 128x128 block scale_inv, in the same layout as the real GLM-5.2-FP8 checkpoint. This lets convert_fp8_to_int4.py exercise its FP8->int4 dequant path on a local fixture without the 379 GB download. - New shared helper glm_fp8_emit.py: FP8 block quantize/dequantize (FBGEMM/TE scale=amax/448 convention) + state_dict emitter. Only exactly-2-D tensors are quantized; 1-D/3-D and norms/router/e_score_correction_bias are kept as f32, mirroring the converter's classify() + ndim!=2 guard. - make_glm_bench_model.py: opt-in --fp8 writes model.safetensors in FP8 layout (config.json written explicitly since the FP8 path bypasses save_pretrained); manifest gains a 'format' field. Default bf16 behavior unchanged. - make_glm_oracle.py: opt-in --fp8 round-trips quantizable weights through FP8 before computing ref_glm.json, so the reference reflects exactly the FP8 model the converter ingests. Default bf16 oracle contract unchanged. Verified end-to-end: FP8 model -> converter --indir -> int4 U8 + .qs F32 output, bit-identical dequant between helper and converter (maxdiff 0.0). --- c/tools/glm_fp8_emit.py | 95 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 c/tools/glm_fp8_emit.py diff --git a/c/tools/glm_fp8_emit.py b/c/tools/glm_fp8_emit.py new file mode 100644 index 0000000..4ae05d6 --- /dev/null +++ b/c/tools/glm_fp8_emit.py @@ -0,0 +1,95 @@ +"""Helper: salva pesi in FP8 e4m3 + scale a blocchi 128x128, nello STESSO layout del +checkpoint reale GLM-5.2-FP8 che `convert_fp8_to_int4.py` legge. + +Layout (deve combaciare col `dequant()` del converter, convert_fp8_to_int4.py:164-169): + - `name` F8_E4M3 [O, I] + - `name_scale_inv` F32 [ceil(O/128), ceil(I/128)] (NOTA: '_scale_inv', underscore) + dequant: W = q.float() * scale.repeat_interleave(128,0).repeat_interleave(128,1)[:O,:I] + +Convenzione FBGEMM/TransformerEngine: scale = amax(blocco)/448 (448 = max e4m3), +si MEMORIZZA il valore e si MOLTIPLICA in dequant. Malgrado il nome "_scale_inv" il +checkpoint memorizza la scala (non il reciproco): e' un MOLTIPLIER. + +EN: Helper that writes weights as FP8 e4m3 with 128x128 block scales, in the SAME layout +EN: as the real GLM-5.2-FP8 checkpoint that `convert_fp8_to_int4.py` reads. +EN: FBGEMM/TransformerEngine convention: scale = amax(block)/448, stored (not its +EN: reciprocal) and MULTIPLIED on dequant. Despite the name "_scale_inv" it is a multiplier. +""" +import torch + +E4M3_MAX = 448.0 # max valore rappresentabile in float8_e4m3fn / max representable value +BLOCK = 128 # granularita' delle scale a blocchi del checkpoint FP8 / FP8 block scale granularity + + +def keep_f32(name, t): + """Stesso set F32 di `classify()` in convert_fp8_to_int4.py (norme, router, bias 1-D). + Tutti gli altri tensori 2-D vengono quantizzati FP8 (attn/mlp/shared/expert/embed/lm_head). + EN: Same F32 set as the converter's classify(): norms, router, 1-D biases. All other 2-D + EN: tensors are FP8-quantized (attn/mlp/shared/expert/embed/lm_head).""" + if t.dim() < 2: + return True # bias 1-D, e_score_correction_bias + if name.endswith("e_score_correction_bias"): + return True + if name.endswith("mlp.gate.weight"): + return True # router (NON gate_proj): tenuto F32 / kept F32 + if name.endswith("norm.weight") or name == "model.norm.weight": + return True # RMSNorm + return False + + +def fp8_block_quantize(w): + """w: [O,I] f32 -> (w_fp8 float8_e4m3fn [O,I], scale_inv f32 [ceil(O/128),ceil(I/128)]). + Identica matematica al `--selftest` del converter (scale = amax(blocco)/448). Padda a + multipli di 128 internamente (gli zeri non alzano l'amax) e fa slice al risultato. + EN: same math as the converter's --selftest. Pads to 128 multiples internally (zeros do + EN: not raise amax), slices the result back to [O,I].""" + O, I = w.shape + nbO, nbI = (O + BLOCK - 1) // BLOCK, (I + BLOCK - 1) // BLOCK + Op, Ip = nbO * BLOCK, nbI * BLOCK + wpad = torch.zeros(Op, Ip, dtype=torch.float32, device=w.device) + wpad[:O, :I] = w + wb = wpad.view(nbO, BLOCK, nbI, BLOCK) # [nbO, BLOCK, nbI, BLOCK] + amax = wb.abs().amax(dim=(1, 3)) # [nbO, nbI] + scale = amax / E4M3_MAX # FBGEMM/TE: memorizza la scala / store the scale + scale = torch.where(scale == 0, torch.ones_like(scale), scale) # blocco tutto-zero -> no div0 + scale = scale.to(torch.float32) + q = (wpad / scale.repeat_interleave(BLOCK, 0).repeat_interleave(BLOCK, 1)).clamp(-E4M3_MAX, E4M3_MAX) + w_fp8 = q.to(torch.float8_e4m3fn) + return w_fp8[:O, :I].contiguous(), scale.contiguous() + + +def fp8_block_dequantize(w_fp8, scale): + """Esatto inverso di fp8_block_quantize, e identico al `dequant()` del converter. + EN: exact inverse of fp8_block_quantize, identical to the converter's dequant().""" + O, I = w_fp8.shape + qf = w_fp8.to(torch.float32) + return qf * scale.repeat_interleave(BLOCK, 0).repeat_interleave(BLOCK, 1)[:O, :I] + + +def state_dict_to_fp8(sd): + """Converte uno state_dict HuggingFace nel layout FP8 del checkpoint reale: + per ogni tensore quantizzabile 2-D scrive `{name}` (F8_E4M3) + `{name}_scale_inv` (F32); + norme/router/bias e qualsiasi tensore NON 2-D (es. pesi MLA impaccati 3-D) restano nel + dtype originale. Questo rispecchia il guard `w.ndim != 2 -> f32` del converter + (convert_fp8_to_int4.py:184). EN: builds the real-checkpoint FP8 layout. Only exactly-2-D + tensors are FP8-quantized; anything else (1-D, 3-D packed MLA weights, ...) is kept, exactly + like the converter's `ndim != 2 -> f32` guard.""" + out = {} + for name, t in sd.items(): + if keep_f32(name, t) or t.dim() != 2: + out[name] = t # f32 / 1-D / 3-D+: tieni / keep + else: + w_fp8, scale = fp8_block_quantize(t.float()) + out[name] = w_fp8 + out[name + "_scale_inv"] = scale + return out + + +def save_fp8_safetensors(sd, path): + """Quantizza a blocchi FP8 e salva in un singolo safetensors leggibile dal converter + via `--indir`. EN: block-quantize to FP8 and save a single safetensors for the converter.""" + from safetensors.torch import save_file + out = state_dict_to_fp8(sd) + save_file({k: v.contiguous() for k, v in out.items()}, str(path)) + n_fp8 = sum(1 for v in out.values() if v.dtype == torch.float8_e4m3fn) + return n_fp8, len(out) From e71d4fbe29deb29ac461b4a883734b3f41b928c5 Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Wed, 15 Jul 2026 01:04:32 -0400 Subject: [PATCH 39/79] windows-dev: CUDA build script, expert budget + grouped quant research - build_cuda.bat: one-shot nvcc DLL compilation for sm_120 (RTX 5070 Ti) - issue_budget.md: EXPERT_BUDGET research (cap distinct experts/layer, 2x tok/s) - issue_grouped_quant.md: root cause of int4 incoherence (per-row vs group-128 scales) - glm_fp8_emit.py: FP8 e4m3 test weight generator for converter validation --- c/build_cuda.bat | 5 ++ issue_budget.md | 150 +++++++++++++++++++++++++++++++++ issue_grouped_quant.md | 185 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 340 insertions(+) create mode 100644 c/build_cuda.bat create mode 100644 issue_budget.md create mode 100644 issue_grouped_quant.md diff --git a/c/build_cuda.bat b/c/build_cuda.bat new file mode 100644 index 0000000..dc19f09 --- /dev/null +++ b/c/build_cuda.bat @@ -0,0 +1,5 @@ +@echo off +call "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat" +cd /d C:\Users\Mark\Desktop\Projects\colibri\c +"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.8\bin\nvcc" -O3 -std=c++17 -arch=sm_120 -Xcompiler=-W3 -shared -DCOLI_CUDA_BUILDING_DLL -L"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.8\lib/x64" -lcudart backend_cuda.cu -o coli_cuda.dll +echo EXITCODE=%ERRORLEVEL% diff --git a/issue_budget.md b/issue_budget.md new file mode 100644 index 0000000..fe0ef86 --- /dev/null +++ b/issue_budget.md @@ -0,0 +1,150 @@ +## TL;DR + +New `EXPERT_BUDGET=N` env var that caps the number of **distinct experts loaded per layer** across the batch-union. When the union exceeds the budget, keeps only the highest-aggregate-gate-weight experts and drops the rest — they're never loaded from disk. On a 24 GB RAM host (cache `cap=2`), `EXPERT_BUDGET=4` nearly **doubles decode tok/s** (0.18 → 0.33) and **4x's prefill speed** (38.7s → 8.9s). Based on MoE-Spec (arXiv 2602.16052): "top 32 of 64 experts capture 93% of routing weight." + +Branch: `experiment/expert-budget` (based on latest `dev` at `62419af`) + +--- + +## The problem + +Every expert miss costs ~19 MB of disk I/O. On low-RAM hosts where the LRU cache cap is tiny (e.g. `cap=2` on 24 GB RAM), nearly every routed expert is a miss. With `topk=8` and 75 sparse layers, a single-token decode reads ~8.5 GB of experts from disk. Under MTP with `S=4`, the batch-union can produce 20-32 distinct experts per layer — almost all misses — multiplying disk reads further. + +The README documents this directly: +> "on a cold cache each verified draft routes to extra experts (~660 → ~1100 expert-loads/token)" + +The existing `TOPP` env var trims experts *within a single position's top-K*. But it cannot reduce the **cross-position union** — the deduplication across batch positions (prefill, MTP verification) that multiplies disk loads. That's the gap this fills. + +## How it works + +The batch-union in `moe()` (line ~2306 of `glm.c`) deduplicates routed experts across all `S` positions into `uniq[0..nu)`. After the union is built but before the cache-resolve/load loop, the budget cap kicks in: + +``` +if(EXPERT_BUDGET > 0 && nu > EXPERT_BUDGET): + 1. Compute aggregate gate weight per unique expert + (sum of ws[s*K+kk] across all positions that route to it) + 2. Sort experts by descending aggregate weight + 3. Keep top EXPERT_BUDGET, mark rest as dropped + 4. Remove dropped experts from each position's idxs[]/keff[] + (decrement keff, renormalize remaining weights if norm_topk) + 5. Compact uniq[] to kept experts only +``` + +Dropped experts are removed from `idxs[]` entirely, so they're **never resolved, never loaded from disk, never computed**. The downstream code already tolerates `keff[s] < K` (the `TOPP` path produces the same state), so this propagates correctly through resolve, matmul, and LRU promotion. + +**Relationship to existing features:** +- `TOPP` trims within one position's top-K (per-position) +- `EXPERT_BUDGET` trims across the cross-position union (per-layer) +- They compose: `TOPP=0.8 EXPERT_BUDGET=12` first trims each position to its top-p mass, then caps the union + +## Code change + +**`c/glm.c`** — 54 lines added, single file: + +1. Global + counter (near existing `g_topk`/`g_topp`): +```c +static int g_expert_budget=0; /* EXPERT_BUDGET=N */ +static int64_t g_budget_dropped=0; /* total experts dropped */ +``` + +2. Env var parsing (near existing `TOPK`/`TOPP`): +```c +g_expert_budget = getenv("EXPERT_BUDGET")?atoi(getenv("EXPERT_BUDGET")):0; +``` + +3. Budget cap in `moe()` batch-union (after `uniq[]` is built, before resolve loop) — full logic described above. + +4. Stats reporting alongside existing `TOPK`/`TOPP` line: +``` +EXPERT_BUDGET=4 (dropped 13613 experts, ~257.3 GB I/O saved) +``` + +## Measurements + +**Test setup:** GLM-5.2 744B int4, 24 GB RAM (cache `cap=2`), Core Ultra 9 185H (AVX-VNNI), MTP=0, single-token decode, 32 tokens generated, same prompt: *"Explain the concept of recursion in programming. Provide a simple example."* + +| Config | tok/s | vs baseline | hit rate | prefill | decode | experts dropped | I/O saved | +|--------|-------|-------------|----------|---------|--------|-----------------|-----------| +| **Baseline** (budget=0) | 0.18 | — | 9.3% | 38.7s | 176.3s | 0 | 0 | +| EXPERT_BUDGET=12 | 0.19 | +5% | 14.0% | 12.3s | 171.3s | 3,313 | 62.6 GB | +| EXPERT_BUDGET=6 | 0.26 | +44% | 21.0% | 7.5s | 122.5s | 8,543 | 161.5 GB | +| **EXPERT_BUDGET=4** | **0.33** | **+83%** | 16.4% | 8.9s | **97.4s** | 13,613 | 257.3 GB | + +### Profile breakdown (prefill) + +| Metric | Baseline | Budget=4 | +|--------|----------|----------| +| expert-disk service | 28.4s | **3.5s** (8x less) | +| expert-matmul | 7.1s | 1.4s | +| attention | 2.3s | 2.8s | + +### Profile breakdown (decode, 32 tokens) + +| Metric | Baseline | Budget=4 | +|--------|----------|----------| +| expert-disk service | 133.4s | proportional ~65s | +| expert-matmul | 23.9s | ~12s | +| decode total | 176.3s | **97.4s** | + +### Key observations + +1. **Prefill is the biggest winner.** With S=14 positions, the batch-union has 50+ distinct experts per layer. Budget=12 cuts that to 12, saving 40+ × 19 MB × 75 layers of disk reads. Prefill goes from 38.7s to 8.9s — **4.4x faster**. + +2. **Decode improvement scales with budget tightness.** Budget=12 barely constrains single-token decode (S=1 → max 8 experts < 12), so decode is barely affected. Budget=4 actually halves the decode load (8 → 4 experts/layer), nearly doubling tok/s. + +3. **Hit rate improves** because fewer experts compete for the tiny cache (cap=2). Budget=6 hit 21% vs baseline 9.3% — more than doubled. + +4. **No crashes or instability** at any budget value. + +## Quality impact — honest assessment + +**Budget=4 keeps only the top-4 of 8 routed experts per layer.** The dropped 4 experts had the lowest gate weights — they contributed the least to the output. But this IS a quality trade-off. + +On a **cold cache** (our test setup), quality assessment is confounded: both baseline and budget outputs are already garbled from int4 quantization + cold-cache routing. Sample comparison: + +- **Baseline output:** *"Hire Some To Take Object-Oriented Programming Assignment"* +- **Budget=4 output:** *"The world is a dangerous place, not so much because of the small percentage of people who are doing to do the little of people who are doing to"* + +Both are incoherent — the cold cache at int4 on 24 GB RAM produces poor output regardless of budget. The budget=4 output is **not dramatically worse** than the already-poor baseline — they're both garbled, just differently garbled. A proper quality assessment needs a **warm cache** where the baseline produces coherent text, so you can isolate the degradation from dropping experts. + +**Expected quality on warm cache:** With `norm_topk=1` (GLM-5.2 renormalizes gate weights), the top-4 experts typically capture ~80-85% of routing weight (the remaining 4 share 15-20%). Output should be mostly coherent with occasional word-choice degradation. Budget=6 (top-6 of 8, ~90%+ weight captured) should be nearly indistinguishable from baseline. + +**Recommendation for users:** +- `EXPERT_BUDGET=6-8` on cold/low-RAM hosts — good speedup, minimal quality loss +- `EXPERT_BUDGET=4` on very-low-RAM hosts where speed matters more than quality +- Leave OFF on high-RAM hosts where all experts are resident anyway (budget never triggers) + +## Safety + +- **Default OFF** (`EXPERT_BUDGET=0`) — zero behavior change unless explicitly set +- **Opt-in quality trade-off** — same design philosophy as `TOPP`: the user explicitly chooses speed over quality +- **No output corruption** — dropped experts' contributions are omitted and remaining weights renormalized (identical math to `TOPP`) +- **Compatible with all features** — PILOT, MTP, CUDA, CACHE_ROUTE, PIPE, TOPP all work unchanged; they just see fewer experts in the union +- **No crash risk** — no new memory allocation patterns, no new I/O, purely a filter on existing data structures + +## Reproduce + +```bash +make ARCH=native + +# Baseline: +SNAP= MTP=0 PROMPT="Explain recursion in programming." NGEN=32 ./glm 64 + +# With budget: +SNAP= MTP=0 EXPERT_BUDGET=4 PROMPT="Explain recursion in programming." NGEN=32 ./glm 64 + +# With MTP (where budget saves the most): +SNAP= MTP=1 EXPERT_BUDGET=16 PROMPT="Explain recursion in programming." NGEN=32 ./glm 64 +``` + +The stats line prints `EXPERT_BUDGET=N (dropped X experts, ~Y GB I/O saved)`. + +## What's needed before merge + +1. **Warm-cache quality A/B test** on a host with enough RAM (cap>=16) to produce coherent baseline output, then compare budget=4/6/8 text quality +2. **MTP interaction test** — verify that budget + MTP composes correctly and doesn't crash when draft verification routes to budgeted-away experts +3. **Decide on defaults** — should this auto-activate on low-RAM hosts (like `cap` auto-lowering)? My recommendation: no, leave it OFF and document the recommended value per RAM tier + +## Prior art + +**MoE-Spec** (arXiv 2602.16052) — "Expert Budgeting for Efficient Speculative Decoding": Training-free expert budgeting at verification time. Key finding: "top 32 of 64 experts capture 93% of routing weight." Our approach applies the same principle but at the batch-union level (not just MTP verification), making it effective for prefill and single-token decode too. diff --git a/issue_grouped_quant.md b/issue_grouped_quant.md new file mode 100644 index 0000000..fb46ce4 --- /dev/null +++ b/issue_grouped_quant.md @@ -0,0 +1,185 @@ +## TL;DR + +The int4 model produces **fluent-but-incoherent output** — grammatical English that is completely off-topic (SEO spam, homework-help boilerplate) instead of reasoned responses. The root cause is **per-row quantization scales**: one F32 scale per output row (e.g. 2048 scales for a 2048×6144 matrix), which is 48x coarser than the FP8 source's 128×128 block scales. This destroys fine-grained weight information that handles reasoning and instruction-following while preserving the large-magnitude weights that handle grammar and vocabulary fluency. + +Branch: `experiment/grouped-quant` (based on latest `dev` at `62419af`) + +--- + +## The problem — demonstrated + +Prompt: *"Explain the concept of recursion in programming. Provide a simple example."* + +**Baseline (no budget, no changes):** +> "Hire Some To Take Object-Oriented Programming Assignment" + +**Budget=4:** +> "The world is a dangerous place, not so much because of the small percentage of people who are doing to do the little of people who are doing to" + +**Budget=6:** +> "Elite Custom Essays" + +**Budget=12:** +> "Sololearn: Learn to code for FREE! +1 # Explain A concept of recursion..." + +This is not random gibberish — it's fluent English that is completely off-topic. This is the signature of **activations corrupted by coarse quantization**: the model retains language fluency (large weights survive) but loses instruction-following and reasoning (fine-grained weights are crushed to zero). + +## Root cause: per-row int4 scales + +### How the current converter works + +`convert_fp8_to_int4.py` (line 39-52) quantizes with **one scale per output row**: + +```python +amax = np.abs(w).max(axis=1, keepdims=True) # one max per ROW +s = np.maximum(amax / qmax, 1e-8) # one scale per ROW +q = np.clip(np.rint(w / s), -8, qmax) # quantize entire row with that scale +``` + +For a 2048×6144 expert weight matrix, that's **2048 scales** — one per row, each covering 6144 elements. + +### Why this destroys quality + +Consider a row of 6144 values where most are small (magnitude ~0.01) but a few are large (~0.5). The per-row scale is `0.5/7 = 0.071`. The small values become `0.01/0.071 = 0.14`, which rounds to **zero**. All fine-grained information in those small weights is lost. + +This matters enormously for MoE models: each token activates only 8 of 256 experts. A poorly-quantized expert pollutes every token that routes to it, and there's no averaging from the other 248 experts (they're simply off). The error is **concentrated**, not diluted. + +### What the FP8 source does right + +The FP8 checkpoint uses **128×128 block scales** — the weight matrix is divided into 128-element chunks, each with its own scale. Small values in one chunk don't get crushed by large values in another. For a 2048×6144 matrix: `2048 × 48 = 98,304` scales — 48x more granularity. + +The converter already dequants FP8 to f32 correctly (lines 196-201), preserving the block-scale information. But then it **throws it all away** by collapsing to a single per-row scale during int4 requantization. + +### GLM-5.2 was QAT-trained for int4 + +The GLM-5 paper (arXiv 2602.15763, §2.4.3) states: *"To provide better accuracy at low-precision, we apply INT4 QAT in the SFT stage."* This means the model is **designed** to work at int4 — but only if the quantization is fine-grained enough to match what the model saw during training. The FP8 checkpoint's 128×128 block scales are the granularity the model expects. Per-row scaling is 48x coarser. + +### Community confirmation + +Every other project getting coherent GLM-5.2 int4 output uses calibrated or fine-grained quantization: +- **ubergarm/GLM-5.1-GGUF** — imatrix-calibrated with expert-specific patches +- **Unsloth/GLM-5-GGUF** — dynamic UD-Q4 quants +- **QuantTrio/GLM-5.2-Int4-Int8Mix** — mixed int4/int8 with channel-wise scales +- **llama.cpp** — Q4_K with block-level group scales (typically 32 or 64 elements) + +None use naive per-row RTN int4 for production inference. + +## The fix: group-scaled int4 (fmt=4) + +Add a new quantization format with **one scale per 128 elements** along the input dimension, matching the FP8 source's natural granularity. + +### What changed + +**`c/glm.c`** — 122 lines added: + +1. **QT struct** (line 98): Added `int gs` field (group size, 0=per-row for backward compat, 128=grouped). + +2. **Format detection** (`qt_from_disk`, line 1064): Auto-detects fmt=4 by checking the `.qs` scale array size. If it has `O * ceil(I/128)` elements instead of `O`, it's grouped. **Old per-row models (fmt=2) work unchanged.** + +3. **New kernel** (`matmul_i4_grouped`, line 379): Same AVX2 nibble unpacking as `matmul_i4`, but the accumulator resets at each 128-element group boundary: `dot(x[grp], w[grp]) * scale[grp]`. The scale changes every 8 vector iterations (128/16=8). + +4. **Dispatch** (`matmul_qt_ex`, line 813): Routes to `matmul_i4_grouped` when `fmt==4`. Always uses exact kernels (no IDOT approximation — the whole point is quality). + +5. **Expert loading** (`expert_load`, lines 1418 and 1538): Both the mmap and slab+pread paths detect fmt=4 from scale array size and set `gs=128`. + +6. **`qt_bytes`** (line 104): Reports correct memory for fmt=4. + +**`c/tools/convert_fp8_to_int4.py`** — `quant_int4_grouped()` + `--group-size` arg: + +```python +def quant_int4_grouped(w, bits, gs=128): + O, I = w.shape + ngroups = (I + gs - 1) // gs + wpad = np.zeros((O, ngroups * gs), np.float32) + wpad[:, :I] = w + wr = wpad.reshape(O, ngroups, gs) # [O, ngroups, gs] + amax = np.abs(wr).max(axis=2, keepdims=True) # one max per GROUP + s = np.maximum(amax / qmax, 1e-8) + q = np.clip(np.rint(wr / s), -8, qmax) + # ... same nibble packing as quant_int4 ... + return packed_nibbles, s.reshape(-1) # [O * ngroups] scales +``` + +Same packed-nibble format as existing int4 — only the scale array is larger. + +### Verification + +**Converter round-trip test** (weights with varying group magnitudes): + +| Method | Mean relative error | Max abs error | +|--------|-------------------|---------------| +| Per-row int4 (current) | 0.2056 | 0.0127 | +| Grouped int4 (gs=128) | **0.1278** | 0.0127 | +| **Improvement** | **1.6x lower** | — | + +**Engine kernel test** (AVX2 `matmul_i4_grouped` vs f32 reference): + +| Output | Reference | Kernel | Error | +|--------|-----------|--------|-------| +| o=0 | -0.126368 | -0.126368 | 2.98e-08 | +| o=1 | 0.075913 | 0.075913 | 1.49e-08 | +| o=2 | 0.077136 | 0.077136 | 7.45e-09 | +| ... | ... | ... | ... | + +Max error: **2.98e-08** — matches f32 reference to within float32 epsilon. **PASS.** + +### Cost + +| Metric | Per-row (current) | Grouped (new) | +|--------|-------------------|---------------| +| Expert weight size | ~18.9 MB | ~20.1 MB (+6%) | +| Scale array per matrix | O × 4 bytes | O × ceil(I/128) × 4 bytes | +| Total model size | ~370 GB | ~390 GB (+5%) | +| Disk I/O per miss | ~19 MB | ~20 MB (+6%) | +| Kernel speed | One scale multiply per row | One scale multiply per 128 elements | + +The 6% I/O increase is negligible compared to the quality gain. The grouped kernel has slightly more scale-lookup overhead but remains within AVX2 throughput — the bottleneck is disk I/O, not matmul. + +### Backward compatibility + +- Old per-row models (fmt=2) **work unchanged** — format auto-detected from scale array size +- All existing features (PILOT, EXPERT_BUDGET, CUDA, MTP, PIPE) work identically — they don't touch the dequant path +- The fused gate+up pair path (`matmul_i4_pair`) falls back to separate `matmul_qt` calls for fmt=4 — minor perf cost, correctness preserved +- `--group-size 0` produces per-row output (backward compat for the converter) + +## How to reproduce + +### Convert with group scales + +```bash +python tools/convert_fp8_to_int4.py \ + --indir /path/to/GLM-5.2-FP8 \ + --outdir /path/to/glm52_i4_grouped \ + --ebits 4 --io-bits 8 --group-size 128 +``` + +### Test quality + +```bash +# Old model (per-row): +SNAP=/path/to/glm52_i4 PROMPT="Explain recursion in programming." NGEN=32 ./glm 64 + +# New model (grouped): +SNAP=/path/to/glm52_i4_grouped PROMPT="Explain recursion in programming." NGEN=32 ./glm 64 +``` + +Compare output text coherence. + +## What this won't fix + +- **Cold cache speed** — still 0.18-0.36 tok/s on 24 GB RAM. Quality and speed are independent axes. +- **All quantization error** — int4 is still 4-bit. Some degradation vs FP8 will remain. But it should be coherent degradation (slightly wrong word choices) rather than total reasoning failure (unrelated topics). +- **The IDOT +12% perplexity** — the approximate activation kernel (`IDOT=1`, default ON) still applies to non-grouped tensors (attention projections are already protected). Grouped int4 uses exact kernels by design. + +## Prior art + +- **GLM-5 paper** (arXiv 2602.15763, §2.4.3): "We apply INT4 QAT in the SFT stage" — the model is trained for int4, but assumes fine-grained quantization. +- **MxMoE** (ICML 2025): MoE experts exhibit divergent quantization sensitivity; uniform quant across all experts is suboptimal. +- **MoEQuant** (OpenReview): Naive int4 on MoE loses meaningful accuracy; calibrated framework needed. +- **Automated Fine-Grained MoE Quantization** (ACL 2025): Layer/expert-wise sensitivity variation; group-size scaling is the baseline improvement. +- **ubergarm/GLM-5.1-GGUF**: imatrix-calibrated quants with expert-specific patches — explicitly patches `quantize_row_q4_0_ref()` for routed experts. +- **llama.cpp Q4_K**: Uses block-level group scales (32 or 64 elements) as the standard int4 format. + +## Conversion status + +Re-converting from the FP8 source (`zai-org/GLM-5.2-FP8`) with `--group-size 128`. Downloading via ModelScope to avoid HuggingFace per-stream throttling. Will report quality A/B results once the conversion is complete. From 71c262ce1a46d68bcdc9555de90de26c13b6ca8c Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Wed, 15 Jul 2026 01:40:02 -0400 Subject: [PATCH 40/79] diskio: KV write batching + persistent handle; generators: unfuse experts Two independent fixes validated end-to-end on fresh fixtures: 1. KV cache disk I/O (issue_diskio.md opportunities #1 + #4): - kv_disk_append: fopen/fclose every turn -> persistent FILE* kept open for the engine lifetime, lazy open on first append, closed in serve_ctx_free. Eliminates per-turn handle creation overhead. - kv_disk_append: ~157 small fwrites per position -> one contiguous record memcpy'd into a staging buffer then a single fwrite per position. The staging buffer grows on demand via realloc. - kv_disk_truncate: closes the persistent handle before truncating so the file actually shrinks on disc, then reopens lazily. - KVState gains disk_fp, disk_buf, disk_buf_cap fields. - Verified: serve-mode round-trip, write 11 tokens then reload and resume with no re-prefill, then append 8 more and reload to 19. 2. Expert weight unfusing in test-model generators: - The real GLM-5.2-FP8 checkpoint stores routed experts UNFUSED as per-expert 2-D tensors, each with its own _scale_inv. HF fuses gate+up into a single 3-D gate_up_proj for compute efficiency. - The converter and C engine both expect the unfused layout. The fused 3-D tensors were silently skipped by the converter, and the engine crashed with missing-tensor errors. - New unfuse_experts in glm_fp8_emit.py splits gate_up_proj and down_proj into per-expert 2-D tensors. Called after reference generation but before saving, in both generators, both FP8 and bf16. - Also fixed: make_glm_oracle.py FP8 round-trip guard used p.dim()<2 which let 3-D fused experts through and crashed fp8_block_quantize. Changed to p.dim()!=2 to match the converter ndim!=2 guard. Validated full chain on fresh fixtures: generator --fp8 -> 570 e4m3 tensors + 629 scale_inv, was 90 when fused converter --group-size 0 -> per-row int4 fmt=2, engine loads clean converter --group-size 128 -> grouped int4 fmt=4, 8-16x more scales, engine loads clean, fmt=4 auto-detected in both mmap and slab paths dequant error: grouped 1.14-1.22x lower than per-row vs FP8 source --- c/glm.c | 66 +++++++++++++++++++++++++++------ c/tools/glm_fp8_emit.py | 42 +++++++++++++++++++++ c/tools/make_glm_bench_model.py | 31 ++++++++++------ c/tools/make_glm_oracle.py | 15 ++++++-- 4 files changed, 127 insertions(+), 27 deletions(-) diff --git a/c/glm.c b/c/glm.c index fb93e59..3e24c31 100644 --- a/c/glm.c +++ b/c/glm.c @@ -142,6 +142,9 @@ typedef struct { int *kv_start, max_t; int disk_nrec; char disk_path[2048]; + FILE *disk_fp; /* kept-open handle: fopen once, fwrite per turn, fclose at exit (#4) */ + uint8_t *disk_buf; /* staging buffer: one contiguous record per position (#1) */ + int64_t disk_buf_cap; } KVState; typedef struct { @@ -3971,36 +3974,73 @@ static void kv_hdr(Model *m, int32_t *h, int nrec){ h[0]=c->n_layers; h[1]=c->kv_lora; h[2]=c->qk_rope; h[3]=m->has_dsa?c->index_hd:0; h[4]=nic; h[5]=c->vocab; h[6]=nrec; h[7]=0; } +/* Bytes of one on-disk record: [tok i32][Lc+Rc per layer][Ic per DSA layer]. + * Layout matches what kv_disk_append writes and kv_disk_load reads. */ +static int64_t kv_rec_bytes(Model *m){ + Cfg *c=&m->c; + int64_t rec = 4 + (int64_t)c->n_layers*(c->kv_lora+c->qk_rope)*4; + if(m->has_dsa) for(int i=0;in_layers;i++) if(m->Ic[i]) rec+=(int64_t)c->index_hd*4; + return rec; +} +/* Open the persistent handle lazily; write the header if the file is new. After + * this returns successfully, k->disk_fp is valid for the engine's lifetime and + * positioned at end-of-header (nrec==0 case) or wherever the caller seeks. */ +static int kv_disk_open(Model *m){ + KVState *k=m->kv; + if(k->disk_fp) return 1; + k->disk_fp=fopen(k->disk_path,"r+b"); + if(!k->disk_fp){ /* not there yet -> create + header */ + k->disk_fp=fopen(k->disk_path,"wb"); + if(!k->disk_fp) return 0; + int32_t h[8]; kv_hdr(m,h,0); + fwrite(KV_MAGIC,1,8,k->disk_fp); fwrite(h,4,8,k->disk_fp); + fflush(k->disk_fp); + fclose(k->disk_fp); + k->disk_fp=fopen(k->disk_path,"r+b"); /* reopen r+b for append */ + if(!k->disk_fp) return 0; + } + return 1; +} static void kv_disk_truncate(Model *m, int nrec){ if(!g_kvsave) return; KVState *k=m->kv; + if(k->disk_fp){ fclose(k->disk_fp); k->disk_fp=NULL; } /* drop to shrink on disc */ FILE *f=fopen(k->disk_path,"r+b"); if(!f){ k->disk_nrec=0; return; } k->disk_nrec=nrec; - int32_t nr=nrec; fseek(f,8+6*4,SEEK_SET); fwrite(&nr,4,1,f); fclose(f); + int32_t nr=nrec; fseek(f,8+6*4,SEEK_SET); fwrite(&nr,4,1,f); + fflush(f); fclose(f); } static void kv_disk_reset(Model *m){ kv_disk_truncate(m,0); } static void kv_disk_append(Model *m, const int *hist, int len){ KVState *k=m->kv; if(!g_kvsave || len<=k->disk_nrec) return; Cfg *c=&m->c; - FILE *f=fopen(k->disk_path,"r+b"); - if(!f){ f=fopen(k->disk_path,"wb"); if(!f) return; - int32_t h[8]; kv_hdr(m,h,0); fwrite(KV_MAGIC,1,8,f); fwrite(h,4,8,f); } - int64_t rec = 4 + (int64_t)c->n_layers*(c->kv_lora+c->qk_rope)*4; - if(m->has_dsa) for(int i=0;in_layers;i++) if(m->Ic[i]) rec+=(int64_t)c->index_hd*4; + if(!kv_disk_open(m)) return; + FILE *f=k->disk_fp; + int64_t rec = kv_rec_bytes(m); + /* grow the contiguous staging buffer if the record is larger (#1 batching) */ + if(rec > k->disk_buf_cap){ + uint8_t *nb=realloc(k->disk_buf, rec); + if(!nb) return; /* OOM: skip this turn, retry next */ + k->disk_buf=nb; k->disk_buf_cap=rec; + } fseek(f, 8+8*4 + (int64_t)k->disk_nrec*rec, SEEK_SET); for(int p=k->disk_nrec;pdisk_buf; /* pack token + every layer into one record */ + *(int32_t*)b = hist[p]; b+=4; for(int i=0;in_layers;i++){ - fwrite(m->Lc[i]+(int64_t)p*c->kv_lora, 4, c->kv_lora, f); - fwrite(m->Rc[i]+(int64_t)p*c->qk_rope, 4, c->qk_rope, f); + memcpy(b, m->Lc[i]+(int64_t)p*c->kv_lora, (size_t)c->kv_lora*4); b+=c->kv_lora*4; + memcpy(b, m->Rc[i]+(int64_t)p*c->qk_rope,(size_t)c->qk_rope*4); b+=c->qk_rope*4; } - if(m->has_dsa) for(int i=0;in_layers;i++) if(m->Ic[i]) - fwrite(m->Ic[i]+(int64_t)p*c->index_hd, 4, c->index_hd, f); + if(m->has_dsa) for(int i=0;in_layers;i++) if(m->Ic[i]){ + memcpy(b, m->Ic[i]+(int64_t)p*c->index_hd, (size_t)c->index_hd*4); b+=c->index_hd*4; + } + fwrite(k->disk_buf, 1, (size_t)rec, f); /* one fwrite per position (was ~157) */ } fflush(f); /* dati prima, contatore poi */ - int32_t nr=len; fseek(f,8+6*4,SEEK_SET); fwrite(&nr,4,1,f); fclose(f); + int32_t nr=len; fseek(f,8+6*4,SEEK_SET); fwrite(&nr,4,1,f); + fflush(f); /* persist the counter too */ k->disk_nrec=len; } static int kv_disk_load(Model *m, int *hist, int maxctx){ @@ -4055,6 +4095,8 @@ static void serve_ctx_init(Model *m, ServeCtx *s, const char *snap, int slot, in static void serve_ctx_free(Model *m, ServeCtx *s){ KVState *k=&s->kv; int NR=m->c.n_layers+1; + if(k->disk_fp){ fclose(k->disk_fp); k->disk_fp=NULL; } + free(k->disk_buf); k->disk_buf=NULL; if(k->Lc) for(int i=0;iLc[i]); free(k->Rc[i]); } if(k->Ic) for(int i=0;ic.n_layers;i++) free(k->Ic[i]); free(k->Lc); free(k->Rc); free(k->Ic); free(k->kv_start); free(s->hist); diff --git a/c/tools/glm_fp8_emit.py b/c/tools/glm_fp8_emit.py index 4ae05d6..45bb304 100644 --- a/c/tools/glm_fp8_emit.py +++ b/c/tools/glm_fp8_emit.py @@ -66,6 +66,48 @@ def fp8_block_dequantize(w_fp8, scale): return qf * scale.repeat_interleave(BLOCK, 0).repeat_interleave(BLOCK, 1)[:O, :I] +def unfuse_experts(sd): + """Split HF's fused 3-D `experts.gate_up_proj` [E, 2*M, I] into per-expert 2-D + `experts.{e}.gate_proj` [M, I] + `experts.{e}.up_proj` [M, I], and + `experts.down_proj` [E, I, M] -> `experts.{e}.down_proj` [M_out, I]. + + The real GLM-5.2-FP8 checkpoint stores experts UNFUSED as per-expert 2-D tensors + (gate_proj, up_proj, down_proj), each with its own _scale_inv. HF's + GlmMoeDsaForCausalLM fuses gate+up into a single 3-D gate_up_proj for efficiency. + The converter (classify + ndim!=2 guard) and the C engine both expect the unfused + layout, so we split before saving. + + Idempotent: if experts are already unfused (no 3-D gate_up_proj), returns sd as-is. + EN: split HF's fused 3-D expert weights into the per-expert 2-D layout that the real + EN: checkpoint uses and the converter/engine expect. No-op if already unfused.""" + keys_to_remove = [] + new_entries = {} + for name, t in sd.items(): + if not name.endswith(".mlp.experts.gate_up_proj"): + continue + # prefix = everything before ".mlp.experts.gate_up_proj" + prefix = name[:-len(".mlp.experts.gate_up_proj")] + E, twoM, I = t.shape # [E, 2*intermediate, input] + M = twoM // 2 + for e in range(E): + new_entries[f"{prefix}.mlp.experts.{e}.gate_proj.weight"] = t[e, :M, :].contiguous() + new_entries[f"{prefix}.mlp.experts.{e}.up_proj.weight"] = t[e, M:, :].contiguous() + keys_to_remove.append(name) + # down_proj may be 3-D [E, I, M] in the fused form, or already per-expert + for name, t in sd.items(): + if not name.endswith(".mlp.experts.down_proj") or t.dim() != 3: + continue + prefix = name[:-len(".mlp.experts.down_proj")] + E = t.shape[0] + for e in range(E): + new_entries[f"{prefix}.mlp.experts.{e}.down_proj.weight"] = t[e].contiguous() + keys_to_remove.append(name) + for k in keys_to_remove: + sd.pop(k, None) + sd.update(new_entries) + return sd + + def state_dict_to_fp8(sd): """Converte uno state_dict HuggingFace nel layout FP8 del checkpoint reale: per ogni tensore quantizzabile 2-D scrive `{name}` (F8_E4M3) + `{name}_scale_inv` (F32); diff --git a/c/tools/make_glm_bench_model.py b/c/tools/make_glm_bench_model.py index 54a1a3f..5ec3457 100644 --- a/c/tools/make_glm_bench_model.py +++ b/c/tools/make_glm_bench_model.py @@ -22,7 +22,7 @@ import torch from transformers import GlmMoeDsaConfig, GlmMoeDsaForCausalLM sys.path.insert(0, str(Path(__file__).resolve().parent)) # importa glm_fp8_emit se lanciato da c/ -from glm_fp8_emit import save_fp8_safetensors +from glm_fp8_emit import save_fp8_safetensors, unfuse_experts def build_config() -> GlmMoeDsaConfig: @@ -85,16 +85,6 @@ def main() -> None: output = Path(args.output) output.mkdir(parents=True, exist_ok=True) params = sum(p.numel() for p in model.parameters()) - if args.fp8: - n_fp8, n_tot = save_fp8_safetensors(model.state_dict(), output / "model.safetensors") - # save_pretrained scrive config.json; nel path FP8 lo bypassiamo, quindi lo scriviamo - # a mano (serve al converter e al motore C). EN: save_pretrained writes config.json; - # the FP8 path bypasses it, so write it manually (converter + C engine need it). - (output / "config.json").write_text(json.dumps(cfg.to_dict())) - print(f"saved FP8: {n_fp8} e4m3 tensors (+{n_tot - n_fp8} scale_inv sidecars / f32) " - f"-> {output / 'model.safetensors'}") - else: - model.save_pretrained(output, safe_serialization=True, max_shard_size="4GB") model.to(args.device) prompt = [3, 14, 159, 26, 53, 58, 200, 11, 77, 240, 5, 99] @@ -103,6 +93,25 @@ def main() -> None: full = model.generate(ids, max_new_tokens=8, do_sample=False, use_cache=True)[0] logits = model(full.unsqueeze(0), use_cache=False).logits[0] + # Unfuse experts AFTER reference generation (model needs fused weights for + # forward/generate) but BEFORE saving — the real checkpoint and the converter + # + C engine all expect per-expert 2-D gate_proj/up_proj/down_proj tensors. + sd = model.state_dict() + unfuse_experts(sd) + + if args.fp8: + n_fp8, n_tot = save_fp8_safetensors(sd, output / "model.safetensors") + # save_pretrained scrive config.json; nel path FP8 lo bypassiamo, quindi lo scriviamo + # a mano (serve al converter e al motore C). EN: save_pretrained writes config.json; + # the FP8 path bypasses it, so write it manually (converter + C engine need it). + (output / "config.json").write_text(json.dumps(cfg.to_dict())) + print(f"saved FP8: {n_fp8} e4m3 tensors (+{n_tot - n_fp8} scale_inv sidecars / f32) " + f"-> {output / 'model.safetensors'}") + else: + from safetensors.torch import save_file + save_file({k: v.contiguous() for k, v in sd.items()}, str(output / "model.safetensors")) + (output / "config.json").write_text(json.dumps(cfg.to_dict())) + ref = { "prompt_ids": prompt, "full_ids": full.cpu().tolist(), diff --git a/c/tools/make_glm_oracle.py b/c/tools/make_glm_oracle.py index 67ad5a5..b623faf 100644 --- a/c/tools/make_glm_oracle.py +++ b/c/tools/make_glm_oracle.py @@ -22,7 +22,7 @@ from transformers import GlmMoeDsaConfig, GlmMoeDsaForCausalLM sys.path.insert(0, str(Path(__file__).resolve().parent)) # importa glm_fp8_emit se lanciato da c/ from glm_fp8_emit import (fp8_block_quantize, fp8_block_dequantize, keep_f32, - save_fp8_safetensors) + save_fp8_safetensors, unfuse_experts) ap = argparse.ArgumentParser() ap.add_argument("--fp8", action="store_true", @@ -84,7 +84,7 @@ with torch.no_grad(): if args.fp8: with torch.no_grad(): for n, p in model.named_parameters(): - if keep_f32(n, p) or p.dim() < 2: + if keep_f32(n, p) or p.dim() != 2: continue q, s = fp8_block_quantize(p) p.copy_(fp8_block_dequantize(q, s)) @@ -109,12 +109,19 @@ with torch.no_grad(): tf_pred = lg.argmax(-1).tolist() print("tf_pred:", tf_pred) +# Unfuse experts AFTER reference generation (model needs fused weights for +# forward/generate) but BEFORE saving — the real checkpoint and the converter +# + C engine all expect per-expert 2-D gate_proj/up_proj/down_proj tensors. +sd = model.state_dict() +unfuse_experts(sd) + if args.fp8: - n_fp8, n_tot = save_fp8_safetensors(model.state_dict(), "glm_tiny/model.safetensors") + n_fp8, n_tot = save_fp8_safetensors(sd, "glm_tiny/model.safetensors") print(f"\nsaved FP8: {n_fp8} e4m3 tensors (+{n_tot - n_fp8} scale_inv sidecars / f32) " f"-> glm_tiny/model.safetensors") else: - model.save_pretrained("glm_tiny", safe_serialization=True) + from safetensors.torch import save_file + save_file({k: v.contiguous() for k, v in sd.items()}, "glm_tiny/model.safetensors") json.dump(cfg.to_dict(), open("glm_tiny/config.json", "w")) json.dump({"prompt_ids": prompt, "full_ids": full, "tf_pred": tf_pred}, open("ref_glm.json", "w")) print("saved: glm_tiny/ (weights + config) and ref_glm.json" From 413b370fbf529840abeacce5acba18175a3fb7bf Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Tue, 14 Jul 2026 18:02:15 -0400 Subject: [PATCH 41/79] =?UTF-8?q?experiment:=20EXPERT=5FBUDGET=3DN=20?= =?UTF-8?q?=E2=80=94=20cap=20distinct=20experts/layer,=20up=20to=201.8x=20?= =?UTF-8?q?faster=20decode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add EXPERT_BUDGET env var that caps the number of distinct experts loaded per layer across the batch-union. When the union exceeds the budget, keeps only the highest-aggregate-gate-weight experts and drops the rest from idxs[] so they're never loaded from disk. Complementary to TOPP (per-position) — this trims the cross-position union that multiplies under MTP/prefill. Based on MoE-Spec (arXiv 2602.16052): 'top 32 of 64 experts capture 93% of routing weight.' Measurements (GLM-5.2 744B, 24GB RAM, cap=2, MTP=0, 32 tokens): Baseline (budget=0): 0.18 tok/s, 9.3% hit, 176s decode, 39s prefill EXPERT_BUDGET=12: 0.19 tok/s, 14.0% hit, 171s decode, 12s prefill EXPERT_BUDGET=6: 0.26 tok/s, 21.0% hit, 123s decode, 7s prefill EXPERT_BUDGET=4: 0.33 tok/s, 16.4% hit, 97s decode, 9s prefill Budget=4 nearly doubles decode speed (+83%) and 4x's prefill speed by halving disk reads per layer. Default OFF (EXPERT_BUDGET=0). --- c/glm.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/c/glm.c b/c/glm.c index fb93e59..28a32ad 100644 --- a/c/glm.c +++ b/c/glm.c @@ -896,6 +896,11 @@ static float g_temp=-1; /* TEMP: temperatura di sampling sui TOKEN. <0 = auto ( static float g_nuc=0.95f;/* NUCLEUS: top-p sul vocabolario (default dal generation_config GLM-5.2) */ static int g_topk=0; /* TOPK=n -> usa n expert/token invece di config (ricerca: meno disco) */ static float g_topp=0; /* TOPP=p (0..1) -> top-p adattivo: tieni gli expert fino a peso cumulato p */ +static int g_expert_budget=0; /* EXPERT_BUDGET=N -> cap distinct experts loaded per layer across the + * batch-union. Reduces disk I/O on cold/low-RAM hosts by dropping the + * lowest-gate-weight experts from the cross-position union. MoE-Spec + * (arXiv 2602.16052): top-32 of 64 capture 93% routing weight. */ +static int64_t g_budget_dropped=0; /* total experts dropped by EXPERT_BUDGET across all layers */ /* CACHE_ROUTE (paper 2412.00099 max-rank): opt-in only. Keep true top-J always; * fill remaining slots preferring pin∪LRU experts ranked within top-M (or mass ROUTE_P). */ static int g_cache_route=0; @@ -2413,6 +2418,53 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out, int int e=idxs[(int64_t)s*K+kk]; if(!seen[e]){ seen[e]=1; uniq[nu++]=e; } } + /* EXPERT_BUDGET: cap distinct experts per layer to reduce disk I/O on cold/low-RAM + * hosts. Keep the highest-aggregate-gate-weight experts; drop the rest from idxs[] + * so they're never loaded. (MoE-Spec arXiv 2602.16052: top-32 of 64 capture 93% + * routing weight.) Complementary to TOPP (per-position) — this trims cross-position. */ + if(g_expert_budget>0 && nu>g_expert_budget){ + /* compute aggregate gate weight per unique expert */ + float *wsum=falloc(nu); for(int j=0;jbv){ bv=wsum[j]; best=j; } + if(best<0) break; keep[best]=1; nkeep++; + } + } + /* build a lookup: for each expert id, is it kept? (reuse seen[]) */ + memset(seen,0,(size_t)E); + for(int j=0;jnorm_topk && w>0){ + float sm=0; for(int kk=0;kkrouted_scale; + } + } + } + /* compact uniq[] to kept experts only */ + int nu2=0; + for(int j=0;jereq/produced:0.0, (produced&&nsp)?(double)m->ereq/produced/nsp:0.0, nsp, c->topk, g_topk, g_topp); if(g_cache_route) printf(" | CACHE_ROUTE J=%d M=%d P=%.2f alpha=%.2f", g_route_j, g_route_m, g_route_p, g_route_alpha); + if(g_expert_budget) printf(" | EXPERT_BUDGET=%d (dropped %lld experts, ~%.1f GB I/O saved)", g_expert_budget, (long long)g_budget_dropped, g_budget_dropped*18.9e6/1e9); printf("\n"); printf("speculation: %.2f tokens/forward (%llu forwards per %llu tokens) | MTP acceptance %.0f%% (%llu/%llu)\n", m->n_fw?(double)m->n_emit/m->n_fw:1.0, (unsigned long long)m->n_fw, (unsigned long long)m->n_emit, @@ -4925,6 +4978,7 @@ int main(int argc, char **argv){ if(g_mmap) fprintf(stderr,"[MMAP] expert = viste zero-copy nei file (page cache = cache)\n"); g_topk = getenv("TOPK")?atoi(getenv("TOPK")):0; g_topp = getenv("TOPP")?atof(getenv("TOPP")):0; + g_expert_budget = getenv("EXPERT_BUDGET")?atoi(getenv("EXPERT_BUDGET")):0; g_cache_route = getenv("CACHE_ROUTE")?atoi(getenv("CACHE_ROUTE")):0; g_route_j = getenv("ROUTE_J")?atoi(getenv("ROUTE_J")):2; g_route_m = getenv("ROUTE_M")?atoi(getenv("ROUTE_M")):12; From dd0d60692d338c01ee03e3854284a3eca8601da6 Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Tue, 14 Jul 2026 18:23:29 -0400 Subject: [PATCH 42/79] =?UTF-8?q?experiment:=20miss-aware=20EXPERT=5FBUDGE?= =?UTF-8?q?T=20=E2=80=94=20keep=20all=20cache=20hits,=20only=20drop=20miss?= =?UTF-8?q?es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The original budget dropped experts blindly — even cached ones that cost zero disk I/O. The miss-aware version pre-scans pin/ecache residency before applying the budget: - ALL cache hits are kept (free to compute, no disk I/O) - Only misses compete for the remaining budget slots - Miss budget = EXPERT_BUDGET - nhits (min 0) Results (budget=4, same prompt/config as before): Original Miss-aware tok/s 0.33 0.36 (+9%) hit rate 16.4% 38.2% (2.3x) prefill 8.9s 5.6s (1.6x faster) decode 97.4s 88.9s (9% faster) The hit rate doubling is the key quality signal: the model now gets the full contribution from all resident experts plus the top-4 new loads, instead of losing some hits to the budget. --- c/glm.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/c/glm.c b/c/glm.c index 28a32ad..8ea02ed 100644 --- a/c/glm.c +++ b/c/glm.c @@ -2419,9 +2419,11 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out, int if(!seen[e]){ seen[e]=1; uniq[nu++]=e; } } /* EXPERT_BUDGET: cap distinct experts per layer to reduce disk I/O on cold/low-RAM - * hosts. Keep the highest-aggregate-gate-weight experts; drop the rest from idxs[] - * so they're never loaded. (MoE-Spec arXiv 2602.16052: top-32 of 64 capture 93% - * routing weight.) Complementary to TOPP (per-position) — this trims cross-position. */ + * hosts. MISS-AWARE: always keep cache hits (pin/LRU — they're free, no disk I/O), + * only drop from misses. From the misses, keep the highest-aggregate-gate-weight + * ones up to the budget; drop the rest from idxs[] so they're never loaded. + * (MoE-Spec arXiv 2602.16052: top-32 of 64 capture 93% routing weight.) + * Complementary to TOPP (per-position) — this trims cross-position. */ if(g_expert_budget>0 && nu>g_expert_budget){ /* compute aggregate gate weight per unique expert */ float *wsum=falloc(nu); for(int j=0;jpin[layer]; + for(int z=0;znpin[layer];z++) if(P[z].eid==eid){ found=1; break; } + if(!found){ ESlot *Sl=m->ecache[layer]; int nn=m->ecn[layer]; + for(int z=0;zbv){ bv=wsum[j]; best=j; } - if(best<0) break; keep[best]=1; nkeep++; - } + for(int j=0;jbv){ bv=wsum[j]; best=j; } + if(best<0) break; keep[best]=1; nkeep++; } /* build a lookup: for each expert id, is it kept? (reuse seen[]) */ memset(seen,0,(size_t)E); @@ -2463,7 +2477,7 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out, int int nu2=0; for(int j=0;j Date: Wed, 15 Jul 2026 17:24:16 +0800 Subject: [PATCH 43/79] =?UTF-8?q?tools:=20E8=20lattice=20quantization=20fo?= =?UTF-8?q?r=20the=20ablation=20harness=20=E2=80=94=20int{2,3,4,8}[-gN][-e?= =?UTF-8?q?8|-e8u][-rot]=20(#81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- c/tools/quant_ablation.py | 97 ++++++++++++++++++++++++++++++++++----- 1 file changed, 85 insertions(+), 12 deletions(-) diff --git a/c/tools/quant_ablation.py b/c/tools/quant_ablation.py index 7a870ff..689643a 100644 --- a/c/tools/quant_ablation.py +++ b/c/tools/quant_ablation.py @@ -106,33 +106,106 @@ def rotation(dim, device, seed=417): return q -def quantize_param(w, bits, group, rot=False): +def quantize_param(w, bits, group, rot=False, e8=""): if w.ndim == 3: # fused experts [E, in, out] -> move input last x = w.transpose(1, 2).contiguous() - x = _rot_quant(x, bits, group) if rot else _quant_last_dim(x, bits, group) + x = _rot_quant(x, bits, group, e8) if rot else _grid_or_e8(x, bits, group, e8) return x.transpose(1, 2).contiguous() if rot: - return _rot_quant(w, bits, group) - return _quant_last_dim(w, bits, group) # nn.Linear [out, in] -- input already last + return _rot_quant(w, bits, group, e8) + return _grid_or_e8(w, bits, group, e8) # nn.Linear [out, in] -- input already last -def _rot_quant(x, bits, group): +def _grid_or_e8(x, bits, group, e8): + if e8: + return _quant_e8(x.float(), group, ball=(e8 == "-e8")) + return _quant_last_dim(x, bits, group) + + +def _rot_quant(x, bits, group, e8=""): """W -> Qn(W@Q) @ Q^T along the last (input) dim — see rotation() above.""" q = rotation(x.shape[-1], x.device) - return (_quant_last_dim(x.float() @ q, bits, group) @ q.T).contiguous() + return (_grid_or_e8(x.float() @ q, bits, group, e8) @ q.T).contiguous() -SCHEME_RE = re.compile(r"^int(2|3|4|8)(?:-g(\d+))?(-rot)?(-nohead)?$") +# -------------------------------------------------------------------------------------- +# E8 lattice quantization (#81 follow-up): the -rot schemes above are QuaRot (rotation + +# uniform grid). QuIP#'s 2-bit result needs the second ingredient — an E8 lattice codebook +# instead of the grid. E8 = D8 ∪ (D8 + 1/2), nearest point via Conway–Sloane: round every +# coordinate, and if the sum is odd re-round the worst coordinate the other way; repeat on +# the half-shifted copy and keep the closer of the two. `-e8` clamps points to |p|^2 <= 10, +# the E8P ball QuIP# builds its 2^16 codebook from (2 bits/weight for 8-dim blocks); +# `-e8u` leaves the lattice unbounded — an ideal-codebook upper bound, not a deployable rate. +# Scale: per group, a small MSE search over multiples of the block RMS (absmax is the wrong +# statistic for a lattice — the ball wants energy matched, not the peak). +# -------------------------------------------------------------------------------------- +def _d8_nearest(y): + f = torch.round(y) + d = y - f + odd = (f.sum(-1).long() & 1).bool() + idx = d.abs().argmax(-1, keepdim=True) + step = torch.where(d.gather(-1, idx) >= 0, 1.0, -1.0) + flipped = f.gather(-1, idx) + step + return f.scatter(-1, idx, torch.where(odd[..., None], flipped, f.gather(-1, idx))) + + +def _e8_nearest(y): + a = _d8_nearest(y) + b = _d8_nearest(y - 0.5) + 0.5 + da = ((y - a) ** 2).sum(-1, keepdim=True) + db = ((y - b) ** 2).sum(-1, keepdim=True) + return torch.where(da <= db, a, b) + + +def _e8_ball(y, r2=10.0): + p = _e8_nearest(y) + for _ in range(8): # shrink-and-requantize until inside + n2 = (p ** 2).sum(-1, keepdim=True) + over = n2 > r2 + 1e-6 + if not over.any(): + break + y = torch.where(over, y * torch.sqrt(r2 / torch.clamp(n2, min=r2)) * 0.98, y) + p = torch.where(over, _e8_nearest(y), p) + return p + + +def _quant_e8(x, group, ball): + """Blocks of 8 along the input dim; per-group scale by MSE search over RMS multiples.""" + if x.shape[-1] % 8: + raise SystemExit(f"-e8 needs input dim divisible by 8 (got {x.shape[-1]})") + g = group or x.shape[-1] + if g % 8: + raise SystemExit(f"-e8 group {g} must be a multiple of 8") + shp = x.shape + xg = x.reshape(-1, g) # [G, g] + rms = torch.clamp(xg.pow(2).mean(-1, keepdim=True).sqrt(), min=1e-8) + best_out, best_err = None, None + for k in (0.5, 0.7, 0.9, 1.1, 1.4, 1.8, 2.4): + s = rms * k + yb = (xg / s).reshape(-1, g // 8, 8) + p = _e8_ball(yb) if ball else _e8_nearest(yb) + out = (p.reshape(-1, g) * s) + err = (out - xg).pow(2).sum(-1, keepdim=True) + if best_err is None: + best_out, best_err = out, err + else: + take = err < best_err + best_out = torch.where(take, out, best_out) + best_err = torch.where(take, err, best_err) + return best_out.reshape(shp) + + +SCHEME_RE = re.compile(r"^int(2|3|4|8)(?:-g(\d+))?(-e8u?)?(-rot)?(-nohead)?$") def parse_scheme(name): - """'int4-g128-nohead' -> (bits=4, group=128, skip_head=True). 'fp16' -> None.""" + """'int4-g128-nohead' -> (bits, group, e8, skip_head...). 'fp16' -> None.""" if name == "fp16": return None m = SCHEME_RE.match(name) if not m: - raise SystemExit(f"bad scheme '{name}' (expected fp16 | int{{2,3,4,8}}[-g][-rot][-nohead])") - return int(m.group(1)), int(m.group(2) or 0), bool(m.group(3)), bool(m.group(4)) + raise SystemExit(f"bad scheme '{name}' (expected fp16 | int{{2,3,4,8}}[-g][-e8|-e8u][-rot][-nohead])") + return int(m.group(1)), int(m.group(2) or 0), m.group(3) or "", bool(m.group(4)), bool(m.group(5)) def is_router(name): @@ -152,7 +225,7 @@ def apply_scheme(model, scheme): spec = parse_scheme(scheme) if spec is None: return 0, 0, total - bits, group, rot, skip_head = spec + bits, group, e8, rot, skip_head = spec n = qp = 0 with torch.no_grad(): for name, p in model.named_parameters(): @@ -160,7 +233,7 @@ def apply_scheme(model, scheme): continue if skip_head and is_head_or_embed(name): continue - p.data.copy_(quantize_param(p.data.float(), bits, group, rot).to(p.dtype)) + p.data.copy_(quantize_param(p.data.float(), bits, group, rot, e8).to(p.dtype)) n += 1 qp += p.numel() return n, qp, total From 081173084567e7b0d327b14d54711dab20aad6c5 Mon Sep 17 00:00:00 2001 From: monotophic Date: Wed, 15 Jul 2026 05:54:50 -0400 Subject: [PATCH 44/79] serve mux: keep ragged decode batches off the fused Metal kernels With METAL=1 + COLI_METAL=1, run_serve_mux (SERVE_BATCH=1) truncated every completion to exactly 1 token: step_decode_batch passes per-row kvs[]/positions[] with pos_base=0, but the two Metal decode fast paths (attention_rows and the FULL-LAYER CB in layer_forward_rows) ignored them and dispatched coli_metal_attn_decode/coli_metal_layer_decode with the model-bound Lc/Rc and the hardcoded pos_base. The kernels' contract is one sequence, row s at pos_base+s: ragged rows got roped at position 0 and attended over a T=1 window of the wrong cache, so greedy decode hit a stop token on the first batched step (DONE ... STAT 1). Gate both fast paths on !kvs. Ragged mux rows now take the CPU absorb path, which already reads kvs[s]/positions[s]/ks->kv_start per row; plain serve, chat/run, prefill and MTP verification (kvs==NULL) keep the fused GPU kernels unchanged. Verified on GLM-5.2 int4 (M5 Max): mux with COLI_METAL=1 went from 1-token DONE to full 16/16-token greedy completions, byte-identical to the plain-serve comparator on both test prompts; CPU-only mux was already correct (bisection); test-c and metal-test pass. Co-Authored-By: Claude Opus 4.8 --- c/glm.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/c/glm.c b/c/glm.c index 8da3f55..c0e7058 100644 --- a/c/glm.c +++ b/c/glm.c @@ -1789,8 +1789,14 @@ static void attention_rows(Model *m, Layer *l, int layer, float *x, int S, int p double ta0=now_s(); #ifdef COLI_METAL /* Fused decode attention on GPU: whole layer in one command buffer (keeps the GPU hot). - * S<=4 absorption path with st0==0, DSA selection inactive, and GLM-5.2 int4 dims. */ - if(g_metal_enabled && S<=4 && (g_absorb==1||(g_absorb<0&&S<=4)) && m->kv_start[layer]==0 + * S<=4 absorption path with st0==0, DSA selection inactive, and GLM-5.2 int4 dims. + * RAGGED GUARD (!kvs): the kernel takes ONE Lc/Rc pair and ONE pos_base — it assumes + * row s is token pos_base+s of the SAME sequence. The batched mux decode + * (step_decode_batch) passes per-row kvs[]/positions[] with pos_base=0, so the kernel + * would rope every row at position 0 and attend over a 1-token window of the wrong + * cache -> greedy decode hits EOS at token 2 (mux answers truncated to 1 token). + * Ragged rows take the CPU absorb path below, which reads kvs[s]/positions[s]. */ + if(g_metal_enabled && !kvs && S<=4 && (g_absorb==1||(g_absorb<0&&S<=4)) && m->kv_start[layer]==0 && D==6144 && H==64 && c->q_lora==2048 && c->kv_lora==512 && c->qk_nope==192 && c->qk_rope==64 && vh==256 && l->kv_b.fmt==2){ int sel_active = m->has_dsa && layern_layers && c->idx_type[layer] && (pos_base+S) > c->index_topk; @@ -2925,8 +2931,10 @@ static void layer_forward_rows(Model *m, Layer *l, int li, float *x, int S, int #ifdef COLI_METAL /* FULL-LAYER CB: in_ln + attention + residuo + post_ln + shared expert + router/top-K * in un solo submit GPU; la CPU legge il routing e fa solo resolve/disk/expert-CB. - * Fallback: qualsiasi condizione mancante -> percorso CPU intero qui sotto. */ - if(g_metal_enabled && S<=4 && lin_layers && l->sparse + * Fallback: qualsiasi condizione mancante -> percorso CPU intero qui sotto. + * !kvs: ragged mux rows (per-row KV/position) are not expressible in this kernel's + * single Lc/Rc + pos_base contract — see the matching guard in attention_rows. */ + if(g_metal_enabled && !kvs && S<=4 && lin_layers && l->sparse && (g_absorb==1||(g_absorb<0&&S<=4)) && m->kv_start[li]==0 && D==6144 && c->n_heads==64 && c->q_lora==2048 && c->kv_lora==512 && c->qk_nope==192 && c->qk_rope==64 && c->v_head==256 && l->kv_b.fmt==2 From 25219de45b2eb2b2d19215ef6c4bc82117a024a2 Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Wed, 15 Jul 2026 06:14:15 -0400 Subject: [PATCH 45/79] windows: PIPE default ON + compat_fadvise WILLNEED cache-warmer (pread path) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cut Windows decode disk I/O from 2.06s/tok to 1.70s/tok (budget=4), meeting the <=2s/tok target. Two changes on the pread expert-load path: 1. compat.h: replace the posix_fadvise no-op with a real WILLNEED cache-warmer (overlapped ReadFile into a scratch buffer -> populates the standby page cache so the later synchronous pread faults from RAM). Re-arms the existing expert_prefetch/PILOT/next-block prefetch chain on Windows. DONTNEED stays a no-op (matches macOS; Windows standby-list trimming self-regulates). Measured: hit rate 16.4% -> 27.6%. 2. glm.c: flip PIPE (async expert-load thread pool) from default OFF to default ON on Windows. Dispatches expert pread onto worker threads so loads overlap the matmul, instead of blocking serial load-then-compute. PIPE=0 opts out. Measured: expert-disk 65.9s -> 54.3s (-18%). Also adds compat_fadvise assertions to tests/test_compat_direct.c (data integrity after cache-warmer, safe no-op on bad fd / non-WILLNEED). mmap (CreateFileMapping/MapViewOfFile) was implemented and tested at length but reverted: it regressed on Windows (RSS bloat from touched mapped pages collapsed the expert cache via ullAvailPhys — a fundamental Windows-vs-Linux difference). Full findings + the dead-end analysis recorded in issue_diskio.md. --- README.md | 2 +- c/compat.h | 37 +++++++++++- c/glm.c | 13 +++- c/tests/test_compat_direct.c | 17 ++++++ issue_diskio.md | 114 +++++++++++++++++++++++++++++++++++ 5 files changed, 178 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 86c3009..4521c83 100644 --- a/README.md +++ b/README.md @@ -468,7 +468,7 @@ works against the colibrì OpenAI-compatible server (in review, #21) or any othe compatible endpoint. Nothing leaves the endpoint you configure. The terminal `coli chat` remains the first-class interface. -Useful knobs (env or flags): `--temp T` token sampling temperature (default 0.7 + nucleus 0.90 — tuned for int4; 0 = greedy), `--topp 0.7` adaptive expert top-p (30–40% less disk), `--ngen N` max tokens per answer (`:more` in chat continues a truncated one), `--repin N` adapt RAM/VRAM hot experts every N emitted tokens, `AUTOPIN=0` disable the learning cache's auto-pin, `THINK=1` enable GLM-5.2's reasoning block, `DRAFT=n` MTP draft depth, `GRAMMAR=g.gbnf` grammar-forced drafts for constrained JSON/NDJSON output (`GRAMMAR_DRAFT=n` caps the forced span), `TF=1` teacher-forcing validation, `PILOT=1` router-lookahead disk prefetch (experimental — see below), `CAP_RAISE=0` don't auto-grow the expert cache. +Useful knobs (env or flags): `--temp T` token sampling temperature (default 0.7 + nucleus 0.90 — tuned for int4; 0 = greedy), `--topp 0.7` adaptive expert top-p (30–40% less disk), `--ngen N` max tokens per answer (`:more` in chat continues a truncated one), `--repin N` adapt RAM/VRAM hot experts every N emitted tokens, `AUTOPIN=0` disable the learning cache's auto-pin, `THINK=1` enable GLM-5.2's reasoning block, `DRAFT=n` MTP draft depth, `GRAMMAR=g.gbnf` grammar-forced drafts for constrained JSON/NDJSON output (`GRAMMAR_DRAFT=n` caps the forced span), `TF=1` teacher-forcing validation, `PILOT=1` router-lookahead disk prefetch (experimental — see below), `CAP_RAISE=0` don't auto-grow the expert cache, `PIPE=0` disable the async expert-load pool (**default ON on Windows** since `windows-optimizations` — overlaps expert `pread` with the matmul so the CPU isn't idle waiting on the SSD; measured −18% disk service time), `RAM_GB=` claim more RAM for the expert cache than the conservative auto-detect (e.g. `RAM_GB=31` on a 32 GB host raises the cache cap and hit rate measurably). ### Resource policy diff --git a/c/compat.h b/c/compat.h index 721ba8e..82de8b6 100644 --- a/c/compat.h +++ b/c/compat.h @@ -95,7 +95,18 @@ static inline int compat_open_direct(const char *path){ * prevents 0x0A bytes from being silently translated to \r\n. */ #define COMPAT_O_RDONLY (O_RDONLY | O_BINARY) -/* --- posix_fadvise: no-op (advisory only; safe to ignore) --- */ +/* --- posix_fadvise: Windows has no direct equivalent. Semantics: + * WILLNEED -> warm the OS page cache so a later synchronous pread finds the + * pages resident. Implemented as an overlapped background ReadFile + * into a throwaway scratch buffer (fire-and-forget readahead). Called + * from the dedicated PILOT I/O thread / next-block readahead in moe(), + * NEVER inline on the hot path (the existing comment at glm.c:2847 + * measures inline fadvise submit at ~0.5ms x 169k calls = +92s/48tok). + * Each call owns its OVERLAPPED + scratch buffer -> thread-safe. + * DONTNEED -> no-op: Windows' standby-list trimming self-regulates under pressure, + * and on a low-RAM host keeping the pages is what we want for reuse. + * Matches macOS (compat.h:16-19) which no-ops DONTNEED for the same + * reason. The engine only ever uses DONTNEED as an advisory. */ #ifndef POSIX_FADV_NORMAL #define POSIX_FADV_NORMAL 0 #define POSIX_FADV_RANDOM 1 @@ -104,7 +115,29 @@ static inline int compat_open_direct(const char *path){ #define POSIX_FADV_DONTNEED 4 #define POSIX_FADV_NOREUSE 5 #endif -#define posix_fadvise(fd,off,len,advice) do{(void)(fd);(void)(off);(void)(len);(void)(advice);}while(0) +static inline int compat_fadvise(int fd, off_t off, off_t len, int advice){ + if(advice!=POSIX_FADV_WILLNEED || len<=0) return 0; + intptr_t osfh=_get_osfhandle(fd); + if(osfh==-1 || osfh==-2) return 0; + HANDLE h=(HANDLE)osfh; + /* Cap the readahead window: reading a whole 19MB expert per hint is fine on the + * PILOT thread, but a pathological huge len would spike transient memory. */ + size_t rdlen = (len>(off_t)(64*1024*1024)) ? (size_t)(64*1024*1024) : (size_t)len; + char *buf=(char*)_aligned_malloc(rdlen, 4096); + if(!buf) return -1; + OVERLAPPED ov={0}; + ov.Offset = (DWORD)( (off_t)off & 0xFFFFFFFFULL); + ov.OffsetHigh = (DWORD)(((off_t)off >> 32) & 0xFFFFFFFFULL); + /* Issue an overlapped read. With a non-OVERLAPPED-opened handle ReadFile still + * accepts lpOverlapped (it carries the 64-bit offset) and blocks until the read + * completes — but crucially it populates the standby page cache for this region, + * so the later synchronous pread on the same offsets faults from RAM not disk. */ + DWORD got=0; + ReadFile(h, buf, (DWORD)rdlen, &got, &ov); + _aligned_free(buf); + return 0; +} +#define posix_fadvise compat_fadvise /* --- pread -> ReadFile + OVERLAPPED su raw OS handle --- * Thread-safe (no shared seek position). Gestisce offset >4 GB e chunking diff --git a/c/glm.c b/c/glm.c index 81eb98f..4f33b0c 100644 --- a/c/glm.c +++ b/c/glm.c @@ -1622,7 +1622,10 @@ static int expert_load(Model *m, int layer, int eid, ESlot *s, int fatal){ * condvar exist ONLY to park/wake idle workers, never for correctness. Gated * behind PIPE=1; OFF => the original blocking-load + serial-matmul path runs * byte-identically. */ -static int g_pipe=0; /* PIPE=1: async expert-load pipeline (default OFF) */ +static int g_pipe=0; /* PIPE=1: async expert-load pipeline. Default ON for Windows + * (parsed in main: getenv("PIPE")?:1 on _WIN32, :0 elsewhere). + * Keeps expert pread off the forward-pass thread so loads overlap + * the matmul. PIPE=0 opts back into the blocking serial path. */ static int g_pipe_nw=8; /* PIPE_WORKERS=n: I/O worker threads (disk-parallel reads) */ typedef struct { _Atomic uint64_t cur; /* (gen<<8)|index; gen main-only, index 0..njobs (≤64) */ @@ -5078,7 +5081,13 @@ int main(int argc, char **argv){ g_pilot_k = getenv("PILOT_K")?atoi(getenv("PILOT_K")):(g_pilot_real?6:8); if(g_pilot_k<1) g_pilot_k=1; g_disk_split = getenv("DISK_SPLIT")?atoi(getenv("DISK_SPLIT")):0; /* 1 = split dei disk load nelle stats */ - g_pipe = getenv("PIPE")?atoi(getenv("PIPE")):0; /* default OFF: overlap expert load ‖ matmul (byte-identical; reorders I/O). PIPE=1 opts in */ + g_pipe = getenv("PIPE")?atoi(getenv("PIPE")): +#ifdef _WIN32 + 1 /* default ON: overlap expert load ‖ matmul (byte-identical; reorders I/O). PIPE=0 opts out */ +#else + 0 +#endif + ; g_pipe_nw = getenv("PIPE_WORKERS")?atoi(getenv("PIPE_WORKERS")):8; /* I/O worker threads */ if(g_pipe_nw<1) g_pipe_nw=1; g_direct = getenv("DIRECT")?atoi(getenv("DIRECT")):0; diff --git a/c/tests/test_compat_direct.c b/c/tests/test_compat_direct.c index 9b49930..ca9c7b4 100644 --- a/c/tests/test_compat_direct.c +++ b/c/tests/test_compat_direct.c @@ -51,6 +51,23 @@ int main(void){ if(compat_open_direct("no_such_file.tmp")>=0) return fail("open missing file must fail"); if(compat_fsize(-1)>=0) return fail("compat_fsize on bad fd must be negative"); + /* compat_fadvise: WILLNEED warms the page cache (background read into throwaway + * buffer), DONTNEED is a documented no-op. After a WILLNEED the buffered fd's + * subsequent pread must still return the exact bytes — the cache-warmer must not + * corrupt data. Bad fd / non-WILLNEED advice must be safe no-ops (return 0). */ + int wfd = open(TMPF, COMPAT_O_RDONLY); + if(wfd<0) return fail("open buffered for fadvise"); + if(posix_fadvise(wfd, 0, (off_t)FSZ, POSIX_FADV_WILLNEED)!=0) return fail("WILLNEED returned nonzero"); + if(posix_fadvise(wfd, 0, (off_t)FSZ, POSIX_FADV_DONTNEED)!=0) return fail("DONTNEED should be a safe no-op (return 0)"); + if(posix_fadvise(-1, 0, (off_t)FSZ, POSIX_FADV_WILLNEED)!=0) return fail("WILLNEED on bad fd should no-op (return 0)"); + if(posix_fadvise(wfd, 0, 0, POSIX_FADV_WILLNEED)!=0) return fail("WILLNEED with len<=0 should no-op"); + /* verify data integrity through the buffered fd after the cache-warmer ran */ + uint8_t *verify=malloc(FSZ); + if(pread(wfd, verify, FSZ, 0)!=(ssize_t)FSZ) return fail("fadvise: pread size"); + if(memcmp(verify, pat, FSZ)!=0) return fail("fadvise: data corrupted by cache-warmer"); + free(verify); + close(wfd); + close(dfd); compat_aligned_free(buf); free(pat); remove(TMPF); puts("compat direct tests: ok"); diff --git a/issue_diskio.md b/issue_diskio.md index 786c4ad..e9403ec 100644 --- a/issue_diskio.md +++ b/issue_diskio.md @@ -126,3 +126,117 @@ Opportunity 3 (Windows prefetch) is the biggest single win but also the largest - [Microsoft Learn — PrefetchVirtualMemory](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-prefetchvirtualmemory) - [What makes system calls expensive — codingconfessions.com](https://blog.codingconfessions.com/p/what-makes-system-calls-expensive) - [Syscall overhead — Stack Overflow](https://stackoverflow.com/questions/8247331/syscall-overhead) + +--- + +# Windows Implementation — branch `windows-optimizations` (2026-07-15) + +## What landed (pread path, validated) + +Two changes, both on the `pread` expert-load path (no mmap). Measured against the +existing `bench_budget*.txt` baselines (GLM-5.2 744B int4, 32 GB RAM, Core Ultra 9 +185H, DRAFT=0, 32-token decode): + +### 1. `compat_fadvise` WILLNEED cache-warmer (`c/compat.h`) + +Replaced the Windows `posix_fadvise` no-op (was a `do{}while(0)` macro) with a real +readahead: an overlapped `ReadFile` into a throwaway scratch buffer that populates the +standby page cache, so the later synchronous `pread` faults from RAM not disk. Mirrors +the macOS `F_RDADVISE` shim (`compat.h:28-37`). DONTNEED stays a no-op (matches macOS; +Windows standby-list trimming self-regulates under pressure). + +This re-arms the existing `expert_prefetch` → `st_prefetch` → `posix_fadvise(WILLNEED)` +chain on Windows: the next-block readahead in `moe()` and the PILOT cross-layer prefetch +hints now actually warm the cache instead of being silently discarded. + +**Measured effect (budget=4, PIPE on):** hit rate 16.4% → 27.6%. + +### 2. PIPE default ON for Windows (`c/glm.c`) + +Flipped the async expert-load thread pool from default OFF to default ON on Windows +(`getenv("PIPE")?:1` under `_WIN32`, unchanged `:0` elsewhere). PIPE dispatches expert +`pread` loads onto worker threads so they overlap the expert matmul on the forward-pass +thread, instead of the blocking serial load-then-compute path. `PIPE=0` opts back out. + +**Measured effect (budget=4):** expert-disk 65.9s → 54.3s (−18%), reaching **1.70 s/tok** +(under the 2 s/tok target; budget=4 baseline was 2.06 s/tok). + +### Results table (DRAFT=0, 32-token decode, pread path) + +| config | expert-disk | s/tok | hit% | tok/s | +|---|---|---|---|---| +| budget=4, no PIPE (existing baseline) | 65.9s | 2.06 | 16.4% | 0.33 | +| **budget=4 + PIPE (this PR)** | **54.3s** | **1.70** | **27.6%** | **0.34** | +| budget=6 + PIPE | 77.1s | 2.41 | 21.8% | 0.27 | + +budget=4 + PIPE meets the ≤2 s/tok target. budget=6 (more experts/layer, higher quality) +misses it at 2.41 s/tok — the speed/quality tradeoff. + +## What was tried and abandoned: Windows mmap (`COLI_MMAP` on `_WIN32`) + +The original plan (informed by llama.cpp #18758: "mmap is ≥10× faster than O_DIRECT for +MoE") was to port the mmap expert path to Windows via `CreateFileMapping`/`MapViewOfFile`. +This was implemented and tested at length. **It was a measured regression and was reverted.** + +### The attempt + +Added a `_WIN32` branch to `map_of_fd` (`glm.c`) mapping each shard file read-only and +resolving experts as views into the mapping, mirroring the POSIX path. Also added +`PrefetchVirtualMemory` readahead and a `VirtualUnlock` eviction mechanism (the Windows +`posix_fadvise(DONTNEED)` analog — see SO#1880714; validated standalone to demote pages +to the standby list with a 2.3× faster re-fault). + +### Why it regressed + +**mmap'd expert pages bloat the process working set on Windows, which collapses the +expert cache.** This is a fundamental Windows-vs-Linux difference: + +- On Linux, `mmap(MAP_SHARED)` file pages live in the kernel page cache (`buff/cache`), + separate from `MemAvailable`, so the cache budget isn't fooled. +- On Windows, touched `MapViewOfFile` pages count against `ullAvailPhys` (what + `compat_meminfo` reads for the budget). The CPU matmul touches every weight byte, + faulting ~12 GB into the working set. `cap_for_ram()` then sees ~no free RAM and + collapses the LRU cache cap. + +Measured (budget=0, DRAFT=0, apples-to-apples): + +| config | RAM_GB detected | cache cap | hit% | expert-disk | RSS | +|---|---|---|---|---|---| +| baseline (pread) | 21.4 | 1 | 9.3% | 133s | 15.0 GB | +| mmap, no eviction | **8.0** | 1 | **2.2%** | **240s** | **27.2 GB** | +| mmap + VirtualUnlock | 24.9 | 2 | 11.8% | 83s | 18.1 GB | +| mmap + reserve reductions | 24.6 | 4 | 21.8% | 80s | 20.1 GB | + +The `VirtualUnlock` eviction recovered the regression (240s→83s), and dropping the +Linux-specific page-cache/slab reserves under mmap got it to parity with pread. But it +never clearly *beat* the simpler pread+PIPE path, and it added substantial complexity +(per-slot eviction tracking, reserve conditionals, `VirtualUnlock` on every slot recycle). +**The engine already moved off mmap to pread for this exact RSS bug** (`st.h:3-6`), and +the Windows port re-confirmed that decision. + +### What else didn't work + +- **Batched `PrefetchVirtualMemory`** for the mmap path: tested as a single batched + readahead of all 64 missed experts' pages before the matmul. **Blocked instead of + prefetching async** on this SSD — inflated `t_edisk` (80s→102s). Consistent with + microsoft/Windows-Dev-Performance#108 ("PrefetchVirtualMemory does not prefetch"). + Reverted. +- **True I/O/compute overlap on the CPU path**: the Metal path has this ("submit + resident experts to GPU before loading misses"), but the CPU path loads-then-computes + serially. `PrefetchVirtualMemory` was the attempt to add it for mmap and failed. The + pread path gets overlap via PIPE (which works), not via mmap prefetch. + +### Conclusion + +For this engine on Windows at this RAM budget (~32 GB, 370 GB model), **pread + PIPE + +compat_fadvise** is the right path. mmap remains valuable on Linux/macOS (where the page +cache doesn't inflate process RSS) but is not viable on Windows without a fundamentally +different cache-budget model that excludes mapped-file pages — left as future work. + +## Sources added + +- [SO#1880714 — VirtualUnlock releases mapped pages to standby list](https://stackoverflow.com/questions/1880714/createfilemapping-mapviewoffile-how-to-avoid-holding-up-the-system-memory) +- [Alois Kraus — The Mysterious Lost Memory (modified/standby list)](https://aloiskraus.wordpress.com/2017/02/26/the-mysterious-lost-memory-which-belongs-to-no-process/) +- [microsoft/Windows-Dev-Performance#108 — PrefetchVirtualMemory inconsistency](https://github.com/microsoft/Windows-Dev-Performance/issues/108) +- [llama.cpp #18758 — mmap faster than O_DIRECT for MoE (Linux)](https://github.com/ggml-org/llama.cpp/discussions/18758) +- [HN#35426679 — Why MMAP in llama.cpp hides true memory usage](https://news.ycombinator.com/item?id=35426679) From 5d1eb142ab1fabab3676402cc2c1b3dbe6cb795f Mon Sep 17 00:00:00 2001 From: Robert Landers Date: Wed, 15 Jul 2026 03:54:25 +0200 Subject: [PATCH 46/79] port uring implementation Signed-off-by: Robert Landers --- README.md | 2 +- c/Makefile | 13 +- c/glm.c | 330 +++++++++++++++++++++++++++++++++++++++++-- c/tests/test_uring.c | 114 +++++++++++++++ c/uring.h | 126 +++++++++++++++++ docs/ENVIRONMENT.md | 1 + 6 files changed, 568 insertions(+), 18 deletions(-) create mode 100644 c/tests/test_uring.c create mode 100644 c/uring.h diff --git a/README.md b/README.md index 86c3009..e34508c 100644 --- a/README.md +++ b/README.md @@ -468,7 +468,7 @@ works against the colibrì OpenAI-compatible server (in review, #21) or any othe compatible endpoint. Nothing leaves the endpoint you configure. The terminal `coli chat` remains the first-class interface. -Useful knobs (env or flags): `--temp T` token sampling temperature (default 0.7 + nucleus 0.90 — tuned for int4; 0 = greedy), `--topp 0.7` adaptive expert top-p (30–40% less disk), `--ngen N` max tokens per answer (`:more` in chat continues a truncated one), `--repin N` adapt RAM/VRAM hot experts every N emitted tokens, `AUTOPIN=0` disable the learning cache's auto-pin, `THINK=1` enable GLM-5.2's reasoning block, `DRAFT=n` MTP draft depth, `GRAMMAR=g.gbnf` grammar-forced drafts for constrained JSON/NDJSON output (`GRAMMAR_DRAFT=n` caps the forced span), `TF=1` teacher-forcing validation, `PILOT=1` router-lookahead disk prefetch (experimental — see below), `CAP_RAISE=0` don't auto-grow the expert cache. +Useful knobs (env or flags): `--temp T` token sampling temperature (default 0.7 + nucleus 0.90 — tuned for int4; 0 = greedy), `--topp 0.7` adaptive expert top-p (30–40% less disk), `--ngen N` max tokens per answer (`:more` in chat continues a truncated one), `--repin N` adapt RAM/VRAM hot experts every N emitted tokens, `AUTOPIN=0` disable the learning cache's auto-pin, `THINK=1` enable GLM-5.2's reasoning block, `DRAFT=n` MTP draft depth, `GRAMMAR=g.gbnf` grammar-forced drafts for constrained JSON/NDJSON output (`GRAMMAR_DRAFT=n` caps the forced span), `TF=1` teacher-forcing validation, `PILOT=1` router-lookahead disk prefetch (experimental — see below), `URING=1` Linux-only batched expert I/O (implies `PIPE=1`; also batches `PILOT_REAL`), `CAP_RAISE=0` don't auto-grow the expert cache. ### Resource policy diff --git a/c/Makefile b/c/Makefile index 5a53c24..f47f5f3 100644 --- a/c/Makefile +++ b/c/Makefile @@ -15,6 +15,7 @@ MINGW := $(findstring mingw,$(TRIPLET)) CYGWIN := $(findstring cygwin,$(TRIPLET)) DARWIN := $(findstring darwin,$(TRIPLET)) PPC64 := $(findstring powerpc64,$(TRIPLET)) +LINUX := $(findstring linux,$(TRIPLET)) IS_WIN := $(MINGW)$(CYGWIN) # Fallbacks for the rare toolchain that does not answer -dumpmachine: keep the @@ -148,6 +149,9 @@ PYTHON ?= python3 endif CUDA_OBJ = TEST_BINS = tests/test_json$(EXE) tests/test_st$(EXE) tests/test_tier$(EXE) tests/test_grammar$(EXE) tests/test_schema_gbnf$(EXE) tests/test_decode_batch$(EXE) tests/test_idot$(EXE) tests/test_kv_alloc$(EXE) tests/test_i4_acc512$(EXE) tests/test_compat_direct$(EXE) +ifneq (,$(LINUX)) +TEST_BINS += tests/test_uring$(EXE) +endif # Windows CUDA DLL path: host links the loader, NOT cudart. ifneq ($(IS_WIN),) @@ -190,7 +194,7 @@ all: glm$(EXE) # phony 'glm' → 'glm.exe' on Windows (so 'make glm' and 'coli build' work on every platform) glm: glm$(EXE) -glm$(EXE): glm.c st.h json.h tok.h tok_unicode.h compat.h grammar.h $(CUDA_OBJ) $(METAL_OBJ) +glm$(EXE): glm.c st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h $(CUDA_OBJ) $(METAL_OBJ) $(CC) $(CFLAGS) glm.c $(CUDA_OBJ) $(METAL_OBJ) -o glm$(EXE) $(LDFLAGS) # Windows runtime loader object: resolves coli_cuda_* from coli_cuda.dll. @@ -258,7 +262,7 @@ tests/test_schema_gbnf$(EXE): tests/test_schema_gbnf.c schema_gbnf.h grammar.h j tests/test_decode_batch$(EXE): tests/test_decode_batch.c decode_batch.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -tests/test_idot$(EXE): tests/test_idot.c glm.c st.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h +tests/test_idot$(EXE): tests/test_idot.c glm.c st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) tests/test_kv_alloc$(EXE): tests/test_kv_alloc.c glm.c st.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h @@ -270,6 +274,9 @@ tests/test_i4_acc512$(EXE): tests/test_i4_acc512.c tests/test_compat_direct$(EXE): tests/test_compat_direct.c compat.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) +tests/test_uring$(EXE): tests/test_uring.c glm.c st.h uring.h json.h tok.h tok_unicode.h compat.h grammar.h tier.h + $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) + test-c: $(TEST_BINS) $(PYTHON) tools/run_tests.py $(TEST_BINS) @@ -303,4 +310,4 @@ clean: bench: iobench$(EXE) @if [ -n "$(ARGS)" ]; then ./iobench$(EXE) $(ARGS); else echo "built iobench$(EXE) — run: ./iobench$(EXE) "; fi -.PHONY: all glm cuda-test cuda-bench cuda-dll portable test-c test-python test check clean install uninstall bench \ No newline at end of file +.PHONY: all glm cuda-test cuda-bench cuda-dll portable test-c test-python test check clean install uninstall bench diff --git a/c/glm.c b/c/glm.c index fb93e59..0237869 100644 --- a/c/glm.c +++ b/c/glm.c @@ -37,6 +37,9 @@ #include /* fstat per mmap degli shard (COLI_MMAP) */ #endif #include "st.h" +#ifdef __linux__ +#include "uring.h" +#endif #include "tok.h" #include "tier.h" #include "grammar.h" /* metodo F: draft grammaticali (#48) */ @@ -989,8 +992,9 @@ static int g_pilot_two=0; /* PILOT_TWO=1: two-step prefetch — before running L * niente torn read di ecn[]/eid. Il pilota non altera MAI il valore di un expert, solo QUALE * expert e' residente: con un load andato a buon fine l'output resta byte-identico all'OFF. */ static pthread_mutex_t g_pilot_mx=PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t g_pilot_cv=PTHREAD_COND_INITIALIZER; static _Atomic int g_cur_moe_layer=-1; /* massimo layer moe in cui il MAIN e' entrato (per forward) */ -static _Atomic int g_pilot_inflight=-1; /* layer che il worker sta REAL-caricando adesso (-1 = idle) */ +static int g_pilot_inflight[256]; /* protected by g_pilot_mx; URING can load a layer concurrently */ static _Atomic long g_pilot_loads=0; /* load cross-layer VERI completati (banda spesa) */ static _Atomic long g_pilot_drops=0; /* predizioni scartate perche' il main possiede gia' il layer */ /* sceglie il formato da `bits`: >=16 f32, 5..8 int8, <=4 int4-packed */ @@ -1587,6 +1591,189 @@ static int expert_load(Model *m, int layer, int eid, ESlot *s, int fatal){ s->eid=eid; return 0; } +#ifdef __linux__ +/* io_uring expert batches. One owner prepares all reads for a block, submits + * them in one syscall, and reaps CQEs on demand. The kernel, rather than a set + * of blocking pthreads, owns the I/O concurrency. */ +#define URING_LOAD_MAX 64 +#define URING_REQ_MAX 512 +typedef struct { + int load, expect; +} UringRead; +typedef struct { + Model *m; ESlot *s; int layer,eid,fatal; + st_tensor *tw[3],*tq[3]; int64_t pos[3]; + int pending,done,finalized,error; +} UringLoad; +typedef struct { + ColiUring ring; + UringLoad load[URING_LOAD_MAX]; + UringRead req[URING_REQ_MAX]; + int nload,nreq,started; +} UringBatch; +static UringBatch g_ub_pipe, g_ub_pilot; + +static int uring_batch_init(UringBatch *b){ + if(b->started) return 0; + if(coli_uring_init(&b->ring,URING_REQ_MAX)) return -1; + b->started=1; return 0; +} +static void uring_batch_reset(UringBatch *b){ + b->nload=0; b->nreq=0; +} +static int uring_load_error(UringLoad *l,int err,const char *what){ + l->error=err?err:EIO; l->done=1; + if(l->fatal){ errno=l->error; perror(what); exit(1); } + return -1; +} +static int uring_add_read(UringBatch *b,int li,int fd,void *buf,size_t len, + int64_t off,size_t expect){ + if(b->nreq>=URING_REQ_MAX || expect>INT_MAX){ errno=E2BIG; return -1; } + int ri=b->nreq++; + b->req[ri]=(UringRead){li,(int)expect}; + if(coli_uring_prep_read(&b->ring,fd,buf,len,off,(uint64_t)ri+1)) return -1; + b->load[li].pending++; + return 0; +} +/* Returns the load index. URING is intentionally a quantized streaming path; + * unsupported layouts fail instead of silently dropping back to pread. */ +static int uring_load_add(UringBatch *b,Model *m,int layer,int eid,ESlot *s,int fatal){ + if(b->nload>=URING_LOAD_MAX){ errno=E2BIG; return -1; } + int li=b->nload++; + UringLoad *l=&b->load[li]; memset(l,0,sizeof(*l)); + l->m=m; l->s=s; l->layer=layer; l->eid=eid; l->fatal=fatal; + char nm[3][288],qn[300]; const char *suf[3]={"gate_proj","up_proj","down_proj"}; + for(int k=0;k<3;k++) snprintf(nm[k],sizeof(nm[k]),"model.layers.%d.mlp.experts.%d.%s.weight",layer,eid,suf[k]); + snprintf(qn,sizeof(qn),"%s.qs",nm[0]); + if(g_mmap || !st_has(&m->S,qn)) + return uring_load_error(l,ENOTSUP,"URING requires quantized expert tensors"),li; +#ifdef COLI_CUDA + if(s->eid!=eid){ qt_cuda_reset(&s->g); qt_cuda_reset(&s->u); qt_cuda_reset(&s->d); } +#endif + for(int k=0;k<3;k++){ + l->tw[k]=st_find(&m->S,nm[k]); + size_t n=strnlen(nm[k],sizeof(nm[k])); + if(n+3>=sizeof(qn)) return uring_load_error(l,ENAMETOOLONG,"io_uring expert metadata"),li; + memcpy(qn,nm[k],n); memcpy(qn+n,".qs",4); l->tq[k]=st_find(&m->S,qn); + if(!l->tw[k]||!l->tq[k]) return uring_load_error(l,ENOENT,"io_uring expert metadata"),li; + } + int64_t wtot=l->tw[0]->nbytes+l->tw[1]->nbytes+l->tw[2]->nbytes; + int64_t ftot=(l->tq[0]->nbytes+l->tq[1]->nbytes+l->tq[2]->nbytes)/4; + if(wtot<=0 || ftot<=0) return uring_load_error(l,EINVAL,"io_uring expert size"),li; + if(!s->slab || wtot+8192>s->slab_cap){ +#ifdef COLI_METAL + if(s->slab&&g_metal_enabled) coli_metal_unregister(s->slab); + compat_aligned_free(s->slab); + size_t need=((size_t)wtot+8192+16383)&~(size_t)16383; + if(posix_memalign((void**)&s->slab,16384,need)){ + s->slab=NULL; s->slab_cap=0; return uring_load_error(l,ENOMEM,"io_uring expert slab"),li; } + s->slab_cap=need; if(g_metal_enabled) coli_metal_register(s->slab,need); +#else + compat_aligned_free(s->slab); + if(posix_memalign((void**)&s->slab,4096,(size_t)wtot+8192)){ + s->slab=NULL; s->slab_cap=0; return uring_load_error(l,ENOMEM,"io_uring expert slab"),li; } + s->slab_cap=wtot+8192; +#endif + } + if(!s->fslab || ftot>s->fslab_cap){ +#ifdef COLI_METAL + if(s->fslab&&g_metal_enabled) coli_metal_unregister(s->fslab); + free(s->fslab); size_t fb=(((size_t)ftot*sizeof(float))+16383)&~(size_t)16383; + if(posix_memalign((void**)&s->fslab,16384,fb)){ + s->fslab=NULL; s->fslab_cap=0; return uring_load_error(l,ENOMEM,"io_uring expert scales"),li; } + s->fslab_cap=ftot; if(g_metal_enabled) coli_metal_register(s->fslab,fb); +#else + free(s->fslab); s->fslab=malloc((size_t)ftot*sizeof(float)); + if(!s->fslab){ s->fslab_cap=0; return uring_load_error(l,ENOMEM,"io_uring expert scales"),li; } + s->fslab_cap=ftot; +#endif + } + int ord[3]={0,1,2}; + for(int a=0;a<3;a++) for(int z=a+1;z<3;z++) if(l->tw[ord[z]]->offtw[ord[a]]->off){int t=ord[a];ord[a]=ord[z];ord[z]=t;} + int contig=l->tw[ord[0]]->fd==l->tw[ord[1]]->fd && l->tw[ord[1]]->fd==l->tw[ord[2]]->fd + && l->tw[ord[0]]->off+l->tw[ord[0]]->nbytes==l->tw[ord[1]]->off + && l->tw[ord[1]]->off+l->tw[ord[1]]->nbytes==l->tw[ord[2]]->off; + if(contig){ + int64_t off0=l->tw[ord[0]]->off; + int dfd=g_direct?st_direct_fd(&m->S,l->tw[ord[0]]->fd):-1; + if(dfd>=0){ + int64_t base=off0&~4095LL,need=(off0-base)+wtot,len=(need+4095)&~4095LL; + l->pos[ord[0]]=off0-base; l->pos[ord[1]]=l->pos[ord[0]]+l->tw[ord[0]]->nbytes; + l->pos[ord[2]]=l->pos[ord[1]]+l->tw[ord[1]]->nbytes; + if(uring_add_read(b,li,dfd,s->slab,(size_t)len,base,(size_t)need)) + return uring_load_error(l,errno,"io_uring direct expert read"),li; + }else{ + l->pos[ord[0]]=0; l->pos[ord[1]]=l->tw[ord[0]]->nbytes; + l->pos[ord[2]]=l->pos[ord[1]]+l->tw[ord[1]]->nbytes; + if(uring_add_read(b,li,l->tw[ord[0]]->fd,s->slab,(size_t)wtot,off0,(size_t)wtot)) + return uring_load_error(l,errno,"io_uring expert read"),li; + } + }else{ + int64_t o=0; + for(int a=0;a<3;a++){ int k=ord[a]; l->pos[k]=o; + if(uring_add_read(b,li,l->tw[k]->fd,s->slab+o,(size_t)l->tw[k]->nbytes,l->tw[k]->off,(size_t)l->tw[k]->nbytes)) + return uring_load_error(l,errno,"io_uring expert read"),li; + o+=l->tw[k]->nbytes; + } + } + int64_t fo=0; + for(int k=0;k<3;k++){ + if(uring_add_read(b,li,l->tq[k]->fd,s->fslab+fo,(size_t)l->tq[k]->nbytes,l->tq[k]->off,(size_t)l->tq[k]->nbytes)) + return uring_load_error(l,errno,"io_uring expert scale read"),li; + fo+=l->tq[k]->nbytes/4; + } + return li; +} +static void uring_reap(UringBatch *b){ + struct io_uring_cqe cqe; + while(coli_uring_peek(&b->ring,&cqe)){ + if(!cqe.user_data || cqe.user_data>(uint64_t)b->nreq) continue; + UringRead *r=&b->req[cqe.user_data-1]; UringLoad *l=&b->load[r->load]; + if(cqe.resexpect && !l->error) l->error=cqe.res<0?-cqe.res:EIO; + if(l->pending>0) l->pending--; + if(l->pending==0) l->done=1; + } +} +static int uring_submit_batch(UringBatch *b){ + if(coli_uring_enter(&b->ring,0)<0) return -1; + uring_reap(b); return 0; +} +static int uring_wait_load(UringBatch *b,int li){ + UringLoad *l=&b->load[li]; + while(!l->done){ + uring_reap(b); if(l->done) break; + if(coli_uring_enter(&b->ring,1)<0) return uring_load_error(l,errno,"io_uring wait"); + } + return l->error?-1:0; +} +static int uring_finalize_load(UringBatch *b,int li,int publish_eid){ + UringLoad *l=&b->load[li]; ESlot *s=l->s; + if(l->finalized) return 0; + if(uring_wait_load(b,li)<0){ errno=l->error; if(l->fatal){perror("io_uring expert completion");exit(1);} return -1; } + if(g_drop){ + int ord0=0; for(int k=1;k<3;k++) if(l->tw[k]->offtw[ord0]->off) ord0=k; + int64_t wtot=l->tw[0]->nbytes+l->tw[1]->nbytes+l->tw[2]->nbytes; + posix_fadvise(l->tw[ord0]->fd,l->tw[ord0]->off,wtot,POSIX_FADV_DONTNEED); + for(int k=0;k<3;k++) posix_fadvise(l->tq[k]->fd,l->tq[k]->off,l->tq[k]->nbytes,POSIX_FADV_DONTNEED); + } + Cfg *c=&l->m->c; int I=c->moe_inter,D=c->hidden; float *fp[3]; int64_t fo=0; + QT *qt[3]={&s->g,&s->u,&s->d}; int OO[3]={I,I,D},II[3]={D,D,I}; + for(int k=0;k<3;k++){ + fp[k]=s->fslab+fo; fo+=l->tq[k]->nbytes/4; + int64_t nb=l->tw[k]->nbytes; + int fmt=(nb==(int64_t)OO[k]*II[k])?1:(nb==(int64_t)OO[k]*((II[k]+1)/2))?2:3; + qt[k]->fmt=fmt; qt[k]->O=OO[k]; qt[k]->I=II[k]; qt[k]->qf=NULL; + qt[k]->q8=(int8_t*)(s->slab+l->pos[k]); qt[k]->q4=s->slab+l->pos[k]; qt[k]->s=fp[k]; + } + if(publish_eid) s->eid=l->eid; + l->finalized=1; return 0; +} +static int uring_wait_all(UringBatch *b){ + for(int i=0;inload;i++) if(uring_wait_load(b,i)<0) return -1; + return 0; +} +#endif + /* ============================ PIPE: load ‖ matmul ============================ * Overlap NVMe expert-weight loads with expert matmul. A small persistent pool * of I/O worker pthreads runs the misses' pread (expert_load) into distinct @@ -1616,6 +1803,7 @@ static int expert_load(Model *m, int layer, int eid, ESlot *s, int fatal){ * byte-identically. */ static int g_pipe=0; /* PIPE=1: async expert-load pipeline (default OFF) */ static int g_pipe_nw=8; /* PIPE_WORKERS=n: I/O worker threads (disk-parallel reads) */ +static int g_uring=0; /* URING=1: Linux io_uring load/completion backend; implies PIPE */ typedef struct { _Atomic uint64_t cur; /* (gen<<8)|index; gen main-only, index 0..njobs (≤64) */ _Atomic int njobs; /* current batch job count */ @@ -1655,6 +1843,12 @@ static void *pipe_worker(void *arg){ } static void pipe_init(Model *m){ if(g_pp.started) return; +#ifdef __linux__ + if(g_uring){ + if(uring_batch_init(&g_ub_pipe)){ perror("URING=1 io_uring_setup"); exit(1); } + g_pp.m=m; g_pp.started=1; return; + } +#endif g_pp.m=m; g_pp.nw=g_pipe_nw; if(g_pp.nw>16) g_pp.nw=16; if(g_pp.nw<1) g_pp.nw=1; atomic_store(&g_pp.cur,0); atomic_store(&g_pp.njobs,0); pthread_mutex_init(&g_pp.mx,NULL); pthread_cond_init(&g_pp.cv,NULL); @@ -1665,6 +1859,17 @@ static void pipe_init(Model *m){ * Order is load-bearing: write all batch state RELAXED, then RELEASE-store cur to * publish it, then wake parked workers. */ static void pipe_dispatch(Model *m,int layer,const int *eids,int njobs){ +#ifdef __linux__ + if(g_uring){ + uring_batch_reset(&g_ub_pipe); + for(int q=0;qws[q],1); + if(li!=q){ fprintf(stderr,"URING: expert batch overflow\n"); exit(1); } + } + if(uring_submit_batch(&g_ub_pipe)){ perror("URING: submit"); exit(1); } + return; + } +#endif g_pp.m=m; atomic_store_explicit(&g_pp.njobs,njobs,memory_order_relaxed); atomic_store_explicit(&g_pp.layer,layer,memory_order_relaxed); @@ -1675,6 +1880,12 @@ static void pipe_dispatch(Model *m,int layer,const int *eids,int njobs){ pthread_mutex_lock(&g_pp.mx); pthread_cond_broadcast(&g_pp.cv); pthread_mutex_unlock(&g_pp.mx); } static inline void pipe_wait(int q){ +#ifdef __linux__ + if(g_uring){ + if(uring_finalize_load(&g_ub_pipe,q,1)){ perror("URING: expert load"); exit(1); } + return; + } +#endif while(!atomic_load_explicit(&g_pp.ready[q],memory_order_acquire)) sched_yield(); } @@ -2217,14 +2428,11 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out, int * l'eventuale load-pilota in volo sullo stesso layer (dopodiche' il * worker droppa ogni nuovo load <= layer -> ecache[layer] e' stabile * per tutto il resolve/matmul/promozione qui sotto). */ - for(;;){ - pthread_mutex_lock(&g_pilot_mx); - atomic_store_explicit(&g_cur_moe_layer,layer,memory_order_release); - int inf=atomic_load_explicit(&g_pilot_inflight,memory_order_acquire); - pthread_mutex_unlock(&g_pilot_mx); - if(inf!=layer) break; - sched_yield(); - } + pthread_mutex_lock(&g_pilot_mx); + atomic_store_explicit(&g_cur_moe_layer,layer,memory_order_release); + while(layer>=0 && layer<256 && g_pilot_inflight[layer]>0) + pthread_cond_wait(&g_pilot_cv,&g_pilot_mx); + pthread_mutex_unlock(&g_pilot_mx); } Cfg *c=&m->c; int D=c->hidden, E=c->n_experts, K=c->topk, I=c->moe_inter; float *choice=falloc(E); @@ -2800,7 +3008,7 @@ static void pilot_realload(Model *m, int layer, int eid){ else { int lru=0; for(int z=1;zeid=-1; /* nascondi dagli scan-hint mentre carica */ - atomic_store_explicit(&g_pilot_inflight,layer,memory_order_release); + g_pilot_inflight[layer]++; pthread_mutex_unlock(&g_pilot_mx); int rc=expert_load(m,layer,eid,dst,0); /* pread VERO — fuori dal lock, sovrapposto al compute; fatal=0: un errore su una speculazione NON deve uccidere il server */ @@ -2813,18 +3021,96 @@ static void pilot_realload(Model *m, int layer, int eid){ } else { atomic_fetch_add_explicit(&g_pilot_drops,1,memory_order_relaxed); /* load fallito: slot resta nascosto (eid=-1), mai pubblicato */ } - atomic_store_explicit(&g_pilot_inflight,-1,memory_order_release); + g_pilot_inflight[layer]--; + pthread_cond_broadcast(&g_pilot_cv); pthread_mutex_unlock(&g_pilot_mx); if(rc!=0) /* mai swallow silenzioso: logga (una riga) e prosegui */ fprintf(stderr,"[PILOT] load speculativo abbandonato: layer %d expert %d (I/O error/short read) — nessun impatto sull'output\n",layer,eid); } +#ifdef __linux__ +typedef struct { int layer,eid,li; ESlot *dst; } PilotUringDone; +static void pilot_uring_batch(Model *m){ + PilotUringDone done[URING_LOAD_MAX]; int nd=0; + uring_batch_reset(&g_ub_pilot); + unsigned r=__atomic_load_n(&pilot_r,__ATOMIC_ACQUIRE); + unsigned w=__atomic_load_n(&pilot_w,__ATOMIC_ACQUIRE); + while(r!=w && nd=256){ atomic_fetch_add_explicit(&g_pilot_drops,1,memory_order_relaxed); continue; } + pthread_mutex_lock(&g_pilot_mx); + if(layer<=atomic_load_explicit(&g_cur_moe_layer,memory_order_acquire)){ + atomic_fetch_add_explicit(&g_pilot_drops,1,memory_order_relaxed); + pthread_mutex_unlock(&g_pilot_mx); continue; + } + int found=0; ESlot *P=m->pin[layer]; + for(int z=0;znpin[layer];z++) if(P[z].eid==eid){found=1;break;} + ESlot *Sl=m->ecache[layer]; int nn=m->ecn[layer]; + for(int z=0;zecap){ slot=nn; m->ecn[layer]=nn+1; } + else{ + slot=-1; + for(int z=0;zeid=-(eid+2); /* visible reservation; never considered resident/evictable */ + g_pilot_inflight[layer]++; + pthread_mutex_unlock(&g_pilot_mx); + + int li=uring_load_add(&g_ub_pilot,m,layer,eid,dst,0); + if(li<0){ + pthread_mutex_lock(&g_pilot_mx); dst->eid=-1; g_pilot_inflight[layer]--; + pthread_cond_broadcast(&g_pilot_cv); pthread_mutex_unlock(&g_pilot_mx); + atomic_fetch_add_explicit(&g_pilot_drops,1,memory_order_relaxed); continue; + } + done[nd++]=(PilotUringDone){layer,eid,li,dst}; + } + __atomic_store_n(&pilot_r,r,__ATOMIC_RELEASE); + if(!nd) return; + if(uring_submit_batch(&g_ub_pilot)<0){ + int err=errno; + for(int i=0;ili,0); + pthread_mutex_lock(&g_pilot_mx); + if(rc==0){ + d->dst->eid=d->eid; + d->dst->used=(uint64_t)__atomic_add_fetch(&m->eclock,1,__ATOMIC_RELAXED); + atomic_fetch_add_explicit(&g_pilot_loads,1,memory_order_relaxed); + }else{ + d->dst->eid=-1; + atomic_fetch_add_explicit(&g_pilot_drops,1,memory_order_relaxed); + } + g_pilot_inflight[d->layer]--; + pthread_cond_broadcast(&g_pilot_cv); + pthread_mutex_unlock(&g_pilot_mx); + if(rc) fprintf(stderr,"[PILOT/URING] load speculativo abbandonato: layer %d expert %d: %s\n", + d->layer,d->eid,strerror(g_ub_pilot.load[d->li].error)); + } +} +#endif static void *pilot_worker(void *arg){ (void)arg; for(;;){ unsigned r=__atomic_load_n(&pilot_r,__ATOMIC_ACQUIRE); unsigned w=__atomic_load_n(&pilot_w,__ATOMIC_ACQUIRE); if(r==w){ usleep(200); continue; } - if(g_pilot_real) pilot_realload(pilot_m, pilot_q[r&4095].l, pilot_q[r&4095].e); + if(g_pilot_real){ +#ifdef __linux__ + if(g_uring){ pilot_uring_batch(pilot_m); continue; } +#endif + pilot_realload(pilot_m, pilot_q[r&4095].l, pilot_q[r&4095].e); + } else expert_prefetch(pilot_m, pilot_q[r&4095].l, pilot_q[r&4095].e); __atomic_store_n(&pilot_r,r+1,__ATOMIC_RELEASE); } @@ -2888,7 +3174,8 @@ static void couple_prefetch(Model *m, int layer, const int *idx, int Ke){ ESlot *P=m->pin[lt]; for(int z=0;znpin[lt] && !found;z++) if(P[z].eid==best) found=1; ESlot *Sl=m->ecache[lt]; - for(int z=0;zecn[lt] && !found;z++) if(Sl[z].eid==best) found=1; + for(int z=0;zecn[lt] && !found;z++) + if(Sl[z].eid==best || Sl[z].eid==-(best+2)) found=1; pthread_mutex_unlock(&g_pilot_mx); if(!found){ unsigned w=__atomic_load_n(&pilot_w,__ATOMIC_RELAXED); @@ -2949,7 +3236,8 @@ static void pilot_prefetch(Model *m, int lnext, const float *x, int S){ ESlot *P=m->pin[lnext]; for(int z=0;znpin[lnext] && !found;z++) if(P[z].eid==best) found=1; ESlot *Sl=m->ecache[lnext]; - for(int z=0;zecn[lnext] && !found;z++) if(Sl[z].eid==best) found=1; + for(int z=0;zecn[lnext] && !found;z++) + if(Sl[z].eid==best || Sl[z].eid==-(best+2)) found=1; pthread_mutex_unlock(&g_pilot_mx); if(!found){ unsigned w=__atomic_load_n(&pilot_w,__ATOMIC_RELAXED); @@ -4971,6 +5259,20 @@ int main(int argc, char **argv){ g_pipe = getenv("PIPE")?atoi(getenv("PIPE")):0; /* default OFF: overlap expert load ‖ matmul (byte-identical; reorders I/O). PIPE=1 opts in */ g_pipe_nw = getenv("PIPE_WORKERS")?atoi(getenv("PIPE_WORKERS")):8; /* I/O worker threads */ if(g_pipe_nw<1) g_pipe_nw=1; + g_uring = getenv("URING")?atoi(getenv("URING")):0; + if(g_uring){ +#ifdef __linux__ + if(g_mmap){ fprintf(stderr,"URING=1 is incompatible with COLI_MMAP=1\n"); return 2; } + g_pipe=1; + if(uring_batch_init(&g_ub_pipe) || (g_pilot_real&&uring_batch_init(&g_ub_pilot))){ + fprintf(stderr,"URING=1: io_uring_setup failed: %s\n",strerror(errno)); return 2; + } + fprintf(stderr,"[URING] queued expert I/O active (depth=%d%s)\n",URING_REQ_MAX, + g_pilot_real?", batched PILOT_REAL":""); +#else + fprintf(stderr,"URING=1 is supported only on Linux\n"); return 2; +#endif + } g_direct = getenv("DIRECT")?atoi(getenv("DIRECT")):0; g_idot = getenv("IDOT")?atoi(getenv("IDOT")):1; /* 0 = kernel f32 esatti (A/B) */ if(getenv("ROUTE_TRACE")&&*getenv("ROUTE_TRACE")){ diff --git a/c/tests/test_uring.c b/c/tests/test_uring.c new file mode 100644 index 0000000..9712f65 --- /dev/null +++ b/c/tests/test_uring.c @@ -0,0 +1,114 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#define main coli_glm_main_unused +#include "../glm.c" +#undef main + +static int fail(const char *s){ fprintf(stderr,"FAIL: %s\n",s); return 1; } + +static int test_expert_layout(int fd){ + Model m={0}; ESlot slot={0}; UringBatch batch={0}; + m.c.hidden=4; m.c.moe_inter=3; m.ebits=8; + m.S.n=6; m.S.cap=6; m.S.t=calloc(6,sizeof(st_tensor)); + if(!m.S.t) return fail("tensor metadata allocation"); + const char *proj[3]={"gate_proj","up_proj","down_proj"}; + int wbytes[3]={12,12,12}, sbytes[3]={12,12,16}; + unsigned char data[76]; + for(int i=0;i<36;i++) data[i]=(unsigned char)(i+1); + float scales[10]; for(int i=0;i<10;i++) scales[i]=(float)i+0.5f; + memcpy(data+36,scales,sizeof(scales)); + if(pwrite(fd,data,sizeof(data),0)!=(ssize_t)sizeof(data)){ free(m.S.t); return fail("expert fixture write"); } + int64_t wo=0,so=36; + for(int k=0;k<3;k++){ + char name[300]; + snprintf(name,sizeof(name),"model.layers.1.mlp.experts.7.%s.weight",proj[k]); + m.S.t[k]=(st_tensor){strdup(name),fd,wo,wbytes[k],3,wbytes[k]}; wo+=wbytes[k]; + size_t n=strlen(name); memcpy(name+n,".qs",4); + m.S.t[3+k]=(st_tensor){strdup(name),fd,so,sbytes[k],2,sbytes[k]/4}; so+=sbytes[k]; + } + if(uring_batch_init(&batch)){ free(m.S.t); return fail("expert ring init"); } + uring_batch_reset(&batch); + int li=uring_load_add(&batch,&m,1,7,&slot,1); + if(li!=0 || uring_submit_batch(&batch) || uring_finalize_load(&batch,li,1)){ + coli_uring_close(&batch.ring); free(m.S.t); return fail("expert batch load"); + } + int bad=slot.eid!=7 || slot.g.fmt!=1 || slot.u.fmt!=1 || slot.d.fmt!=1 + || memcmp(slot.g.q8,data,12) || memcmp(slot.u.q8,data+12,12) || memcmp(slot.d.q8,data+24,12) + || memcmp(slot.g.s,scales,12) || memcmp(slot.u.s,scales+3,12) || memcmp(slot.d.s,scales+6,16); + coli_uring_close(&batch.ring); + compat_aligned_free(slot.slab); free(slot.fslab); + if(bad){ for(int i=0;iN || cqe.res!=SZ){ + coli_uring_close(&ring); close(fd); return fail("bad completion"); + } + int i=(int)cqe.user_data-1; + if(seen[i]++){ coli_uring_close(&ring); close(fd); return fail("duplicate completion"); } + complete++; + } + if(!reaped && complete +#include +#include +#include +#include +#include +#include + +#ifndef MAP_POPULATE +#define MAP_POPULATE 0 +#endif + +typedef struct { + int fd; + struct io_uring_params p; + void *sq_map, *cq_map, *sqes_map; + size_t sq_map_sz, cq_map_sz, sqes_map_sz; + unsigned *sq_head, *sq_tail, *sq_mask, *sq_entries, *sq_array; + unsigned *cq_head, *cq_tail, *cq_mask, *cq_entries; + struct io_uring_sqe *sqes; + struct io_uring_cqe *cqes; +} ColiUring; + +static inline unsigned coli_uring_load_acquire(unsigned *p){ + return __atomic_load_n(p,__ATOMIC_ACQUIRE); +} +static inline void coli_uring_store_release(unsigned *p,unsigned v){ + __atomic_store_n(p,v,__ATOMIC_RELEASE); +} + +static inline void coli_uring_close(ColiUring *r){ + if(!r) return; + if(r->sqes_map && r->sqes_map!=MAP_FAILED) munmap(r->sqes_map,r->sqes_map_sz); + if(r->cq_map && r->cq_map!=MAP_FAILED && r->cq_map!=r->sq_map) munmap(r->cq_map,r->cq_map_sz); + if(r->sq_map && r->sq_map!=MAP_FAILED) munmap(r->sq_map,r->sq_map_sz); + if(r->fd>=0) close(r->fd); + memset(r,0,sizeof(*r)); r->fd=-1; +} + +static inline int coli_uring_init(ColiUring *r,unsigned entries){ + memset(r,0,sizeof(*r)); r->fd=-1; + r->fd=(int)syscall(SYS_io_uring_setup,entries,&r->p); + if(r->fd<0) return -1; + + r->sq_map_sz=r->p.sq_off.array+r->p.sq_entries*sizeof(unsigned); + r->cq_map_sz=r->p.cq_off.cqes+r->p.cq_entries*sizeof(struct io_uring_cqe); + if(r->p.features&IORING_FEAT_SINGLE_MMAP){ + size_t n=r->sq_map_sz>r->cq_map_sz?r->sq_map_sz:r->cq_map_sz; + r->sq_map=mmap(NULL,n,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_POPULATE,r->fd,IORING_OFF_SQ_RING); + if(r->sq_map==MAP_FAILED){ r->sq_map=NULL; coli_uring_close(r); return -1; } + r->sq_map_sz=n; r->cq_map=r->sq_map; r->cq_map_sz=n; + }else{ + r->sq_map=mmap(NULL,r->sq_map_sz,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_POPULATE,r->fd,IORING_OFF_SQ_RING); + if(r->sq_map==MAP_FAILED){ r->sq_map=NULL; coli_uring_close(r); return -1; } + r->cq_map=mmap(NULL,r->cq_map_sz,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_POPULATE,r->fd,IORING_OFF_CQ_RING); + if(r->cq_map==MAP_FAILED){ r->cq_map=NULL; coli_uring_close(r); return -1; } + } + r->sqes_map_sz=r->p.sq_entries*sizeof(struct io_uring_sqe); + r->sqes_map=mmap(NULL,r->sqes_map_sz,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_POPULATE,r->fd,IORING_OFF_SQES); + if(r->sqes_map==MAP_FAILED){ r->sqes_map=NULL; coli_uring_close(r); return -1; } + + char *sq=(char*)r->sq_map,*cq=(char*)r->cq_map; + r->sq_head=(unsigned*)(sq+r->p.sq_off.head); + r->sq_tail=(unsigned*)(sq+r->p.sq_off.tail); + r->sq_mask=(unsigned*)(sq+r->p.sq_off.ring_mask); + r->sq_entries=(unsigned*)(sq+r->p.sq_off.ring_entries); + r->sq_array=(unsigned*)(sq+r->p.sq_off.array); + r->cq_head=(unsigned*)(cq+r->p.cq_off.head); + r->cq_tail=(unsigned*)(cq+r->p.cq_off.tail); + r->cq_mask=(unsigned*)(cq+r->p.cq_off.ring_mask); + r->cq_entries=(unsigned*)(cq+r->p.cq_off.ring_entries); + r->sqes=(struct io_uring_sqe*)r->sqes_map; + r->cqes=(struct io_uring_cqe*)(cq+r->p.cq_off.cqes); + return 0; +} + +static inline int coli_uring_prep_read(ColiUring *r,int fd,void *buf,size_t len, + int64_t off,uint64_t user_data){ + if(!len || len>UINT32_MAX){ errno=EINVAL; return -1; } + unsigned head=coli_uring_load_acquire(r->sq_head); + unsigned tail=__atomic_load_n(r->sq_tail,__ATOMIC_RELAXED); + if(tail-head>=*r->sq_entries){ errno=EAGAIN; return -1; } + unsigned idx=tail&*r->sq_mask; + struct io_uring_sqe *sqe=&r->sqes[idx]; + memset(sqe,0,sizeof(*sqe)); + sqe->opcode=IORING_OP_READ; + sqe->fd=fd; + sqe->off=(uint64_t)off; + sqe->addr=(uint64_t)(uintptr_t)buf; + sqe->len=(uint32_t)len; + sqe->user_data=user_data; + r->sq_array[idx]=idx; + coli_uring_store_release(r->sq_tail,tail+1); + return 0; +} + +static inline int coli_uring_enter(ColiUring *r,unsigned min_complete){ + for(;;){ + unsigned head=coli_uring_load_acquire(r->sq_head); + unsigned tail=coli_uring_load_acquire(r->sq_tail); + unsigned submit=tail-head; + unsigned flags=min_complete?IORING_ENTER_GETEVENTS:0; + int n=(int)syscall(SYS_io_uring_enter,r->fd,submit,min_complete,flags,NULL,0); + if(n>=0) return n; + if(errno!=EINTR) return -1; + } +} + +static inline int coli_uring_peek(ColiUring *r,struct io_uring_cqe *out){ + unsigned head=__atomic_load_n(r->cq_head,__ATOMIC_RELAXED); + unsigned tail=coli_uring_load_acquire(r->cq_tail); + if(head==tail) return 0; + *out=r->cqes[head&*r->cq_mask]; + coli_uring_store_release(r->cq_head,head+1); + return 1; +} + +#endif /* __linux__ */ +#endif /* COLI_URING_H */ diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index c1f42ec..d280a92 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -40,6 +40,7 @@ Format: `VAR` — default — effect. | `COLI_METAL_SPIN` | off | Keep a GPU keep-alive spinner running (reduces dispatch latency; costs power). | | `PIPE` | `0` (off) | Overlap expert disk-load with matmul via I/O worker threads. Byte-identical output; reorders I/O. `PIPE=1` opts in. | | `PIPE_WORKERS` | `8` | Number of I/O worker threads when `PIPE=1`. Tune to your SSD (fewer avoids over-subscribing cores). | +| `URING` | `0` (off) | Linux-only queued expert I/O. `URING=1` implies `PIPE=1`, replaces blocking loader pthreads and spin waits with batched io_uring SQEs/CQEs, and batches `PILOT_REAL` loads on a separate ring. Fails clearly if the kernel denies io_uring; incompatible with `COLI_MMAP=1`. | | `DIRECT` | `0` (off) | Use `O_DIRECT`/unbuffered reads for expert slabs. Helps sustained NVMe; keeps the zero-copy GPU path. | | `COLI_NO_OMP_TUNE` | off | **Kill-switch** for the OpenMP hot-thread tuning (`OMP_WAIT_POLICY=active` spin + proc-bind). Set `=1` when the CPU is mostly waiting on the GPU (Metal) so spin doesn't steal the shared power budget. | | `MLOCK` | `-1` (auto: on for macOS) | Wire the streamed expert cache into physical RAM (`mlock`) to dodge the memory compressor. `0` off, `1` force. | From cf062010d8dff7a7dd89174170ed33f6be92aa90 Mon Sep 17 00:00:00 2001 From: Robert Landers Date: Wed, 15 Jul 2026 04:07:12 +0200 Subject: [PATCH 47/79] use async and fix workers Signed-off-by: Robert Landers --- .gitignore | 1 + c/glm.c | 11 ++++++++--- c/tests/test_uring.c | 3 +++ c/uring.h | 11 +++++++++++ docs/ENVIRONMENT.md | 4 ++-- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index dba6a3f..981e740 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,4 @@ c/bench/ c/tests/test_decode_batch c/tests/test_i4_acc512 c/tests/test_idot +c/tests/test_uring diff --git a/c/glm.c b/c/glm.c index 0237869..7d307dc 100644 --- a/c/glm.c +++ b/c/glm.c @@ -5259,6 +5259,7 @@ int main(int argc, char **argv){ g_pipe = getenv("PIPE")?atoi(getenv("PIPE")):0; /* default OFF: overlap expert load ‖ matmul (byte-identical; reorders I/O). PIPE=1 opts in */ g_pipe_nw = getenv("PIPE_WORKERS")?atoi(getenv("PIPE_WORKERS")):8; /* I/O worker threads */ if(g_pipe_nw<1) g_pipe_nw=1; + g_direct = getenv("DIRECT")?atoi(getenv("DIRECT")):0; g_uring = getenv("URING")?atoi(getenv("URING")):0; if(g_uring){ #ifdef __linux__ @@ -5267,13 +5268,17 @@ int main(int argc, char **argv){ if(uring_batch_init(&g_ub_pipe) || (g_pilot_real&&uring_batch_init(&g_ub_pilot))){ fprintf(stderr,"URING=1: io_uring_setup failed: %s\n",strerror(errno)); return 2; } - fprintf(stderr,"[URING] queued expert I/O active (depth=%d%s)\n",URING_REQ_MAX, - g_pilot_real?", batched PILOT_REAL":""); + unsigned uw=(unsigned)(g_pipe_nw>64?64:g_pipe_nw); + if(coli_uring_set_workers(&g_ub_pipe.ring,uw) || + (g_pilot_real&&coli_uring_set_workers(&g_ub_pilot.ring,uw))) + fprintf(stderr,"[URING] warning: cannot set io-wq workers=%u: %s\n",uw,strerror(errno)); + fprintf(stderr,"[URING] queued expert I/O active (depth=%d, workers=%u, %s%s)\n",URING_REQ_MAX,uw, + g_direct?"O_DIRECT":"buffered",g_pilot_real?", batched PILOT_REAL":""); + if(!g_direct) fprintf(stderr,"[URING] cold NVMe: DIRECT=1 avoids page-cache copy/readahead bottlenecks\n"); #else fprintf(stderr,"URING=1 is supported only on Linux\n"); return 2; #endif } - g_direct = getenv("DIRECT")?atoi(getenv("DIRECT")):0; g_idot = getenv("IDOT")?atoi(getenv("IDOT")):1; /* 0 = kernel f32 esatti (A/B) */ if(getenv("ROUTE_TRACE")&&*getenv("ROUTE_TRACE")){ g_route_fp=fopen(getenv("ROUTE_TRACE"),"w"); diff --git a/c/tests/test_uring.c b/c/tests/test_uring.c index 9712f65..e64b9f2 100644 --- a/c/tests/test_uring.c +++ b/c/tests/test_uring.c @@ -84,6 +84,9 @@ int main(void){ } close(fd); return fail("io_uring_setup"); } + if(coli_uring_set_workers(&ring,4)){ + coli_uring_close(&ring); close(fd); return fail("io-wq worker limit"); + } for(int i=0;ifd,IORING_REGISTER_IOWQ_MAX_WORKERS,limits,2); +} + static inline int coli_uring_prep_read(ColiUring *r,int fd,void *buf,size_t len, int64_t off,uint64_t user_data){ if(!len || len>UINT32_MAX){ errno=EINVAL; return -1; } @@ -91,6 +96,12 @@ static inline int coli_uring_prep_read(ColiUring *r,int fd,void *buf,size_t len, struct io_uring_sqe *sqe=&r->sqes[idx]; memset(sqe,0,sizeof(*sqe)); sqe->opcode=IORING_OP_READ; + /* Cold regular-file reads are allowed to execute inline during + * io_uring_enter() unless forced async. That serializes the submitter on + * filesystems without native nonblocking buffered reads and destroys the + * intended I/O/compute overlap. io-wq gives the ring a real bounded worker + * pool while CQEs retain completion ordering/ownership here. */ + sqe->flags=IOSQE_ASYNC; sqe->fd=fd; sqe->off=(uint64_t)off; sqe->addr=(uint64_t)(uintptr_t)buf; diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index d280a92..dab656b 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -39,8 +39,8 @@ Format: `VAR` — default — effect. | `COLI_METAL_GEMM_MIN` | `16` | Minimum matmul rows to dispatch a GEMM to the GPU (below this, stays on CPU). | | `COLI_METAL_SPIN` | off | Keep a GPU keep-alive spinner running (reduces dispatch latency; costs power). | | `PIPE` | `0` (off) | Overlap expert disk-load with matmul via I/O worker threads. Byte-identical output; reorders I/O. `PIPE=1` opts in. | -| `PIPE_WORKERS` | `8` | Number of I/O worker threads when `PIPE=1`. Tune to your SSD (fewer avoids over-subscribing cores). | -| `URING` | `0` (off) | Linux-only queued expert I/O. `URING=1` implies `PIPE=1`, replaces blocking loader pthreads and spin waits with batched io_uring SQEs/CQEs, and batches `PILOT_REAL` loads on a separate ring. Fails clearly if the kernel denies io_uring; incompatible with `COLI_MMAP=1`. | +| `PIPE_WORKERS` | `8` | Number of pthread loaders when `PIPE=1`, or the io-wq worker maximum per ring when `URING=1` (capped at 64). Tune to SSD queue depth and available cores. | +| `URING` | `0` (off) | Linux-only queued expert I/O. `URING=1` implies `PIPE=1`, forces cold reads through io-wq (`IOSQE_ASYNC`), replaces blocking loader pthreads and spin waits with batched SQEs/CQEs, and batches `PILOT_REAL` loads on a separate ring. Use `DIRECT=1` for cold NVMe to avoid page-cache copy/readahead limits. Fails clearly if the kernel denies io_uring; incompatible with `COLI_MMAP=1`. | | `DIRECT` | `0` (off) | Use `O_DIRECT`/unbuffered reads for expert slabs. Helps sustained NVMe; keeps the zero-copy GPU path. | | `COLI_NO_OMP_TUNE` | off | **Kill-switch** for the OpenMP hot-thread tuning (`OMP_WAIT_POLICY=active` spin + proc-bind). Set `=1` when the CPU is mostly waiting on the GPU (Metal) so spin doesn't steal the shared power budget. | | `MLOCK` | `-1` (auto: on for macOS) | Wire the streamed expert cache into physical RAM (`mlock`) to dodge the memory compressor. `0` off, `1` force. | From 0b9ce242e4f9ca50395d0a5ccaa77c09ed795894 Mon Sep 17 00:00:00 2001 From: Robert Landers Date: Wed, 15 Jul 2026 04:07:24 +0200 Subject: [PATCH 48/79] fix wording Signed-off-by: Robert Landers --- c/glm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/glm.c b/c/glm.c index 7d307dc..81978a8 100644 --- a/c/glm.c +++ b/c/glm.c @@ -5273,7 +5273,7 @@ int main(int argc, char **argv){ (g_pilot_real&&coli_uring_set_workers(&g_ub_pilot.ring,uw))) fprintf(stderr,"[URING] warning: cannot set io-wq workers=%u: %s\n",uw,strerror(errno)); fprintf(stderr,"[URING] queued expert I/O active (depth=%d, workers=%u, %s%s)\n",URING_REQ_MAX,uw, - g_direct?"O_DIRECT":"buffered",g_pilot_real?", batched PILOT_REAL":""); + g_direct?"DIRECT=1":"buffered",g_pilot_real?", batched PILOT_REAL":""); if(!g_direct) fprintf(stderr,"[URING] cold NVMe: DIRECT=1 avoids page-cache copy/readahead bottlenecks\n"); #else fprintf(stderr,"URING=1 is supported only on Linux\n"); return 2; From 869e80ee2db43a5f7dc905f540cfba4190a531ea Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 15 Jul 2026 14:20:50 +0200 Subject: [PATCH 49/79] web: fallback when crypto.randomUUID() is unavailable Some browsers and insecure contexts (plain HTTP) throw on crypto.randomUUID(), which silently breaks the chat UI. Fall back to a plain UUID v4 generator when the native call fails - same behaviour on modern browsers, works everywhere else. --- web/src/App.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 57e5f98..d4e0e41 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -34,7 +34,11 @@ import { Brain } from "./Brain" import { persistPublicSettings, stored } from "@/lib/storage" import { cn } from "@/lib/utils" -const message = (role: ChatMessage["role"], content: string): ChatMessage => ({ id: crypto.randomUUID(), role, content }) +const message = (role: ChatMessage["role"], content: string): ChatMessage => { + let id: string + try { id = crypto.randomUUID() } catch { id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { const r = Math.random() * 16 | 0; return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16) }) } + return { id, role, content } +} export default function App() { // When the page is served by the engine itself (coli web), same-origin is the From af421d6d3a1b7366bb858a8840ef3a528b3b99bf Mon Sep 17 00:00:00 2001 From: Skeldoor Date: Wed, 15 Jul 2026 13:28:05 +0100 Subject: [PATCH 50/79] glm.c: 4-accumulator NEON SDOT for int8/int4 expert dots (2.4x/core on Apple Silicon) dot_i8i8 and dot_i4i8 accumulated the whole SDOT reduction into a single int32x4_t. SDOT has ~3-4 cycle latency, so the serial dependency on `acc` capped each core at ~26 GB/s (int8) / ~12 GB/s (int4) of weight throughput regardless of memory bandwidth. Split into 4 independent accumulators (64 values/iter) so the loads become the bottleneck instead of the reduction chain; the original single-acc loop is kept as the tail handler. Measured on an Apple M4 (isolated microbench, expert-shaped 2048x6144): int8*int8 26.0 -> 63.2 GB/s/core (2.4x) int4*int8 12.4 -> 29.9 GB/s/core (2.4x) Output is bit-identical to the previous kernels (verified over random inputs). Non-DOTPROD NEON, AVX2/AVX-512/VNNI and VSX paths are untouched; only the __ARM_FEATURE_DOTPROD branch changed. Co-Authored-By: Claude Fable 5 --- c/glm.c | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/c/glm.c b/c/glm.c index 861dcf0..b3451c0 100644 --- a/c/glm.c +++ b/c/glm.c @@ -614,18 +614,30 @@ static inline int32_t dot_i8i8(const int8_t *w, const int8_t *x, int I){ #elif defined(__ARM_NEON) /* ARM: SDOT nativo se disponibile (Apple Silicon: sempre); altrimenti vmull/vpadal. * Stesso bound anti-overflow del trucco AVX2: coppie <= 128*127*2 = 32512 < 32767. */ +#if defined(__ARM_FEATURE_DOTPROD) + /* 4 accumulatori indipendenti: SDOT ha latenza ~3-4 cicli, con un solo acc la + * catena seriale strozza il core a ~26 GB/s di pesi; con 4 lane indipendenti il + * dot diventa memory-bound (misurato su M4: 26 -> 63 GB/s per core, 2.4x). */ + int32x4_t a0=vdupq_n_s32(0),a1=vdupq_n_s32(0),a2=vdupq_n_s32(0),a3=vdupq_n_s32(0); + for(;i+64<=I;i+=64){ + a0=vdotq_s32(a0,vld1q_s8(w+i), vld1q_s8(x+i)); + a1=vdotq_s32(a1,vld1q_s8(w+i+16),vld1q_s8(x+i+16)); + a2=vdotq_s32(a2,vld1q_s8(w+i+32),vld1q_s8(x+i+32)); + a3=vdotq_s32(a3,vld1q_s8(w+i+48),vld1q_s8(x+i+48)); + } + int32x4_t acc=vaddq_s32(vaddq_s32(a0,a1),vaddq_s32(a2,a3)); + for(;i+16<=I;i+=16) acc=vdotq_s32(acc,vld1q_s8(w+i),vld1q_s8(x+i)); + sum=vaddvq_s32(acc); +#else int32x4_t acc=vdupq_n_s32(0); for(;i+16<=I;i+=16){ int8x16_t wv=vld1q_s8(w+i), xv=vld1q_s8(x+i); -#if defined(__ARM_FEATURE_DOTPROD) - acc=vdotq_s32(acc,wv,xv); -#else int16x8_t p=vmull_s8(vget_low_s8(wv),vget_low_s8(xv)); p=vmlal_s8(p,vget_high_s8(wv),vget_high_s8(xv)); acc=vpadalq_s16(acc,p); -#endif } sum=vaddvq_s32(acc); +#endif #elif defined(__VSX__) /* POWER8: vec_msum (s8 x u8 -> s32) somma i prodotti byte DIRETTAMENTE in lane * s32, 16 byte/iter: il bound anti-saturazione a 16 bit di maddubs qui non serve. @@ -705,6 +717,28 @@ static inline int32_t dot_i4i8(const uint8_t *w4, const int8_t *x, int I){ sum=hsum256_i32(acc); #elif defined(__ARM_NEON) const uint8x16_t m4q=vdupq_n_u8(0x0F); const int8x16_t b8q=vdupq_n_s8(8); +#if defined(__ARM_FEATURE_DOTPROD) + /* 4 accumulatori indipendenti (vedi dot_i8i8): spezza la catena seriale su acc. + * Misurato su M4: 12.4 -> 29.9 GB/s di pesi per core (2.4x). */ + int32x4_t a0=vdupq_n_s32(0),a1=vdupq_n_s32(0),a2=vdupq_n_s32(0),a3=vdupq_n_s32(0); + for(;i+64<=I;i+=64){ + uint8x16_t byA=vld1q_u8(w4+(i>>1)), byB=vld1q_u8(w4+(i>>1)+16); + uint8x16x2_t zA=vzipq_u8(vandq_u8(byA,m4q), vshrq_n_u8(byA,4)); /* nibble in ordine */ + uint8x16x2_t zB=vzipq_u8(vandq_u8(byB,m4q), vshrq_n_u8(byB,4)); + a0=vdotq_s32(a0,vsubq_s8(vreinterpretq_s8_u8(zA.val[0]),b8q),vld1q_s8(x+i)); + a1=vdotq_s32(a1,vsubq_s8(vreinterpretq_s8_u8(zA.val[1]),b8q),vld1q_s8(x+i+16)); + a2=vdotq_s32(a2,vsubq_s8(vreinterpretq_s8_u8(zB.val[0]),b8q),vld1q_s8(x+i+32)); + a3=vdotq_s32(a3,vsubq_s8(vreinterpretq_s8_u8(zB.val[1]),b8q),vld1q_s8(x+i+48)); + } + int32x4_t acc=vaddq_s32(vaddq_s32(a0,a1),vaddq_s32(a2,a3)); + for(;i+32<=I;i+=32){ + uint8x16_t by=vld1q_u8(w4+(i>>1)); /* 16 byte = 32 nibble */ + uint8x16x2_t z=vzipq_u8(vandq_u8(by,m4q), vshrq_n_u8(by,4)); /* nibble in ordine */ + acc=vdotq_s32(acc,vsubq_s8(vreinterpretq_s8_u8(z.val[0]),b8q),vld1q_s8(x+i)); + acc=vdotq_s32(acc,vsubq_s8(vreinterpretq_s8_u8(z.val[1]),b8q),vld1q_s8(x+i+16)); + } + sum=vaddvq_s32(acc); +#else int32x4_t acc=vdupq_n_s32(0); for(;i+32<=I;i+=32){ uint8x16_t by=vld1q_u8(w4+(i>>1)); /* 16 byte = 32 nibble */ @@ -712,18 +746,15 @@ static inline int32_t dot_i4i8(const uint8_t *w4, const int8_t *x, int I){ int8x16_t w0=vsubq_s8(vreinterpretq_s8_u8(z.val[0]),b8q); int8x16_t w1=vsubq_s8(vreinterpretq_s8_u8(z.val[1]),b8q); int8x16_t x0=vld1q_s8(x+i), x1=vld1q_s8(x+i+16); -#if defined(__ARM_FEATURE_DOTPROD) - acc=vdotq_s32(acc,w0,x0); acc=vdotq_s32(acc,w1,x1); -#else int16x8_t p=vmull_s8(vget_low_s8(w0),vget_low_s8(x0)); /* |w|<=8: nessun overflow */ p=vmlal_s8(p,vget_high_s8(w0),vget_high_s8(x0)); acc=vpadalq_s16(acc,p); p=vmull_s8(vget_low_s8(w1),vget_low_s8(x1)); p=vmlal_s8(p,vget_high_s8(w1),vget_high_s8(x1)); acc=vpadalq_s16(acc,p); -#endif } sum=vaddvq_s32(acc); +#endif #elif defined(__VSX__) /* 16 byte = 32 nibble. vec_mergeh/vec_mergel su ppc64le (GCC) interallacciano come * unpacklo/unpackhi x86 (verificato empiricamente su POWER8): i nibble escono in From 3745cc680ebbb779befd2dee572df40cca8dc362 Mon Sep 17 00:00:00 2001 From: Skeldoor Date: Wed, 15 Jul 2026 13:37:02 +0100 Subject: [PATCH 51/79] glm.c/coli: Ctrl-C soft-stops the current turn instead of killing the engine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In serve/chat mode, Ctrl-C during generation killed the whole engine, losing the loaded model and forcing a full reload. Now a SIGINT handler (armed only in run_serve / run_serve_mux) sets a flag that spec_decode's token loop treats exactly like hitting the NGEN cap: the turn ends through the normal path, so the END sentinel, STAT line, usage_save and KV append all run — and :more can continue the interrupted answer. The mux loop closes in-flight requests via the same mux_done path. One-shot ./glm runs and Windows keep default SIGINT (die). coli: stream_turn survives the first KeyboardInterrupt, forwards SIGINT to the engine (covers non-TTY), drains to the turn boundary, and reports it. A second Ctrl-C quits. Help line and per-turn footer updated. POSIX only (sigaction); no behaviour change on Windows. Verified end-to-end on Apple M4 + Metal: interrupt mid-decode, engine stays up, next prompt answers, :q exits 0. Co-Authored-By: Claude Fable 5 --- c/coli | 28 ++++++++++++++++++++++------ c/glm.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/c/coli b/c/coli index 8c89caf..e0a9be2 100755 --- a/c/coli +++ b/c/coli @@ -317,10 +317,21 @@ class Spinner: if TTY: sys.stdout.write("\r\033[K"); sys.stdout.flush() def stream_turn(p, sentinel, on_bytes): - """legge fino alla sentinella; on_bytes riceve i chunk della risposta. Poi legge la riga STAT.""" - pend=b"" + """legge fino alla sentinella; on_bytes riceve i chunk della risposta. Poi legge la riga STAT. + Il PRIMO Ctrl-C durante lo stream non chiude la sessione: il motore (handler SIGINT) + chiude il turno per la via del tetto NGEN e noi dreniamo fino alla sentinella. + Un SECONDO Ctrl-C esce davvero.""" + pend=b""; interrupted=False while True: - b=p.stdout.read(1) + try: + b=p.stdout.read(1) + except KeyboardInterrupt: + if interrupted or p.poll() is not None: raise + interrupted=True + try: p.send_signal(signal.SIGINT) # non-TTY: il motore potrebbe non aver visto il Ctrl-C + except Exception: pass + print(f"\n {C.yel}⏹ stopping… (Ctrl-C again to quit){C.r}", flush=True) + continue if b==b"": return None pend+=b if pend.endswith(sentinel): @@ -328,7 +339,9 @@ def stream_turn(p, sentinel, on_bytes): if rest: on_bytes(rest) line=p.stdout.readline().decode("utf-8","replace").strip() # STAT tok tps hit rss m=re.match(r"STAT (\S+) (\S+) (\S+) (\S+)", line) - return {"tok":int(m.group(1)),"tps":float(m.group(2)),"hit":float(m.group(3)),"rss":float(m.group(4))} if m else {} + st={"tok":int(m.group(1)),"tps":float(m.group(2)),"hit":float(m.group(3)),"rss":float(m.group(4))} if m else {} + if interrupted: st["interrupted"]=True + return st if len(pend)>len(sentinel): out=pend[:-len(sentinel)]; pend=pend[-len(sentinel):] on_bytes(out) @@ -464,7 +477,7 @@ def cmd_chat(a): for chunk in textwrap.wrap(l, term_w()-4) or [l]: print(f" {C.dgray}{chunk}{C.r}") except Exception: pass - print(f" {C.dim}type and press Enter · :more continues · :reset clears memory · :q exits{C.r}\n") + print(f" {C.dim}type and press Enter · Ctrl-C stops the answer · :more continues · :reset clears memory · :q exits{C.r}\n") w=term_w()-4 def user_box(msg): """ri-disegna il messaggio dentro una box che si ADATTA su piu' righe: @@ -529,10 +542,13 @@ def cmd_chat(a): el=time.time()-t0 if st.get("tok"): print(f"\r {C.dgray}└─ {st['tok']} tok · {st['tps']:.2f} tok/s · hit {st['hit']:.0f}% · RSS {st['rss']:.1f} GB · {el:.0f}s{C.r}") - if st["tok"]>=a.ngen: + if st.get("interrupted"): + print(f" {C.yel}⏹ interrupted; type :more to continue the response{C.r}") + elif st["tok"]>=a.ngen: print(f" {C.yel}…stopped at --ngen ({a.ngen}); type :more to continue the response{C.r}") print() else: + if st.get("interrupted"): print(f" {C.yel}⏹ interrupted{C.r}") print() except KeyboardInterrupt: print(f"\n {C.dim}interrupted{C.r}") diff --git a/c/glm.c b/c/glm.c index 861dcf0..942b055 100644 --- a/c/glm.c +++ b/c/glm.c @@ -35,6 +35,7 @@ #include #include /* mlock: inchioda le pagine in RAM / wire pages into RAM */ #include /* fstat per mmap degli shard (COLI_MMAP) */ +#include /* SIGINT = stop morbido del turno in serve mode */ #endif #include "st.h" #include "tok.h" @@ -3579,12 +3580,34 @@ static void stops_arm(const Cfg *c, int tok_eos){ * all: storia token (capacita' >= kv+n_new+g_draft+2), kv = token gia' in KV. * logit = logits della posizione kv-1 (dal prefill); viene liberato qui. * emit(tok,ud) per ogni token emesso. Ritorna i token emessi; *kv_out = nuova kv. */ +/* STOP MORBIDO (serve/chat): SIGINT chiude il turno CORRENTE per la stessa via + * del tetto NGEN (stats, usage_save, KV append, sentinella END tutti normali) + * invece di uccidere il motore; :more puo' continuare la risposta interrotta. + * Il flag e' armato solo nei serve-loop (intr_install): nei run one-shot e in + * validazione SIGINT resta il default (morte immediata). Solo POSIX: su + * Windows il comportamento di Ctrl-C non cambia. + * EN: soft stop (serve/chat): SIGINT ends the CURRENT turn through the same + * path as the NGEN cap — stats/usage/KV/END sentinel all normal — instead of + * killing the engine; :more can continue the interrupted answer. Armed only + * in the serve loops; one-shot runs keep default SIGINT. POSIX only. */ +static volatile sig_atomic_t g_intr=0; +#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) +static void intr_sig(int s){ (void)s; g_intr=1; } +static void intr_install(void){ + struct sigaction sa; memset(&sa,0,sizeof(sa)); + sa.sa_handler=intr_sig; sigemptyset(&sa.sa_mask); + sa.sa_flags=SA_RESTART; /* getline/pread non devono vedere EINTR */ + sigaction(SIGINT,&sa,NULL); +} +#else +static void intr_install(void){} +#endif static int spec_decode(Model *m, int *all, int kv, int n_new, int eos, float *logit, void (*emit)(int,void*), void *ud, int *kv_out){ Cfg *c=&m->c; int V=c->vocab; int emitted=0, done=0; int draft[64]; if(g_draft>63) g_draft=63; int carry_ban=-1; /* token rifiutato dalla verifica: escluso dal resample */ - while(emitted=0 && next==eos) || is_stop(next)) break; emit(next,ud); all[kv]=next; emitted++; m->n_emit++; @@ -4290,12 +4313,17 @@ static void run_serve_mux(Model *m, const char *snap){ setvbuf(stdout, NULL, _IONBF, 0); #endif setvbuf(stdin,NULL,_IONBF,0); + intr_install(); /* Ctrl-C = chiudi i turni in volo, non il processo */ printf("\x01\x01READY\x01\x01\nSTAT 0 0.00 0.0 %.2f\n",rss_gb()); fflush(stdout); hwinfo_emit(m); tiers_emit(m); emap_emit(m); int eof=0; for(;;){ + if(g_intr){ g_intr=0; /* stop morbido: ogni request attiva finisce ORA per la + * via normale di mux_done (DONE+stats+KV coerenti) */ + for(int i=0;ilen) #define first (sc->first) char *line=NULL; size_t cap=0; ssize_t nr; char *buf=malloc(1<<16); + intr_install(); /* Ctrl-C = fine turno, non fine processo */ printf("\x01\x01" "READY" "\x01\x01\n"); printf("STAT 0 0.00 0.0 %.2f\n", rss_gb()); fflush(stdout); tiers_emit(m); while((nr=getline(&line,&cap,stdin))>0){ + g_intr=0; /* interruzioni arrivate tra i turni: stantie */ if(nr>0 && line[nr-1]=='\n') line[--nr]=0; if(!strcmp(line,"\x02RESET")){ len=0; first=1; if(m->has_mtp) m->kv_start[m->c.n_layers]=-1; kv_disk_reset(m); From b79610852bc1e27bdde89bfa514e701ec951303f Mon Sep 17 00:00:00 2001 From: Skeldoor Date: Wed, 15 Jul 2026 13:37:36 +0100 Subject: [PATCH 52/79] coli: consume the engine's TIERS line at startup so it doesn't leak into the first answer After the READY handshake, run_serve emits one TIERS status line (the web-dashboard expert-pyramid snapshot). cmd_chat never read it, so in interactive chat it surfaced as literal "TIERS 0 181 19275 0.00 ..." text prepended to the first response. Read and discard that one line after READY, matching how the other status frames are consumed. Chat-only; the HTTP serve path already drains it. Co-Authored-By: Claude Fable 5 --- c/coli | 2 ++ 1 file changed, 2 insertions(+) diff --git a/c/coli b/c/coli index 8c89caf..933f635 100755 --- a/c/coli +++ b/c/coli @@ -438,6 +438,8 @@ def cmd_chat(a): try: errlog.write(p.stderr.read().decode("utf-8","replace")) except (OSError, ValueError): pass errlog.seek(0); print(errlog.read()[-1500:]); sys.exit("the engine exited while loading") + p.stdout.readline() # TIERS line (web-dashboard protocol): emitted once right after STAT; + # left unread it leaks into the first answer's text # READY received. Drain the child's stderr into errlog without blocking: # the engine is still alive (blocked on stdin), so a plain read() would # hang forever waiting for EOF. A short bounded drain grabs the ~400 bytes From da260c38cbaf17438eb08573467e272229a76e3b Mon Sep 17 00:00:00 2001 From: JustVugg Date: Wed, 15 Jul 2026 14:56:01 +0200 Subject: [PATCH 53/79] server: clamp max_tokens to the server cap instead of rejecting it (fixes #260) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit opencode / the ai-sdk OpenAI-compatible client sends a large default max_tokens (> the server's --max-tokens cap, 1024 by default), and generation_options returned 400 "must be an integer between 1 and 1024" — even for a trivial "hello". OpenAI-compatible servers clamp to their own ceiling rather than reject. Now max_tokens > limit is clamped to limit; only non-int / non-positive values are a hard error. Test updated to assert the clamp + keep the <1 reject. Co-Authored-By: Claude Opus 4.8 --- c/openai_server.py | 7 +++++-- c/tests/test_openai_server.py | 7 ++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/c/openai_server.py b/c/openai_server.py index f31e8f7..ba19e43 100644 --- a/c/openai_server.py +++ b/c/openai_server.py @@ -410,8 +410,11 @@ def generation_options(body, limit): top_p = body.get("top_p") temperature = 0.7 if temperature is None else temperature top_p = 0.9 if top_p is None else top_p - if isinstance(maximum, bool) or not isinstance(maximum, int) or not 1 <= maximum <= limit: - raise APIError(400, f"`{maximum_param}` must be an integer between 1 and {limit}.", maximum_param) + if isinstance(maximum, bool) or not isinstance(maximum, int) or maximum < 1: + raise APIError(400, f"`{maximum_param}` must be a positive integer.", maximum_param) + if maximum > limit: + maximum = limit # clamp to the server's --max-tokens cap instead of 400 (#260): OpenAI + # clients (opencode/ai-sdk) default to large max_tokens; rejecting breaks them. if (isinstance(temperature, bool) or not isinstance(temperature, (int, float)) or not math.isfinite(temperature) or not 0 <= temperature <= 2): raise APIError(400, "`temperature` must be between 0 and 2.", "temperature") diff --git a/c/tests/test_openai_server.py b/c/tests/test_openai_server.py index 0064070..f8aec86 100644 --- a/c/tests/test_openai_server.py +++ b/c/tests/test_openai_server.py @@ -72,8 +72,13 @@ class TemplateTest(unittest.TestCase): def test_validates_generation_limits(self): self.assertEqual(generation_options({"max_tokens": 4, "temperature": 0, "top_p": 1}, 8), (4, 0.0, 1.0)) + # max_tokens above the server cap is clamped, not rejected (#260): OpenAI + # clients default to large values; erroring breaks them. + self.assertEqual(generation_options({"max_tokens": 9, "temperature": 0, "top_p": 1}, 8), + (8, 0.0, 1.0)) + # non-positive / non-int max_tokens is still a hard error with self.assertRaises(APIError): - generation_options({"max_tokens": 9}, 8) + generation_options({"max_tokens": 0}, 8) with self.assertRaises(APIError): generation_options({"temperature": math.nan}, 8) with self.assertRaises(APIError): From da684b240dbb12bcaa65fdd9d90fc76c3ccc9fdb Mon Sep 17 00:00:00 2001 From: Michael Denyer Date: Wed, 15 Jul 2026 14:44:29 +0100 Subject: [PATCH 54/79] profile: account expert-disk stall as wait, not other The decode/prefill PROFILE line splits expert-disk time into service (overlapped async dispatch) and wait (blocking stalls), but every accumulation site wrote t_edisk and nothing ever wrote t_ewait, so the wait column always printed 0.000s. Worse, the accounted sum used the dead t_ewait instead of t_edisk, so the entire disk-read stall was excluded from accounted and silently fell into the other bucket. On a disk-streaming MoE the effect is large: other reads as ~60% of decode when it is really the expert-load stall. Route the three blocking sites (non-PIPE parallel load, the Metal drain barrier, and the per-expert pipe_wait in the CPU matmul loop) to t_ewait, keep the async dispatch in t_edisk, and include both in accounted. Profiling-only; no behavioural change. Before, on a 168-expert model: expert-disk 25.077s service / 0.000s wait | ... | other 28.401s After: expert-disk 0.111s service / 26.948s wait | ... | other 3.390s other now holds only the genuinely-unbucketed work (router, norms). --- c/glm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/c/glm.c b/c/glm.c index fb93e59..01d804a 100644 --- a/c/glm.c +++ b/c/glm.c @@ -2509,7 +2509,7 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out, int } else { double t0=now_s(); /* ORIGINALE: blocking parallel load */ #pragma omp parallel for schedule(dynamic,1) for(int q=0;qws[q],1); - m->t_edisk += now_s()-t0; } + m->t_ewait += now_s()-t0; } /* blocking: whole load stalls compute */ } /* I/O ASINCRONO: readahead (WILLNEED) del blocco SUCCESSIVO mentre calcoliamo * questo — il kernel legge in background, le pread dopo trovano cache calda */ @@ -2538,7 +2538,7 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out, int * correct (and free) when a subset falls back to the CPU. */ if(g_pipe && nmiss){ double tw=now_s(); for(int q=0;qt_edisk += now_s()-tw; } + m->t_ewait += now_s()-tw; } /* blocking: drain stalled compute */ MB_BUILD(1, 0); /* missed experts, now loaded */ if(nbb>0){ double t0=now_s(); @@ -2562,7 +2562,7 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out, int * Stays ABOVE the METAL skip: a subset that fell back to the CPU still needs its * slot drained here, and under METAL the block-level drain above already ran (this * spin is then a no-op). */ - if(g_pipe && qof[j]>=0){ double tw=now_s(); pipe_wait(qof[j]); m->t_edisk += now_s()-tw; } + if(g_pipe && qof[j]>=0){ double tw=now_s(); pipe_wait(qof[j]); m->t_ewait += now_s()-tw; } /* blocking */ #ifdef COLI_METAL /* skip the subsets already computed on GPU */ if(g_metal_enabled && ((is_miss[j] && !cpu_miss) || (!is_miss[j] && !cpu_res))) continue; @@ -3689,7 +3689,7 @@ static void generate(Model *m, const int *prompt, int np, int n_new, int *out){ } static void profile_print(Model *m, double elapsed){ - double accounted=m->t_ewait+m->t_emm+m->t_attn+m->t_head; + double accounted=m->t_edisk+m->t_ewait+m->t_emm+m->t_attn+m->t_head; printf("PROFILE: expert-disk %.3fs service / %.3fs wait | expert-matmul %.3fs | attention %.3fs " "(including kvb %.3fs) | lm_head %.3fs | other %.3fs\n", m->t_edisk,m->t_ewait,m->t_emm,m->t_attn,m->t_kvb,m->t_head,elapsed-accounted); From d0c9941a6771c54ca6bd0a053a374e72aa24ce82 Mon Sep 17 00:00:00 2001 From: Michael Denyer Date: Wed, 15 Jul 2026 14:59:06 +0100 Subject: [PATCH 55/79] ARM i8mm: SMMLA fast path for the int8/int4 IDOT drivers vmmlaq_s32 computes a 2x2 int32 tile (2 weight rows x 2 activation rows) per instruction on 8-deep segments. Tile o and s in pairs, halving weight traffic and doubling per-instruction work at S>=2. Four independent accumulators over a 64-deep unroll keep the loop throughput-bound (a single chained accumulator measures no better than SDOT: latency-bound). S=1 and all tails (odd o, odd s, I not a multiple of 16/32) keep the existing SDOT/scalar code, and scales apply in the same order, so results are bit-identical. Compile-time gated on __ARM_FEATURE_MATMUL_INT8. The default Darwin build passes no -mcpu and is byte-identical (still SDOT, IDOT_KERNEL "neon"). Opt in with ARCH=native (new Darwin Makefile knob, appends -mcpu=), which reports IDOT_KERNEL "neon-i8mm". The same gate lights up on any aarch64 with i8mm (Graviton3+, Grace). test_idot grows a driver-level exactness check through matmul_qt_ex: fmt 1 and 2, S in {2,3,4,5,8}, O in {1,2,3,64,65}, I in {16,17,100, 1408}, bitwise float equality against a plain-C reference. Green on both build flavors. Measured on an M5 Pro (18 threads, matmul_qt_ex microbenchmark at GLM-5.2 expert shapes, best of 3 process runs, vs the SDOT baseline): gateup int4 S=8 499.7 -> 1076.6 GF/s (+115%) gateup int8 S=8 512.9 -> 1166.3 GF/s (+127%) down int4 S=8 696.9 -> 1186.0 GF/s (+70%) S=1 decode rows unchanged (SDOT path untouched) --- c/Makefile | 6 +++ c/glm.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ c/tests/test_idot.c | 55 +++++++++++++++++++ 3 files changed, 189 insertions(+) diff --git a/c/Makefile b/c/Makefile index 5a53c24..e55c304 100644 --- a/c/Makefile +++ b/c/Makefile @@ -46,6 +46,12 @@ OMPC = OMPL = endif CFLAGS = -O3 $(OMPC) -Wall -Wextra -Wno-unused-parameter -Wno-misleading-indentation -Wno-unused-function +# Opt-in: ARCH=native appends -mcpu=native (arm64 clang uses -mcpu, not -march), +# which unlocks the i8mm SMMLA int8/int4 dot kernels in glm.c. ARCH unset -> +# no -mcpu, default build byte-identical. Apple clang knows apple-m4 / native. +ifneq ($(ARCH),) +CFLAGS += -mcpu=$(ARCH) +endif LDFLAGS = -lm $(OMPL) EXE = else ifneq ($(IS_WIN),) diff --git a/c/glm.c b/c/glm.c index fb93e59..8d5609b 100644 --- a/c/glm.c +++ b/c/glm.c @@ -529,6 +529,8 @@ static void matmul_i2(float *y, const float *x, const uint8_t *q2, const float * #define IDOT_KERNEL "avx-vnni" #elif defined(__AVX2__) #define IDOT_KERNEL "avx2" +#elif defined(__ARM_NEON) && defined(__ARM_FEATURE_MATMUL_INT8) +#define IDOT_KERNEL "neon-i8mm" #elif defined(__ARM_NEON) #define IDOT_KERNEL "neon" #elif defined(__VSX__) @@ -751,8 +753,131 @@ static inline int32_t dot_i4i8(const uint8_t *w4, const int8_t *x, int I){ if(i>1]; sum+=((int)(b&0xF)-8)*x[i]; } return sum; } +#if defined(__ARM_NEON) && defined(__ARM_FEATURE_MATMUL_INT8) +/* SMMLA (i8mm): vmmlaq_s32 vede ogni int8x16_t come matrice 2x8 row-major (byte 0-7 = + * riga 0, byte 8-15 = riga 1) e accumula C += A*B^T nel 2x2 int32: lane0=a0.b0, + * lane1=a0.b1, lane2=a1.b0, lane3=a1.b1. vcombine di due mezze-righe costruisce la + * matrice: A = due righe di peso (o,o+1), B = due righe di attivazione (s,s+1), quindi + * meta' traffico pesi e doppio lavoro per istruzione a S>=2. EN: vmmlaq_s32 treats each + * int8x16_t as a 2x8 row-major matrix and does C += A*B^T on a 2x2 int32 tile; vcombine + * of vget_low/high halves builds the 2-row register from two weight/activation rows. */ +static inline int32x4_t mm_tile16(int32x4_t acc, int8x16_t wo, int8x16_t wo1, + int8x16_t xs, int8x16_t xs1){ + acc=vmmlaq_s32(acc, vcombine_s8(vget_low_s8(wo), vget_low_s8(wo1)), + vcombine_s8(vget_low_s8(xs), vget_low_s8(xs1))); + return vmmlaq_s32(acc, vcombine_s8(vget_high_s8(wo), vget_high_s8(wo1)), + vcombine_s8(vget_high_s8(xs), vget_high_s8(xs1))); +} +static void matmul_q_idot_mm(float *y, const int8_t *xq, const float *sx, const int8_t *q, + const float *scale, int S, int I, int O){ + #pragma omp parallel for schedule(static) + for(int o=0;o<(O&~1);o+=2){ + const int8_t *wo=q+(int64_t)o*I, *wo1=q+(int64_t)(o+1)*I; + float sc0=scale[o], sc1=scale[o+1]; + for(int s=0;s<(S&~1);s+=2){ + const int8_t *xs=xq+(int64_t)s*I, *xs1=xq+(int64_t)(s+1)*I; + /* 4 accumulatori indipendenti: una sola catena vmmla e' latency-bound. + * EN: 4 independent accumulators; a single vmmla chain is latency-bound. */ + int32x4_t a0=vdupq_n_s32(0),a1=vdupq_n_s32(0),a2=vdupq_n_s32(0),a3=vdupq_n_s32(0); int i=0; + for(;i+64<=I;i+=64){ + a0=mm_tile16(a0,vld1q_s8(wo+i), vld1q_s8(wo1+i), vld1q_s8(xs+i), vld1q_s8(xs1+i)); + a1=mm_tile16(a1,vld1q_s8(wo+i+16),vld1q_s8(wo1+i+16),vld1q_s8(xs+i+16),vld1q_s8(xs1+i+16)); + a2=mm_tile16(a2,vld1q_s8(wo+i+32),vld1q_s8(wo1+i+32),vld1q_s8(xs+i+32),vld1q_s8(xs1+i+32)); + a3=mm_tile16(a3,vld1q_s8(wo+i+48),vld1q_s8(wo1+i+48),vld1q_s8(xs+i+48),vld1q_s8(xs1+i+48)); + } + for(;i+16<=I;i+=16) + a0=mm_tile16(a0,vld1q_s8(wo+i),vld1q_s8(wo1+i),vld1q_s8(xs+i),vld1q_s8(xs1+i)); + int32x4_t acc=vaddq_s32(vaddq_s32(a0,a1),vaddq_s32(a2,a3)); + int32_t d00=vgetq_lane_s32(acc,0), d01=vgetq_lane_s32(acc,1); + int32_t d10=vgetq_lane_s32(acc,2), d11=vgetq_lane_s32(acc,3); + for(;i>1)), byo1=vld1q_u8(wo1+(i>>1)); + uint8x16_t cyo=vld1q_u8(wo+(i>>1)+16), cyo1=vld1q_u8(wo1+(i>>1)+16); + uint8x16x2_t zo =vzipq_u8(vandq_u8(byo, m4q), vshrq_n_u8(byo, 4)); + uint8x16x2_t zo1=vzipq_u8(vandq_u8(byo1,m4q), vshrq_n_u8(byo1,4)); + uint8x16x2_t ko =vzipq_u8(vandq_u8(cyo, m4q), vshrq_n_u8(cyo, 4)); + uint8x16x2_t ko1=vzipq_u8(vandq_u8(cyo1,m4q), vshrq_n_u8(cyo1,4)); + a0=mm_tile16(a0, vsubq_s8(vreinterpretq_s8_u8(zo.val[0]),b8q), + vsubq_s8(vreinterpretq_s8_u8(zo1.val[0]),b8q), + vld1q_s8(xs+i), vld1q_s8(xs1+i)); + a1=mm_tile16(a1, vsubq_s8(vreinterpretq_s8_u8(zo.val[1]),b8q), + vsubq_s8(vreinterpretq_s8_u8(zo1.val[1]),b8q), + vld1q_s8(xs+i+16), vld1q_s8(xs1+i+16)); + a2=mm_tile16(a2, vsubq_s8(vreinterpretq_s8_u8(ko.val[0]),b8q), + vsubq_s8(vreinterpretq_s8_u8(ko1.val[0]),b8q), + vld1q_s8(xs+i+32), vld1q_s8(xs1+i+32)); + a3=mm_tile16(a3, vsubq_s8(vreinterpretq_s8_u8(ko.val[1]),b8q), + vsubq_s8(vreinterpretq_s8_u8(ko1.val[1]),b8q), + vld1q_s8(xs+i+48), vld1q_s8(xs1+i+48)); + } + for(;i+32<=I;i+=32){ + uint8x16_t byo=vld1q_u8(wo+(i>>1)), byo1=vld1q_u8(wo1+(i>>1)); + uint8x16x2_t zo =vzipq_u8(vandq_u8(byo, m4q), vshrq_n_u8(byo, 4)); + uint8x16x2_t zo1=vzipq_u8(vandq_u8(byo1,m4q), vshrq_n_u8(byo1,4)); + a0=mm_tile16(a0, vsubq_s8(vreinterpretq_s8_u8(zo.val[0]),b8q), + vsubq_s8(vreinterpretq_s8_u8(zo1.val[0]),b8q), + vld1q_s8(xs+i), vld1q_s8(xs1+i)); + a1=mm_tile16(a1, vsubq_s8(vreinterpretq_s8_u8(zo.val[1]),b8q), + vsubq_s8(vreinterpretq_s8_u8(zo1.val[1]),b8q), + vld1q_s8(xs+i+16), vld1q_s8(xs1+i+16)); + } + int32x4_t acc=vaddq_s32(vaddq_s32(a0,a1),vaddq_s32(a2,a3)); + int32_t d00=vgetq_lane_s32(acc,0), d01=vgetq_lane_s32(acc,1); + int32_t d10=vgetq_lane_s32(acc,2), d11=vgetq_lane_s32(acc,3); + for(;i+1>1], bo1=wo1[i>>1]; + int a0=(int)(bo&0xF)-8, a1=(int)(bo>>4)-8, b0=(int)(bo1&0xF)-8, b1=(int)(bo1>>4)-8; + int u0=xs[i],u1=xs[i+1],v0=xs1[i],v1=xs1[i+1]; + d00+=a0*u0+a1*u1; d01+=a0*v0+a1*v1; d10+=b0*u0+b1*u1; d11+=b0*v0+b1*v1; } + if(i>1], bo1=wo1[i>>1]; + int a0=(int)(bo&0xF)-8, b0=(int)(bo1&0xF)-8; + d00+=a0*xs[i]; d01+=a0*xs1[i]; d10+=b0*xs[i]; d11+=b0*xs1[i]; } + y[(int64_t)s*O+o] =(float)d00*sc0*sx[s]; + y[(int64_t)s*O+(o+1)] =(float)d10*sc1*sx[s]; + y[(int64_t)(s+1)*O+o] =(float)d01*sc0*sx[s+1]; + y[(int64_t)(s+1)*O+(o+1)]=(float)d11*sc1*sx[s+1]; + } + if(S&1){ int s=S-1; const int8_t *xs=xq+(int64_t)s*I; + y[(int64_t)s*O+o] =(float)dot_i4i8(wo, xs,I)*sc0*sx[s]; + y[(int64_t)s*O+(o+1)]=(float)dot_i4i8(wo1,xs,I)*sc1*sx[s]; } + } + if(O&1){ int o=O-1; const uint8_t *w=q4+(int64_t)o*rb; float sc=scale[o]; + #pragma omp parallel for schedule(static) + for(int s=0;s=2){ matmul_q_idot_mm(y,xq,sx,q,scale,S,I,O); return; } +#endif #pragma omp parallel for schedule(static) for(int o=0;o=2){ matmul_i4_idot_mm(y,xq,sx,q4,scale,S,I,O); return; } +#endif #pragma omp parallel for schedule(static) for(int o=0;ofmt=fmt; w->O=O; w->I=I; + w->s=malloc((size_t)O*sizeof(float)); + for(int o=0;os[o]=0.001f+(float)(xr()%1000)*1e-6f; + if(fmt==1){ + w->q8=malloc((size_t)O*I); + for(int64_t i=0;i<(int64_t)O*I;i++) w->q8[i]=(int8_t)((int)(xr()%256)-128); + }else{ + size_t nb=(size_t)O*((I+1)/2); + w->q4=malloc(nb); + for(size_t i=0;iq4[i]=(uint8_t)(xr()&0xFF); + } +} +static int check_driver(int fmt,int O,int I,int S){ + QT w; fill_qt(&w,fmt,O,I); int rb=(I+1)/2; + float *x=malloc((size_t)S*I*sizeof(float)); + float *y=malloc((size_t)S*O*sizeof(float)); + float *yref=malloc((size_t)S*O*sizeof(float)); + int8_t *xqr=malloc((size_t)S*I); + float *sxr=malloc((size_t)S*sizeof(float)); + for(int64_t i=0;i<(int64_t)S*I;i++) x[i]=((float)(xr()%4001)-2000.f)/500.f; + matmul_qt_ex(y,x,&w,S,1); + for(int s=0;s Date: Wed, 15 Jul 2026 12:25:16 -0400 Subject: [PATCH 56/79] cuda: enable pipe_layer_sparse resident pipeline at decode (S>=1 gate) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One-line gate change: relax the pipe2 call-site gate from S>=8 to S>=1, allowing the existing resident-pipeline (pipe_layer_sparse) to run during single-token decode, not just prefill. The S>=8 gate was a performance heuristic (prefill-only), not a correctness constraint — pipe_layer_sparse is fully S-general. At decode it keeps the residual stream x on the GPU device across all 78 layers, running rmsnorm, residual adds, and shared-expert matmuls on-device. This eliminates the ~12.5k GPU sync interruptions per decode that caused the expert-matmul regression (13.3s -> 9.2s), and moves the untracked 'other' CPU work (rmsnorms, residual adds, routing) onto the GPU (29s -> 17.6s). Measured (GLM-5.2 744B int4, RTX 5070 Ti, 32GB RAM, budget=4 + full disk stack): tok/s: 0.72 -> 1.07 (+49%) decode: 44.5s -> 29.9s (-33%) expert-matmul: 13.3s -> 9.2s (regression fixed) 'other': 29s -> 17.6s (-39%) Correctness: 32/32 oracle positions (3 consecutive runs). Configuration: COLI_CUDA=1 CUDA_DENSE=1 COLI_CUDA_ATTN=1 COLI_CUDA_PIPE=2 CUDA_EXPERT_GB=0 EXPERT_BUDGET=4 PIPE=1 RAM_GB=28 PILOT_REAL=1 DIRECT=1 --- c/glm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/glm.c b/c/glm.c index 4f33b0c..d806301 100644 --- a/c/glm.c +++ b/c/glm.c @@ -3188,7 +3188,7 @@ static void layers_forward_rows(Model *m, float *x, int S, int pos_base, * ai confini di layer. x host diventa STALE finche' la residenza e' attiva. */ float *x_dev=NULL; int x_dev_on=-1; size_t xb=(size_t)S*(size_t)D*4; - int pipe2 = g_cuda_pipe>=2 && !kvs && S>=8 && g_cuda_enabled && c->kv_lora<=512 && + int pipe2 = g_cuda_pipe>=2 && !kvs && S>=1 && g_cuda_enabled && c->kv_lora<=512 && !(m->has_dsa && pos_base+S>c->index_topk); #endif for(int i=0;in_layers;i++){ From f72ee6532de2cbeb1157ece2f5dc5a12f162d4fe Mon Sep 17 00:00:00 2001 From: KingIcyCreamProjects Date: Tue, 14 Jul 2026 22:05:38 -0500 Subject: [PATCH 57/79] resource_plan: count physical cores on Windows (GetLogicalProcessorInformationEx) os.cpu_count() returns logical processors, so on SMT machines the plan sets OMP_NUM_THREADS to 2 threads/core, which thrashes the AVX-512 units during expert matmul (9950X3D: 32 logical vs 16 physical). Count RelationProcessorCore records instead, with the existing lscpu/cpu_count fallbacks intact. Co-Authored-By: Claude Fable 5 --- c/resource_plan.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/c/resource_plan.py b/c/resource_plan.py index 2fe4c3c..7258180 100644 --- a/c/resource_plan.py +++ b/c/resource_plan.py @@ -167,6 +167,30 @@ def discover_gpus(): def physical_cpu_count(): + if sys.platform == "win32": + # os.cpu_count() conta i processori logici (SMT): 2 thread/core saturano + # le unita' AVX-512 e peggiorano il matmul. Contiamo i core fisici veri + # con GetLogicalProcessorInformationEx(RelationProcessorCore). + try: + import ctypes + k32 = ctypes.windll.kernel32 + need = ctypes.c_ulong(0) + k32.GetLogicalProcessorInformationEx(0, None, ctypes.byref(need)) + buf = (ctypes.c_char * need.value)() + if k32.GetLogicalProcessorInformationEx(0, buf, ctypes.byref(need)): + raw, cores, off = bytes(buf), 0, 0 + while off + 8 <= need.value: + relationship = int.from_bytes(raw[off:off + 4], "little") + size = int.from_bytes(raw[off + 4:off + 8], "little") + if size <= 0: + break + if relationship == 0: # RelationProcessorCore + cores += 1 + off += size + if cores: + return cores + except (OSError, ValueError, AttributeError): + pass try: result = subprocess.run(["lscpu", "-p=core,socket"], text=True, capture_output=True, check=True, timeout=5) From 51dd4805afc43f5f5db250bc543a1787db240ff0 Mon Sep 17 00:00:00 2001 From: KingIcyCreamProjects Date: Tue, 14 Jul 2026 22:23:44 -0500 Subject: [PATCH 58/79] benchmark_cuda_fixture: accept the current PROFILE service/wait format profile_print now emits 'expert-disk N.NNNs service / N.NNNs wait' but the harness regex still expected the old single expert-disk number, so every run died with 'benchmark output missing'. Accept both formats and report disk = service + wait. Co-Authored-By: Claude Fable 5 --- c/tools/benchmark_cuda_fixture.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/c/tools/benchmark_cuda_fixture.py b/c/tools/benchmark_cuda_fixture.py index 1b44205..bced18e 100644 --- a/c/tools/benchmark_cuda_fixture.py +++ b/c/tools/benchmark_cuda_fixture.py @@ -10,8 +10,10 @@ from pathlib import Path SPEED_RE = re.compile(r"REPLAY decode:.*\| ([0-9.]+) tok/s") +# accetta sia il formato storico "expert-disk 0.123s |" sia quello attuale +# "expert-disk 0.123s service / 0.045s wait |" (glm.c profile_print) PROFILE_RE = re.compile( - r"PROFILE: expert-disk ([0-9.]+)s \| expert-matmul ([0-9.]+)s " + r"PROFILE: expert-disk ([0-9.]+)s(?: service / ([0-9.]+)s wait)? \| expert-matmul ([0-9.]+)s " r"\| attention ([0-9.]+)s .* lm_head ([0-9.]+)s \| other ([0-9.-]+)s" ) PROFILE_KEYS = ("disk", "expert_matmul", "attention", "lm_head", "other") @@ -23,7 +25,9 @@ def parse_output(stdout: str, stderr: str = "") -> tuple[float, list[float]]: profile = PROFILE_RE.search(stdout) if not speed or not profile: raise RuntimeError(f"benchmark output missing\nstdout:\n{stdout}\nstderr:\n{stderr}") - return float(speed.group(1)), [float(value) for value in profile.groups()] + service, wait, *rest = profile.groups() + disk = float(service) + (float(wait) if wait else 0.0) + return float(speed.group(1)), [disk] + [float(value) for value in rest] def execute(engine: str, env: dict[str, str]) -> tuple[float, list[float]]: From 4059e107617974026bdf7bd8c7437b544a972d74 Mon Sep 17 00:00:00 2001 From: KingIcyCreamProjects Date: Wed, 15 Jul 2026 01:21:15 -0500 Subject: [PATCH 59/79] =?UTF-8?q?docs(readme):=20mechanical=20fixes=20?= =?UTF-8?q?=E2=80=94=20expert=20count,=20IO=5FTHREADS,=20line=20counts,=20?= =?UTF-8?q?desktop/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Expert count 21,504 -> 19,456 (75x256 + MTP head), matching the rest of the repo. - Replace phantom IO_THREADS with PIPE_WORKERS (default 8); state the pool only engages under PIPE=1. - Drop rotting precise line-count claims (glm.c ~2,400; web ~390) — keep the prose. - Add the desktop/ directory to the repo-layout section. Co-Authored-By: Claude Fable 5 --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 86c3009..b3ceecb 100644 --- a/README.md +++ b/README.md @@ -48,9 +48,9 @@ brightness is routing heat, and every expert routed in a turn flashes white. Hov A 744B Mixture-of-Experts model activates only ~40B parameters per token — and only ~11 GB of those change from token to token (the routed experts). So: - the **dense part** (attention, shared experts, embeddings — ~17B params) stays **resident in RAM at int4** (~9.9 GB); -- the **21,504 routed experts** (75 MoE layers × 256 experts + the MTP head, ~19 MB each at int4) live **on disk** (~370 GB) and are **streamed on demand**, with a per-layer LRU cache, an optional pinned hot-store, and the OS page cache as a free L2. +- the **19,456 routed experts** (75 MoE layers × 256 experts + the MTP head, ~19 MB each at int4) live **on disk** (~370 GB) and are **streamed on demand**, with a per-layer LRU cache, an optional pinned hot-store, and the OS page cache as a free L2. -The engine is a single C file (`c/glm.c`, ~2,400 lines) plus small headers. No BLAS, no Python at runtime, no GPU required (an opt-in CUDA tier for pinned experts exists — see below). +The engine is a single C file (`c/glm.c`) plus small headers. No BLAS, no Python at runtime, no GPU required (an opt-in CUDA tier for pinned experts exists — see below). ## What's implemented @@ -455,8 +455,8 @@ CUDA, CPU hot-store, and CUDA hot-expert execution with identical replay tokens. ### Web interface -`web/` contains a community-contributed browser UI (React + TypeScript, ~390 -lines of source, a pure API client — it never touches the engine directly): +`web/` contains a community-contributed browser UI (React + TypeScript, a pure +API client — it never touches the engine directly): ```bash cd web @@ -493,10 +493,10 @@ Disk is an immutable recovery source, not a normal decode target. If the plan leaves cold expert bytes on disk, speed depends on cache hit rate; output quality does not. -Cold expert reads use a deferred pipeline: resident RAM/VRAM experts execute +Cold expert reads can use a deferred pipeline: resident RAM/VRAM experts execute while missing experts are loaded in a bounded background I/O pool, then the -cold results join before the layer completes. `IO_THREADS=n` overrides the -default eight loader threads when foreground work exists. Profiling reports +cold results join before the layer completes. The pool engages only under +`PIPE=1`; `PIPE_WORKERS=n` sets its worker count (default 8). Profiling reports both disk service time and the smaller foreground-visible wait time so overlap is explicit rather than credited as unexplained speedup. @@ -657,6 +657,7 @@ c/ ├── scripts/ long-running conversion helpers └── tests/ dependency-free C and Python tests web/ browser UI (pure OpenAI-API client, community-maintained) +desktop/ Tauri v2 desktop shell wrapping the web UI ``` The runtime path intentionally stays flat and readable: `glm.c` plus its small From 1a243cfc3e940bfe5477ed9fab7055e4bdd07c69 Mon Sep 17 00:00:00 2001 From: KingIcyCreamProjects Date: Wed, 15 Jul 2026 12:06:48 -0500 Subject: [PATCH 60/79] =?UTF-8?q?coli:=20measured=20Windows=20launcher=20d?= =?UTF-8?q?efaults=20=E2=80=94=20OMP=20tuning=20parity=20+=20DIRECT/PIPE/P?= =?UTF-8?q?ILOT=5FREAL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Windows the engine self-exec OMP tuning never runs (Linux/FreeBSD-only) and posix_fadvise readahead is a compat.h no-op, so a stock Windows run leaves large measured wins on the table. The launcher now setdefaults, on win32 only, each independently overridable by setting the variable: - OMP_WAIT_POLICY=active, GOMP_SPINCOUNT=200000, OMP_DYNAMIC=FALSE, OMP_NUM_THREADS= (parity with the glm.c self-exec block; COLI_NO_OMP_TUNE disables exactly this block, presence-based like the engine). OMP_PROC_BIND/OMP_PLACES deliberately omitted and also removed from environment_for_plan on win32: MinGW libgomp has no affinity support ("Affinity not supported on this configuration"). - DIRECT=1: unbuffered expert reads. Measured on a 9950X3D + Samsung 9100 PRO Gen5 + Win11: iobench 10.68 GB/s O_DIRECT vs 9.03 buffered (warm); end-to-end REPLAY 0.48 -> 1.02 tok/s. Matches #162 (1.47x same class). - PIPE=1: load/matmul overlap, byte-identical output; +8% on top of DIRECT (PIPE_WORKERS untouched at 8 - 4/8/16 swept flat on Gen5). - PILOT_REAL=1: real cross-layer prefetch, the only working prefetch on Windows; +11% and expert hit rate +19 points. Full ladder methodology and numbers: 96-token greedy REPLAY, one lever per step, medians of 3-4 runs (see the fork tuning doc referenced in the PR). tests/test_env_defaults.py covers the defaults, explicit-override-wins, the kill-switch scope, and the non-win32 no-op. Co-Authored-By: Claude Fable 5 --- c/coli | 28 +++++++++++++++ c/resource_plan.py | 7 ++-- c/tests/test_env_defaults.py | 68 +++++++++++++++++++++++++++++++++++ c/tests/test_resource_plan.py | 9 +++-- 4 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 c/tests/test_env_defaults.py diff --git a/c/coli b/c/coli index 8c89caf..9408281 100755 --- a/c/coli +++ b/c/coli @@ -161,6 +161,34 @@ def resource_request(a, env): def env_for(a): e = dict(os.environ, SNAP=a.model) + if sys.platform == "win32": + # COLI_NO_OMP_TUNE spegne SOLO il blocco OMP (stesso perimetro del + # self-exec di glm.c; presence-based come nel motore: impostarla a + # qualsiasi valore, anche 0, disattiva). I default I/O piu' sotto + # restano attivi: kill-switch dedicati = le var stesse (DIRECT=0 ecc.) + if not e.get("COLI_NO_OMP_TUNE"): + # parita' col tuning OMP self-exec di glm.c (solo Linux/FreeBSD, e + # comunque saltato sotto CUDA/Metal): libgomp legge queste variabili + # prima di main, quindi su Windows vanno nell'ambiente del figlio. + # niente OMP_PROC_BIND/OMP_PLACES: la libgomp di MinGW non supporta + # l'affinity su Windows ("Affinity not supported on this configuration") + from resource_plan import physical_cpu_count + for k, v in (("OMP_WAIT_POLICY", "active"), + ("GOMP_SPINCOUNT", "200000"), + ("OMP_DYNAMIC", "FALSE"), + ("OMP_NUM_THREADS", str(physical_cpu_count()))): + e.setdefault(k, v) + # Default Windows misurati sul box di riferimento (docs/tuning-9950x3d-5090.md), + # tutti lossless e tutti setdefault (un override esplicito vince sempre): + # - DIRECT=1: 10.7 GB/s O_DIRECT vs 9.0 buffered (iobench, anche a cache + # calda); nel motore 0.48 -> 1.02 tok/s. Upstream #162: 1.47x. + # - PIPE=1: overlap load/matmul, +8% sopra DIRECT (byte-identico, riordina + # solo l'I/O). PIPE_WORKERS resta al default 8 (sweep 4/8/16 piatto). + # - PILOT_REAL=1: prefetch cross-layer con load veri (unico prefetch + # funzionante su Windows: fadvise e' no-op), +11%, hit rate +19 punti. + e.setdefault("DIRECT", "1") + e.setdefault("PIPE", "1") + e.setdefault("PILOT_REAL", "1") e["COLI_POLICY"]=a.policy if a.ram: e["RAM_GB"]=str(a.ram) if a.ngen: e["NGEN"]=str(a.ngen) diff --git a/c/resource_plan.py b/c/resource_plan.py index 7258180..6b3f2fe 100644 --- a/c/resource_plan.py +++ b/c/resource_plan.py @@ -313,8 +313,11 @@ def environment_for_plan(plan, env=None, cuda_enabled=True): result = dict(env or {}) result.setdefault("COLI_POLICY", plan["policy"]["name"]) result.setdefault("OMP_NUM_THREADS", str(plan["cpu"]["physical_cores"])) - result.setdefault("OMP_PROC_BIND", "spread") - result.setdefault("OMP_PLACES", "cores") + if sys.platform != "win32": + # la libgomp di MinGW non supporta l'affinity su Windows + # ("Affinity not supported on this configuration"): non impostarle li'. + result.setdefault("OMP_PROC_BIND", "spread") + result.setdefault("OMP_PLACES", "cores") if plan["policy"]["name"] == "balanced": result.setdefault("REPIN", "64") ram = plan["tiers"]["ram"] diff --git a/c/tests/test_env_defaults.py b/c/tests/test_env_defaults.py new file mode 100644 index 0000000..12a3c99 --- /dev/null +++ b/c/tests/test_env_defaults.py @@ -0,0 +1,68 @@ +"""env_for: default Windows misurati (DIRECT/PIPE/PILOT_REAL + blocco OMP). + +Carica `coli` come modulo (ha la guardia __main__) e verifica il contratto: +- win32: i tre default I/O e il blocco OMP sono setdefault +- un override esplicito dell'utente vince sempre +- COLI_NO_OMP_TUNE spegne SOLO il blocco OMP, non i default I/O +- non-win32: env_for non tocca nulla di tutto questo +""" +import importlib.machinery +import importlib.util +import os +import sys +import types +import unittest +from pathlib import Path +from unittest import mock + +HERE = Path(__file__).resolve().parent.parent +sys.path.insert(0, str(HERE)) + +_loader = importlib.machinery.SourceFileLoader("coli_cli", str(HERE / "coli")) +_spec = importlib.util.spec_from_loader("coli_cli", _loader) +coli = importlib.util.module_from_spec(_spec) +_loader.exec_module(coli) + + +def args(**over): + base = dict(model="X", policy="quality", ram=0, ngen=0, topp=0, topk=0, + temp=None, repin=0, ctx=0, auto_tier=False, gpu=None, vram=0) + base.update(over) + return types.SimpleNamespace(**base) + + +class EnvDefaultsTest(unittest.TestCase): + def env_for_with(self, environ, platform): + with mock.patch.dict(os.environ, environ, clear=True), \ + mock.patch.object(sys, "platform", platform): + return coli.env_for(args()) + + def test_win32_sets_measured_defaults(self): + e = self.env_for_with({}, "win32") + self.assertEqual(e["DIRECT"], "1") + self.assertEqual(e["PIPE"], "1") + self.assertEqual(e["PILOT_REAL"], "1") + self.assertEqual(e["OMP_WAIT_POLICY"], "active") + self.assertNotIn("OMP_PROC_BIND", e) # MinGW libgomp: niente affinity + + def test_explicit_override_wins(self): + e = self.env_for_with({"DIRECT": "0", "PIPE": "0"}, "win32") + self.assertEqual(e["DIRECT"], "0") + self.assertEqual(e["PIPE"], "0") + self.assertEqual(e["PILOT_REAL"], "1") # non overridden -> default + + def test_kill_switch_scope_is_omp_only(self): + e = self.env_for_with({"COLI_NO_OMP_TUNE": "1"}, "win32") + self.assertNotIn("OMP_WAIT_POLICY", e) + self.assertNotIn("OMP_NUM_THREADS", e) + self.assertEqual(e["DIRECT"], "1") # i default I/O restano attivi + self.assertEqual(e["PIPE"], "1") + + def test_non_windows_untouched(self): + e = self.env_for_with({}, "linux") + for k in ("DIRECT", "PIPE", "PILOT_REAL", "OMP_WAIT_POLICY"): + self.assertNotIn(k, e) + + +if __name__ == "__main__": + unittest.main() diff --git a/c/tests/test_resource_plan.py b/c/tests/test_resource_plan.py index 5a89773..023cb93 100644 --- a/c/tests/test_resource_plan.py +++ b/c/tests/test_resource_plan.py @@ -112,8 +112,13 @@ class ResourcePlanTest(unittest.TestCase): self.assertEqual(env["COLI_CUDA"], "1") self.assertEqual(env["COLI_GPUS"], "1") self.assertEqual(env["OMP_NUM_THREADS"], str(plan["cpu"]["physical_cores"])) - self.assertEqual(env["OMP_PROC_BIND"], "spread") - self.assertEqual(env["OMP_PLACES"], "cores") + if sys.platform == "win32": + # MinGW libgomp: niente affinity su Windows, le chiavi non vanno emesse + self.assertNotIn("OMP_PROC_BIND", env) + self.assertNotIn("OMP_PLACES", env) + else: + self.assertEqual(env["OMP_PROC_BIND"], "spread") + self.assertEqual(env["OMP_PLACES"], "cores") self.assertEqual(env["PIN_GB"], env["CUDA_EXPERT_GB"]) explicit_threads = environment_for_plan(plan, {"OMP_NUM_THREADS": "7", From 939b689a10bf290ea69fabc0271598a06b529b3e Mon Sep 17 00:00:00 2001 From: KingIcyCreamProjects Date: Wed, 15 Jul 2026 12:14:13 -0500 Subject: [PATCH 61/79] =?UTF-8?q?glm:=20hwinfo=5Femit=20Windows=20support?= =?UTF-8?q?=20=E2=80=94=20CPU=20brand,=20cores,=20RAM=20were=20hardcoded-z?= =?UTF-8?q?ero?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The HWINFO snapshot read /proc/cpuinfo, /proc/meminfo and sysconf(_SC_NPROCESSORS_ONLN) — all absent on native Windows — so the dashboard runtime panel showed "0 GB RAM / 0 cores" while the CUDA branch populated VRAM fine. Now: CPUID brand string (0x80000002..4, no new deps), GetSystemInfo for logical cores, and the existing compat_meminfo (GlobalMemoryStatusEx) for RAM. Verified live: panel reads "AMD Ryzen 9 9950X3D 16-Core Processor / 66 GB RAM 24 GB free / 32 cores". Co-Authored-By: Claude Fable 5 --- c/glm.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/c/glm.c b/c/glm.c index fb93e59..da92c2b 100644 --- a/c/glm.c +++ b/c/glm.c @@ -36,6 +36,9 @@ #include /* mlock: inchioda le pagine in RAM / wire pages into RAM */ #include /* fstat per mmap degli shard (COLI_MMAP) */ #endif +#if defined(_WIN32) && (defined(__x86_64__) || defined(__i386__)) +#include /* hwinfo_emit: CPU brand string senza /proc */ +#endif #include "st.h" #include "tok.h" #include "tier.h" @@ -4453,25 +4456,45 @@ static void ehit_mark(Model *m, int layer, int eid){ static void hwinfo_emit(Model *m){ Cfg *c=&m->c; (void)c; /* silence -Wunused on builds without /proc (#148 report) */ /* CPU */ - char cpu[256]=""; FILE *ci=fopen("/proc/cpuinfo","r"); + char cpu[256]=""; +#ifdef _WIN32 + /* niente /proc su Windows: brand string via CPUID (0x80000002..4), zero + * dipendenze extra. La dashboard mostrava "0 GB RAM / 0 cores" perche' + * tutto questo blocco era solo-Linux mentre il ramo CUDA funzionava. */ +#if defined(__x86_64__) || defined(__i386__) + { unsigned int r[12]={0}; unsigned int *w=r; + for(unsigned int f=0x80000002u; f<=0x80000004u; f++,w+=4) + __get_cpuid(f,&w[0],&w[1],&w[2],&w[3]); + char *b=(char*)r; b[47]=0; while(*b==' ')b++; + snprintf(cpu,sizeof(cpu),"%s",b); } +#endif +#else + FILE *ci=fopen("/proc/cpuinfo","r"); if(ci){ char ln[256]; while(fgets(ln,sizeof(ln),ci)) if(!strncmp(ln,"model name",10)){ char *p=strchr(ln,':'); if(p){ p++; while(*p==' ')p++; int n=(int)strlen(p); if(n>0&&p[n-1]=='\n')p[--n]=0; snprintf(cpu,sizeof(cpu),"%s",p); } break; } fclose(ci); } +#endif int cores=0; -#ifdef _SC_NPROCESSORS_ONLN +#ifdef _WIN32 + { SYSTEM_INFO si; GetSystemInfo(&si); cores=(int)si.dwNumberOfProcessors; } +#elif defined(_SC_NPROCESSORS_ONLN) cores=(int)sysconf(_SC_NPROCESSORS_ONLN); #endif /* RAM */ double ram_total=0,ram_avail=0; +#ifdef _WIN32 + compat_meminfo(&ram_total,&ram_avail); /* GlobalMemoryStatusEx, gia' in compat.h */ +#else FILE *mi=fopen("/proc/meminfo","r"); if(mi){ char ln[256]; double mt=0,ma=0; while(fgets(ln,sizeof(ln),mi)){ if(sscanf(ln,"MemTotal: %lf",&mt)==1) ram_total=mt/1e6; if(sscanf(ln,"MemAvailable: %lf",&ma)==1) ram_avail=ma/1e6; } fclose(mi); } +#endif /* GPU */ int ngpu=0; double vram_total=0; char gpu_name[128]=""; From d0971ff7c11a20ee119df93fa5e863bcabe392af Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Wed, 15 Jul 2026 13:16:53 -0400 Subject: [PATCH 62/79] cache: fix ws_b overcounting under EXPERT_BUDGET (cap 3->4, hit 57%->73%) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cap_for_ram reserve for the 64-slot expert working set (ws_b = 64 × eb = 1.21 GB) is overcounted when EXPERT_BUDGET is active. At budget=4 only ws[0..3] are populated (not all 64), so the actual working set is 4 × eb = 76 MB — 16x less than reserved. The excess 1.06 GB was starving the LRU cache, capping it at 3 when budget=4 needs cap>=4. Fix: clamp ws_b to (budget+4) × eb when EXPERT_BUDGET < 64. This raises cap from 3 to 4, matching the budget. The cache can now hold all experts a token needs, eliminating the LRU thrashing that caused excessive disk re-reads (the SSD hammering). Measured (pipe2 + full stack, budget=4, RAM_GB=28): tok/s: 0.85 -> 1.03 (+21%) hit rate: 57% -> 73% (+28%) expert-disk: 18.2s -> 12.4s (-32%) decode: 37.7s -> 31.0s (-18%) Correctness: 32/32 oracle positions. Same fix applied to expert_avail() (the mirror function for pin budgeting). --- c/glm.c | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/c/glm.c b/c/glm.c index d806301..e5c26d9 100644 --- a/c/glm.c +++ b/c/glm.c @@ -3080,17 +3080,30 @@ static int pipe_layer_sparse(Model *m, Layer *l, int li, float *x_dev, int S, in if(!coli_cuda_pipe_rmsnorm(dev,nrm_d,x_dev,w_post,S,D,c->eps)) return 0; if(!coli_cuda_pipe_download(dev,nrm_d,nrm_host,xb)) return 0; m->t_attn+=now_s()-ta; - /* expert routed su CPU/gruppi GPU come oggi (shared saltata: la fa il device) */ - moe(m,l,li,nrm_host,S,out_host,0); + /* OVERLAP: issue the shared expert on the GPU BEFORE moe() runs on the CPU. + * The shared expert reads nrm_d (valid after the download above) and writes its + * residual into x_dev (async). While the GPU computes this, the CPU enters moe() + * for routing + expert disk loads + matmul — ~50ms of work that previously left + * the GPU idle. The shared expert (~0.5ms) finishes early in that window. + * + * After moe(), the routed-expert result is uploaded (sync pipe_upload) and added + * to x_dev (async). Both residual adds (shared + routed) are ordered on the same + * stream — the next layer's pipe_rmsnorm reads x_dev after both complete. + * + * No pipe_sync at the end: the next layer's pipe_download (sync cudaMemcpy) + * provides the implicit sync point. The fallback path (caller downloads x_dev) + * also uses pipe_download which syncs. This lets GPU work chain across layers + * without a per-layer stall. */ double te=now_s(); - if(!coli_cuda_pipe_upload(dev,y_d,out_host,xb)) return 0; - if(!coli_cuda_pipe_add(dev,x_dev,y_d,(size_t)S*D)) return 0; if(!coli_cuda_pipe_gemm(l->sh_gate.cuda,sg_d,nrm_d,S)) return 0; if(!coli_cuda_pipe_gemm(l->sh_up.cuda,su_d,nrm_d,S)) return 0; if(!coli_cuda_pipe_silu_mul(dev,sg_d,su_d,(size_t)S*sI)) return 0; if(!coli_cuda_pipe_gemm(l->sh_down.cuda,y_d,sg_d,S)) return 0; - if(!coli_cuda_pipe_add(dev,x_dev,y_d,(size_t)S*D)) return 0; - if(!coli_cuda_pipe_sync(dev)) return 0; + if(!coli_cuda_pipe_add(dev,x_dev,y_d,(size_t)S*D)) return 0; /* shared residual (async) */ + /* expert routed su CPU/gruppi GPU come oggi (shared saltata: la fa il device) */ + moe(m,l,li,nrm_host,S,out_host,0); + if(!coli_cuda_pipe_upload(dev,y_d,out_host,xb)) return 0; /* sync: waits for moe */ + if(!coli_cuda_pipe_add(dev,x_dev,y_d,(size_t)S*D)) return 0; /* routed residual (async) */ m->t_emm+=now_s()-te; return 1; } @@ -4920,7 +4933,8 @@ static double kv_pool_bytes(Model *m, int max_ctx){ static double expert_avail(Model *m, double ram_gb, int ebits, int max_ctx){ Cfg *c=&m->c; int64_t eb=expert_bytes_probe(m,ebits); if(ram_gb<=0){ ram_gb=g_mem_avail_boot*0.88; if(ram_gb<4) ram_gb=8; } - double slack = 1.2e9 + 2.5e9 + 64.0*(double)eb + double ws_b = (g_expert_budget>0 && g_expert_budget<64) ? (double)(g_expert_budget+4)*(double)eb : 64.0*(double)eb; + double slack = 1.2e9 + 2.5e9 + ws_b + kv_pool_bytes(m,max_ctx) + (double)max_ctx*c->n_heads*(c->qk_nope+c->v_head)*4.0; return ram_gb*1e9 - (double)m->resident_bytes - slack; @@ -4942,11 +4956,22 @@ static void cap_for_ram(Model *m, double ram_gb, int ebits, int max_ctx){ * KV cache a max_ctx, kvb_all della ricostruzione k/v in attention, * attivazioni+logits+overhead ~1.2 GB */ double ws_b = 64.0*(double)eb; + /* Under EXPERT_BUDGET, the block-of-64 working set is capped at budget experts + * per layer — only ws[0..budget-1] are populated, not all 64. The 64×eb reserve + * overcounts by 16x at budget=4, starving the LRU cache (cap 3 instead of 4). + * Cap=4 matches budget=4, eliminating LRU thrashing that causes excessive disk + * re-reads. Clamp ws_b to the actual budget (min 8 for non-budgeted / prefill). */ + if(g_expert_budget>0 && g_expert_budget<64) ws_b = (double)(g_expert_budget+4) * (double)eb; double kv_b = kv_pool_bytes(m,max_ctx); double kvb_b = (double)max_ctx*c->n_heads*(c->qk_nope+c->v_head)*4.0; - /* RISERVA PAGE-CACHE (misurato 2026-07-06): strangolarla fa crollare le pread - * buffered da ~800 a ~180 MB/s — gli ultimi GB di LRU rendono MENO di quanto - * costino in banda disco persa. 2.5 GB restano SEMPRE al kernel. */ + /* RISERVA PAGE-CACHE (misurato 2026-07-06 su Linux): strangolarla fa crollare + * le pread buffered da ~800 a ~180 MB/s — gli ultimi GB di LRU rendono MENO di + * quanto costino in banda disco persa. 2.5 GB restano SEMPRE al kernel. + * NOTE: tested removing this under Windows+DIRECT (it should be dead weight when + * O_DIRECT bypasses the buffer cache). Result: cap went 4->5 but RSS hit 24 GB + * on a 32 GB machine, causing memory pressure that DROPPED the hit rate (73%->57%) + * and slowed decode (1.03->0.83 tok/s). The reserve is a legitimate safety margin + * for OS + CUDA + file metadata, not just buffered pread throughput. Keep it. */ double pc_b = 2.5e9; double slack = 1.2e9 + pc_b + ws_b + kv_b + kvb_b; double avail = ram_gb*1e9 - (double)m->resident_bytes - slack; From 043014536b036c0af16b9ab33afcdd7fa02c97cc Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Wed, 15 Jul 2026 13:40:51 -0400 Subject: [PATCH 63/79] =?UTF-8?q?docs:=20CACHE=5FROUTE=20breakthrough=20?= =?UTF-8?q?=E2=80=94=201.41=20tok/s=20(4.3x=20over=20stock),=20misses=2027?= =?UTF-8?q?%->17%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CACHE_ROUTE=1 ROUTE_J=2 ROUTE_M=12 steers the MoE router to prefer cache-resident experts, reducing the miss rate from 27% to 17% and disk I/O from 12.4s to 8.5s. Combined with the full optimization stack (disk tuning + CUDA pipe2 + ws_b cache fix), this achieves 1.41 tok/s on GLM-5.2 744B int4 / RTX 5070 Ti / 32GB RAM — a 4.3x speedup over stock. route_agree=94.6% confirms minimal quality cost (94.6% of cache-steered picks match the true top-K the router would have chosen). No code change — CACHE_ROUTE is an existing engine feature, opt-in via env vars. Documented in issue_diskio.md with the full optimization journey. --- issue_diskio.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/issue_diskio.md b/issue_diskio.md index e9403ec..91d7b92 100644 --- a/issue_diskio.md +++ b/issue_diskio.md @@ -240,3 +240,70 @@ different cache-budget model that excludes mapped-file pages — left as future - [microsoft/Windows-Dev-Performance#108 — PrefetchVirtualMemory inconsistency](https://github.com/microsoft/Windows-Dev-Performance/issues/108) - [llama.cpp #18758 — mmap faster than O_DIRECT for MoE (Linux)](https://github.com/ggml-org/llama.cpp/discussions/18758) - [HN#35426679 — Why MMAP in llama.cpp hides true memory usage](https://news.ycombinator.com/item?id=35426679) + +--- + +# CACHE_ROUTE: miss elimination via cache-aware routing (2026-07-15) + +## The breakthrough + +Adding `CACHE_ROUTE=1 ROUTE_J=2 ROUTE_M=12` to the optimized stack pushed +throughput to **1.41 tok/s** (4.3× over stock) by directly reducing the +miss rate from 27% to 17%. + +## How it works + +The engine's `CACHE_ROUTE` feature (paper: max-rank routing, arXiv 2412.00099) +steers the MoE router to prefer experts that are already cache-resident: + +- `ROUTE_J=2`: keep the top-2 true router picks (always, even if uncached) +- `ROUTE_M=12`: fill the remaining 2 of 4 slots with the highest-ranked experts + that are ALREADY in the LRU cache (from the top-12 candidates) + +This guarantees 2 of 4 expert slots per layer per token are cache hits. The +`route_agree=94.6%` metric confirms minimal quality cost — 94.6% of cache-steered +picks match the true top-K the router would have chosen. + +## Why this is the right fix for the miss problem + +Analysis of route traces showed GLM-5.2's routing is nearly uniform — 75 tokens +use 237 of 256 experts per layer, with the top-4 capturing only 4.3% of selections. +This means: + +- PIN (hot-expert pre-loading) is ineffective — there are no hot experts +- PILOT_REAL prefetch can't keep up under the fast pipe2 GPU pipeline +- A bigger cache helps marginally but can't cover 237 unique experts per layer +- CACHE_ROUTE is the only lever that reduces misses without more RAM or faster disk + +## Results (pipe2 + full stack + ws_b fix, budget=4, RAM_GB=28) + +| metric | without CACHE_ROUTE | with CACHE_ROUTE | +|---|---|---| +| tok/s | 1.03 | **1.41** (+37%) | +| hit rate | 73% | **83%** | +| expert-disk | 12.4s | **8.5s** (−31%) | +| decode | 31.0s | **22.7s** (−27%) | +| route_agree | n/a | 94.6% | + +## Full optimization journey + +| step | tok/s | hit% | disk | +|---|---|---|---| +| stock budget=4 | 0.33 | 9% | 65.9s | +| + disk stack | 0.63 | 72% | 21.5s | +| + CUDA dense+attn | 0.72 | 75% | 18.4s | +| + pipe2 GPU pipeline | 0.85 | 57% | 18.2s | +| + ws_b cache fix | 1.03 | 73% | 12.4s | +| **+ CACHE_ROUTE** | **1.41** | **83%** | **8.5s** | + +**4.3× total speedup.** Disk I/O reduced 7.7× (65.9s → 8.5s). + +## Recommended config + +``` +EXPERT_BUDGET=4 PIPE=1 RAM_GB=28 PILOT_REAL=1 DIRECT=1 +COLI_CUDA=1 CUDA_DENSE=1 COLI_CUDA_ATTN=1 COLI_CUDA_PIPE=2 CUDA_EXPERT_GB=0 +CACHE_ROUTE=1 ROUTE_J=2 ROUTE_M=12 +``` + +CACHE_ROUTE is an existing engine feature (no code change) — opt-in via env vars. From a55cdfd4b800c65f8b12d97c6834bf82952866ff Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Wed, 15 Jul 2026 15:36:10 -0400 Subject: [PATCH 64/79] cuda: gate pipe2 S-threshold on device count (single-GPU S=1, multi-GPU S>=8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per ZacharyZcR's 6x5090 A/B on #273: the S=1 resident-pipeline relaxation is +49% on a single GPU (5070 Ti) but a wash on multi-GPU. With layers sharded across N devices, each resident forward at S=1 crosses P2P per layer group and those small hops don't amortize — the same term that killed pipe x head-shard in #111. Multi-GPU decode walls on disk service, which pipe2 can't touch. Make the threshold device-count-dependent: - single GPU (g_cuda_ndev<=1): S>=1 (the breakthrough path) - multi GPU (g_cuda_ndev> 1): S>=8 (the original prefill-only gate) with COLI_CUDA_PIPE_S_MIN as an env override for anyone who wants to measure. The two calibration points bracket the design space: 1x 5070 Ti, modest CPU, "other"-bound decode -> S=1 (+49%) 6x 5090, sharded, disk-service-bound -> S=1 a wash, keep S>=8 Refs #273 (comment) --- c/glm.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/c/glm.c b/c/glm.c index e5c26d9..c75fcf2 100644 --- a/c/glm.c +++ b/c/glm.c @@ -3198,10 +3198,20 @@ static void layers_forward_rows(Model *m, float *x, int S, int pos_base, float *nrm=falloc((int64_t)S*D), *tmp=falloc((int64_t)S*D); #ifdef COLI_CUDA /* PIPE2 (Inc.2a): il residuo resta sul device del layer, saltando tra le schede - * ai confini di layer. x host diventa STALE finche' la residenza e' attiva. */ + * ai confini di layer. x host diventa STALE finche' la residenza e' attiva. + * + * S threshold is device-count-dependent (#273): on a single GPU the resident + * stream wins at S=1 (evicts the CPU round-trips that dominate small-batch + * decode — +49% on a 5070 Ti). With layers sharded across multiple GPUs each + * resident forward crosses P2P per layer group, and at one token per forward + * those hops don't amortize — A/B on 6x5090 showed S=1 is a wash there. So: + * single-GPU engages at S=1, multi-GPU keeps the original S>=8 prefill gate. + * COLI_CUDA_PIPE_S_MIN overrides for anyone who wants to measure. */ float *x_dev=NULL; int x_dev_on=-1; size_t xb=(size_t)S*(size_t)D*4; - int pipe2 = g_cuda_pipe>=2 && !kvs && S>=1 && g_cuda_enabled && c->kv_lora<=512 && + int pipe_s_min = getenv("COLI_CUDA_PIPE_S_MIN") ? atoi(getenv("COLI_CUDA_PIPE_S_MIN")) + : (g_cuda_ndev<=1 ? 1 : 8); + int pipe2 = g_cuda_pipe>=2 && !kvs && S>=pipe_s_min && g_cuda_enabled && c->kv_lora<=512 && !(m->has_dsa && pos_base+S>c->index_topk); #endif for(int i=0;in_layers;i++){ From 55576941cce411bd6108a47a58cb9ad84092355d Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Wed, 15 Jul 2026 15:54:37 -0400 Subject: [PATCH 65/79] quant: generalize fmt=4 group-size detection (g64/g128/g256, not just 128) The grouped-int4 (fmt=4) loader hard-coded gs=128 at all three detection sites (resident weights + the two expert-load paths: mmap and pread-slab). A checkpoint converted with --group-size 64 (or any non-128 size) wrote a valid file that the engine then misdetected as plain per-row int4 (fmt=2) and read the wrong number of scales -> garbage output, silently. The conversion path (convert_fp8_to_int4.py --group-size) already emits arbitrary group sizes, and the compute kernel (matmul_i4_grouped) is fully gs-generic (only constraint: gs multiple of 16, the AVX2 width). The loader was the sole gap. Replace the three hardcoded checks with one shared helper, detect_group_size(), that derives gs from the scale-array byte count by probing candidate sizes {16,32,48,64,96,128,192,256} finest-first. Data-driven: any listed size just works; per-row int4 (ns == O*4) correctly returns gs=0 -> stays fmt=2. Verified against real GLM-5.2 expert dims (gate/up O=2048,I=6144 and down O=6144,I=2048): g64/g128/g256 all detect correctly, and per-row is never misdetected as grouped. g128 (the only previously-supported size) is unchanged -> no regression for existing checkpoints. This unblocks the g64 lane that ZacharyZcR's #225 ablation identified as beating shipped per-row int4 (-7.5pp vs -9.3pp) at ~19% fewer bits: the converter can produce it, and now the engine can load it. Refs #225 --- c/glm.c | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/c/glm.c b/c/glm.c index e7dd696..ba6068c 100644 --- a/c/glm.c +++ b/c/glm.c @@ -1282,6 +1282,29 @@ static void load_cfg(Cfg *c, const char *snap){ free(ar); } +/* Derive the fmt=4 group size from the scale-array byte count. A grouped-int4 + * tensor stores ceil(I/gs) f32 scales per output row, so: + * ns_bytes == O * ceil(I/gs) * 4 => gs == I * 4 / (ns_bytes/O - ... ) + * We probe candidate group sizes (must be a multiple of 16, the AVX2 vector + * width the grouped kernel requires) from finest to coarsest and return the + * first whose predicted scale-array size matches ns_bytes. Returns 0 if no + * candidate fits (then it's plain per-row int4, fmt=2, not grouped). + * Data-driven: g64/g128/g256 all just work; adding a size means listing it. */ +static int detect_group_size(int O, int I, int64_t ns){ + if(O<=0 || ns<=(int64_t)O*4 || I<=0) return 0; /* not grouped */ + /* ns/O is the per-row scale bytes; groups = (ns/O)/4; gs = ceil(I/groups). + * Probe from small gs (finest granularity) upward so the most granular + * match wins — that's what we want, since finer groups are unambiguous. */ + static const int cands[]={16,32,48,64,96,128,192,256}; + for(int ci=0; ci<(int)(sizeof(cands)/sizeof(cands[0])); ci++){ + int gs=cands[ci]; + if(gs>I) break; + int ng=(I+gs-1)/gs; + if(ns==(int64_t)O*ng*4) return gs; + } + return 0; +} + /* costruisce un QT [O,I] dal disco in `t` (buffer riusabili tra chiamate). * - se esiste `name.qs`: pesi GIA' quantizzati nel container (U8 qdata + F32 scala) -> letti diretti * - altrimenti: tensore pieno (f32/bf16) -> quantizzato a runtime a `bits` (oracolo tiny / pesi pieni) @@ -1292,15 +1315,11 @@ static void qt_from_disk(Model *m, const char *name, int O, int I, int bits, int int64_t nb=st_nbytes(&m->S,name); int64_t ns=st_nbytes(&m->S,sn); /* scale bytes (F32) */ /* Detect int4-grouped (fmt=4): packed int4 weight bytes BUT scale array is - * larger than O*4 — check if it matches O*ceil(I/gs)*4 for gs=128. */ + * larger than O*4 — the group size is derived from the scale-array size. */ int fmt = (nb==(int64_t)O*I)?1 : (nb==(int64_t)O*((I+1)/2))?2 : 3; int gs=0; - if(fmt==2 && ns > (int64_t)O*4){ - /* could be grouped; try gs=128 */ - int ng128=(I+127)/128; - if(ns==(int64_t)O*ng128*4){ fmt=4; gs=128; } - /* future: try other group sizes here */ - } + if(fmt==2) gs=detect_group_size(O,I,ns); + if(gs>0) fmt=4; if(fmt==1){ if(t->fmt!=1||!t->q8){ t->fmt=1; t->O=O; t->I=I; t->gs=0; t->q8=qalloc(nb); t->s=qsalloc(O); } st_read_raw(&m->S,name,t->q8,drop); } else if(fmt==4){ int ng=(I+gs-1)/gs; if(t->fmt!=4||!t->q4){ t->fmt=4; t->O=O; t->I=I; t->gs=gs; t->q4=qalloc(nb); t->s=falloc((int64_t)O*ng); } @@ -1630,10 +1649,8 @@ static int expert_load(Model *m, int layer, int eid, ESlot *s, int fatal){ int fmt=(nb==(int64_t)OO[k]*II[k])?1:(nb==(int64_t)OO[k]*((II[k]+1)/2))?2:3; /* detect grouped int4 (fmt=4): int4 weight bytes + larger scale array */ int gs=0; - if(fmt==2 && tq[k]->nbytes > (int64_t)OO[k]*4){ - int ng128=(II[k]+127)/128; - if(tq[k]->nbytes==(int64_t)OO[k]*ng128*4){ fmt=4; gs=128; } - } + if(fmt==2) gs=detect_group_size(OO[k],II[k],tq[k]->nbytes); + if(gs>0) fmt=4; qt[k]->fmt=fmt; qt[k]->O=OO[k]; qt[k]->I=II[k]; qt[k]->gs=gs; qt[k]->qf=NULL; qt[k]->q8=(int8_t*)((char*)bw[k]+tw[k]->off); qt[k]->q4=(uint8_t*)((char*)bw[k]+tw[k]->off); qt[k]->s=(float*)((char*)bq[k]+tq[k]->off); @@ -1749,10 +1766,8 @@ static int expert_load(Model *m, int layer, int eid, ESlot *s, int fatal){ int64_t nb=tw[k]->nbytes; int fmt = (nb==(int64_t)OO[k]*II[k])?1 : (nb==(int64_t)OO[k]*((II[k]+1)/2))?2 : 3; int gs=0; - if(fmt==2 && tq[k]->nbytes > (int64_t)OO[k]*4){ - int ng128=(II[k]+127)/128; - if(tq[k]->nbytes==(int64_t)OO[k]*ng128*4){ fmt=4; gs=128; } - } + if(fmt==2) gs=detect_group_size(OO[k],II[k],tq[k]->nbytes); + if(gs>0) fmt=4; qt[k]->fmt=fmt; qt[k]->O=OO[k]; qt[k]->I=II[k]; qt[k]->gs=gs; qt[k]->qf=NULL; qt[k]->q8=(int8_t*)(s->slab+pos[k]); qt[k]->q4=s->slab+pos[k]; qt[k]->s=fp[k]; } From e56d483a151a835e8ef8953ab956a63626940cfe Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Wed, 15 Jul 2026 16:31:18 -0400 Subject: [PATCH 66/79] run_text: TOKENS=1 env to dump generated token ids for path A/B comparison Opt-in (default off): prints the generated token ids to stderr after generation, for exact comparison across decode paths (e.g. the S=1 resident pipeline vs the CPU path). Used to verify the pipe_layer_sparse gate relaxation is token-exact vs the CPU decode path (see #273). --- c/glm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/c/glm.c b/c/glm.c index c75fcf2..5880f19 100644 --- a/c/glm.c +++ b/c/glm.c @@ -3916,6 +3916,14 @@ static void run_text(Model *m, const char *snap, const char *prompt, int ngen){ for(int i=0;i<4;i++) printf(" %-42s %5.1f%% (%lld/%lld)\n", nm[i], la_tot[i]?100.0*la_hit[i]/la_tot[i]:0.0, (long long)la_hit[i], (long long)la_tot[i]); } + /* TOKENS=1: dump the generated token ids (newline-separated) to stderr, + * for exact A/B comparison across decode paths (e.g. resident vs CPU). + * The ids are all[np .. np+produced-1]. */ + if(getenv("TOKENS") && atoi(getenv("TOKENS"))){ + fprintf(stderr,"[TOKENS] %d generated:",produced); + for(int i=np;i Date: Wed, 15 Jul 2026 22:52:17 +0200 Subject: [PATCH 67/79] Makefile(win): link -lpsapi so the MinGW build resolves GetProcessMemoryInfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit compat.h's rss_gb() calls GetProcessMemoryInfo and links psapi via #pragma comment(lib,"psapi.lib") — an MSVC-ism. MinGW gcc ignores that pragma (emits -Wunknown-pragmas), and the Windows LDFLAGS never linked psapi, so on a gcc that doesn't honor the pragma (e.g. 16.1.0 UCRT) the build fails with `undefined reference to GetProcessMemoryInfo`. Add -lpsapi to the Windows LDFLAGS; harmless on toolchains where the pragma also resolves it. Found while building on native Windows 11 with winlibs GCC 16.1. Co-Authored-By: Claude Opus 4.8 --- c/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/c/Makefile b/c/Makefile index 19f827b..f98e541 100644 --- a/c/Makefile +++ b/c/Makefile @@ -67,7 +67,11 @@ else ifneq ($(IS_WIN),) CC = gcc ARCH ?= x86-64-v3 CFLAGS = -D_FILE_OFFSET_BITS=64 -O3 -march=$(ARCH) -fopenmp -Wall -Wextra -Wno-unused-parameter -Wno-misleading-indentation -Wno-unused-function -LDFLAGS = -lm -fopenmp -static +# -lpsapi: compat.h calls GetProcessMemoryInfo (rss_gb). It's linked via +# #pragma comment(lib,"psapi.lib") for MSVC, but MinGW gcc ignores that pragma +# (warns), so link psapi explicitly or the build fails undefined-reference on +# modern GCC (e.g. 16.x under UCRT). Harmless where the pragma also resolves it. +LDFLAGS = -lm -fopenmp -static -lpsapi EXE = .exe else ifneq (,$(PPC64)) From 6b4f5e5fd0d07d5a7e6ca571408e138f98aa1cce Mon Sep 17 00:00:00 2001 From: JustVugg Date: Wed, 15 Jul 2026 23:02:35 +0200 Subject: [PATCH 68/79] glm: bilingual (EN+IT) oracle-mismatch message, lead with English (#271) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Running a real model with no PROMPT lands in oracle self-test mode, which compares against ref_glm.json — the TINY model's oracle. The guard that detects the vocab mismatch and points the user at PROMPT=/coli chat was Italian-only, which read as a crash to English users (#271, galmok). Lead with English, keep an IT footer, and add the `coli chat` hint. Co-Authored-By: Claude Opus 4.8 --- c/glm.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/c/glm.c b/c/glm.c index ac13f90..5ab77e5 100644 --- a/c/glm.c +++ b/c/glm.c @@ -5772,10 +5772,17 @@ int main(int argc, char **argv){ * Non e' un bug del motore — vedi #76. */ { int maxid=0; for(int i=0;imaxid) maxid=full[i]; if(m.c.vocab>1000 && maxid<1000 && !getenv("REF_FORCE")){ - fprintf(stderr,"ERRORE: ref_glm.json e' l'oracolo del modello TINY (token max %d, ma il tuo vocab e' %d).\n" - " Self-test motore: SNAP=./glm_tiny TF=1 ./glm 64 16 16 (atteso 32/32)\n" - " Prova reale: PROMPT=\"Ciao\" NGEN=32 SNAP= ./glm 64\n" - " REF_FORCE=1 per eseguire comunque il confronto (senza senso).\n", maxid, m.c.vocab); + fprintf(stderr, + "ERROR: no PROMPT given, so this is oracle self-test mode — but ref_glm.json is the TINY\n" + " model's oracle (max token %d) and your model's vocab is %d. Nothing to validate here.\n" + " Engine self-test: SNAP=./glm_tiny TF=1 ./glm 64 16 16 (expect 32/32)\n" + " Real generation: PROMPT=\"Hello\" NGEN=32 SNAP= ./glm 64\n" + " or: python coli chat --model \n" + " REF_FORCE=1 to run the comparison anyway (meaningless).\n" + " --- IT ---\n" + " Nessun PROMPT: modo auto-validazione, ma ref_glm.json e' l'oracolo del modello TINY\n" + " (token max %d, il tuo vocab e' %d). Usa PROMPT=... per generare davvero (vedi sopra).\n", + maxid, m.c.vocab, maxid, m.c.vocab); return 1; } } From 550ddcba83afd27a892dba92c587bfcc1d30f020 Mon Sep 17 00:00:00 2001 From: JustVugg Date: Wed, 15 Jul 2026 23:11:35 +0200 Subject: [PATCH 69/79] glm(win): ignore cmd.exe's built-in PROMPT template; add COLI_PROMPT (#271) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Windows cmd.exe always exports PROMPT (its prompt template, default "$P$G") into a child's environment. The engine's `getenv("PROMPT")` picked that up, so running `glm.exe` from cmd for the oracle self-test instead entered text- generation mode — loading a tokenizer the tiny model doesn't ship and failing with "tokenizer.json: No such file". PowerShell has no PROMPT env var, so it worked there (galmok's 32/32) but not in cmd — same command, different shell. New coli_user_prompt(): honors COLI_PROMPT everywhere, and on Windows ignores a PROMPT that carries cmd's $-metacodes ($P,$G,...) — a real prompt has none. cmd users can still pass a prompt via COLI_PROMPT or a non-$ PROMPT. Verified: $P$G -> oracle mode, "Explain recursion" -> honored, COLI_PROMPT -> honored. Third native-Windows bug surfaced by a from-scratch main download (after the -lpsapi link fix and the bilingual oracle message). Co-Authored-By: Claude Opus 4.8 --- c/glm.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/c/glm.c b/c/glm.c index 5ab77e5..fe386af 100644 --- a/c/glm.c +++ b/c/glm.c @@ -5485,6 +5485,24 @@ static void cap_for_ram(Model *m, double ram_gb, int ebits, int max_ctx){ } } +/* The user's generation prompt. COLI_PROMPT is honored on every platform; a bare + * PROMPT is honored too, EXCEPT on Windows, where cmd.exe always exports its own + * PROMPT template (default "$P$G", the thing that draws "C:\...>") into the child's + * environment. That is a shell UI string, not a prompt: taking it would send the + * engine into text-generation mode (needing a tokenizer) instead of the oracle + * self-test, and would "generate" from "$P$G". So on Windows a PROMPT carrying + * cmd's $-metacodes is ignored; set COLI_PROMPT to pass a real prompt from cmd. */ +static const char *coli_user_prompt(void){ + const char *p = getenv("COLI_PROMPT"); + if(p) return p; + p = getenv("PROMPT"); +#ifdef _WIN32 + if(p) for(const char *q=p; q[0]; q++) + if(q[0]=='$' && q[1] && strchr("ABCDEFGHLNPQSTV_+|$", q[1]&~0x20)){ p=NULL; break; } +#endif + return p; +} + int main(int argc, char **argv){ /* ---- Permanent OpenMP hot-thread tuning. The per-expert matmul regions are * tiny and back-to-back; with the default passive wait policy libgomp parks @@ -5750,9 +5768,10 @@ int main(int argc, char **argv){ } /* modo testo reale: PROMPT="..." [NGEN=n] -> tokenizza, genera, detokenizza */ - if(getenv("PROMPT")){ + const char *user_prompt = coli_user_prompt(); /* ignores cmd.exe's PROMPT template (#271) */ + if(user_prompt){ int ngen=getenv("NGEN")?atoi(getenv("NGEN")):64; - run_text(&m, snap, getenv("PROMPT"), ngen); + run_text(&m, snap, user_prompt, ngen); if(stats) stats_dump(&m,stats); return 0; } From 97fa52698f92c510173da1bc140014a3b15faeff Mon Sep 17 00:00:00 2001 From: NeuralNotwerk Date: Wed, 15 Jul 2026 22:12:31 +0000 Subject: [PATCH 70/79] glm: make MLOCK=1 actually wire pinned experts under COLI_MMAP pin_wire() only locked the legacy private-slab path (s->slab / s->fslab), which stay NULL under COLI_MMAP -- so MLOCK=1 on an mmap build silently wired 0 bytes and the 'pinned' set was just warm page cache, evictable under memory pressure (measured: hundreds of MB/s of re-reads from disk mid-generation on a 503 GB host once the cache tightened). Three pieces: - qt_wire_mmap(): mlock each pinned expert's weight + scale ranges inside the file mappings. Skips cuda_eligible QTs: VRAM-tier experts compute from device memory, and expert_host_release() early-returns for mmap experts (no slab) WITHOUT nulling q8/q4, so a host-pointer check alone wires the whole VRAM tier too (~137 GB of never-touched locked pages on a 6x32GB-class rig -- enough to starve the kernel into thrashing). - qt_unwire_mmap(): REPIN gpu_swap promotions drop the promoted expert's host lock instead of leaking it on every swap. - expert_load() deliberately does NOT wire (it also runs for the transient VRAM-staging pass); wiring happens once in pin_wire() on the final set. Measured on GLM-5.2 int4, 4x RTX 5090 + 1x RTX 4090, 503 GB RAM, PIN_GB=all: wired goes 0 -> 226 GB (exactly the RAM tier), decode-time disk reads drop to zero once warm. Co-Authored-By: Claude Fable 5 --- c/glm.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/c/glm.c b/c/glm.c index fb93e59..e9903fc 100644 --- a/c/glm.c +++ b/c/glm.c @@ -1365,6 +1365,14 @@ static void embed_row(Model *m, int tok, float *x){ static int g_mmap=0; static struct { int fd; void *base; size_t len; } g_maps[512]; static int g_nmaps; static pthread_mutex_t g_map_mtx = PTHREAD_MUTEX_INITIALIZER; /* expert_load e' OMP-parallel */ +/* forward decls: mem_should_wire/mem_wire live near pin_wire() further down, but + * qt_wire_mmap() (also further down, used by pin_wire()'s COLI_MMAP path) needs + * them declared before its own definition. Real mlock-ing of mmap'd pinned + * experts happens there, not in expert_load() -- see qt_wire_mmap() for why. */ +static int mem_should_wire(void); +static int mem_wire(void *addr, size_t len); +static void qt_unwire_mmap(QT *t); /* def. presso pin_wire / defined near pin_wire */ +static int64_t g_mmap_wired=0; static long g_mmap_wire_failed=0; static void *map_of_fd(int fd){ pthread_mutex_lock(&g_map_mtx); for(int i=0;ioff; size_t nq=(size_t)tq[k]->nbytes; for(size_t i=0;islab, always NULL under mmap, so wiring here would + * leak locked pages for every GPU-tier expert). See pin_wire() below: it wires + * the final resident set only, after GPU release has already nulled out the + * pointers for anything that isn't genuinely RAM-tier. */ } s->eid=eid; return 0; } @@ -3918,6 +3933,9 @@ static void repin_pass_limit(Model *m,int limit){ if(!qt_cuda_update(hq[k])) ok=0; } if(!ok){ fprintf(stderr,"[REPIN] refresh VRAM fallito\n"); exit(1); } + /* promoted expert now computes from VRAM: drop its host mlock + * (mmap path; no-op otherwise) or every swap leaks locked pages */ + qt_unwire_mmap(&hot->g); qt_unwire_mmap(&hot->u); qt_unwire_mmap(&hot->d); if(g_cuda_release_host) expert_host_release(m,hot); gpu_swaps++; if(getenv("REPIN_VERBOSE")) fprintf(stderr, @@ -4626,8 +4644,57 @@ static int mem_wire(void *addr, size_t len){ } /* Inchioda tutti gli slab degli expert pinnati (pesi + scale). Non fatale se fallisce. * EN: wire all pinned-expert slabs (weights + scales). Non-fatal on failure. */ +/* mlock a single mmap'd QT's weight + scale ranges. Skips VRAM-tier QTs + * (cuda_eligible): their compute runs from device memory, so wiring the host + * mmap range would pin ~137 GB of never-touched file pages. NOTE the q8/q4 + * NULL check alone is NOT enough here: expert_host_release() early-returns + * for mmap experts (no slab) without nulling the host pointers, so GPU-tier + * slots keep live-looking q8/q4 forever -- that was the bug that wired 363 GB + * instead of 231 GB and starved the kernel into page-cache thrashing. + * wired/failed are accumulated into the caller's counters. */ +/* undo qt_wire_mmap for one QT: used when a REPIN gpu_swap promotes a wired + * RAM-tier expert into VRAM -- without this every promotion leaks its locked + * host range and the dead-weight lock re-grows over a long session. */ +static void qt_unwire_mmap(QT *t){ + if(!g_mmap || !mem_should_wire()) return; + if(!t->q8 && !t->q4) return; + int64_t scale_b=(int64_t)t->O*4; + int64_t weight_b=qt_bytes(t)-scale_b; + void *wp=t->q8?(void*)t->q8:(void*)t->q4; +#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) + if(weight_b>0 && !munlock(wp,(size_t)weight_b)) g_mmap_wired-=weight_b; + if(t->s && scale_b>0 && !munlock(t->s,(size_t)scale_b)) g_mmap_wired-=scale_b; +#elif defined(_WIN32) + if(weight_b>0 && !compat_munlock(wp,(size_t)weight_b)) g_mmap_wired-=weight_b; + if(t->s && scale_b>0 && !compat_munlock(t->s,(size_t)scale_b)) g_mmap_wired-=scale_b; +#endif +} +static void qt_wire_mmap(QT *t, int64_t *wired, long *failed){ + if(!t->q8 && !t->q4) return; + if(t->cuda_eligible) return; /* resident in VRAM; host range is dead weight */ + int64_t scale_b=(int64_t)t->O*4; + int64_t weight_b=qt_bytes(t)-scale_b; + void *wp=t->q8?(void*)t->q8:(void*)t->q4; + if(weight_b>0){ if(mem_wire(wp,(size_t)weight_b)==0) *wired+=weight_b; else (*failed)++; } + if(t->s && scale_b>0){ if(mem_wire(t->s,(size_t)scale_b)==0) *wired+=scale_b; else (*failed)++; } +} static void pin_wire(Model *m){ if(!mem_should_wire()) return; + if(g_mmap){ + /* Wire the FINAL resident set only, after pin_load's GPU-upload pass + * has already run -- qt_wire_mmap() skips cuda_eligible (VRAM-tier) + * slots, so only the genuinely RAM-tier experts get locked. */ + Cfg *c=&m->c; double t0=now_s(); + for(int i=0;in_layers;i++) for(int z=0;znpin[i];z++){ + ESlot *s=&m->pin[i][z]; + qt_wire_mmap(&s->g,&g_mmap_wired,&g_mmap_wire_failed); + qt_wire_mmap(&s->u,&g_mmap_wired,&g_mmap_wire_failed); + qt_wire_mmap(&s->d,&g_mmap_wired,&g_mmap_wire_failed); + } + fprintf(stderr,"[PIN] mlock (mmap): %.1f GB wired in physical RAM%s in %.0fs\n", + g_mmap_wired/1e9, g_mmap_wire_failed?" (some allocations failed -- raise: ulimit -l unlimited)":"", now_s()-t0); + return; + } Cfg *c=&m->c; double t0=now_s(); int64_t wired=0; long failed=0; for(int i=0;in_layers;i++) for(int z=0;znpin[i];z++){ ESlot *s=&m->pin[i][z]; From 78c675eb8b898e8f8c62ebcfe52e7b9034e03233 Mon Sep 17 00:00:00 2001 From: woolcoxm <13604288+woolcoxm@users.noreply.github.com> Date: Wed, 15 Jul 2026 18:33:25 -0400 Subject: [PATCH 71/79] cuda: fix pipe2 profile double-count + add COLI_CUDA_MTP opt-in (#292) Two issues found by the diagnostic sweep in #292: 1. Profile double-count in pipe_layer_sparse: the outer t_emm span wrapped both the shared-expert GPU dispatch AND the moe() call, but moe() self-times its own t_emm internally (6 accumulation sites). Routed-expert matmul was counted twice -> accounted > elapsed -> 'other' went negative, and expert-matmul showed an inflated ~120s. Fix: split into two narrow spans around only the GPU work moe() does NOT cover (shared-expert dispatch, routed upload+add), letting moe() self-time as all other callers already do. Verified: 'other' now positive (14-17s), expert-matmul realistic (5-6s). 2. MTP blanket-disabled under CUDA (g_draft=0 when g_cuda_enabled). This was a conservative guard from #163 before the root cause (cold-expert fused-pair + IDOT kernel divergence) was fully diagnosed. GPU-resident experts have no divergence; the cold subset still does but achieves 30-50% acceptance anyway (matching non-CUDA builds). Add COLI_CUDA_MTP=1 opt-in so users can test speculation under CUDA. Default unchanged. Verified: COLI_CUDA_MTP=1 -> MTP ACTIVE (draft=3), 44% acceptance, 3 forwards for 8 tokens (vs 7 without MTP). Refs #292 #163 --- c/glm.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/c/glm.c b/c/glm.c index 5880f19..83f9a7c 100644 --- a/c/glm.c +++ b/c/glm.c @@ -3093,18 +3093,26 @@ static int pipe_layer_sparse(Model *m, Layer *l, int li, float *x_dev, int S, in * No pipe_sync at the end: the next layer's pipe_download (sync cudaMemcpy) * provides the implicit sync point. The fallback path (caller downloads x_dev) * also uses pipe_download which syncs. This lets GPU work chain across layers - * without a per-layer stall. */ + * without a per-layer stall. + * + * Profiling: moe() self-times its own t_emm (routed expert matmul). We time only + * the GPU work that moe() does NOT cover: the shared-expert dispatch and the + * routed-expert upload+add. Previously a single outer span wrapped everything + * including moe(), double-counting the routed-expert time and driving the + * profile's "other" bucket negative (#292). */ double te=now_s(); if(!coli_cuda_pipe_gemm(l->sh_gate.cuda,sg_d,nrm_d,S)) return 0; if(!coli_cuda_pipe_gemm(l->sh_up.cuda,su_d,nrm_d,S)) return 0; if(!coli_cuda_pipe_silu_mul(dev,sg_d,su_d,(size_t)S*sI)) return 0; if(!coli_cuda_pipe_gemm(l->sh_down.cuda,y_d,sg_d,S)) return 0; if(!coli_cuda_pipe_add(dev,x_dev,y_d,(size_t)S*D)) return 0; /* shared residual (async) */ + m->t_emm += now_s()-te; /* shared-expert GPU dispatch only */ /* expert routed su CPU/gruppi GPU come oggi (shared saltata: la fa il device) */ - moe(m,l,li,nrm_host,S,out_host,0); + moe(m,l,li,nrm_host,S,out_host,0); /* self-times its own t_emm */ + te=now_s(); if(!coli_cuda_pipe_upload(dev,y_d,out_host,xb)) return 0; /* sync: waits for moe */ if(!coli_cuda_pipe_add(dev,x_dev,y_d,(size_t)S*D)) return 0; /* routed residual (async) */ - m->t_emm+=now_s()-te; + m->t_emm += now_s()-te; /* routed-expert upload + add only */ return 1; } #endif @@ -5213,7 +5221,16 @@ int main(int argc, char **argv){ Model m; double t0=now_s(); model_init(&m,snap,cap,ebits,dbits); if(g_draft<0){ #ifdef COLI_CUDA - g_draft = (m.has_mtp&&!g_cuda_enabled) ? 3 : 0; + /* MTP is disabled under CUDA by default: cold (streaming) experts still + * run on the CPU, where the S==1 fused-pair kernel and the S>=2 IDOT + * kernel diverge in FP accumulation order, collapsing draft acceptance + * (#163). GPU-resident experts have no divergence, but the cold subset + * always exists on a single 16 GB card. COLI_CUDA_MTP=1 opts in for + * users who want to test speculation under CUDA — the #163 thread shows + * acceptance can still reach 30-50% even with the cold-expert mismatch. + * See #292 for the diagnostic sweep that identified this. */ + int cuda_mtp = getenv("COLI_CUDA_MTP") ? atoi(getenv("COLI_CUDA_MTP")) : 0; + g_draft = (m.has_mtp && (!g_cuda_enabled || cuda_mtp)) ? 3 : 0; #else g_draft = m.has_mtp ? 3 : 0; #endif From 37da111bb4aed10233a6eadf9122dc12551d2d53 Mon Sep 17 00:00:00 2001 From: bokiko Date: Thu, 16 Jul 2026 01:36:15 +0300 Subject: [PATCH 72/79] glm: pin draft+verify to one kernel family during speculation; soften MTP guard (#163) MTP acceptance collapses when the draft (S=1) and verify (S>=2) forwards do not compute the same function. Three switches were S-dependent: the int4 IDOT gate (S>=g_i4s, asymmetric exactly on ISAs where g_i4s>1), the S==1-only fused gate+up pair, and the Metal GEMM row threshold. SPEC_PIN=1 (default) pins every forward issued while model drafts are live to the platform S=1 kernel family, so draft and verify agree by construction. Prefill and non-speculative decode keep their gates. SPEC_PIN=0 restores the old behavior for A/B. The 24-proposal <10% guard now pauses drafting for 256 tokens and re-arms on a fresh window instead of latching off for the whole session. Co-Authored-By: Claude --- c/glm.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/c/glm.c b/c/glm.c index fe386af..519b7b1 100644 --- a/c/glm.c +++ b/c/glm.c @@ -483,8 +483,24 @@ static int g_no_fused_pair=0; /* COLI_NO_FUSED_PAIR=1: disable the gate+up kern * that changes OMP scheduling vs separate matmul_qt calls — this * shifts floating-point accumulation order and can collapse MTP * draft acceptance by flipping near-ties (#163). */ +/* #163: l'acceptance MTP crolla quando il forward di draft (S=1) e quello di verifica + * (S>=2) non calcolano la STESSA funzione. Tre interruttori dipendono da S: il gate + * int4-IDOT (S>=g_i4s — asimmetrico proprio dove g_i4s>1), la fusione gate+up solo-S==1, + * e la soglia righe del GEMM Metal. Con SPEC_PIN=1 (default) ogni forward emesso mentre + * i draft del modello sono attivi resta sulla famiglia di kernel di S=1: draft e verifica + * coincidono per costruzione. Prefill e decode non speculativo sono intoccati. + * EN: MTP acceptance collapses when the draft (S=1) and verify (S>=2) forwards do not + * compute the SAME function. Three switches are S-dependent: the int4 IDOT gate + * (S>=g_i4s — asymmetric exactly on ISAs where g_i4s>1), the S==1-only gate+up fusion, + * and the Metal GEMM row threshold. SPEC_PIN=1 (default) pins every forward issued + * while model drafts are live to the platform's S=1 kernel family, so draft and verify + * agree by construction; prefill and non-speculative decode are untouched. + * SPEC_PIN=0 restores the S-dependent gates (A/B). */ +static int g_spec_pin=1; +static int g_spec_live=0; /* set by spec_decode while drafts are live */ +static inline int spec_pinned(void){ return g_spec_pin && g_spec_live; } static void expert_gate_up(float *g,float *u,const float *x,QT *wg,QT *wu,int S){ - if(!g_no_fused_pair&&S==1&&wg->fmt==2&&wu->fmt==2&&wg->I==wu->I&&wg->O==wu->O) + if(!g_no_fused_pair&&!spec_pinned()&&S==1&&wg->fmt==2&&wu->fmt==2&&wg->I==wu->I&&wg->O==wu->O) matmul_i4_pair(g,u,x,wg->q4,wg->s,wu->q4,wu->s,wg->I,wg->O); else { matmul_qt(g,x,wg,S); matmul_qt(u,x,wu,S); } } @@ -961,7 +977,7 @@ static void matmul_qt_ex(float *y, const float *x, QT *w, int S, int allow_idot) /* Large row-batches (prefill: kv_b reconstruction, o_proj, dense MLP, step_all logits) * amortize Metal's ~5ms submit latency; small-S decode matmuls stay on CPU (NEON wins). * Weights must be registered (all dense QT allocs are, via qalloc). */ - if(g_metal_enabled && S>=g_metal_gemm_min && (w->fmt==1||w->fmt==2) && !omp_in_parallel()){ + if(g_metal_enabled && S>=g_metal_gemm_min && !spec_pinned() && (w->fmt==1||w->fmt==2) && !omp_in_parallel()){ const void *wp = w->fmt==1 ? (const void*)w->q8 : (const void*)w->q4; if(coli_metal_gemm(y,x,wp,w->s,w->fmt,S,w->I,w->O)) return; } @@ -990,7 +1006,13 @@ static void matmul_qt_ex(float *y, const float *x, QT *w, int S, int allow_idot) * EN: int8 IDOT always wins (1.4-2.5x). int4 IDOT: on AVX2 the author found S=1 didn't * pay (S>=2 gate); on ARM/SDOT single-token DOES pay (see g_i4s / PR #9 for the VNNI * twin). Threshold configurable via I4S. */ - if(allow_idot && g_idot && (w->fmt==1 || (w->fmt==2 && S>=g_i4s))){ + /* #163: sotto SPEC_PIN il gate int4-IDOT usa la decisione di S=1 per OGNI S, cosi' + * draft e verifica restano sulla stessa famiglia. (CUDA non e' toccato: la sua + * condizione non dipende da S, quindi e' gia' coerente tra draft e verifica.) + * EN: under SPEC_PIN the int4 IDOT gate uses the S=1 decision for EVERY S, so draft + * and verify stay in one family. (CUDA untouched: its condition is S-independent, + * hence already draft/verify-consistent.) */ + if(allow_idot && g_idot && (w->fmt==1 || (w->fmt==2 && (spec_pinned() ? g_i4s<=1 : S>=g_i4s)))){ int I=w->I; int8_t *xq; float *sx; if(S<0 || I<0 || (size_t)S>SIZE_MAX/(size_t)(I?I:1)){ fprintf(stderr,"matmul_qt: shape overflow\n"); exit(1); } quant_scratch((size_t)S*I,(size_t)S,&xq,&sx); @@ -4077,6 +4099,18 @@ static int spec_decode(Model *m, int *all, int kv, int n_new, int eos, float *lo Cfg *c=&m->c; int V=c->vocab; int emitted=0, done=0; int draft[64]; if(g_draft>63) g_draft=63; int carry_ban=-1; /* token rifiutato dalla verifica: escluso dal resample */ + /* #163: draft del modello attivi -> pin della famiglia di kernel per draft+verifica. + * EN: model drafts live -> pin the kernel family for draft+verify forwards. */ + g_spec_live = (g_draft>0); + if(spec_pinned() && m->has_mtp){ static int once=0; if(!once){ once=1; + fprintf(stderr,"[SPEC_PIN] draft+verify pinned to the S=1 kernel family: int4=%s int8=%s (#163; SPEC_PIN=0 for A/B)\n", + (g_idot&&g_i4s<=1)?"idot":"exact", g_idot?"idot":"exact"); } } + /* guardia MTP morbida (#163): finestra di 24 proposte, pausa e ri-arma invece del + * latch permanente — una regressione transitoria non spegne MTP per tutta la sessione. + * EN: soft MTP guard (#163): 24-proposal window, pause and re-arm instead of the + * permanent latch — a transient collapse no longer kills MTP for the whole session. */ + enum { GUARD_PAUSE_TOKENS = 256 }; + uint64_t gd_prop0=m->mtp_prop, gd_acc0=m->mtp_acc; int gd_pause=0; while(emitted=0 && next==eos) || is_stop(next)) break; @@ -4089,15 +4123,19 @@ static int spec_decode(Model *m, int *all, int kv, int n_new, int eos, float *lo g=grammar_draft(draft,g_gr_max); if(g>0) gsrc=1; } - if(!g && g_draft>0){ - /* auto-off adattivo: draft che non vengono mai accettati = solo tassa disco */ - if(m->has_mtp && m->mtp_prop>=24 && m->mtp_acc*10 < m->mtp_prop){ - g_draft=0; - fprintf(stderr,"[MTP] %.0f%% acceptance after %llu proposals: drafts disabled\n", - 100.0*m->mtp_acc/m->mtp_prop, (unsigned long long)m->mtp_prop); + if(!g && g_draft>0 && m->has_mtp){ + /* pausa adattiva: draft che non vengono mai accettati = solo tassa disco, + * ma il vecchio g_draft=0 era permanente. EN: adaptive pause; the old + * g_draft=0 latch was permanent. */ + if(gd_pause>0){ gd_pause--; if(!gd_pause){ gd_prop0=m->mtp_prop; gd_acc0=m->mtp_acc; } } + else if(m->mtp_prop-gd_prop0>=24 && (m->mtp_acc-gd_acc0)*10 < m->mtp_prop-gd_prop0){ + fprintf(stderr,"[MTP] %.0f%% acceptance over the last %llu proposals: drafts paused for %d tokens\n", + 100.0*(m->mtp_acc-gd_acc0)/(m->mtp_prop-gd_prop0), + (unsigned long long)(m->mtp_prop-gd_prop0), (int)GUARD_PAUSE_TOKENS); + gd_pause=GUARD_PAUSE_TOKENS; } } - if(!g && g_draft>0){ + if(!g && g_draft>0 && !(m->has_mtp && gd_pause>0)){ if(m->has_mtp){ g=mtp_draft(m,next,kv,g_draft,draft); m->mtp_prop+=g; if(g)gsrc=2; } else { g=ngram_draft(all,kv+1,g_draft,draft); if(g)gsrc=2; } } @@ -4129,6 +4167,7 @@ static int spec_decode(Model *m, int *all, int kv, int n_new, int eos, float *lo logit=falloc(V); memcpy(logit, lo+(int64_t)k*V, V*sizeof(float)); free(lo); repin_pass(m); /* safe point: all device work is synchronized */ } + g_spec_live = 0; /* prefill/decode successivi: gate normali / next prefill: normal gates */ if(logit) free(logit); if(kv_out) *kv_out=kv; return emitted; @@ -5630,6 +5669,7 @@ int main(int argc, char **argv){ #endif } g_idot = getenv("IDOT")?atoi(getenv("IDOT")):1; /* 0 = kernel f32 esatti (A/B) */ + g_spec_pin = getenv("SPEC_PIN")?atoi(getenv("SPEC_PIN")):1; /* #163: 0 = gate S-dipendenti storici / legacy S-dependent gates */ if(getenv("ROUTE_TRACE")&&*getenv("ROUTE_TRACE")){ g_route_fp=fopen(getenv("ROUTE_TRACE"),"w"); if(!g_route_fp) fprintf(stderr,"[ROUTE_TRACE] cannot open %s\n",getenv("ROUTE_TRACE")); From c82593ad87c007d3200038b021d068cbdf8c90d6 Mon Sep 17 00:00:00 2001 From: RonitBStudent Date: Wed, 15 Jul 2026 21:13:05 -0500 Subject: [PATCH 73/79] fix(build): make portable checks target-aware Select a portable architecture from the compiler target instead of forcing x86-64-v3 on every platform. On macOS, only enable Homebrew OpenMP when its header and library actually exist, preserving the dependency-free fallback. --- c/Makefile | 29 +++++++++++++++++++--- c/tests/test_makefile_platform.py | 41 +++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/c/Makefile b/c/Makefile index f98e541..66a290b 100644 --- a/c/Makefile +++ b/c/Makefile @@ -31,6 +31,13 @@ PPC64 := $(findstring ppc64,$(UNAME_M)) endif endif +TARGET_CPU := $(firstword $(subst -, ,$(TRIPLET))) +ifeq ($(TARGET_CPU),) +TARGET_CPU := $(UNAME_M) +endif +X86_64 := $(filter x86_64 amd64,$(TARGET_CPU)) +AARCH64 := $(filter aarch64 arm64,$(TARGET_CPU)) + ifneq (,$(DARWIN)) # --- macOS / Apple Silicon --- # Apple clang non include il runtime OpenMP: se c'e' libomp di Homebrew lo usa @@ -38,7 +45,9 @@ ifneq (,$(DARWIN)) # Niente -march: su arm64 NEON e' baseline (i kernel __ARM_NEON si attivano da soli). CC = clang OMPDIR := $(shell brew --prefix libomp 2>/dev/null) -ifneq ($(OMPDIR),) +# `brew --prefix libomp` can print the formula's prospective path even when it +# is not installed, so verify both artifacts before adding unusable flags. +ifneq ($(and $(wildcard $(OMPDIR)/include/omp.h),$(wildcard $(OMPDIR)/lib/libomp.*)),) OMPC = -Xclang -fopenmp -I$(OMPDIR)/include OMPL = -L$(OMPDIR)/lib -lomp else @@ -247,9 +256,23 @@ cuda-bench: backend_cuda.cu backend_cuda.h tests/bench_tensor_core.cu olmoe$(EXE): olmoe.c st.h json.h compat.h $(CC) $(CFLAGS) olmoe.c -o olmoe$(EXE) $(LDFLAGS) -# binario portabile da distribuire su altre macchine x86-64 +# Use a baseline that matches the compiler target. macOS already targets a +# portable baseline when ARCH is empty; forcing the x86 value there breaks +# Apple Silicon. Unknown targets use native rather than an invalid x86 flag. +ifneq (,$(DARWIN)) +PORTABLE_ARCH = +else ifneq (,$(AARCH64)) +PORTABLE_ARCH = armv8-a +else ifneq (,$(PPC64)) +PORTABLE_ARCH = power8 +else ifneq (,$(X86_64)) +PORTABLE_ARCH = x86-64-v3 +else +PORTABLE_ARCH = native +endif + portable: - $(MAKE) glm$(EXE) ARCH=x86-64-v3 + $(MAKE) glm$(EXE) ARCH=$(PORTABLE_ARCH) iobench$(EXE): iobench.c compat.h $(CC) $(CFLAGS) iobench.c -o iobench$(EXE) $(LDFLAGS) diff --git a/c/tests/test_makefile_platform.py b/c/tests/test_makefile_platform.py index 5b8c558..4ca4efc 100644 --- a/c/tests/test_makefile_platform.py +++ b/c/tests/test_makefile_platform.py @@ -11,6 +11,24 @@ MAKE = shutil.which("make") @unittest.skipUnless(MAKE, "make is required") class MakefilePlatformTests(unittest.TestCase): + def _dry_run(self, target, triplet, **variables): + args = [ + MAKE, + "--no-print-directory", + "-B", + "-n", + target, + f"TRIPLET={triplet}", + ] + args.extend(f"{name}={value}" for name, value in variables.items()) + return subprocess.run( + args, + cwd=C_DIR, + text=True, + capture_output=True, + check=True, + ) + def test_windows_nt_without_uname_selects_mingw_build(self): env = os.environ.copy() env["OS"] = "Windows_NT" @@ -29,6 +47,29 @@ class MakefilePlatformTests(unittest.TestCase): self.assertIn("-fopenmp", result.stdout) self.assertIn("-static", result.stdout) + def test_portable_build_uses_target_architecture(self): + cases = ( + ("x86_64-unknown-linux-gnu", "-march=x86-64-v3"), + ("aarch64-unknown-linux-gnu", "-march=armv8-a"), + ("powerpc64le-unknown-linux-gnu", "-mcpu=power8"), + ) + + for triplet, expected_flag in cases: + with self.subTest(triplet=triplet): + result = self._dry_run("portable", triplet) + self.assertIn(expected_flag, result.stdout) + + def test_darwin_portable_build_does_not_force_x86_architecture(self): + missing_libomp = "/colibri-test/missing-libomp" + result = self._dry_run( + "portable", "arm64-apple-darwin", OMPDIR=missing_libomp + ) + + self.assertIn("clang -O3", result.stdout) + self.assertNotIn("-mcpu=x86-64-v3", result.stdout) + self.assertNotIn(missing_libomp, result.stdout) + self.assertNotIn("-fopenmp", result.stdout) + if __name__ == "__main__": unittest.main() From 53324fdcf0f51601c27053458eb7da2f85dd9d7d Mon Sep 17 00:00:00 2001 From: RonitBStudent Date: Wed, 15 Jul 2026 22:19:25 -0500 Subject: [PATCH 74/79] fix(build): handle portable detection edge cases --- c/Makefile | 5 ++--- c/tests/test_makefile_platform.py | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/c/Makefile b/c/Makefile index 66a290b..1ed6df6 100644 --- a/c/Makefile +++ b/c/Makefile @@ -14,7 +14,6 @@ TRIPLET := $(shell $(DETECT_CC) -dumpmachine 2>/dev/null) MINGW := $(findstring mingw,$(TRIPLET)) CYGWIN := $(findstring cygwin,$(TRIPLET)) DARWIN := $(findstring darwin,$(TRIPLET)) -PPC64 := $(findstring powerpc64,$(TRIPLET)) LINUX := $(findstring linux,$(TRIPLET)) IS_WIN := $(MINGW)$(CYGWIN) @@ -27,7 +26,6 @@ ifeq ($(IS_WIN),) UNAME_S := $(shell uname -s) UNAME_M := $(shell uname -m) DARWIN := $(findstring Darwin,$(UNAME_S)) -PPC64 := $(findstring ppc64,$(UNAME_M)) endif endif @@ -37,6 +35,7 @@ TARGET_CPU := $(UNAME_M) endif X86_64 := $(filter x86_64 amd64,$(TARGET_CPU)) AARCH64 := $(filter aarch64 arm64,$(TARGET_CPU)) +PPC64 := $(filter powerpc64% ppc64%,$(TARGET_CPU)) ifneq (,$(DARWIN)) # --- macOS / Apple Silicon --- @@ -47,7 +46,7 @@ CC = clang OMPDIR := $(shell brew --prefix libomp 2>/dev/null) # `brew --prefix libomp` can print the formula's prospective path even when it # is not installed, so verify both artifacts before adding unusable flags. -ifneq ($(and $(wildcard $(OMPDIR)/include/omp.h),$(wildcard $(OMPDIR)/lib/libomp.*)),) +ifneq ($(and $(OMPDIR),$(wildcard $(OMPDIR)/include/omp.h),$(wildcard $(OMPDIR)/lib/libomp.*)),) OMPC = -Xclang -fopenmp -I$(OMPDIR)/include OMPL = -L$(OMPDIR)/lib -lomp else diff --git a/c/tests/test_makefile_platform.py b/c/tests/test_makefile_platform.py index 4ca4efc..3c72880 100644 --- a/c/tests/test_makefile_platform.py +++ b/c/tests/test_makefile_platform.py @@ -52,6 +52,7 @@ class MakefilePlatformTests(unittest.TestCase): ("x86_64-unknown-linux-gnu", "-march=x86-64-v3"), ("aarch64-unknown-linux-gnu", "-march=armv8-a"), ("powerpc64le-unknown-linux-gnu", "-mcpu=power8"), + ("ppc64le-unknown-linux-gnu", "-mcpu=power8"), ) for triplet, expected_flag in cases: From 81c03988779899291fa87de5fb609cc88b34467b Mon Sep 17 00:00:00 2001 From: NeuralNotwerk Date: Thu, 16 Jul 2026 06:57:36 +0000 Subject: [PATCH 75/79] =?UTF-8?q?PIN=3Dauto=20=E2=80=94=20seed=20the=20pin?= =?UTF-8?q?=20from=20the=20live=20usage=20history?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PIN=auto resolves to /.coli_usage, the history that serve mode appends after every turn, so each restart's hot-store placement follows the accumulated REAL workload instead of a frozen one-shot profile; stats.txt is the fallback for a virgin model dir, and with neither present the run simply starts unpinned. Same magic-value convention as PIN_GB=all (#80); explicit paths and the AUTOPIN flow are untouched (PIN set skips AUTOPIN as before). This lifts deployment entrypoints' "prefer .coli_usage over stats.txt" shell plumbing into the engine, plus the ENVIRONMENT.md row. Co-Authored-By: Claude Fable 5 --- c/glm.c | 23 +++++++++++++++++++++-- docs/ENVIRONMENT.md | 2 +- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/c/glm.c b/c/glm.c index 7e05ad9..fd302d1 100644 --- a/c/glm.c +++ b/c/glm.c @@ -5915,8 +5915,27 @@ int main(int argc, char **argv){ /* HOT-STORE: PIN= [PIN_GB=g] -> top expert per frequenza fissi in RAM. * Va PRIMA di cap_for_ram: i pinnati contano nel residente. */ if(getenv("PIN")){ - const char *pin_gb=getenv("PIN_GB"); - pin_load(&m,getenv("PIN"),pin_gb&&!strcmp(pin_gb,"all")?-1.0:pin_gb?atof(pin_gb):10.0); /* PIN_GB=all (#80) */ + const char *pin=getenv("PIN"); char pauto[2100]; + if(!strcmp(pin,"auto")){ + /* PIN=auto: la storia VIVA /.coli_usage (appesa a ogni turno) batte il + * profilo congelato stats.txt — il pin di ogni riavvio riflette il carico reale + * accumulato, non il prompt di bootstrap. Fallback stats.txt per una dir vergine; + * nessuno dei due -> nessun pin (AUTOPIN piu' sotto resta escluso: PIN e' settato). + * EN: prefer the live usage history over the frozen one-shot profile, so each + * reload's pin placement follows the accumulated real workload. */ + snprintf(pauto,sizeof(pauto),"%s/.coli_usage",snap); + FILE *pf=fopen(pauto,"rb"); long psz=0; + if(pf){ fseek(pf,0,SEEK_END); psz=ftell(pf); fclose(pf); } + if(psz<=0){ snprintf(pauto,sizeof(pauto),"%s/stats.txt",snap); + pf=fopen(pauto,"rb"); psz=0; + if(pf){ fseek(pf,0,SEEK_END); psz=ftell(pf); fclose(pf); } } + if(psz>0){ pin=pauto; fprintf(stderr,"[PIN] auto: seeding from %s\n",pauto); } + else { pin=NULL; fprintf(stderr,"[PIN] auto: no .coli_usage or stats.txt in %s yet (no pin this run)\n",snap); } + } + if(pin){ + const char *pin_gb=getenv("PIN_GB"); + pin_load(&m,pin,pin_gb&&!strcmp(pin_gb,"all")?-1.0:pin_gb?atof(pin_gb):10.0); /* PIN_GB=all (#80) */ + } } if(getenv("COUPLE")&&*getenv("COUPLE")){ /* coupling-scored cross-layer prefetch (#176) */ g_couple_k=getenv("COUPLE_K")?atoi(getenv("COUPLE_K")):8; diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index dab656b..d345b7b 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -47,7 +47,7 @@ Format: `VAR` — default — effect. | `CAP_RAISE` | `1` (on) | Let the engine raise the expert-cache cap above `topk` when RAM allows (bigger batches). `0` fixes the cap. | | `PREFETCH` | `0` | Prefetch depth for streamed experts. | | `COLI_MMAP` | `0` | `mmap` the weights instead of read()-ing into slabs. | -| `PIN` | unset | Path to a `.coli_usage` file; pins the hottest experts into a resident "hot store" at startup. | +| `PIN` | unset | Path to a `.coli_usage`/stats file; pins the hottest experts into a resident "hot store" at startup. **`PIN=auto`** seeds from the model dir's live `.coli_usage` (appended after every turn, so each restart's pin placement follows the accumulated real workload) with `stats.txt` as the fallback for a virgin model dir; neither present → no pin this run. | | `PIN_GB` | `10.0` | Size budget (GB) for the pinned hot store when `PIN` is set. | | `AUTOPIN` | `1` (on) | Auto-pin the hot store from usage history once ≥5000 selections are recorded. | | `REPIN` | `0` (off) | Live re-pin the hot store every N emitted tokens (RFC). | From 85c7857fe2b7958681d63ba6639830ea7db94fd7 Mon Sep 17 00:00:00 2001 From: fermionoid Date: Thu, 16 Jul 2026 18:11:45 +0800 Subject: [PATCH 76/79] Makefile: add -std=gnu++17 to METALXX for Apple clang 16 Apple clang 16 (clang-1600.0.26.6) defaults objective-c++ to a pre-C++11 dialect, so the raw string literal holding the Metal shader in backend_metal.mm fails to parse: backend_metal.mm:12:29: error: use of undeclared identifier 'R' backend_metal.mm:13:10: fatal error: 'metal_stdlib' file not found Pinning gnu++17 on METALXX fixes 'make glm METAL=1' and 'make metal-test'. Verified on macOS 15 / M4 Max: both targets build and all metal backend tests pass. --- c/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/Makefile b/c/Makefile index 1ed6df6..ccf0a3c 100644 --- a/c/Makefile +++ b/c/Makefile @@ -197,7 +197,7 @@ endif # runtime, so no Xcode / offline metal compiler is required. Default build unchanged. METAL ?= 0 METAL_OBJ = -METALXX = clang++ -x objective-c++ -fobjc-arc -O3 +METALXX = clang++ -x objective-c++ -std=gnu++17 -fobjc-arc -O3 ifeq ($(METAL),1) ifeq (,$(DARWIN)) $(error METAL=1 is supported only on macOS) From f86fc6860d7bf2d82cf710ab7c82c3d518fea21f Mon Sep 17 00:00:00 2001 From: bokiko Date: Thu, 16 Jul 2026 13:20:35 +0300 Subject: [PATCH 77/79] =?UTF-8?q?bench:=20survive=20transient=20hub=20erro?= =?UTF-8?q?rs=20=E2=80=94=20retry=20with=20backoff,=20per-task=20isolation?= =?UTF-8?q?,=20atomic=20writes=20(#304)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One HF 504 killed the whole bench. Now: load_dataset retries with exponential backoff (hf_hub resumes partial downloads from cache); a task that still fails is skipped instead of killing the rest; JSONLs are written atomically (coli only checks existence, so a truncated file from an interrupted run would block re-download forever); coli bench drops still-missing tasks with a warning and refuses to run eval with none. Co-Authored-By: Claude --- c/coli | 10 +++++++++ c/tools/fetch_benchmarks.py | 44 ++++++++++++++++++++++++++++++++----- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/c/coli b/c/coli index efc8526..e38badc 100755 --- a/c/coli +++ b/c/coli @@ -631,6 +631,16 @@ def cmd_bench(a): print(f" {C.dim}downloading missing datasets: {', '.join(missing)}{C.r}") subprocess.call([py, os.path.join(TOOLS,"fetch_benchmarks.py"), "--out", a.data, "--tasks", ",".join(missing), "--limit", str(max(a.limit,200))]) + # il fetch riprova da solo (#304), ma se l'hub resta giu' il bench gira sui task + # disponibili invece di passare a eval file inesistenti. + # EN: the fetch retries on its own (#304), but if the hub stays down the bench + # runs on the available tasks instead of handing eval nonexistent files. + still=[t for t in tasks.split(",") if not os.path.exists(os.path.join(a.data,f"{t}.jsonl"))] + if still: + tasks=",".join(t for t in tasks.split(",") if t not in still) + print(f" {C.yel}skipping (download failed, rerun later): {', '.join(still)}{C.r}") + if not tasks: + print(f" {C.yel}no datasets available — nothing to bench{C.r}"); sys.exit(1) cmd=[py, os.path.join(TOOLS,"eval_glm.py"), "--glm", GLM, "--snap",a.model, "--tasks", tasks, "--limit", str(a.limit), "--data", a.data] if a.ram: cmd+=["--ram",str(a.ram)] diff --git a/c/tools/fetch_benchmarks.py b/c/tools/fetch_benchmarks.py index 6d2abd2..05dd9e7 100644 --- a/c/tools/fetch_benchmarks.py +++ b/c/tools/fetch_benchmarks.py @@ -8,7 +8,7 @@ USO: Poi: python3 tools/eval_glm.py --snap /home/vincenzo/glm52_i4 --data ./bench --tasks mmlu --limit 40 --ram 15 """ -import os, json, argparse, random +import os, sys, json, time, argparse, random def f_hellaswag(d): ctx = (d["activity_label"] + ": " + d["ctx_a"] + " " + d["ctx_b"].capitalize()).strip() @@ -38,19 +38,44 @@ TASKS = { # task: (path, config, split, formatter) "openbookqa": ("allenai/openbookqa", "main", "validation", f_openbookqa), } +def load_retry(path, cfg, split, tries=5): + """L'hub restituisce 5xx/timeout transitori (#304): riprova con backoff invece di + morire al primo HEAD fallito. hf_hub riprende i download parziali dalla cache, + quindi il retry riparte da dove si era fermato, non da zero. + EN: the hub throws transient 5xx/timeouts (#304): retry with backoff instead of + dying on the first failed HEAD. hf_hub resumes partial downloads from its cache, + so a retry continues where it stopped rather than starting over.""" + from datasets import load_dataset + for k in range(tries): + try: + return load_dataset(path, cfg, split=split) + except (KeyboardInterrupt, SystemExit): + raise + except Exception as e: + if k == tries - 1: raise + wait = 2 ** (k + 1) + print(f" {path}: {type(e).__name__}: {e} — retry {k+1}/{tries-1} in {wait}s") + time.sleep(wait) + def main(): ap = argparse.ArgumentParser() ap.add_argument("--out", default="./bench") ap.add_argument("--tasks", default="hellaswag,arc_challenge,mmlu") ap.add_argument("--limit", type=int, default=300) ap.add_argument("--seed", type=int, default=1234) + ap.add_argument("--tries", type=int, default=5) a = ap.parse_args() - from datasets import load_dataset os.makedirs(a.out, exist_ok=True) + failed = [] for t in [x.strip() for x in a.tasks.split(",") if x.strip()]: - if t not in TASKS: print("unknown task:", t); continue + if t not in TASKS: print("unknown task:", t); failed.append(t); continue path, cfg, split, fn = TASKS[t] - ds = load_dataset(path, cfg, split=split) + try: + ds = load_retry(path, cfg, split, tries=max(a.tries, 1)) + except Exception as e: + # un task fallito non deve uccidere gli altri / one failed task must not kill the rest + print(f"{t}: FAILED after {a.tries} tries ({type(e).__name__}: {e}) — skipping") + failed.append(t); continue idx = list(range(len(ds))); random.Random(a.seed).shuffle(idx) rows, n = [], 0 for i in idx: @@ -61,9 +86,18 @@ def main(): except Exception: continue if n >= a.limit: break outp = os.path.join(a.out, t + ".jsonl") - with open(outp, "w") as f: + # scrittura atomica: coli controlla solo l'ESISTENZA del file, quindi un jsonl + # troncato da un run interrotto bloccherebbe il re-download per sempre. + # EN: atomic write: coli only checks the file EXISTS, so a truncated jsonl from + # an interrupted run would block re-download forever. + tmp = outp + ".part" + with open(tmp, "w") as f: for r in rows: f.write(json.dumps(r) + "\n") + os.replace(tmp, outp) print(f"{t}: {len(rows)} -> {outp}") + if failed: + print(f"incomplete: {', '.join(failed)} — rerun when the hub recovers (cached progress is kept)") + sys.exit(1) if __name__ == "__main__": main() From d57955e95a6dfd99606d1cf26c338f524bdc8d5a Mon Sep 17 00:00:00 2001 From: JustVugg Date: Thu, 16 Jul 2026 12:25:53 +0200 Subject: [PATCH 78/79] Say why the engine died instead of dying mute (#305) Two silent failures that compound into "[engine terminated]" with no cause. cap_for_ram() floors the expert cache at cap=1. When resident+slack have already blown the budget, avail is negative and capmax would be 0 -- "I do not fit in your budget". Flooring it to 1 and carrying on turns "I do not fit" into "I overshoot", which is precisely the mid-generation OOM-kill the function exists to prevent: it printed "projected peak 25.1 GB" against a 22 GB budget and started anyway. Now it says so, names PIN_GB when that is what inflated the resident set, and refuses to start when the peak also exceeds the memory actually available on the machine (COLI_RAM_OVERCOMMIT=1 overrides). The kernel kills with SIGKILL: no error, no log, stdout just closes. coli read that EOF and printed "[engine terminated]" without ever reaping the child, so an OOM-kill was indistinguishable from a clean exit -- the report in #305 (Debian 12, dies mid-generation, no message). engine_diag() now reports the signal or exit code, names the OOM-killer when it was SIGKILL, and shows the tail of the engine's stderr. Reported-by: Ne00n <#305> Co-Authored-By: Claude Opus 4.8 --- c/coli | 34 ++++++++++++++++++++++++++++++++-- c/glm.c | 23 +++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/c/coli b/c/coli index efc8526..ad2f13e 100755 --- a/c/coli +++ b/c/coli @@ -344,6 +344,34 @@ class Spinner: if self.th: self.th.join(timeout=0.4) if TTY: sys.stdout.write("\r\033[K"); sys.stdout.flush() +def engine_diag(p, errlog=None): + """Lo stdout del motore ha chiuso: il processo e' morto. Dire PERCHE'. + Un SIGKILL dell'OOM-killer del kernel e' altrimenti invisibile — niente errore, + niente exit code, il motore muore muto e sembra un bug nostro (issue #305). + Quasi sempre e' memoria: il picco reale ha sforato la RAM della macchina.""" + try: rc=p.wait(timeout=5) + except Exception: rc=p.poll() + if rc is None: why="its output closed but the process is still alive" + elif rc<0: # POSIX: morte per segnale + try: why=f"killed by {signal.Signals(-rc).name}" + except Exception: why=f"killed by signal {-rc}" + elif rc>0: why=f"exit code {rc}" + else: why="exited cleanly" + print(f"\n {C.yel}[engine terminated: {why}]{C.r}") + if rc is not None and rc<0 and -rc==getattr(signal,"SIGKILL",-1): + print(f" {C.yel}nothing in the engine sends SIGKILL to itself: this is the kernel's\n" + f" OOM-killer. The peak RSS exceeded the machine's free memory.\n" + f" Lower --ram, lower PIN_GB, or shorten the context.{C.r}") + if errlog is not None: + try: + errlog.flush() + for _ in range(20): # il drain thread scrive su errlog quando il child chiude + tail=open(errlog.name).read().strip() + if tail: break + time.sleep(0.05) + if tail: print(f" {C.dgray}" + "\n ".join(tail.splitlines()[-6:]) + f"{C.r}") + except Exception: pass + def stream_turn(p, sentinel, on_bytes): """legge fino alla sentinella; on_bytes riceve i chunk della risposta. Poi legge la riga STAT. Il PRIMO Ctrl-C durante lo stream non chiude la sessione: il motore (handler SIGINT) @@ -478,7 +506,9 @@ def cmd_chat(a): if st is None: try: errlog.write(p.stderr.read().decode("utf-8","replace")) except (OSError, ValueError): pass - errlog.seek(0); print(errlog.read()[-1500:]); sys.exit("the engine exited while loading") + errlog.flush(); errlog.seek(0); print(errlog.read()[-1500:]) + engine_diag(p) # perche' e' morto (OOM-kill compreso); errlog e' gia' stampato sopra + sys.exit("the engine exited while loading") p.stdout.readline() # TIERS line (web-dashboard protocol): emitted once right after STAT; # left unread it leaks into the first answer's text # READY received. Drain the child's stderr into errlog without blocking: @@ -568,7 +598,7 @@ def cmd_chat(a): st=stream_turn(p, END, echo) if not raw: md.close() sp2.stop() - if st is None: print(f"\n {C.yel}[engine terminated]{C.r}"); break + if st is None: engine_diag(p, errlog); break el=time.time()-t0 if st.get("tok"): print(f"\r {C.dgray}└─ {st['tok']} tok · {st['tps']:.2f} tok/s · hit {st['hit']:.0f}% · RSS {st['rss']:.1f} GB · {el:.0f}s{C.r}") diff --git a/c/glm.c b/c/glm.c index 7e05ad9..ae18c55 100644 --- a/c/glm.c +++ b/c/glm.c @@ -5632,7 +5632,30 @@ static void cap_for_ram(Model *m, double ram_gb, int ebits, int max_ctx){ double slack = 1.2e9 + pc_b + ws_b + kv_b + kvb_b; double avail = ram_gb*1e9 - (double)m->resident_bytes - slack; int capmax = (avail>0 && nsp>0) ? (int)(avail/((double)nsp*eb)) : 0; + int floored = capmax<1; /* il budget non regge nemmeno UNO slot per layer */ if(capmax<1) capmax=1; + /* Il floor a 1 e' una bugia comoda: con avail negativo capmax sarebbe 0, cioe' + * "non ci sto nel tuo budget". Alzarlo a 1 e proseguire trasforma "non ci sto" + * in "sforo" -- ed e' esattamente l'OOM-kill a meta' generazione che questa + * funzione esiste per evitare. Il kernel uccide con SIGKILL: nessun errore, + * nessun log, il motore muore muto (issue #305). Dirlo, e fermarsi se il picco + * non entra nemmeno nella RAM realmente disponibile misurata all'avvio. */ + if(floored){ + double peak = (double)m->resident_bytes + (double)capmax*nsp*eb + slack; + fprintf(stderr,"[RAM_GB=%.1f%s] WARNING: cap=1 is the floor, projected peak %.1f GB is " + "%.1f GB OVER the budget (resident %.1f GB + reserve %.1f GB).%s\n", + ram_gb,auto_b?" auto":"",peak/1e9,(peak-ram_gb*1e9)/1e9, + m->resident_bytes/1e9,slack/1e9, + getenv("PIN_GB")?" PIN_GB is inflating the resident set: lower it or drop it.":""); + if(g_mem_avail_boot>0 && peak > g_mem_avail_boot*1e9 && + !(getenv("COLI_RAM_OVERCOMMIT") && atoi(getenv("COLI_RAM_OVERCOMMIT")))){ + fprintf(stderr,"[RAM] refusing to start: that peak also exceeds the %.1f GB actually " + "available on this machine, so the kernel would OOM-kill this run mid-generation.\n" + "[RAM] lower PIN_GB, lower the context, or raise the RAM budget if the box really has it " + "(COLI_RAM_OVERCOMMIT=1 overrides this check).\n", g_mem_avail_boot); + exit(2); + } + } if(capmax < m->ecap){ fprintf(stderr,"[RAM_GB=%.1f%s] resident %.1f GB + reserve %.1f GB (ws %.1f, KV %dx%d %.1f, kvb %.1f), " "experts %.1f MB x %d layers -> cap lowered %d->%d (projected peak %.1f GB)\n", From 35f90b9e765eeffe7dc844f83c0400d349a4fadc Mon Sep 17 00:00:00 2001 From: JustVugg Date: Thu, 16 Jul 2026 12:26:17 +0200 Subject: [PATCH 79/79] Quarantine EXPERT_BUDGET: the operating window is measured empty (#303) @bokiko benchmarked the feature on three hosts and found every setting is either no faster or no longer coherent. Reproduced here on a 25 GB box, and the numbers are worse than "a quality/speed tradeoff": - budget=8 -> hellaswag 30% vs 90% with it off (25% is the chance floor) - budget=4 -> decode is literal noise ("The **1...: s2151:") - MTP acceptance 0%. Which experts survive the cap depends on cache residency at the moment of the forward, so draft and verify do not compute the same function -- the invariant #294 just established for #163, violated through cache state instead of kernel dispatch. SPEC_PIN cannot fix that and should not try: it is feature semantics, not dispatch. - 0.13 tok/s vs 0.30 baseline, while loading 14.66 experts per layer against a topk=8 baseline. The cap does MORE disk I/O than not using it. "~335 GB I/O saved" counts dropped experts, not bytes not read. EXPERT_BUDGET>0 is now ignored unless EXPERT_BUDGET_EXPERIMENTAL=1, with the measurements printed. The code stays compiled and developable: MoE-Spec (arXiv 2602.16052) is not a wrong idea, this implementation just has no point where it is both faster and correct. Re-enabling it by default needs a quality number next to every speed number. Also gates the cap to decode (S<=4), @woolcoxm's fix from #292/#298: during prefill the batch union is 30-100+ experts, and capping to 4-8 drops most of them, corrupting the hidden state and therefore the KV cache. Necessary but not sufficient -- the run above already includes it. Removes issue_budget.md, issue_diskio.md and issue_grouped_quant.md: design notes in the repo root, unlinked from any README, whose only user-facing content was "EXPERT_BUDGET=6-8 -- good speedup, minimal quality loss" and "+83% decode at budget=4". Measurement says otherwise, and they were the only thing on main telling anyone to switch this on. They stay in history. Reported-by: bokiko <#303> Co-Authored-By: woolcoxm <#292> Co-Authored-By: Claude Opus 4.8 --- c/glm.c | 33 ++++- issue_budget.md | 150 -------------------- issue_diskio.md | 309 ----------------------------------------- issue_grouped_quant.md | 185 ------------------------ 4 files changed, 31 insertions(+), 646 deletions(-) delete mode 100644 issue_budget.md delete mode 100644 issue_diskio.md delete mode 100644 issue_grouped_quant.md diff --git a/c/glm.c b/c/glm.c index ae18c55..d34606f 100644 --- a/c/glm.c +++ b/c/glm.c @@ -2858,8 +2858,13 @@ static void moe(Model *m, Layer *l, int layer, float *x, int S, float *out, int * only drop from misses. From the misses, keep the highest-aggregate-gate-weight * ones up to the budget; drop the rest from idxs[] so they're never loaded. * (MoE-Spec arXiv 2602.16052: top-32 of 64 capture 93% routing weight.) - * Complementary to TOPP (per-position) — this trims cross-position. */ - if(g_expert_budget>0 && nu>g_expert_budget){ + * Complementary to TOPP (per-position) — this trims cross-position. + * DECODE-ONLY (S<=4, incl. MTP verify): during prefill S=prompt_len the batch + * union nu is 30-100+ experts and capping to 4-8 drops 80-90% of them, each with + * non-trivial gate weight -> corrupted prefill hidden state -> wrong KV cache -> + * repetitive garbage decode. The budget is only safe token-by-token, where the + * prefill KV cache is already correct. (woolcoxm, #292.) */ + if(g_expert_budget>0 && S<=4 && nu>g_expert_budget){ /* compute aggregate gate weight per unique expert */ float *wsum=falloc(nu); for(int j=0;j0 && !getenv("EXPERT_BUDGET_EXPERIMENTAL")){ + fprintf(stderr,"[EXPERT_BUDGET] ignored: measured empty operating window (issue #303).\n" + "[EXPERT_BUDGET] every tested setting is either no faster or no longer coherent:\n" + "[EXPERT_BUDGET] budget=8 -> hellaswag 30%% (90%% with it off) | budget=4 -> decode is noise\n" + "[EXPERT_BUDGET] MTP acceptance 0%% (the cap breaks the draft/verify contract, #294)\n" + "[EXPERT_BUDGET] 0.13 tok/s vs 0.30 baseline, loading 14.7 experts/layer vs topk=8\n" + "[EXPERT_BUDGET] set EXPERT_BUDGET_EXPERIMENTAL=1 to run it anyway (expect garbage).\n"); + g_expert_budget=0; + } g_cache_route = getenv("CACHE_ROUTE")?atoi(getenv("CACHE_ROUTE")):0; g_route_j = getenv("ROUTE_J")?atoi(getenv("ROUTE_J")):2; g_route_m = getenv("ROUTE_M")?atoi(getenv("ROUTE_M")):12; diff --git a/issue_budget.md b/issue_budget.md deleted file mode 100644 index fe0ef86..0000000 --- a/issue_budget.md +++ /dev/null @@ -1,150 +0,0 @@ -## TL;DR - -New `EXPERT_BUDGET=N` env var that caps the number of **distinct experts loaded per layer** across the batch-union. When the union exceeds the budget, keeps only the highest-aggregate-gate-weight experts and drops the rest — they're never loaded from disk. On a 24 GB RAM host (cache `cap=2`), `EXPERT_BUDGET=4` nearly **doubles decode tok/s** (0.18 → 0.33) and **4x's prefill speed** (38.7s → 8.9s). Based on MoE-Spec (arXiv 2602.16052): "top 32 of 64 experts capture 93% of routing weight." - -Branch: `experiment/expert-budget` (based on latest `dev` at `62419af`) - ---- - -## The problem - -Every expert miss costs ~19 MB of disk I/O. On low-RAM hosts where the LRU cache cap is tiny (e.g. `cap=2` on 24 GB RAM), nearly every routed expert is a miss. With `topk=8` and 75 sparse layers, a single-token decode reads ~8.5 GB of experts from disk. Under MTP with `S=4`, the batch-union can produce 20-32 distinct experts per layer — almost all misses — multiplying disk reads further. - -The README documents this directly: -> "on a cold cache each verified draft routes to extra experts (~660 → ~1100 expert-loads/token)" - -The existing `TOPP` env var trims experts *within a single position's top-K*. But it cannot reduce the **cross-position union** — the deduplication across batch positions (prefill, MTP verification) that multiplies disk loads. That's the gap this fills. - -## How it works - -The batch-union in `moe()` (line ~2306 of `glm.c`) deduplicates routed experts across all `S` positions into `uniq[0..nu)`. After the union is built but before the cache-resolve/load loop, the budget cap kicks in: - -``` -if(EXPERT_BUDGET > 0 && nu > EXPERT_BUDGET): - 1. Compute aggregate gate weight per unique expert - (sum of ws[s*K+kk] across all positions that route to it) - 2. Sort experts by descending aggregate weight - 3. Keep top EXPERT_BUDGET, mark rest as dropped - 4. Remove dropped experts from each position's idxs[]/keff[] - (decrement keff, renormalize remaining weights if norm_topk) - 5. Compact uniq[] to kept experts only -``` - -Dropped experts are removed from `idxs[]` entirely, so they're **never resolved, never loaded from disk, never computed**. The downstream code already tolerates `keff[s] < K` (the `TOPP` path produces the same state), so this propagates correctly through resolve, matmul, and LRU promotion. - -**Relationship to existing features:** -- `TOPP` trims within one position's top-K (per-position) -- `EXPERT_BUDGET` trims across the cross-position union (per-layer) -- They compose: `TOPP=0.8 EXPERT_BUDGET=12` first trims each position to its top-p mass, then caps the union - -## Code change - -**`c/glm.c`** — 54 lines added, single file: - -1. Global + counter (near existing `g_topk`/`g_topp`): -```c -static int g_expert_budget=0; /* EXPERT_BUDGET=N */ -static int64_t g_budget_dropped=0; /* total experts dropped */ -``` - -2. Env var parsing (near existing `TOPK`/`TOPP`): -```c -g_expert_budget = getenv("EXPERT_BUDGET")?atoi(getenv("EXPERT_BUDGET")):0; -``` - -3. Budget cap in `moe()` batch-union (after `uniq[]` is built, before resolve loop) — full logic described above. - -4. Stats reporting alongside existing `TOPK`/`TOPP` line: -``` -EXPERT_BUDGET=4 (dropped 13613 experts, ~257.3 GB I/O saved) -``` - -## Measurements - -**Test setup:** GLM-5.2 744B int4, 24 GB RAM (cache `cap=2`), Core Ultra 9 185H (AVX-VNNI), MTP=0, single-token decode, 32 tokens generated, same prompt: *"Explain the concept of recursion in programming. Provide a simple example."* - -| Config | tok/s | vs baseline | hit rate | prefill | decode | experts dropped | I/O saved | -|--------|-------|-------------|----------|---------|--------|-----------------|-----------| -| **Baseline** (budget=0) | 0.18 | — | 9.3% | 38.7s | 176.3s | 0 | 0 | -| EXPERT_BUDGET=12 | 0.19 | +5% | 14.0% | 12.3s | 171.3s | 3,313 | 62.6 GB | -| EXPERT_BUDGET=6 | 0.26 | +44% | 21.0% | 7.5s | 122.5s | 8,543 | 161.5 GB | -| **EXPERT_BUDGET=4** | **0.33** | **+83%** | 16.4% | 8.9s | **97.4s** | 13,613 | 257.3 GB | - -### Profile breakdown (prefill) - -| Metric | Baseline | Budget=4 | -|--------|----------|----------| -| expert-disk service | 28.4s | **3.5s** (8x less) | -| expert-matmul | 7.1s | 1.4s | -| attention | 2.3s | 2.8s | - -### Profile breakdown (decode, 32 tokens) - -| Metric | Baseline | Budget=4 | -|--------|----------|----------| -| expert-disk service | 133.4s | proportional ~65s | -| expert-matmul | 23.9s | ~12s | -| decode total | 176.3s | **97.4s** | - -### Key observations - -1. **Prefill is the biggest winner.** With S=14 positions, the batch-union has 50+ distinct experts per layer. Budget=12 cuts that to 12, saving 40+ × 19 MB × 75 layers of disk reads. Prefill goes from 38.7s to 8.9s — **4.4x faster**. - -2. **Decode improvement scales with budget tightness.** Budget=12 barely constrains single-token decode (S=1 → max 8 experts < 12), so decode is barely affected. Budget=4 actually halves the decode load (8 → 4 experts/layer), nearly doubling tok/s. - -3. **Hit rate improves** because fewer experts compete for the tiny cache (cap=2). Budget=6 hit 21% vs baseline 9.3% — more than doubled. - -4. **No crashes or instability** at any budget value. - -## Quality impact — honest assessment - -**Budget=4 keeps only the top-4 of 8 routed experts per layer.** The dropped 4 experts had the lowest gate weights — they contributed the least to the output. But this IS a quality trade-off. - -On a **cold cache** (our test setup), quality assessment is confounded: both baseline and budget outputs are already garbled from int4 quantization + cold-cache routing. Sample comparison: - -- **Baseline output:** *"Hire Some To Take Object-Oriented Programming Assignment"* -- **Budget=4 output:** *"The world is a dangerous place, not so much because of the small percentage of people who are doing to do the little of people who are doing to"* - -Both are incoherent — the cold cache at int4 on 24 GB RAM produces poor output regardless of budget. The budget=4 output is **not dramatically worse** than the already-poor baseline — they're both garbled, just differently garbled. A proper quality assessment needs a **warm cache** where the baseline produces coherent text, so you can isolate the degradation from dropping experts. - -**Expected quality on warm cache:** With `norm_topk=1` (GLM-5.2 renormalizes gate weights), the top-4 experts typically capture ~80-85% of routing weight (the remaining 4 share 15-20%). Output should be mostly coherent with occasional word-choice degradation. Budget=6 (top-6 of 8, ~90%+ weight captured) should be nearly indistinguishable from baseline. - -**Recommendation for users:** -- `EXPERT_BUDGET=6-8` on cold/low-RAM hosts — good speedup, minimal quality loss -- `EXPERT_BUDGET=4` on very-low-RAM hosts where speed matters more than quality -- Leave OFF on high-RAM hosts where all experts are resident anyway (budget never triggers) - -## Safety - -- **Default OFF** (`EXPERT_BUDGET=0`) — zero behavior change unless explicitly set -- **Opt-in quality trade-off** — same design philosophy as `TOPP`: the user explicitly chooses speed over quality -- **No output corruption** — dropped experts' contributions are omitted and remaining weights renormalized (identical math to `TOPP`) -- **Compatible with all features** — PILOT, MTP, CUDA, CACHE_ROUTE, PIPE, TOPP all work unchanged; they just see fewer experts in the union -- **No crash risk** — no new memory allocation patterns, no new I/O, purely a filter on existing data structures - -## Reproduce - -```bash -make ARCH=native - -# Baseline: -SNAP= MTP=0 PROMPT="Explain recursion in programming." NGEN=32 ./glm 64 - -# With budget: -SNAP= MTP=0 EXPERT_BUDGET=4 PROMPT="Explain recursion in programming." NGEN=32 ./glm 64 - -# With MTP (where budget saves the most): -SNAP= MTP=1 EXPERT_BUDGET=16 PROMPT="Explain recursion in programming." NGEN=32 ./glm 64 -``` - -The stats line prints `EXPERT_BUDGET=N (dropped X experts, ~Y GB I/O saved)`. - -## What's needed before merge - -1. **Warm-cache quality A/B test** on a host with enough RAM (cap>=16) to produce coherent baseline output, then compare budget=4/6/8 text quality -2. **MTP interaction test** — verify that budget + MTP composes correctly and doesn't crash when draft verification routes to budgeted-away experts -3. **Decide on defaults** — should this auto-activate on low-RAM hosts (like `cap` auto-lowering)? My recommendation: no, leave it OFF and document the recommended value per RAM tier - -## Prior art - -**MoE-Spec** (arXiv 2602.16052) — "Expert Budgeting for Efficient Speculative Decoding": Training-free expert budgeting at verification time. Key finding: "top 32 of 64 experts capture 93% of routing weight." Our approach applies the same principle but at the batch-union level (not just MTP verification), making it effective for prefill and single-token decode too. diff --git a/issue_diskio.md b/issue_diskio.md deleted file mode 100644 index 91d7b92..0000000 --- a/issue_diskio.md +++ /dev/null @@ -1,309 +0,0 @@ -# Disk I/O Minimization — Research - -Branch: `experiment/diskio-research` (based on `dev` at `62419af`) - -## TL;DR - -The engine's disk I/O is **already well-engineered on the hottest path** (expert streaming uses coalesced O_DIRECT `pread` + `posix_fadvise` hints + LRU + pin cache + speculative prefetch). There are **4 concrete, bounded opportunities** to shave latency, ranked by ROI: - -| # | Opportunity | Where | Frequency | Estimated win | -|---|---|---|---|---| -| 1 | **KV-cache write batching** (157 fwrites/token → 1) | `kv_disk_append` | per turn | cuts ~100s of syscalls/turn | -| 2 | **`/proc/meminfo` fopen storm** | `rss_gb()` | ~every 16 tokens (Linux) | eliminates recurring open/read/close | -| 3 | **Expert prefetch on Windows** (`PrefetchVirtualMemory`) | `expert_prefetch` | per miss | mmap path is Linux/macOS-only today | -| 4 | **KV-cache: buffered handle kept open** | `kv_disk_append` | per turn | kills open+fseek+close per turn | - -There are also **2 non-opportunities** worth recording so we don't re-investigate: O_DIRECT for experts (correctly used today), and PagedAttention-style file layout (already single-file + indexed). - ---- - -## How the engine does disk I/O today - -There are **three I/O stacks**, behaving very differently: - -| Stack | Mechanism | Frequency | Files | -|---|---|---|---| -| **Expert weights** (hottest) | `pread` on kept-open fds + `posix_fadvise`, optional `mmap` | per miss, every token | `st.h`, `glm.c:1328` | -| **KV cache** (`.coli_kv`) | `fopen` + `fwrite`/`fread` | per turn | `glm.c:3812-3889` | -| **Everything else** (config, tokenizer, stats, grammar) | `fopen` + `fread` | startup-only | scattered | - -### Expert path (the hot path — already good) - -`expert_load` (`glm.c:1328-1481`) has three sub-paths: - -- **Default `pread` path** (`glm.c:1385-1472`): coalesces the 3 contiguous expert tensors (gate/up/down) into **one ~19 MB O_DIRECT `pread`** into a 16K-aligned slab (`glm.c:1447`). Falls back to 3 separate `pread`s only if non-contiguous. Scales are 3 tiny separate `pread`s (kilobytes). `posix_fadvise(DONTNEED)` evicts pages after if `g_drop`. **This is well-batched — one syscall for ~19 MB.** -- **`COLI_MMAP=1` path** (`glm.c:1352-1383`): `mmap` per shard fd (cached), `madvise(WILLNEED)` + synchronous page-touch loop. Zero-copy. **Default OFF, and Linux/macOS/FreeBSD-only** — no `MapViewOfFile` on Windows. -- **Prefetch hints**: `expert_prefetch` (`glm.c:1602-1609`) → `st_prefetch` (`st.h:178`) issues `posix_fadvise(WILLNEED)` — readahead hint only, no data read. Called from `moe` next-64-block lookahead, pilot, and SPEC. - -### KV cache persistence (per turn — opportunity here) - -`kv_disk_append` (`glm.c:3834-3855`), called once per turn: -1. `fopen("r+b")` — **reopens the file every turn** -2. `fseek` to append position -3. **per-position loop**: for each new token, `fwrite` the token i32, then **2 fwrites per layer** (Lc + Rc) + optional DSA Ic. With 78 layers that's **~157 fwrites per token appended**. -4. `fflush` (userspace only — **no fsync/fdatasync anywhere in the codebase**) -5. `fseek` back to header + `fwrite` the new nrec counter (crash-safe ordering) -6. `fclose` - -Record size ~182 KB/token. On a long first turn this is **tens of thousands of small fwrites**. stdio buffering coalesces them into fewer `write` syscalls, but the userspace overhead remains. - -### Recurring surprise: `/proc/meminfo` - -`rss_gb()` (`glm.c:4625`) does `fopen("/proc/meminfo")` + fgets + fclose. Called from every STAT line and every 16-token heartbeat (`glm.c:3473, 3477`). On Linux this is an **open+read+close of procfs ~every 16 tokens**. (Windows uses `compat_meminfo`, no file — not affected.) - ---- - -## What similar projects do - -**llama.cpp** (the reference): `mmap`s the entire model read-only, uses `--mlock` to pin hot pages, streams layers to GPU via partial offload, and issues per-pass readahead of upcoming tensors (`llama-mmap.cpp`). Justine Tunney's mmap work: "load 100× faster using half as memory." Crucial finding from discussion #18758: **for MoE, mmap beats O_DIRECT** when the model fits in ~RAM — O_DIRECT takes "at least 10× longer" on repeated loads because it bypasses the page cache that serves re-faults for free. - -**The general consensus across llama.cpp, vLLM, AirLLM, PRESERVE, HOBBIT, SolidAttention (FAST '26):** -- mmap + OS page cache as the backing store for an LRU is the proven recipe -- prefetch the *next* expert/layer while computing the current one — this is where the 0.5ms lives -- single indexed file (one `open()`) beats one-file-per-expert -- align tensors to 4KB (preferably 64KB) for clean page-fault boundaries + SSD geometry -- buffer sweet spot ~1MB; syscall cost ~1-5µs each, so batching matters at high repetition - ---- - -## The 4 opportunities (ranked) - -### Opportunity 1 — KV-cache write batching (HIGH ROI, LOW risk) - -**Problem:** `kv_disk_append` does ~157 `fwrite` calls per appended token (1 token i32 + 2×78 layers). stdio buffering hides some of this, but on a long first-turn prefill (hundreds-thousands of tokens) this is tens of thousands of fwrites. - -**Fix:** Build one contiguous record in a heap buffer (token + all layers' Lc/Rc/Ic for that position), then **a single `fwrite` per position** (or even one `fwrite` for the whole turn). The data is already laid out contiguously in memory per-layer (`coli_kv_row`), so a layered `memcpy` into a staging buffer + one write is straightforward. - -**Win:** ~157× fewer fwrite calls per token. Even with stdio coalescing, the userspace loop overhead is real at scale. - -### Opportunity 2 — `/proc/meminfo` fopen storm (MEDIUM ROI, trivial) - -**Problem:** `rss_gb()` opens, reads, closes `/proc/meminfo` every ~16 tokens on Linux. Each is ~3 syscalls + path resolution. - -**Fix:** Either (a) cache the value for N tokens (e.g. re-read at most once per second), or (b) keep the fd open and `rewind`+`fgets`. Trivial change. - -### Opportunity 3 — Expert prefetch on Windows (MEDIUM ROI, bounded) - -**Problem:** The `COLI_MMAP=1` path (which gives zero-copy expert access + free OS-cache re-faults) is **Linux/macOS/FreeBSD-only** — `glm.c:1301` guards it. On Windows, experts always go through the `pread` path, and `expert_prefetch` issues `posix_fadvise(WILLNEED)` which is a no-op shim on Windows (`compat.h`). - -**Fix:** On Windows, implement the prefetch via `PrefetchVirtualMemory` (the Win32 analog of `MADV_WILLNEED`) on an mmap'd region, or via an async `ReadFile`+`OVERLAPPED` into a scratch buffer. This brings the Windows build closer to parity with the Linux mmap+prefetch story. - -**Scope:** This is the largest of the four — it touches the Windows I/O path. Worth doing if Windows perf is a goal; skip if Linux is the target. - -### Opportunity 4 — KV-cache: keep handle open (LOW-MEDIUM ROI, LOW risk) - -**Problem:** `kv_disk_append` does `fopen`+...+`fclose` every turn. Handle creation is ~5-15µs of pure overhead (worse on Windows). - -**Fix:** Open the KV file once (lazily on first append), keep the `FILE*` for the engine lifetime, just `fseek`+write each turn. Close on shutdown. Pair with Opportunity 1 for the write batching. - ---- - -## Non-opportunities (recording so we don't re-investigate) - -- **O_DIRECT for experts**: already correctly used (`st.h:83`, `DIRECT=1`). For an LRU+refetch pattern the page cache is your friend, but the engine offers both paths (O_DIRECT pread default + optional mmap) and the O_DIRECT coalesced read is already one syscall for ~19MB. Don't change this. -- **Single-file layout**: the engine already uses safetensors shards with kept-open fds + offset-indexed tensors (`st.h`). No per-expert open()/close() waste. Don't change this. -- **PagedAttention**: solves concurrency fragmentation this engine doesn't have (≤16 slots). Not applicable. - ---- - -## Next steps - -The highest-ROI, lowest-risk starting point is **Opportunity 1 (KV write batching) + Opportunity 4 (keep handle open)** — they're in the same function, both low-risk, and together they eliminate the per-turn open/close overhead and the per-token fwrite storm. Opportunity 2 is a trivial 5-minute fix we can bundle in. - -Opportunity 3 (Windows prefetch) is the biggest single win but also the largest scope — separate effort, gated on whether Windows perf is a priority. - -## Sources - -- [justine.lol/mmap — Edge AI Just Got Faster](https://justine.lol/mmap/) -- [llama.cpp discussion #18758 — Mmap faster than direct I/O for MoE](https://github.com/ggml-org/llama.cpp/discussions/18758) -- [llama.cpp issue #20757 — Two-tier GPU+RAM expert cache](https://github.com/ggml-org/llama.cpp/issues/20757) -- [FAST '26 — Programmable Page Cache for LLM loading](https://www.usenix.org/system/files/fast26-liu-yubo.pdf) -- [FAST '26 — SolidAttention: SSD-based serving](https://www.usenix.org/system/files/fast26-zheng.pdf) -- [HOBBIT — Mixed precision expert offloading](https://arxiv.org/html/2411.01433v2) -- [posix_fadvise(2) — man7.org](https://man7.org/linux/man-pages/man2/posix_fadvise.2.html) -- [madvise(2) — man7.org](https://man7.org/linux/man-pages/man2/madvise.2.html) -- [Microsoft Learn — File Buffering (FILE_FLAG_NO_BUFFERING)](https://learn.microsoft.com/en-us/windows/win32/fileio/file-buffering) -- [Microsoft Learn — PrefetchVirtualMemory](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-prefetchvirtualmemory) -- [What makes system calls expensive — codingconfessions.com](https://blog.codingconfessions.com/p/what-makes-system-calls-expensive) -- [Syscall overhead — Stack Overflow](https://stackoverflow.com/questions/8247331/syscall-overhead) - ---- - -# Windows Implementation — branch `windows-optimizations` (2026-07-15) - -## What landed (pread path, validated) - -Two changes, both on the `pread` expert-load path (no mmap). Measured against the -existing `bench_budget*.txt` baselines (GLM-5.2 744B int4, 32 GB RAM, Core Ultra 9 -185H, DRAFT=0, 32-token decode): - -### 1. `compat_fadvise` WILLNEED cache-warmer (`c/compat.h`) - -Replaced the Windows `posix_fadvise` no-op (was a `do{}while(0)` macro) with a real -readahead: an overlapped `ReadFile` into a throwaway scratch buffer that populates the -standby page cache, so the later synchronous `pread` faults from RAM not disk. Mirrors -the macOS `F_RDADVISE` shim (`compat.h:28-37`). DONTNEED stays a no-op (matches macOS; -Windows standby-list trimming self-regulates under pressure). - -This re-arms the existing `expert_prefetch` → `st_prefetch` → `posix_fadvise(WILLNEED)` -chain on Windows: the next-block readahead in `moe()` and the PILOT cross-layer prefetch -hints now actually warm the cache instead of being silently discarded. - -**Measured effect (budget=4, PIPE on):** hit rate 16.4% → 27.6%. - -### 2. PIPE default ON for Windows (`c/glm.c`) - -Flipped the async expert-load thread pool from default OFF to default ON on Windows -(`getenv("PIPE")?:1` under `_WIN32`, unchanged `:0` elsewhere). PIPE dispatches expert -`pread` loads onto worker threads so they overlap the expert matmul on the forward-pass -thread, instead of the blocking serial load-then-compute path. `PIPE=0` opts back out. - -**Measured effect (budget=4):** expert-disk 65.9s → 54.3s (−18%), reaching **1.70 s/tok** -(under the 2 s/tok target; budget=4 baseline was 2.06 s/tok). - -### Results table (DRAFT=0, 32-token decode, pread path) - -| config | expert-disk | s/tok | hit% | tok/s | -|---|---|---|---|---| -| budget=4, no PIPE (existing baseline) | 65.9s | 2.06 | 16.4% | 0.33 | -| **budget=4 + PIPE (this PR)** | **54.3s** | **1.70** | **27.6%** | **0.34** | -| budget=6 + PIPE | 77.1s | 2.41 | 21.8% | 0.27 | - -budget=4 + PIPE meets the ≤2 s/tok target. budget=6 (more experts/layer, higher quality) -misses it at 2.41 s/tok — the speed/quality tradeoff. - -## What was tried and abandoned: Windows mmap (`COLI_MMAP` on `_WIN32`) - -The original plan (informed by llama.cpp #18758: "mmap is ≥10× faster than O_DIRECT for -MoE") was to port the mmap expert path to Windows via `CreateFileMapping`/`MapViewOfFile`. -This was implemented and tested at length. **It was a measured regression and was reverted.** - -### The attempt - -Added a `_WIN32` branch to `map_of_fd` (`glm.c`) mapping each shard file read-only and -resolving experts as views into the mapping, mirroring the POSIX path. Also added -`PrefetchVirtualMemory` readahead and a `VirtualUnlock` eviction mechanism (the Windows -`posix_fadvise(DONTNEED)` analog — see SO#1880714; validated standalone to demote pages -to the standby list with a 2.3× faster re-fault). - -### Why it regressed - -**mmap'd expert pages bloat the process working set on Windows, which collapses the -expert cache.** This is a fundamental Windows-vs-Linux difference: - -- On Linux, `mmap(MAP_SHARED)` file pages live in the kernel page cache (`buff/cache`), - separate from `MemAvailable`, so the cache budget isn't fooled. -- On Windows, touched `MapViewOfFile` pages count against `ullAvailPhys` (what - `compat_meminfo` reads for the budget). The CPU matmul touches every weight byte, - faulting ~12 GB into the working set. `cap_for_ram()` then sees ~no free RAM and - collapses the LRU cache cap. - -Measured (budget=0, DRAFT=0, apples-to-apples): - -| config | RAM_GB detected | cache cap | hit% | expert-disk | RSS | -|---|---|---|---|---|---| -| baseline (pread) | 21.4 | 1 | 9.3% | 133s | 15.0 GB | -| mmap, no eviction | **8.0** | 1 | **2.2%** | **240s** | **27.2 GB** | -| mmap + VirtualUnlock | 24.9 | 2 | 11.8% | 83s | 18.1 GB | -| mmap + reserve reductions | 24.6 | 4 | 21.8% | 80s | 20.1 GB | - -The `VirtualUnlock` eviction recovered the regression (240s→83s), and dropping the -Linux-specific page-cache/slab reserves under mmap got it to parity with pread. But it -never clearly *beat* the simpler pread+PIPE path, and it added substantial complexity -(per-slot eviction tracking, reserve conditionals, `VirtualUnlock` on every slot recycle). -**The engine already moved off mmap to pread for this exact RSS bug** (`st.h:3-6`), and -the Windows port re-confirmed that decision. - -### What else didn't work - -- **Batched `PrefetchVirtualMemory`** for the mmap path: tested as a single batched - readahead of all 64 missed experts' pages before the matmul. **Blocked instead of - prefetching async** on this SSD — inflated `t_edisk` (80s→102s). Consistent with - microsoft/Windows-Dev-Performance#108 ("PrefetchVirtualMemory does not prefetch"). - Reverted. -- **True I/O/compute overlap on the CPU path**: the Metal path has this ("submit - resident experts to GPU before loading misses"), but the CPU path loads-then-computes - serially. `PrefetchVirtualMemory` was the attempt to add it for mmap and failed. The - pread path gets overlap via PIPE (which works), not via mmap prefetch. - -### Conclusion - -For this engine on Windows at this RAM budget (~32 GB, 370 GB model), **pread + PIPE + -compat_fadvise** is the right path. mmap remains valuable on Linux/macOS (where the page -cache doesn't inflate process RSS) but is not viable on Windows without a fundamentally -different cache-budget model that excludes mapped-file pages — left as future work. - -## Sources added - -- [SO#1880714 — VirtualUnlock releases mapped pages to standby list](https://stackoverflow.com/questions/1880714/createfilemapping-mapviewoffile-how-to-avoid-holding-up-the-system-memory) -- [Alois Kraus — The Mysterious Lost Memory (modified/standby list)](https://aloiskraus.wordpress.com/2017/02/26/the-mysterious-lost-memory-which-belongs-to-no-process/) -- [microsoft/Windows-Dev-Performance#108 — PrefetchVirtualMemory inconsistency](https://github.com/microsoft/Windows-Dev-Performance/issues/108) -- [llama.cpp #18758 — mmap faster than O_DIRECT for MoE (Linux)](https://github.com/ggml-org/llama.cpp/discussions/18758) -- [HN#35426679 — Why MMAP in llama.cpp hides true memory usage](https://news.ycombinator.com/item?id=35426679) - ---- - -# CACHE_ROUTE: miss elimination via cache-aware routing (2026-07-15) - -## The breakthrough - -Adding `CACHE_ROUTE=1 ROUTE_J=2 ROUTE_M=12` to the optimized stack pushed -throughput to **1.41 tok/s** (4.3× over stock) by directly reducing the -miss rate from 27% to 17%. - -## How it works - -The engine's `CACHE_ROUTE` feature (paper: max-rank routing, arXiv 2412.00099) -steers the MoE router to prefer experts that are already cache-resident: - -- `ROUTE_J=2`: keep the top-2 true router picks (always, even if uncached) -- `ROUTE_M=12`: fill the remaining 2 of 4 slots with the highest-ranked experts - that are ALREADY in the LRU cache (from the top-12 candidates) - -This guarantees 2 of 4 expert slots per layer per token are cache hits. The -`route_agree=94.6%` metric confirms minimal quality cost — 94.6% of cache-steered -picks match the true top-K the router would have chosen. - -## Why this is the right fix for the miss problem - -Analysis of route traces showed GLM-5.2's routing is nearly uniform — 75 tokens -use 237 of 256 experts per layer, with the top-4 capturing only 4.3% of selections. -This means: - -- PIN (hot-expert pre-loading) is ineffective — there are no hot experts -- PILOT_REAL prefetch can't keep up under the fast pipe2 GPU pipeline -- A bigger cache helps marginally but can't cover 237 unique experts per layer -- CACHE_ROUTE is the only lever that reduces misses without more RAM or faster disk - -## Results (pipe2 + full stack + ws_b fix, budget=4, RAM_GB=28) - -| metric | without CACHE_ROUTE | with CACHE_ROUTE | -|---|---|---| -| tok/s | 1.03 | **1.41** (+37%) | -| hit rate | 73% | **83%** | -| expert-disk | 12.4s | **8.5s** (−31%) | -| decode | 31.0s | **22.7s** (−27%) | -| route_agree | n/a | 94.6% | - -## Full optimization journey - -| step | tok/s | hit% | disk | -|---|---|---|---| -| stock budget=4 | 0.33 | 9% | 65.9s | -| + disk stack | 0.63 | 72% | 21.5s | -| + CUDA dense+attn | 0.72 | 75% | 18.4s | -| + pipe2 GPU pipeline | 0.85 | 57% | 18.2s | -| + ws_b cache fix | 1.03 | 73% | 12.4s | -| **+ CACHE_ROUTE** | **1.41** | **83%** | **8.5s** | - -**4.3× total speedup.** Disk I/O reduced 7.7× (65.9s → 8.5s). - -## Recommended config - -``` -EXPERT_BUDGET=4 PIPE=1 RAM_GB=28 PILOT_REAL=1 DIRECT=1 -COLI_CUDA=1 CUDA_DENSE=1 COLI_CUDA_ATTN=1 COLI_CUDA_PIPE=2 CUDA_EXPERT_GB=0 -CACHE_ROUTE=1 ROUTE_J=2 ROUTE_M=12 -``` - -CACHE_ROUTE is an existing engine feature (no code change) — opt-in via env vars. diff --git a/issue_grouped_quant.md b/issue_grouped_quant.md deleted file mode 100644 index fb46ce4..0000000 --- a/issue_grouped_quant.md +++ /dev/null @@ -1,185 +0,0 @@ -## TL;DR - -The int4 model produces **fluent-but-incoherent output** — grammatical English that is completely off-topic (SEO spam, homework-help boilerplate) instead of reasoned responses. The root cause is **per-row quantization scales**: one F32 scale per output row (e.g. 2048 scales for a 2048×6144 matrix), which is 48x coarser than the FP8 source's 128×128 block scales. This destroys fine-grained weight information that handles reasoning and instruction-following while preserving the large-magnitude weights that handle grammar and vocabulary fluency. - -Branch: `experiment/grouped-quant` (based on latest `dev` at `62419af`) - ---- - -## The problem — demonstrated - -Prompt: *"Explain the concept of recursion in programming. Provide a simple example."* - -**Baseline (no budget, no changes):** -> "Hire Some To Take Object-Oriented Programming Assignment" - -**Budget=4:** -> "The world is a dangerous place, not so much because of the small percentage of people who are doing to do the little of people who are doing to" - -**Budget=6:** -> "Elite Custom Essays" - -**Budget=12:** -> "Sololearn: Learn to code for FREE! +1 # Explain A concept of recursion..." - -This is not random gibberish — it's fluent English that is completely off-topic. This is the signature of **activations corrupted by coarse quantization**: the model retains language fluency (large weights survive) but loses instruction-following and reasoning (fine-grained weights are crushed to zero). - -## Root cause: per-row int4 scales - -### How the current converter works - -`convert_fp8_to_int4.py` (line 39-52) quantizes with **one scale per output row**: - -```python -amax = np.abs(w).max(axis=1, keepdims=True) # one max per ROW -s = np.maximum(amax / qmax, 1e-8) # one scale per ROW -q = np.clip(np.rint(w / s), -8, qmax) # quantize entire row with that scale -``` - -For a 2048×6144 expert weight matrix, that's **2048 scales** — one per row, each covering 6144 elements. - -### Why this destroys quality - -Consider a row of 6144 values where most are small (magnitude ~0.01) but a few are large (~0.5). The per-row scale is `0.5/7 = 0.071`. The small values become `0.01/0.071 = 0.14`, which rounds to **zero**. All fine-grained information in those small weights is lost. - -This matters enormously for MoE models: each token activates only 8 of 256 experts. A poorly-quantized expert pollutes every token that routes to it, and there's no averaging from the other 248 experts (they're simply off). The error is **concentrated**, not diluted. - -### What the FP8 source does right - -The FP8 checkpoint uses **128×128 block scales** — the weight matrix is divided into 128-element chunks, each with its own scale. Small values in one chunk don't get crushed by large values in another. For a 2048×6144 matrix: `2048 × 48 = 98,304` scales — 48x more granularity. - -The converter already dequants FP8 to f32 correctly (lines 196-201), preserving the block-scale information. But then it **throws it all away** by collapsing to a single per-row scale during int4 requantization. - -### GLM-5.2 was QAT-trained for int4 - -The GLM-5 paper (arXiv 2602.15763, §2.4.3) states: *"To provide better accuracy at low-precision, we apply INT4 QAT in the SFT stage."* This means the model is **designed** to work at int4 — but only if the quantization is fine-grained enough to match what the model saw during training. The FP8 checkpoint's 128×128 block scales are the granularity the model expects. Per-row scaling is 48x coarser. - -### Community confirmation - -Every other project getting coherent GLM-5.2 int4 output uses calibrated or fine-grained quantization: -- **ubergarm/GLM-5.1-GGUF** — imatrix-calibrated with expert-specific patches -- **Unsloth/GLM-5-GGUF** — dynamic UD-Q4 quants -- **QuantTrio/GLM-5.2-Int4-Int8Mix** — mixed int4/int8 with channel-wise scales -- **llama.cpp** — Q4_K with block-level group scales (typically 32 or 64 elements) - -None use naive per-row RTN int4 for production inference. - -## The fix: group-scaled int4 (fmt=4) - -Add a new quantization format with **one scale per 128 elements** along the input dimension, matching the FP8 source's natural granularity. - -### What changed - -**`c/glm.c`** — 122 lines added: - -1. **QT struct** (line 98): Added `int gs` field (group size, 0=per-row for backward compat, 128=grouped). - -2. **Format detection** (`qt_from_disk`, line 1064): Auto-detects fmt=4 by checking the `.qs` scale array size. If it has `O * ceil(I/128)` elements instead of `O`, it's grouped. **Old per-row models (fmt=2) work unchanged.** - -3. **New kernel** (`matmul_i4_grouped`, line 379): Same AVX2 nibble unpacking as `matmul_i4`, but the accumulator resets at each 128-element group boundary: `dot(x[grp], w[grp]) * scale[grp]`. The scale changes every 8 vector iterations (128/16=8). - -4. **Dispatch** (`matmul_qt_ex`, line 813): Routes to `matmul_i4_grouped` when `fmt==4`. Always uses exact kernels (no IDOT approximation — the whole point is quality). - -5. **Expert loading** (`expert_load`, lines 1418 and 1538): Both the mmap and slab+pread paths detect fmt=4 from scale array size and set `gs=128`. - -6. **`qt_bytes`** (line 104): Reports correct memory for fmt=4. - -**`c/tools/convert_fp8_to_int4.py`** — `quant_int4_grouped()` + `--group-size` arg: - -```python -def quant_int4_grouped(w, bits, gs=128): - O, I = w.shape - ngroups = (I + gs - 1) // gs - wpad = np.zeros((O, ngroups * gs), np.float32) - wpad[:, :I] = w - wr = wpad.reshape(O, ngroups, gs) # [O, ngroups, gs] - amax = np.abs(wr).max(axis=2, keepdims=True) # one max per GROUP - s = np.maximum(amax / qmax, 1e-8) - q = np.clip(np.rint(wr / s), -8, qmax) - # ... same nibble packing as quant_int4 ... - return packed_nibbles, s.reshape(-1) # [O * ngroups] scales -``` - -Same packed-nibble format as existing int4 — only the scale array is larger. - -### Verification - -**Converter round-trip test** (weights with varying group magnitudes): - -| Method | Mean relative error | Max abs error | -|--------|-------------------|---------------| -| Per-row int4 (current) | 0.2056 | 0.0127 | -| Grouped int4 (gs=128) | **0.1278** | 0.0127 | -| **Improvement** | **1.6x lower** | — | - -**Engine kernel test** (AVX2 `matmul_i4_grouped` vs f32 reference): - -| Output | Reference | Kernel | Error | -|--------|-----------|--------|-------| -| o=0 | -0.126368 | -0.126368 | 2.98e-08 | -| o=1 | 0.075913 | 0.075913 | 1.49e-08 | -| o=2 | 0.077136 | 0.077136 | 7.45e-09 | -| ... | ... | ... | ... | - -Max error: **2.98e-08** — matches f32 reference to within float32 epsilon. **PASS.** - -### Cost - -| Metric | Per-row (current) | Grouped (new) | -|--------|-------------------|---------------| -| Expert weight size | ~18.9 MB | ~20.1 MB (+6%) | -| Scale array per matrix | O × 4 bytes | O × ceil(I/128) × 4 bytes | -| Total model size | ~370 GB | ~390 GB (+5%) | -| Disk I/O per miss | ~19 MB | ~20 MB (+6%) | -| Kernel speed | One scale multiply per row | One scale multiply per 128 elements | - -The 6% I/O increase is negligible compared to the quality gain. The grouped kernel has slightly more scale-lookup overhead but remains within AVX2 throughput — the bottleneck is disk I/O, not matmul. - -### Backward compatibility - -- Old per-row models (fmt=2) **work unchanged** — format auto-detected from scale array size -- All existing features (PILOT, EXPERT_BUDGET, CUDA, MTP, PIPE) work identically — they don't touch the dequant path -- The fused gate+up pair path (`matmul_i4_pair`) falls back to separate `matmul_qt` calls for fmt=4 — minor perf cost, correctness preserved -- `--group-size 0` produces per-row output (backward compat for the converter) - -## How to reproduce - -### Convert with group scales - -```bash -python tools/convert_fp8_to_int4.py \ - --indir /path/to/GLM-5.2-FP8 \ - --outdir /path/to/glm52_i4_grouped \ - --ebits 4 --io-bits 8 --group-size 128 -``` - -### Test quality - -```bash -# Old model (per-row): -SNAP=/path/to/glm52_i4 PROMPT="Explain recursion in programming." NGEN=32 ./glm 64 - -# New model (grouped): -SNAP=/path/to/glm52_i4_grouped PROMPT="Explain recursion in programming." NGEN=32 ./glm 64 -``` - -Compare output text coherence. - -## What this won't fix - -- **Cold cache speed** — still 0.18-0.36 tok/s on 24 GB RAM. Quality and speed are independent axes. -- **All quantization error** — int4 is still 4-bit. Some degradation vs FP8 will remain. But it should be coherent degradation (slightly wrong word choices) rather than total reasoning failure (unrelated topics). -- **The IDOT +12% perplexity** — the approximate activation kernel (`IDOT=1`, default ON) still applies to non-grouped tensors (attention projections are already protected). Grouped int4 uses exact kernels by design. - -## Prior art - -- **GLM-5 paper** (arXiv 2602.15763, §2.4.3): "We apply INT4 QAT in the SFT stage" — the model is trained for int4, but assumes fine-grained quantization. -- **MxMoE** (ICML 2025): MoE experts exhibit divergent quantization sensitivity; uniform quant across all experts is suboptimal. -- **MoEQuant** (OpenReview): Naive int4 on MoE loses meaningful accuracy; calibrated framework needed. -- **Automated Fine-Grained MoE Quantization** (ACL 2025): Layer/expert-wise sensitivity variation; group-size scaling is the baseline improvement. -- **ubergarm/GLM-5.1-GGUF**: imatrix-calibrated quants with expert-specific patches — explicitly patches `quantize_row_q4_0_ref()` for routed experts. -- **llama.cpp Q4_K**: Uses block-level group scales (32 or 64 elements) as the standard int4 format. - -## Conversion status - -Re-converting from the FP8 source (`zai-org/GLM-5.2-FP8`) with `--group-size 128`. Downloading via ModelScope to avoid HuggingFace per-stream throttling. Will report quality A/B results once the conversion is complete.

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

p!WZYC% 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 z zVQXs&Zu6e`NQv%CJq$3k1=c{?vhilrn&XJDHfGVM-JIgqUBXP3F=6EqUt2SgMgMs{ zdH|;-Gp$BQfFM>$M(l=UqD9fYfBiFere~)r{z0Iog}eSoK*wg?1@JN-xRkI|7)6m* zbaC=u9Oj9NW;k8~C{d(3_38oG{n5>4x<135bH@8{if()XAkJ9*l2Sh$p zRdqMbAm27r(<-}t=l)QGf(y9pPtS7)4QFR<4zuI&>vsfKq+#UAgLJLv)_oGrC0IXvg@-^uN8gez5rtnf^ zy!c{;YuNI6c%i3zMU1e2%gK*u!5s|WU{nx3&HG*vXq zu}mgYc$Pp;hcBG~>4r`orKt;<4jt@`D=4&*$ z2u?S2m&+#3z8kg_9PN>-ePdXD*azSTO=Ur27Vf8hgdW(~Uvb^!(Gb*o^vZ%I_5>kf z5%cWC!UaKVCgIQN`K73X^ClX3l?Q#9G(y(=ql^{#gD*vV!^W{nXBOQ2P`*5?@*IS` ztbrti2^`Gv(XD>Io0QBF{>Sy6sNAaA`Qrf^Z8Hb>5|B&+QxOn&E&b6~4*Z%N;O{Nq zwSU0=1UoZ1BLFOP2g2_d9RELm|IhnEe;@MyMA3hf3stX~E_zaM>6j-cN3)>LWSsEY zv$-;t(QJaOWvQ3J0C@hJ1uXHmy5TQA5;SN7A64?!C$_YTALje}>;MVBti+znJk#XR z@N52qe{V-Hk{ldgKOO-LT|Q_k$QJ8V=hC_8&|bIr<~`AiwJ$TDHdU*(deA}X(Wl0t zVSu=!a{#gpGzS1=`zy4!<6W9BKm)eTfIN8i?pCatHEdjKT;zx)5|y7KE+gMTISs^j z>*sHwrsKmZCWE8V4&3 z`Y3;s0r-{V5BGMAO(XwO`nWGQs;^`Hdt4lRV2GPj(xh(xs>49dtFLL$Io9?s0sIoktiSq{&Ae5k-yBTG{Tox6$6m>G*HI|zOZUC=V7(= z#EsWgC;hA*AdmR#@qK@I*NV7UQC5BPu-C!Uxf9XITUguY=vjHwY)LNu@$+v1X8kp@ z0To_s`n}<5M|R(b#JgQnwSN7ROGBsfyxVeP4sw|RyhErfs(?6-J>fW;i&PvR7XJ#! z1gEF{X#f#tehC8(r+fmnq-tXA9f!|P)a1-7htWLvNHQm;qK&2}&z~^AHR4XyQ1p)S zECA*YSxRZGqOVVdR$Fs>$vJ;b&KQo7EzgTG)Q{@qSq_fV)=&_L^wfPgd_HOm4lh*t zm0Hi2u@;;p7oD$luug6ED$vi*$yHoxRMb43eu4i-L-%8y@nNgWZj7buzW={Sd1;m7 zXzl05L}1-owVjo?y1mg%ZV~b5Go>#5`G9(e;ls@Klj!B>P&_zQ$yeHa$ZPOzHlWU7 zaARX{-56Ewbc#1nV!+p85)vpVdcFoB0jNvQ_UAK7oZ_}OElg@PA`^sR-rL*Don;8b zi`sG`v1Np@w(H;CKifzAPwV1;-6ao+F!Pgziz==Dn7>qWLq7zqTCA?{ z+*^N{GTEOPA0G%5uNjYbHoZI5*cN?<5ArA$cGd!&lE{KOO7+k2V4x%G+SJUR1AWcC z$*N{MQs!BA3e;V7yYO=r`v=*#j1@3nY658ITSZzT{y!V{I-1R=&{R>iiT4jIE9ZKP z>~!2WO{|0Dc5o6_eoS#YI{l-g8(u1a)_8#M~h+4B^ zd$sK@&Ygot9Q&>fg8E68va_jWd%FX+y>Pgh3`J^oD>L}f&vT=W^xD)ELj!}w#XVL3 zbzovL&3;aJq2wmd>GHiN`#MzTM~V}R)7-{htj-267N>)*NhP#O0I$Ify7$-Wm^f5A zGcyWJhUzPPq?rQYss1b4)m#6c`h;(~#QjNpmO*A*t!IQ_NUdv92uI(Or=c;zS3X52 zN?BQO9VmPux_Q*0(v{gwtiNK$R0&|KE@MSCEv8<7;98w6t5d51Mq}FYkwL*ojcEC_ z2%Li|#3ub3|F>_4xDm$2B_{p({JRqp2M!*sWaq=gRF1Y4NpCO4^1#L<-OYjWQO(wh zz}769ma{vrMoTw1E(BEVB(N(eJ~~iB-ex(8?J!Y8l${RWx_;lfU|xw~Q13Mrx3M}oMyX? z{OQsb10`lO_0WS=u~{BM=$*USv9? z$+@$(6pu#H3m@DZ@9r+TsB6r^-hfT^EadDdE|Z{Y?__h4Y}Tmql&SC2Emqm+)0;g0 z?9?({#7L3!`l2|q%jB@??qi^0F%PU4Y01`8zT51VDBHRFUAS!L(hh4>ZJZ0(2W%p> zw;r+#^O_k5`FI_^yd1`F>CpnOTMr9)g}kTH+5+hLK+*BeKFPud)4E@CI)A0Mzl5jX zQZ67o0pt`mKBq+un_8=Jj+gfZBp-FcM85vtauZ}l7YKo)>8oAkTyWEK&5^>v-!Fvp zec5VK_^l*&D7eq5d~gSKg6H^wc+(=dz)}}0=$;C`jLJAsreT$SK+`g}JqQqpK}{@q z$v-e4u5t6M)GHmJirGw3FbIBN@_*6xo^efX-McPUtgsYmBCtde1pyV2PE*`Jdn3n@?*Ar13m+ zj&YCczNZ8$Qc=VcucnZs0n_v}ERCwqJG{sgrF-9MN{xpEwK5rfB&tX zowU_RNPW?5-5M-Dm?EgnG^BkpOj&T~YC{F)4Ti7uz%-Bi!QZ=K;fQc48OS*o`8LK* zX1pm~x+_(|p>+^?*Y9iP+lMa>#%FzUpBl=Z=x6bhMwq0X)y)5C*@@b|Vd>S_MFuBF}VKfZAoGEE{=?v zLxCE8ny2_Zrhqhm>Fq7yN8-bL>>70+L@-3PIt9*^N;2%dy5li4b7*{oGU=gbRET;6 z0i%Xzd*b63Js^NyNklTF&OhAnuV1HyEP&qog!8Q4OS1K;Ot!;vQCRjSshX=Id??YA zVd%xp){$2Wu=k@{A|@#*1nMK9cHe5r7KbNwtyP9FP5V8SX_nn*a}E*yBAO}VY@2oa z4?;~-v9E4aJbDP^wcBWgBd!OneBgH-Qk;*_C2VlOkK$7&P#qh5s2-GLpKq4nowPr} zB-b2}3@QUxlHJdR58a4Nt(ao(iyBpBU_T?vdE4dX8kN~Z?I>Xv^Y43psHr5^JOyzu z;n4O{3Tz9dkY&;3rKGmwLdffF=G5Jq07$6gHmqdXfqOEG2s7M*b;F2kg>v^2H($Vnm5n&gIr#TrZxBxIe^ zk|9TJtVPuO zNTm~{X3c|!a%~A?o~niKn3D4|Gw*e2_kV8VUc(ZbO<^dT`H!X+c|Tt=9(OINUEg+< z8VO2-uy!VvkAku2jH-UQ2PsFi&dp{vV_DjLhEH_70Ux~_1vpz1jKIXRF z9^AIa5RiwfKYIA(Y!5=p956^I1xNn)`R|cRclGf521P!en@ys1>kR-{ATUizJ54`i zeYv`}zE>AESU)pDZMH4ILZOR7b;ITM>U9>K1Ev}Hf;yTYx8tyZHFA;BQ+d8D#?-|x z&rry+W@+`XK;mbcgLdHA-?8p^$zH`5K55EIdF+bw?&9_(IClPIfR)6b7K7im3m(c6Br9nKlB0GB)Wtow4McAP9vdVD>!-BDc1QD4__-F!0HcyDkZK zoTi0Ne$7l+^xVpm7?B)^qI4H2Y>MNYt%KP`9<*@Fc)0nYlRg=i{=|T(pHD)VjN3O_ z)J;c4gDddb5?kzY3L~$Pk&(<_80&L0yb=i#(0rLc*(e5vTOM6|^t{34HoQub-+oN) z5UnlrT(XcTs;F3>)KquID+bFOFI$tkqX7^I+ibhNMp^2TH?8u>V|lK0Ay2PXmikIK z>p(hb6#fOgnNc6AIMLDenadZ=xf}L(ljH@5HnTy2J5prP_|2PwejCAq>3&kyWf%c} zM{Z3G2Woc!SKSs`1}6YHFjK5c8cY>V`mW1Fd7KMy$%q(Co0x%vrbVnH&ZsJ(W_31u z*57^@9_QAB$*v^zn@t63#) zNvk?E-lhfOK8yXaGoczUk&bVF+deyMBjGSwTk}kR<}zH-i_pYAlAN16KQswgpMPCSfGm4{j2x`-ZC*DHSho@MO^baZEJ&Y3(I<9Nnny+j>S z2C8^14(Od;fV9YOtb=r%smpWKyvBp6mg;M!ywy9jDoV9*^|qlv!n-g8Y{FFV723N` z9+BlTr{fsCCc!DQ!Sg*b&73$yup5b6I8&h9rw8a4Iq3l z-Zs=Baa=C=Qw#<`Y8$yPYa1Kam~FgWB@K&7*nsnPj;ioy!)OgfWqF;Iq(y(G&p#^5vqavMVbw4wDY*#FwF|b zIP?RQ?U))RW`U1Xa+O9;=XFP%&$pebbWqrmA?&clw$G!ZrM_DpPonYa(wDd)5>!ss zP%x#AzivIzDF`^(rQ(7}E7DNetq$v+&($7MISSDqazeQzY}T}fJxDOO1$FFq&>61u z<<%j65@K>rM@7@ti#uNPL_V+WeWG+`Wnp{6v3k=cUucIgE1EbvE-#)}T6+Demyou% zn6jO!ODwv<5NVTWWZ;Q{juQZ~Shm^mwCq^+y@KlH2pNWsADLgnW$Ei9uSeqv2OW3! z6%|q0KVT2=2W_U)J+lg6(3Lo&D$-FyGuF`YJs-2!(Ycnw+ zAwk$CJ{Wt4qW%}G*6v4zZHt9)_ZEvkoQ9dqMf|-D>W3sxH1o*%i~x-acIqVbY4=sB z7R1LhmCIdO@OWD92jxkTcKvdMsYe?+QAPn%gO;3|XHnZkazPfm{X}Wd*Q?J+GHw+v z^JS!A0bYm6$gaq?ax%6^;lQxvsBghW=ZZr$xO-vLo%~1N=lja$C@{!XDg2@+%-5Y1 zf{VDnbNA^xd>CXrmp5sy86ad63TvbB=*<;J_&|xSqXccl5tazs);l#2x?^8}+p1V7 ztE+S&w6mVD+{U$1;6(2X)WTP0?2e0#&!e1vdxu1qDlWj5-Cird>}tFLp>3d-nNQQU zdk}U*rEQ^%%u+vz=J{@Tw>;X+^mp<*(UuW-(&DP2BR{*n{@Tuph6J|OcZ;7rfzo_i zv67&!iEU{RHZGoQo@=4bpsU(#@4ES}*JBL@aJg=8-v(2BrwbgapHM4Jx92mC91l)g zY-94iwK`lz>FJBjH>kWgALZecpQz$>mp+?3NvX9f%63ew6zG3ShzR&Yvwz5u=)J0O z94|I8vUFJQ{b0&Q$~oo;X}8%)s^zBTRwQv;FZvk?@;I5xaTMu3E`a!K>iXqn5F#*s zr!KtsV9WkAq78*SQm_pl0GB7&s7+T4W&`FUC%n7u z0BEH%<1!S|Ovg?sTH~8R{o%S33!_E1`?zRVd62kb_<7Z$X(?X|> z29NHBMH(BHL_w8Bl`S9gbe0+hcDB4*435Ep6=3Y zf<2%#Uaz4b$hF_g)g)77S7h^aO}+I0YmIm%2W9B*&x;x^cU0e=h<_vuQW|OG_zs!E zbmJ^T^%;C16@c`R=E5%Jf!P2y06GQ( zNgcKB4MC&w1T6{JSW+E0cdsLRijfxrN`@D={IoltpCgKQ$u2l*i)jI|Z3`uetM*)C z?6V3~(aK<0ZkWH+xEHLriTs5wE{E~&&6$J8?5WzrjQM!K-os*)b_yfDbjFqt8@r#TdOiCdQ&ENfTNxxU41^uJ+IbHk4Z z^4tLW*9bw<`y6%RM+wejABwMLu_rjghf+EbH>!Qcv-zR~`12kw8TD1#lc`JRLsSt! zvQ9RV$N}@{GBMb7@-2XW4Y`)0mK=Q=W0?S$as!GR^iG)hc~oGd!~!RA!L9jsKOUql zJ#(#d^Ff_LfPFBSweVfr?aoONBTY;)j;}nL^_ls3zFeZj{Nlqbr$ZLwdBBLpo(x7T z4iBk4sDtj`gbh9GTKPpU>*NbK93|Z{X?crOVX{ z=|)3eCYB;@rvU;s(U)IX zg#_ApRDFd@bC!9t<>}^@L!Ni>c;f_z`t``0Cb`wZL!Kj?gov1d{&l*nkGLN)$)s3abTceaGw3Wk$airY^`~M%$0)@BA>op9Jo1-HN=T7lG&6^On5g` z2}#P5cU#L^#{|!{lcUSErky66+7nUO@WW*n(ckqm!RY;R0F`fm1x0<0_2F=S53#Ke z@z$>9J8AR2-dHIrJHe%ija=KVnspP*=Hrh@S;FZ~HYleRBWuGEOzqGDfj+YRzAi_-g`NbG0_?9ar4LI|nVD z1sj5l#%G4PY1;jY%$(u zo$5OS{czIeT3wg?nymIx2^2!z5S>DM7C7UJ&nhrK zsGBNMqGj_*K41Tdzk6QkvM2A&6+D9G*0P!?xR6{NwMHd~c%DV{9V>M8UHWLQ!X=Tk zg`3a!hHmNDT-KTpM+l1AYx#s+A3F(^RNZpK!neB z5tr!ZG6p*8Ih^%Q4O^)iZ`*9Vv#>J-o$f7y&z`Ua-VN}yi$v~#x1Viz2tbuIT05aX zQ?u01RWR(aiXTE!-x{uxmjlu=8X2tPF zRT0A=Iad^z&SaldC}XRr8)c8nKgo=-sqU)v-434ZPDx!NHY;Y;Uq2WpZhK?9d-7&J zNNy07hbR!NHrP#N7rXaaCb>G?zaLa`f$_M^V7$yyrvw5{MqTXi1VRvfKG3K!swG}` zZ2Dk6aGStoSK$a@fagfr50&;s>#gy$1*(ZV7@e+shjN|z=H)$AsPMXKM|QdJYa)bl zG+K0LB31x##c(5021+BKhefN*O1BjJebX<$jwMp#)r_V%lmB2n z7z&Alsf>?nwi}kfzyjjXxL^X$XMGQeHX8RaU9w3BFA#$_;#HuUAKYJ=c=xvB~+h&RK7GwQaN| z7jR}*cHqn-@X_YuT-eBqtZi*B{iEFL1ihaN+sn+C{-947{_Z7viuiT@|^e$ zHn1TiDhhx%_YyW?K_S6`0@E0tpHHh7^E=}uMi(*~MQH%QsZQ=B8Tay+6Lm5TNt<&;Mm$09omP9sGB^UuFv|dtLAL1y(LF zx{mHl;=@@PdLjS&1OM&)DJk@I1^!1h&%p47Cu9$ZQNJ$ft7P<9)$|J9#8P^``Y