feat(st): COLI_MODEL_DIRS - split model shards across N drives, no duplication

Each extra directory holds a DISTINCT subset of the .safetensors shards (search path, dedup by basename; first-listed dir wins). Demand preads hit whichever drive holds the shard, so concurrent expert loads parallelise across drives and combined capacity is used - a 400 GB container fits across two smaller drives that individually cannot hold it, which COLI_MODEL_MIRROR (a full second copy) cannot do. Composable with the mirror: st_mirror_init matches per-shard by basename against the merged index. st_init stays as a back-compat wrapper over st_init_multi. Verified on RTX 5080 / Windows: 72+70 shards across two NVMes, coherent output, [SPLIT] startup log, decode parity with single-drive at full RAM (0.92 vs 0.89-0.90).
This commit is contained in:
Mohamed Mastouri
2026-07-21 01:42:04 +03:00
parent 68ac9ff696
commit 0d2fb6f8a2
3 changed files with 61 additions and 10 deletions
+3 -1
View File
@@ -1031,7 +1031,9 @@ static void layer_cuda_shard_kvb(Layer *l,int H,int Q,int V){
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;
load_cfg(&m->c,snap); st_init(&m->S,snap);
load_cfg(&m->c,snap);
{ const char *xd=getenv("COLI_MODEL_DIRS"); /* SPLIT: model shards spread across N drives */
st_init_multi(&m->S,snap,(xd&&*xd)?xd:NULL); }
Cfg *c=&m->c; char nm[256]; int H=c->n_heads, D=c->hidden;
/* embed e lm_head sono il confine I/O: tenerli ad alta precisione (come i quant dynamic
* reali). A bf16 ~1.9GB su GLM reale: trascurabile. dbits>=8 -> qui f32; piu' basso -> dbits. */
+57 -9
View File
@@ -210,21 +210,66 @@ static void st_pread_full(int fd, void *buf, int64_t n, int64_t off, const char
}
}
static void st_init(shards *S, const char *snap_dir) {
/* Scan one directory for *.safetensors shards, appending to files[] (dedup by
* basename, so a list of directories acts as a SEARCH PATH: the same shard
* present on two drives is taken from the first-listed one only). *added
* returns how many shards this dir contributed. */
static void st_scan_dir(const char *dir, char files[][1024], int *nf, int *added) {
DIR *d = opendir(dir); struct dirent *e;
if (!d) { perror(dir); exit(1); }
int base_n = *nf;
while ((e = readdir(d))) {
const char *dot = strrchr(e->d_name, '.');
if (dot && !strcmp(dot, ".safetensors")) { /* model.safetensors o model-0000N-of-... */
int dup = 0;
for (int i = 0; i < *nf; i++) {
const char *b = strrchr(files[i], '/');
#ifdef _WIN32
const char *b2 = strrchr(files[i], '\\'); if (b2 && (!b || b2 > b)) b = b2;
#endif
b = b ? b + 1 : files[i];
if (!strcmp(b, e->d_name)) { dup = 1; break; } /* already taken from a higher-priority drive */
}
if (dup) continue;
if (*nf >= ST_MAX_SHARDS) { fprintf(stderr, "too many shards (>%d): raise ST_MAX_SHARDS\n", ST_MAX_SHARDS); exit(1); }
snprintf(files[(*nf)++], 1024, "%s/%s", dir, e->d_name);
}
}
closedir(d);
if (added) *added = *nf - base_n;
}
/* Index shards from snap_dir, optionally SPLIT across extra drives listed in
* extra_dirs (';' or ',' separated). Each shard lives on exactly ONE drive
* (no duplication — unlike the dual-SSD mirror); a demand pread hits whichever
* drive holds that shard, so concurrent expert loads parallelise across drives
* and combined capacity is used. Scales to N drives. Metadata (config /
* tokenizer / .coli_usage / .coli_kv) is read from snap_dir only. */
static void st_init_multi(shards *S, const char *snap_dir, const char *extra_dirs) {
memset(S, 0, sizeof(*S));
S->cap = 4096; S->t = calloc(S->cap, sizeof(st_tensor));
/* raccoglie ordinatamente i nomi dei file shard */
static char files[ST_MAX_SHARDS][1024]; int nf = 0;
DIR *d = opendir(snap_dir); struct dirent *e;
if (!d) { perror(snap_dir); exit(1); }
while ((e = readdir(d))) {
const char *dot = strrchr(e->d_name, '.');
if (dot && !strcmp(dot, ".safetensors")) { /* model.safetensors o model-0000N-of-... */
if (nf >= ST_MAX_SHARDS) { fprintf(stderr, "too many shards (>%d): raise ST_MAX_SHARDS\n", ST_MAX_SHARDS); exit(1); }
snprintf(files[nf++], 1024, "%s/%s", snap_dir, e->d_name);
int c0 = 0; st_scan_dir(snap_dir, files, &nf, &c0);
int ndir = 1;
if (extra_dirs && *extra_dirs) {
char buf[4096]; snprintf(buf, sizeof(buf), "%s", extra_dirs);
char *p = buf;
while (p && *p) {
char *sep = p; while (*sep && *sep != ';' && *sep != ',') sep++;
int last = (*sep == 0); *sep = 0;
while (*p == ' ') p++;
size_t plen = strlen(p); while (plen > 0 && p[plen-1] == ' ') p[--plen] = 0;
if (*p) {
int cN = 0; st_scan_dir(p, files, &nf, &cN);
fprintf(stderr, "[SPLIT] +%s -> %d shard(s)\n", p, cN);
ndir++;
}
p = last ? NULL : sep + 1;
}
fprintf(stderr, "[SPLIT] model across %d dir(s): %d shard(s) total (primary %s -> %d shard(s)), no duplication\n",
ndir, nf, snap_dir, c0);
}
closedir(d);
for (int a = 0; a < nf; a++) for (int b = a+1; b < nf; b++)
if (strcmp(files[a], files[b]) > 0) { char tmp[1024]; strcpy(tmp, files[a]); strcpy(files[a], files[b]); strcpy(files[b], tmp); }
@@ -305,6 +350,9 @@ static void st_init(shards *S, const char *snap_dir) {
}
}
/* backward-compatible single-directory entry point */
static void st_init(shards *S, const char *snap_dir) { st_init_multi(S, snap_dir, NULL); }
static st_tensor *st_find(shards *S, const char *name) {
if (S->hidx) {
uint64_t h = st_hash(name) & (S->hcap - 1);