Ciao Salvatore,
ho fatto girare ds4 con DeepSeek V4 Flash (Q2 IQ2XXS, ~80GB) su hardware
consumer "improbabile": dual-socket X99, 2× RTX 4060 Ti 16GB (no NVLink,
PCIe3 x8), 128GB DDR4. Prima cosa: gira e la qualità delle risposte è alta.
Grazie per il progetto.
Una segnalazione sul path CUDA, con numeri riproducibili col tuo ds4-bench.
Il punto
Su GPU discrete (non unified-memory) il path CUDA usa O_DIRECT di default e
scarta le pagine dopo l'uso (madvise/fadvise DONTNEED). Sensato quando la RAM
non basta. Ma quando la RAM è >= modello, questo resta inchiodato alla
velocità dell'SSD mentre la RAM (spesso abbondante su chi ha una scheda seria)
resta inutilizzata.
Ho provato le due env var che hai già previsto:
DS4_CUDA_NO_DIRECT_IO=1
DS4_CUDA_KEEP_MODEL_PAGES=1
- modello pre-scaldato in page cache.
Misure (ds4-bench, GPU singola isolata 16GB, cache esperti 11GB)
Comando (identico before/after, cambia solo le 2 env var):
CUDA_VISIBLE_DEVICES=1 ./ds4-bench -m <model.gguf>
--prompt-file speed-bench/promessi_sposi.txt --cuda --ssd-streaming
--ssd-streaming-cache-experts 11GB --ctx-start 2048 --ctx-max 8192
--step-incr 2048 --gen-tokens 64 --csv out.csv
ctx | prefill_tps O_DIRECT -> page-cache | gen_tps O_DIRECT -> page-cache
2048 | 44.0 -> 24.0 (primo chunk, freddo) | 0.87 -> 1.34
4096 | 42.6 -> 56.4 | 0.88 -> 1.36
6144 | 41.6 -> 57.9 | 0.87 -> 1.32
8192 | 41.4 -> 57.5 | 0.88 -> 1.33
- Decode: +52% costante a ogni contesto (esperti caldi serviti dalla RAM).
- Prefill: penalità solo sul primo chunk freddo (warm-up della cache),
poi +37% sostenuto. I/O disco nel decode passa da ~1.6 GB/s a ~0.
La regola
Il vincolo su GPU discreta non è la VRAM, è la RAM totale >= modello. Combacia
con la tua raccomandazione 96/128GB. E scala verso l'alto: una scheda con
piu' VRAM prenderebbe questo + una cache esperti piu' grande -> piu' veloce
ancora.
Proposta
Attivare automaticamente la residenza in page-cache sul path CUDA quando la
RAM libera >= modello, invece di lasciarlo alle env var manuali. Beneficia
ogni box a GPU discreta con RAM sufficiente (3090/4090/5090 + DDR abbondante),
che è la maggioranza degli utenti CUDA. Costo: un warm-up una tantum sul primo
chunk di prefill, trascurabile su sessioni reali.
Nota: ho visto che O_DIRECT e keep-pages-off sono scelte deliberate per
tenere la RAM libera ad altri processi. Su una macchina dedicata
all'inferenza è un non-problema; per questo proporrei un auto-rilevamento del
regime RAM>=modello, non un cambio secco del default.
PS - multi-GPU
Per curiosità ho provato il distributed (pipeline) sulle due schede: funziona
ma per un singolo stream è piu' lento (~0.23 t/s) per la staffetta
coordinator<->worker a ogni token. Guardando il codice, la cucitura per un
Expert Parallelism sembra esserci (slot-cache per-esperto,
ds4_gpu_stream_expert_cache_begin_selected_load con gli ID selezionati);
l'ostacolo è il backend CUDA single-device (un solo cudaSetDevice, stato
globale singleton). Lo lascio al tuo giudizio.
Macchina: dual Xeon X99, 2× RTX 4060 Ti 16GB, CUDA 12.6, Pop!_OS.
Backend: CUDA, ssd-streaming. Modello: DeepSeek-V4-Flash IQ2XXS (~80GB).
Grazie ancora.
Ciao Salvatore,
ho fatto girare ds4 con DeepSeek V4 Flash (Q2 IQ2XXS, ~80GB) su hardware
consumer "improbabile": dual-socket X99, 2× RTX 4060 Ti 16GB (no NVLink,
PCIe3 x8), 128GB DDR4. Prima cosa: gira e la qualità delle risposte è alta.
Grazie per il progetto.
Una segnalazione sul path CUDA, con numeri riproducibili col tuo ds4-bench.
Il punto
Su GPU discrete (non unified-memory) il path CUDA usa O_DIRECT di default e
scarta le pagine dopo l'uso (madvise/fadvise DONTNEED). Sensato quando la RAM
non basta. Ma quando la RAM è >= modello, questo resta inchiodato alla
velocità dell'SSD mentre la RAM (spesso abbondante su chi ha una scheda seria)
resta inutilizzata.
Ho provato le due env var che hai già previsto:
DS4_CUDA_NO_DIRECT_IO=1
DS4_CUDA_KEEP_MODEL_PAGES=1
Misure (ds4-bench, GPU singola isolata 16GB, cache esperti 11GB)
Comando (identico before/after, cambia solo le 2 env var):
CUDA_VISIBLE_DEVICES=1 ./ds4-bench -m <model.gguf>
--prompt-file speed-bench/promessi_sposi.txt --cuda --ssd-streaming
--ssd-streaming-cache-experts 11GB --ctx-start 2048 --ctx-max 8192
--step-incr 2048 --gen-tokens 64 --csv out.csv
ctx | prefill_tps O_DIRECT -> page-cache | gen_tps O_DIRECT -> page-cache
2048 | 44.0 -> 24.0 (primo chunk, freddo) | 0.87 -> 1.34
4096 | 42.6 -> 56.4 | 0.88 -> 1.36
6144 | 41.6 -> 57.9 | 0.87 -> 1.32
8192 | 41.4 -> 57.5 | 0.88 -> 1.33
poi +37% sostenuto. I/O disco nel decode passa da ~1.6 GB/s a ~0.
La regola
Il vincolo su GPU discreta non è la VRAM, è la RAM totale >= modello. Combacia
con la tua raccomandazione 96/128GB. E scala verso l'alto: una scheda con
piu' VRAM prenderebbe questo + una cache esperti piu' grande -> piu' veloce
ancora.
Proposta
Attivare automaticamente la residenza in page-cache sul path CUDA quando la
RAM libera >= modello, invece di lasciarlo alle env var manuali. Beneficia
ogni box a GPU discreta con RAM sufficiente (3090/4090/5090 + DDR abbondante),
che è la maggioranza degli utenti CUDA. Costo: un warm-up una tantum sul primo
chunk di prefill, trascurabile su sessioni reali.
Nota: ho visto che O_DIRECT e keep-pages-off sono scelte deliberate per
tenere la RAM libera ad altri processi. Su una macchina dedicata
all'inferenza è un non-problema; per questo proporrei un auto-rilevamento del
regime RAM>=modello, non un cambio secco del default.
PS - multi-GPU
Per curiosità ho provato il distributed (pipeline) sulle due schede: funziona
ma per un singolo stream è piu' lento (~0.23 t/s) per la staffetta
coordinator<->worker a ogni token. Guardando il codice, la cucitura per un
Expert Parallelism sembra esserci (slot-cache per-esperto,
ds4_gpu_stream_expert_cache_begin_selected_load con gli ID selezionati);
l'ostacolo è il backend CUDA single-device (un solo cudaSetDevice, stato
globale singleton). Lo lascio al tuo giudizio.
Macchina: dual Xeon X99, 2× RTX 4060 Ti 16GB, CUDA 12.6, Pop!_OS.
Backend: CUDA, ssd-streaming. Modello: DeepSeek-V4-Flash IQ2XXS (~80GB).
Grazie ancora.