Blog / Entwicklung / Assembler
SIMD: Wie eine CPU mehrere Pixel gleichzeitig verarbeitet
Ein Befehl. Mehrere Pixel. Weniger Zeit.
OCR und Bildvorverarbeitung bestehen oft aus Millionen ähnlicher Operationen. SIMD erlaubt es einer CPU, mehrere Datenwerte mit einer einzigen Instruktion zu bearbeiten.
Bei OCR, Dokumentenanalyse und Bildverarbeitung werden große Mengen gleichartiger Daten verarbeitet. Ein Scan besteht nicht aus einigen wenigen Werten, sondern aus Millionen Pixeln.
Wird jeder Pixel einzeln geprüft, muss die CPU dieselbe Abfolge immer wieder ausführen. SIMD verändert dieses Modell: Eine Instruktion kann mehrere Werte gleichzeitig bearbeiten.
Was bedeutet SIMD?
SIMD steht für Single Instruction, Multiple Data. Eine einzelne Maschineninstruktion wird auf mehrere Datenwerte gleichzeitig angewendet.
Statt beispielsweise acht Pixel einzeln zu vergleichen, lädt die CPU mehrere Werte in ein Vektorregister und führt den Vergleich parallel aus.
Skalare Verarbeitung: ein Wert nach dem anderen
Eine klassische skalare Schleife verarbeitet pro Durchlauf genau einen Wert. Für einen einfachen Schwellwert kann sie so aussehen:
Ein einfaches Beispiel in C
for (size_t i = 0; i < count; ++i) {
output[i] = input[i] > threshold ? 255 : 0;
}
Diese Schleife ist verständlich und korrekt. Sie sagt aber noch nicht, wie die CPU sie tatsächlich ausführt. Ein moderner Compiler kann daraus skalaren Maschinencode oder vektorisierten SIMD-Code erzeugen.
Vektorregister: mehrere Pixel in einer Instruktion
Moderne x86-64-Prozessoren bieten Befehlssatzerweiterungen wie SSE, AVX und AVX2. Deren Register sind breiter als normale Ganzzahlregister.
Ein 256-Bit-AVX2-Register kann beispielsweise 32 Werte mit jeweils 8 Bit aufnehmen. Für Graustufenbilder bedeutet das: Bis zu 32 Pixel können gemeinsam geladen, verglichen und weiterverarbeitet werden.
Das heißt nicht automatisch, dass jeder Algorithmus 32-mal schneller wird. Speicherzugriffe, Verzweigungen, Datenlayout und weitere Instruktionen bestimmen, wie viel Beschleunigung tatsächlich übrig bleibt.
Warum SIMD für OCR interessant ist
Bevor eine OCR-Engine Text erkennt, werden Bilder häufig vorbereitet. Typische Schritte sind Graustufenumwandlung, Schwellwertbildung, Kontrastanpassung, Maskierung, Kantenerkennung und Rauschfilterung.
Viele dieser Verfahren wenden dieselbe Operation auf große, zusammenhängende Pixelbereiche an. Genau dafür ist SIMD geeignet.
Auto-Vektorisierung durch den Compiler
Handgeschriebener Assembler ist nicht der erste Schritt. GCC und Clang können viele Schleifen automatisch vektorisieren.
Dafür muss der Compiler erkennen können, dass Speicherbereiche sich nicht überschneiden, Schleifendurchläufe unabhängig voneinander sind und keine schwer vorhersehbaren Seiteneffekte auftreten.
Compileroptionen und Analyseausgaben helfen dabei zu prüfen, ob Vektorisierung tatsächlich stattgefunden hat. Wer nur den C-Code betrachtet, sieht das nicht zuverlässig.
Intrinsics oder Assembler?
Intrinsics sind C- oder C++-Funktionen, die direkt auf SIMD-Instruktionen abbilden. Sie erlauben gezielte Vektorisierung, ohne komplette Funktionen in Assembler zu schreiben.
Handgeschriebener Assembler wird erst dann interessant, wenn Messungen zeigen, dass Compiler und Intrinsics nicht das gewünschte Ergebnis liefern oder wenn ein sehr kleiner, besonders kritischer Kern exakt kontrolliert werden muss.
Alles andere wäre meist nur dekorativer Maschinencode mit erhöhtem Wartungsaufwand.
Der Speicher bleibt entscheidend
SIMD beschleunigt Rechenoperationen, beseitigt aber keine langsamen Speicherzugriffe. Wenn Daten schlecht angeordnet sind oder ständig aus dem RAM nachgeladen werden müssen, wartet die CPU trotz breiter Register.
Sequenzielle Zugriffe, geeignetes Alignment und kompakte Datenstrukturen können daher genauso wichtig sein wie die eigentliche SIMD-Instruktion.
Wo das bei t8core relevant wird
In t8core-Projekten betrifft das unter anderem OCR-Vorverarbeitung, Bildvergleich, Maskenprüfung, Schwärzungsprüfung und die Analyse großer Dokumentstapel.
Die Anwendungen werden nicht vollständig in Assembler geschrieben. Assemblerkenntnisse helfen aber dabei, Compilerergebnisse zu prüfen, Engpässe zu verstehen und kritische Routinen gezielt zu optimieren.
Wichtiger Punkt
SIMD ist kein Ersatz für gute Algorithmen. Eine schlechte Speicherorganisation bleibt langsam, auch wenn die CPU mehrere Werte gleichzeitig bearbeiten könnte.
Kurzfassung
- SIMD verarbeitet mehrere Datenwerte pro Instruktion
- SSE, AVX und AVX2 stellen breite Vektorregister bereit
- OCR und Bildfilter profitieren von gleichartigen Pixeloperationen
- Compiler können viele Schleifen automatisch vektorisieren
- Assembler hilft beim Prüfen und gezielten Optimieren
Fazit
SIMD ist einer der Gründe, warum moderne CPUs Bilddaten deutlich effizienter verarbeiten können, als eine einfache Schleife zunächst vermuten lässt.
Für t8core ist das besonders relevant, weil OCR, Schwärzungsprüfung und Dokumentenanalyse große Mengen ähnlich aufgebauter Daten bearbeiten. Nicht jede Routine braucht handgeschriebenen Assembler. Aber wer den erzeugten Maschinencode versteht, kann fundierter entscheiden, wo Optimierung wirklich sinnvoll ist.