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>
74 lines
2.4 KiB
Go
74 lines
2.4 KiB
Go
package loki
|
|
|
|
// tasks_sched.go — la boucle de planification. Une seule goroutine, un tick par
|
|
// minute, dans le process qui possède la conversation et l'UI (ajean-ui /
|
|
// `ajean link`). Voir StartTaskScheduler, câblée dans newWebMux (web_server.go).
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var taskSchedOnce sync.Once
|
|
|
|
// StartTaskScheduler démarre la boucle de planification (idempotent : sûr à
|
|
// appeler à chaque construction du mux, ne lance qu'une goroutine).
|
|
func StartTaskScheduler() {
|
|
taskSchedOnce.Do(func() { go taskSchedLoop() })
|
|
}
|
|
|
|
// taskSchedLoop réveille les tâches dues, une par tick (elles sont de toute façon
|
|
// sérialisées par le gate de génération). Le tick d'une minute suffit : c'est la
|
|
// résolution de la planification (voir tasks_cron.go).
|
|
func taskSchedLoop() {
|
|
// Premier passage immédiat pour amorcer les NextRun manquants (après un
|
|
// redémarrage du process, ou pour une tâche fraîchement créée sans NextRun).
|
|
primeNextRuns()
|
|
t := time.NewTicker(time.Minute)
|
|
defer t.Stop()
|
|
for range t.C {
|
|
tickTasks(time.Now())
|
|
}
|
|
}
|
|
|
|
// primeNextRuns renseigne NextRun de toute tâche activée qui n'en a pas (0),
|
|
// relativement à maintenant — sinon une tâche à NextRun=0 serait considérée « due »
|
|
// en permanence, ou jamais planifiée selon le sens de la comparaison.
|
|
func primeNextRuns() {
|
|
now := time.Now()
|
|
for _, t := range listTasks() {
|
|
if t.Enabled && t.NextRun == 0 {
|
|
t.NextRun = computeNextRun(t.Schedule, t.TZ, now)
|
|
_ = saveTask(t)
|
|
}
|
|
}
|
|
}
|
|
|
|
// tickTasks lance la première tâche due (si l'interrupteur maître n'est pas en
|
|
// pause). Une seule par tick : lancer plusieurs inférences en parallèle est de
|
|
// toute façon impossible (gate de génération), et étaler leur départ évite qu'une
|
|
// rafale de tâches monopolise le modèle d'un coup.
|
|
func tickTasks(now time.Time) {
|
|
if tasksPaused() || tuneGuard() != nil {
|
|
// Optimisation en cours : la tâche due attend sa fin, elle n'échoue pas.
|
|
return
|
|
}
|
|
nowMs := now.UnixMilli()
|
|
for _, t := range listTasks() {
|
|
if !t.Enabled {
|
|
continue
|
|
}
|
|
if t.NextRun == 0 {
|
|
// Priming raté (schedule invalide) ou tâche neuve : on tente de le poser,
|
|
// sans la déclencher ce tour-ci.
|
|
t.NextRun = computeNextRun(t.Schedule, t.TZ, now)
|
|
_ = saveTask(t)
|
|
continue
|
|
}
|
|
if t.NextRun <= nowMs {
|
|
runTask(t) // met à jour LastRun/NextRun/… et persiste
|
|
return
|
|
}
|
|
}
|
|
}
|