Files
colibri/c/tests/test_uring.c
T
Robert Landers 5d1eb142ab port uring implementation
Signed-off-by: Robert Landers <landers.robert@gmail.com>
2026-07-15 12:42:10 +02:00

115 lines
5.1 KiB
C

#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;i<m.S.n;i++) free(m.S.t[i].name); free(m.S.t); return fail("expert tensor views"); }
m.c.n_experts=8; m.c.n_layers=2; m.ecap=2;
m.pin=calloc(3,sizeof(ESlot*)); m.npin=calloc(3,sizeof(int));
m.ecache=calloc(3,sizeof(ESlot*)); m.ecn=calloc(3,sizeof(int));
m.ecache[1]=calloc(2,sizeof(ESlot));
if(!m.pin||!m.npin||!m.ecache||!m.ecn||!m.ecache[1])
return fail("pilot fixture allocation");
if(uring_batch_init(&g_ub_pilot)) return fail("pilot ring init");
memset(g_pilot_inflight,0,sizeof(g_pilot_inflight));
atomic_store(&g_cur_moe_layer,-1); atomic_store(&g_pilot_loads,0); atomic_store(&g_pilot_drops,0);
pilot_r=0; pilot_w=1; pilot_q[0].l=1; pilot_q[0].e=7;
pilot_uring_batch(&m);
bad=m.ecn[1]!=1 || m.ecache[1][0].eid!=7 || g_pilot_inflight[1]!=0
|| atomic_load(&g_pilot_loads)!=1 || atomic_load(&g_pilot_drops)!=0;
coli_uring_close(&g_ub_pilot.ring);
compat_aligned_free(m.ecache[1][0].slab); free(m.ecache[1][0].fslab);
free(m.ecache[1]);
free(m.pin); free(m.npin); free(m.ecache); free(m.ecn);
for(int i=0;i<m.S.n;i++) free(m.S.t[i].name);
free(m.S.t);
return bad?fail("pilot uring publication"):0;
}
int main(void){
char path[]="/tmp/coli-uring-XXXXXX";
int fd=mkstemp(path); if(fd<0) return fail("mkstemp");
unlink(path);
enum { N=4, SZ=4096 };
unsigned char src[N][SZ],dst[N][SZ];
for(int i=0;i<N;i++){
memset(src[i],0,sizeof(src[i])); memset(dst[i],0,sizeof(dst[i]));
for(int j=0;j<SZ;j++) src[i][j]=(unsigned char)(i*37+j);
if(pwrite(fd,src[i],SZ,(off_t)i*SZ)!=SZ){ close(fd); return fail("pwrite fixture"); }
}
ColiUring ring;
if(coli_uring_init(&ring,8)){
if(errno==EPERM || errno==ENOSYS || errno==EACCES){
printf("test_uring: skipped (%s)\n",strerror(errno)); close(fd); return 0;
}
close(fd); return fail("io_uring_setup");
}
for(int i=0;i<N;i++) if(coli_uring_prep_read(&ring,fd,dst[i],SZ,(off_t)i*SZ,(uint64_t)i+1)){
coli_uring_close(&ring); close(fd); return fail("prepare read");
}
if(coli_uring_enter(&ring,0)<0){ coli_uring_close(&ring); close(fd); return fail("submit"); }
int seen[N]={0},complete=0;
while(complete<N){
struct io_uring_cqe cqe; int reaped=0;
while(coli_uring_peek(&ring,&cqe)){
reaped=1;
if(cqe.user_data<1 || cqe.user_data>N || 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<N && coli_uring_enter(&ring,1)<0){
coli_uring_close(&ring); close(fd); return fail("completion wait");
}
}
for(int i=0;i<N;i++) if(memcmp(src[i],dst[i],SZ)){
coli_uring_close(&ring); close(fd); return fail("read data mismatch");
}
coli_uring_close(&ring);
if(ftruncate(fd,0) || test_expert_layout(fd)){ close(fd); return 1; }
close(fd);
puts("test_uring: ok"); return 0;
}