====== std.cpu — CPU-Erkennung, SIMD und Dispatch ======
→ [[lyx_-_programmiersprache:units|Zurück zur Unit-Übersicht]] · [[lyx_-_programmiersprache:units:cpu:features|std.cpu.features]] · [[lyx_-_programmiersprache:units:cpu:dispatch|std.cpu.dispatch]] · [[lyx_-_programmiersprache:units:sched|std.sched]] · [[lyx_-_programmiersprache:units:systeminfo|std.systeminfo]]
Übersicht über den CPU-Namensraum: zwei Units, die zur Laufzeit die **SIMD-Fähigkeiten der CPU erkennen** (SSE2, SSE4.1, AVX2) und darauf aufbauend einen **Rechen-Pfad auswählen** sowie 16-Byte-ausgerichtete ''float32''-Arrays bereitstellen. Grundlage für SIMD-beschleunigtes Rechnen (Arbeitspaket WP-GPU-02).
''std.cpu'' selbst ist **keine Unit**, sondern ein Verzeichnis — ''import std.cpu;'' scheitert mit ''Modul nicht gefunden''. Importiert wird immer eine konkrete Unit wie ''std.cpu.dispatch''. Einen Wildcard-Import (''%%import std.cpu.*;%%'') gibt es nicht.
**Quelle:** ''std/cpu/''
**Entwicklungsstand:** Beide Units gehören zu WP-GPU-02 und sind in aktiver Entwicklung. Der Scalar-Fallback in ''std.cpu.dispatch'' rechnet **falsch** (f32-Bitmuster werden als Integer behandelt), und der SSE2-Pfad ruft intern den Scalar-Pfad auf. Echte SIMD-Instruktionen (ADDPS/VADDPS) emittiert der Compiler-Codegen (''CGN_BINOP SIMD''), nicht die Stdlib. GPU-Units (''std.gpu.*'') existieren noch nicht (WP-GPU-07–09, geplant).
----
===== Units im Überblick =====
^ Unit ^ Import ^ Beschreibung ^
| [[lyx_-_programmiersprache:units:cpu:features|std.cpu.features]] | ''import std.cpu.features;'' | Feature-Erkennung via ''/proc/cpuinfo'': SSE2, SSE4.1, AVX2 als Bitmaske; Ergebnis wird gecacht |
| [[lyx_-_programmiersprache:units:cpu:dispatch|std.cpu.dispatch]] | ''import std.cpu.dispatch;'' | Dispatch-Level (AVX2 → SSE2 → Scalar), 16-Byte-ausgerichtete f32-Arrays via ''mmap'', elementweise Arithmetik |
''std.cpu.dispatch'' zieht ''std.cpu.features'' automatisch mit — für den Normalfall genügt der Import von ''dispatch''.
----
===== Wann welche Unit =====
^ Aufgabe ^ Unit ^ Kernfunktionen ^
| Prüfen ob AVX2 / SSE4.1 / SSE2 vorhanden ist | ''std.cpu.features'' | ''CpuFeatureDetect'', ''CpuHasAVX2'', ''CpuHasSSE41'', ''CpuHasSSE2'' |
| Rechen-Pfad zur Laufzeit wählen | ''std.cpu.dispatch'' | ''CpuDispatchLevel'' |
| Ausgerichtetes f32-Array anlegen | ''std.cpu.dispatch'' | ''SimdAlloc'', ''SimdLen'' |
| Elementweise f32-Arithmetik | ''std.cpu.dispatch'' | ''SimdAdd'', ''SimdSub'', ''SimdMul'', ''SimdDiv'' |
| Einzelne Elemente lesen/schreiben | ''std.cpu.dispatch'' | ''SimdGet'', ''SimdSet'' |
| Prozess auf einen Kern pinnen, Priorität setzen | [[lyx_-_programmiersprache:units:sched|std.sched]] | ''SchedSetAffinity'', ''CpuSetAdd'', ''GetCurrentCPU'', ''SetPriority'' |
| Kernanzahl und CPU-Zeiten des Systems lesen | [[lyx_-_programmiersprache:units:systeminfo|std.systeminfo]] | ''GetLogicalCores'', ''GetPhysicalCores'', ''GetCpuUserTime''/''SystemTime''/''IdleTime'' |
| Arbeit auf mehrere Kerne verteilen | [[lyx_-_programmiersprache:units:thread|std.thread]] | Threads, Mutex, Condition Variables |
----
===== Begriffe =====
* **SIMD** (Single Instruction, Multiple Data) — eine Instruktion rechnet gleichzeitig auf mehreren Werten. SSE2 arbeitet mit 128-Bit-Registern (4 × f32), AVX2 mit 256 Bit (8 × f32).
* **Dispatch** — die Auswahl des Codepfads zur Laufzeit statt zur Übersetzungszeit. Ein Binary läuft damit auf alter und neuer Hardware und nutzt trotzdem die schnellste verfügbare Erweiterung.
* **Ausrichtung (Alignment)** — SIMD-Ladebefehle erwarten Daten an 16-Byte-Grenzen. ''SimdAlloc'' rundet den ''mmap''-Zeiger entsprechend auf und legt die Elementanzahl bei ''ptr-8'' ab.
* **f32 als Bitmuster** — ''SimdGet'' / ''SimdSet'' reichen rohe 32-Bit-IEEE-754-Muster in einem ''int64'' durch, ohne Typkonvertierung (1.0f = ''0x3F800000'').
----
===== Erkennungsweg =====
/proc/cpuinfo ──CpuFeatureDetect──► Bitmaske (CPU_FEAT_SSE2|SSE41|AVX2)
│ (gecacht, ein Syscall)
▼
CpuDispatchLevel ──► AVX2 | SSE2 | Scalar
│
SimdAlloc / SimdAdd … auf f32-Arrays
Die Erkennung liest ''/proc/cpuinfo'' — **kein** direkter ''cpuid''-Befehl. Damit ist der gesamte Namensraum **Linux-only**; auf macOS, Windows und Bare-Metal liefert ''CpuFeatureDetect'' 0. Der Cache lässt sich nicht zurücksetzen, CPU-Hotplug oder Migration werden nicht erkannt. AVX-512 wird nicht geprüft.
----
===== Einstiegsbeispiel =====
import std.cpu.dispatch;
import std.io;
fn main(): int64 {
var lvl: int64 := CpuDispatchLevel();
if (lvl == CPU_DISPATCH_AVX2) {
PrintLn("Dispatch: AVX2 (256 Bit)");
} else if (lvl == CPU_DISPATCH_SSE2) {
PrintLn("Dispatch: SSE2 (128 Bit)");
} else {
PrintLn("Dispatch: Scalar");
}
// f32-Arrays: Bits 1.0 = 0x3F800000, 2.0 = 0x40000000
var a: int64 := SimdAlloc(4);
var b: int64 := SimdAlloc(4);
var i: int64 := 0;
while (i < 4) {
SimdSet(a, i, 0x3F800000);
SimdSet(b, i, 0x40000000);
i := i + 1;
}
var result: int64 := SimdAdd(a, b);
PrintLn(StrConcat(IntToStr(SimdLen(result)), " Elemente berechnet"));
// Kein SimdFree: Arrays bleiben bis Prozessende belegt
return 0;
}
----
===== Fallstricke =====
^ Thema ^ Details ^
| Scalar-Fallback rechnet falsch | f32-Bitmuster werden als Integer addiert — Ergebnisse sind nur auf dem Codegen-Pfad korrekt |
| SSE2-Pfad = Scalar-Pfad | ''SimdAdd'' ruft bei SSE2 intern ''SimdAddScalar'' auf |
| Kein ''SimdFree'' | Arrays werden erst beim Prozessende vom Kernel zurückgefordert; für eine eigene Freigabe ''n*4+24'' Byte ab dem Basis-Mapping rechnen |
| Keine Bounds-Checks | ''SimdGet(arr, i)'' prüft ''i'' nicht gegen ''SimdLen(arr)'' |
| Kein Typ-Safety bei f32 | Werte sind rohe Bitmuster in ''int64''; eine f32⟺int64-Helper-Unit fehlt in der Stdlib |
| Linux only | ''/proc/cpuinfo'' und ''mmap'' vorausgesetzt |
| Kein AVX-512 | Nur SSE2, SSE4.1 und AVX2 werden erkannt |
| Kernzahlen woanders | Logische/physische Kerne liefert ''std.systeminfo'', nicht ''std.cpu'' |
----
===== Verwandte Seiten =====
* [[lyx_-_programmiersprache:units:sched|std.sched]] — CPU-Affinität, Pinning, Priorität, aktuelle CPU und NUMA-Knoten
* [[lyx_-_programmiersprache:units:systeminfo|std.systeminfo]] — Kernanzahl, CPU-Zeiten aus ''/proc/stat'', Systemlast
* [[lyx_-_programmiersprache:units:thread|std.thread]] — Threads und Synchronisation
* [[lyx_-_programmiersprache:guides:nebenlaeufigkeit|Guide: Nebenläufigkeit]] · [[lyx_-_programmiersprache:guides:laufzeit-messen|Guide: Laufzeit messen]]
Letzte Aktualisierung: 2026-09-02 — Übersichtsseite neu angelegt.