Chargement du modèle : --mlock seul ne coupe plus le mmap

UN VRAI BUG D'ABORD
normalizeLoadFlags traduisait --mlock seul en « --load-mode mlock ». Or,
pour llama.cpp (common/arg.cpp), « mlock » veut dire PAS de mmap + résident :
le modèle entier montait en RAM au lieu d'être mappé. L'ancien --mlock, lui,
gardait le mmap — son équivalent est « mmap+mlock ». Sur un modèle plus gros
que la RAM (Qwen3.8-Flash-Next, 82 Go pour 64 Go), un preset qui avait
coché « Garder en RAM » tournait donc à l'OOM dès qu'un moteur récent
prenait le relais. Correspondance alignée sur AJEAN 0.16.0 :
  --mlock seul → mmap+mlock · --no-mmap → none · les deux → mlock.

DANS LES DEUX SENS
Un moteur ancien (ou un fork) ne connaît pas --load-mode et sort en erreur
si on le lui passe : downgradeLoadMode le retraduit en anciens drapeaux
(dio, inconnu de ces moteurs, est abandonné avec un avertissement).

UN SÉLECTEUR À LA PLACE DE DEUX INTERRUPTEURS
« Garder en RAM » et « Charger tout en mémoire » ne disaient pas leur
combinaison. L'éditeur de preset propose les six modes de llama.cpp (auto,
mmap, none, mlock, mmap+mlock, dio), avec ce que fait chacun en sous-titre,
et écrit la forme moderne. Un preset aux anciens drapeaux s'affiche sur le
bon mode sans modification.

Au passage, q5_1 porte la mention « lent sur CUDA » dans la liste du cache
KV (voir le commit du port occupé : non accéléré en Flash-Attention).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MichaelandClaude Opus 5.5 committed 2026-10-02 23:05:34 +02:00
1 parent f75f3cf27d
commit 1db987844e
5 files changed
+193 -34

No files matched your search

+41 -2
View File
@@ -926,8 +926,47 @@ function populateSettings(){
}
}
chk('s-flash', eaHasFlag('--flash-attn') && !/^off$/i.test(eaGetValued('--flash-attn')));
chk('s-mlock', eaHasFlag('--mlock'));
chk('s-nommap', eaHasFlag('--no-mmap'));
const lm = eaLoadMode();
set('s-loadmode', lm);
syncLoadModeSub(lm);
}
// Chargement du modèle. llama.cpp récent a REMPLACÉ --mlock / --no-mmap par
// --load-mode (auto, none, mmap, mlock, mmap+mlock, dio). L'éditeur écrit la
// forme moderne ; au lancement, loki serve la retraduit pour un moteur ancien
// (normalizeLoadFlags côté Go), et inversement.
function eaLoadMode(){
const lm = (eaGetValued('--load-mode') || eaGetValued('-lm')).toLowerCase();
if(lm) return lm === 'auto' ? '' : lm;
// Preset écrit avec les anciens drapeaux : même correspondance que le serveur.
const mlock = eaHasFlag('--mlock'), nommap = eaHasFlag('--no-mmap');
if(mlock && nommap) return 'mlock';
if(mlock) return 'mmap+mlock';
if(nommap) return 'none';
if(eaHasFlag('--mmap')) return 'mmap';
return '';
}
function eaSetLoadMode(mode){
const t = eaTokens().filter(x=>x!=='--mlock' && x!=='--no-mmap' && x!=='--mmap' && !x.startsWith('--load-mode='));
for(const f of ['--load-mode','-lm']){
const i = t.indexOf(f);
if(i>=0){ const hadVal = i+1<t.length && !t[i+1].startsWith('-'); t.splice(i, hadVal?2:1); }
}
if(mode) t.push('--load-mode', mode);
eaSetTokens(t);
syncLoadModeSub(mode);
}
// Sous-titre : ce que fait le mode choisi (les options ne portent que son nom).
const LOAD_MODE_SUB = {
'': 'mmap, sauf si un périphérique ne le permet pas',
'mmap': 'fichier mappé, lu à la demande',
'none': 'tout charger, sans mmap',
'mlock': 'tout en RAM, verrouillé (sans mmap)',
'mmap+mlock': 'mappé et verrouillé en RAM',
'dio': 'lecture DirectIO si disponible',
};
function syncLoadModeSub(mode){
const el = document.getElementById('s-loadmode-sub');
if(el) el.textContent = LOAD_MODE_SUB[mode] ?? mode;
}
// --- Décodage spéculatif (--spec-type / --spec-draft-n-max) ----------------
// Sélectionne le type courant. --spec-type accepte en réalité une LISTE séparée