====== 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.