mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-11 17:26:57 +02:00
Chercher à la main le bon micro-lot, les threads ou la marge --fit d'un preset demandait de dupliquer, basculer et comparer des bench complets un par un. L'optimiseur le fait sur un moteur d'essai, sans jamais toucher à config.env ni à ce que calcule le modèle, et n'écrit rien sans un clic. - Isolation : moteur principal arrêté puis relancé ; chaque essai est une copie de la configuration (LOKI_HOME/tune/run), lancée par « loki serve » sur 127.0.0.1 et un port libre, groupe de processus tué en sortie - Verrou exclusif inter-processus (LOKI_HOME/tune.lock, PID + démarrage + binaire) vérifié par serviceAction start/restart et par le chat, les tâches, bash_bg, /v1, le bench, la bascule et l'enregistrement de preset, GPU, clé d'API, moteur ; essai orphelin arrêté avant tout démarrage du moteur - Essais : lots, threads, délestage, marges --fit, files CUDA ; placement --fit et SPEC/CUDA_GRAPH_OPT/--backend-sampling seulement sur demande - EXTRA_ARGS jeton par jeton, liste blanche seulement ; ligne de commande de chaque essai composée à blanc et comparée à la référence (« dénature »), contexte, slots et cache KV recontrôlés une fois chargé - Mesure : bench complet du lot 1 à profondeur fixe ; score = durée d'un tour type (médianes de la télémétrie) ; gain > max(3 %, écart entre passages) - Application sur clic : copie du preset, ou preset actuel sauvegardé, réécrit clé par clé, vérifié par une sonde et rétabli en cas d'échec Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
56 lines
1.5 KiB
Go
56 lines
1.5 KiB
Go
//go:build unix
|
|
|
|
package loki
|
|
|
|
import (
|
|
"os/exec"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
// Moteur d'essai de l'optimiseur (backend_tune_run.go), côté Unix.
|
|
//
|
|
// L'essai est un « loki serve » qui devient llama-server par exec : même PID,
|
|
// même groupe. Setpgid en fait le chef d'un groupe à lui — un signal au groupe
|
|
// (-pid) l'atteint, quoi qu'il ait lancé, et rien d'autre : ni le processus web
|
|
// qui l'a démarré, ni le vrai moteur.
|
|
func tuneTrialAttr(cmd *exec.Cmd) {
|
|
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
|
}
|
|
|
|
// tuneKillTree arrête le groupe de l'essai : SIGTERM, puis SIGKILL s'il traîne.
|
|
// done se ferme quand l'appelant a récolté le processus (cmd.Wait) ; nil pour un
|
|
// orphelin d'un ancien Loki, dont on ne peut que sonder l'existence — un enfant
|
|
// non récolté resterait « vivant » (zombie) aux yeux du signal 0.
|
|
func tuneKillTree(pid int, done <-chan struct{}) {
|
|
if pid <= 0 {
|
|
return
|
|
}
|
|
gone := func(wait time.Duration) bool {
|
|
deadline := time.Now().Add(wait)
|
|
for time.Now().Before(deadline) {
|
|
if done != nil {
|
|
select {
|
|
case <-done:
|
|
return true
|
|
case <-time.After(100 * time.Millisecond):
|
|
}
|
|
continue
|
|
}
|
|
if !processAlive(pid) {
|
|
return true
|
|
}
|
|
time.Sleep(100 * time.Millisecond)
|
|
}
|
|
return false
|
|
}
|
|
if err := syscall.Kill(-pid, syscall.SIGTERM); err != nil {
|
|
_ = syscall.Kill(pid, syscall.SIGTERM)
|
|
}
|
|
if gone(10 * time.Second) {
|
|
return
|
|
}
|
|
_ = syscall.Kill(-pid, syscall.SIGKILL)
|
|
gone(5 * time.Second)
|
|
}
|