====== std.sched ====== Scheduling & CPU-Affinität (WP-8): Steuert auf welchen CPUs ein Prozess oder Thread läuft (CPU-Pinning), liest und setzt den Nice-Wert (Priorität) und gibt die CPU freiwillig ab. Enthält Helfer zum Aufbau von ''cpu_set_t''-Bitmasken für bis zu 1024 CPUs. → [[lyx_-_programmiersprache:units|Standard Library]] · [[lyx_-_programmiersprache:units:process_ext|std.process_ext]] · [[lyx_-_programmiersprache:units:thread|std.thread]] ---- ===== Konstanten ===== ==== cpu_set_t ==== ^ Konstante ^ Wert ^ Beschreibung ^ | ''CPU_SET_SIZE'' | 128 | Größe einer ''cpu_set_t''-Bitmap in Bytes (1024 CPUs) | ==== Prioritäts-Scope ==== ^ Konstante ^ Wert ^ Beschreibung ^ | ''PRIO_PROCESS'' | 0 | ''GetPriority''/''SetPriority'' operiert auf Prozess-ID | | ''PRIO_PGRP'' | 1 | Operiert auf Prozessgruppen-ID | | ''PRIO_USER'' | 2 | Operiert auf Benutzer-ID | ---- ===== Funktionen ===== ==== Scheduling ==== ^ Signatur ^ Beschreibung ^ | ''SchedYield(): int64'' | Gibt die CPU freiwillig ab — der aktuelle Thread wird ans Ende der Run-Queue gestellt. Gibt immer 0 zurück | ==== CPU-Affinität ==== ^ Signatur ^ Beschreibung ^ | ''SchedSetAffinity(pid: int64, cpuMask: int64): int64'' | Setzt die CPU-Affinität von ''pid'' auf die in ''cpuMask'' (''alloc(CPU_SET_SIZE)'') erlaubten CPUs. ''pid=0'' → aktueller Prozess. Gibt 0 bei Erfolg | | ''SchedGetAffinity(pid: int64, outMask: int64): int64'' | Liest die aktuelle CPU-Affinität von ''pid'' in ''outMask'' (''alloc(CPU_SET_SIZE)''). Gibt 0 bei Erfolg | ==== cpu_set_t-Helfer ==== ^ Signatur ^ Beschreibung ^ | ''CpuSetZero(buf: int64)'' | Setzt alle Bits auf 0 — keine CPU erlaubt | | ''CpuSetAdd(buf: int64, cpu: int64)'' | Erlaubt CPU ''cpu'' (0-basiert) in der Maske | | ''CpuSetRemove(buf: int64, cpu: int64)'' | Verbietet CPU ''cpu'' in der Maske | | ''CpuSetHas(buf: int64, cpu: int64): bool'' | Gibt ''true'' zurück wenn CPU ''cpu'' in der Maske gesetzt ist | | ''CpuSetCount(buf: int64): int64'' | Zählt die Anzahl erlaubter CPUs in der Maske | ==== Prozess-Priorität (Nice-Wert) ==== ^ Signatur ^ Beschreibung ^ | ''GetPriority(pid: int64): int64'' | Gibt den Nice-Wert von ''pid'' zurück (−20 = höchste, 19 = niedrigste Priorität). ''pid=0'' → aktueller Prozess | | ''SetPriority(pid: int64, nice: int64): int64'' | Setzt den Nice-Wert von ''pid''. Nicht-Root kann nur erhöhen (Priorität senken). Gibt 0 bei Erfolg | ==== Aktuelle CPU ==== ^ Signatur ^ Beschreibung ^ | ''GetCPU(cpuOut: int64, nodeOut: int64): int64'' | Schreibt CPU-Nummer in ''cpuOut'' und NUMA-Knoten in ''nodeOut'' (je ''alloc(8)''). ''nodeOut=0'' auf Nicht-NUMA-Systemen | | ''GetCurrentCPU(): int64'' | Gibt die aktuelle CPU-Nummer direkt zurück (< 0 bei Fehler) | ---- ===== Verwendung ===== ==== Prozess auf eine CPU pinnen ==== import std.sched; import std.alloc; fn PinToCore(cpu: int64): bool { var mask: int64 := alloc(CPU_SET_SIZE); CpuSetZero(mask); CpuSetAdd(mask, cpu); var r := SchedSetAffinity(0, mask); free(mask, CPU_SET_SIZE); return r == 0; } ==== Aktuelle Affinität lesen und ausgeben ==== import std.sched; import std.alloc; import std.io; fn PrintAffinity(): void { var mask: int64 := alloc(CPU_SET_SIZE); SchedGetAffinity(0, mask); Print("Erlaubte CPUs: "); var cpu: int64 := 0; while (cpu < 64) { // Erste 64 CPUs prüfen if (CpuSetHas(mask, cpu)) { Print(IntToStr(cpu) + " "); } cpu := cpu + 1; } PrintLn("Anzahl: " + IntToStr(CpuSetCount(mask))); free(mask, CPU_SET_SIZE); } ==== Prozess auf CPUs 0–3 beschränken ==== import std.sched; import std.alloc; fn LimitToFirstFourCores(): void { var mask: int64 := alloc(CPU_SET_SIZE); CpuSetZero(mask); CpuSetAdd(mask, 0); CpuSetAdd(mask, 1); CpuSetAdd(mask, 2); CpuSetAdd(mask, 3); SchedSetAffinity(0, mask); free(mask, CPU_SET_SIZE); } ==== Nice-Wert und CPU-Diagnose ==== import std.sched; import std.io; fn PrintSchedInfo(): void { var cpu := GetCurrentCPU(); var nice := GetPriority(0); PrintLn("Läuft auf CPU: " + IntToStr(cpu)); PrintLn("Nice-Wert: " + IntToStr(nice)); } fn LowerPriority(): void { // Priorität senken (Nice erhöhen) — kein Root nötig SetPriority(0, 10); } ==== SchedYield in einer Spinloop ==== import std.sched; // Gibt CPU ab während auf ein Flag gewartet wird (statt busy-wait). fn WaitForFlag(flagAddr: int64): void { while (peek64(flagAddr) == 0) { SchedYield(); } } ---- ===== Hinweise ===== * CPU-Pinning erhöht die Cache-Lokalität bei rechenintensiven Prozessen, kann aber den Durchsatz bei I/O-lastigen Programmen senken. * ''SetPriority'' mit einem Nice-Wert < 0 (höhere Priorität) erfordert Root oder ''CAP_SYS_NICE''. * ''GetCurrentCPU'' ist nicht garantiert stabil: Der Scheduler kann den Prozess jederzeit auf eine andere CPU verschieben. * ''SchedYield'' gibt immer 0 zurück und schlägt nie fehl. * ''CpuSetCount'' iteriert alle 128 Bytes (1024 CPUs) — für normale Systeme ist das vernachlässigbar. ---- ===== Verwandte Units ===== * ''[[lyx_-_programmiersprache:units:process_ext|std.process_ext]]'' — Credentials, Session, uname * ''[[lyx_-_programmiersprache:units:thread|std.thread]]'' — Threads (Affinität gilt pro Thread) * ''[[lyx_-_programmiersprache:units:process|std.process]]'' — fork, exec, waitpid Letzte Aktualisierung: 2026-06-05