2 Punkte von GN⁺ 2025-02-23 | 1 Kommentare | Auf WhatsApp teilen

Einführung

  • Willkommen zum Assembly-Sprachkurs von FFmpeg. Dieser Kurs vermittelt die Grundlagen dazu, wie Assembly-Sprache in FFmpeg geschrieben wird.

Erforderliche Kenntnisse

  • Kenntnisse der Programmiersprache C sind erforderlich, insbesondere zu Zeigern.
  • Mathematikkenntnisse auf Oberstufenniveau sind erforderlich (Skalare und Vektoren, Addition, Multiplikation usw.).

Was ist Assembly-Sprache?

  • Assembly-Sprache ist eine Programmiersprache, mit der Code geschrieben wird, der direkt den vom CPU verarbeiteten Befehlen entspricht.
  • Der Großteil des Assembly-Codes in FFmpeg ist SIMD (Single Instruction Multiple Data), was auch als Vektorprogrammierung bezeichnet wird.
  • SIMD eignet sich gut für die Verarbeitung großer Datenmengen, die sequenziell im Speicher abgelegt sind, etwa Bilder, Videos und Audio.

Warum in Assembly schreiben?

  • Um die Geschwindigkeit der Multimedia-Verarbeitung zu erhöhen. Mit Assembly-Code lässt sich eine Beschleunigung um mehr als das Zehnfache erzielen.
  • In FFmpeg wird Assembly-Code direkt geschrieben, ohne Intrinsics zu verwenden. Intrinsics sind normalerweise 10–15 % langsamer als handgeschriebener Assembly-Code.

Arten von Assembly-Sprache

  • Dieser Kurs konzentriert sich auf x86-64-Assembly-Sprache. Diese ist auch als amd64 bekannt und läuft ebenso auf Intel-CPUs.
  • Bei der x86-Assembly-Syntax gibt es zwei Varianten, AT&T und Intel, und hier wird die Intel-Syntax verwendet.

Begleitmaterial

  • Die Assembly-Programmierung in FFmpeg konzentriert sich auf performante Bildverarbeitung und verfolgt dabei einen eigenen Ansatz.
  • Die Diagramme aus dem Buch "The Art of 64-bit assembly" können hilfreich sein.

Register

  • Register sind Bereiche in der CPU, in denen Daten verarbeitet werden. Die CPU manipuliert den Speicher nicht direkt, sondern lädt Daten in Register, verarbeitet sie dort und schreibt sie anschließend zurück in den Speicher.

Allzweckregister

  • Allzweckregister (GPR) können Daten oder Speicheradressen enthalten. Im Assembly-Code von FFmpeg dienen GPRs hauptsächlich als Ausgangspunkt.

Vektorregister

  • Vektor-(SIMD-)Register enthalten mehrere Datenelemente. Es gibt verschiedene Arten von Vektorregistern.
  • Die meisten Berechnungen bei der Video-Kompression und -Dekompression basieren auf Ganzzahlen.

Einbinden von x86inc.asm

  • x86inc.asm ist eine leichtgewichtige Abstraktionsschicht, die in FFmpeg, x264 und dav1d verwendet wird, um die Arbeit von Assembly-Programmierern zu erleichtern.

Einfacher skalarer Assembly-Code

  • Anhand von Beispielcode wird erklärt, wie skalarer Assembly-Code funktioniert.

Grundlegende Vektorfunktionen verstehen

  • Am ersten Beispiel einer SIMD-Funktion wird die Bedeutung jeder Zeile erklärt.
  • Mit Befehlen wie movu und paddb werden Vektoroperationen ausgeführt.
  • Die Funktion verändert die Daten ihrer Argumente und gibt keinen Wert zurück.

1 Kommentare

 
GN⁺ 2025-02-23
Hacker-News-Kommentar
  • Es gibt weiteres Material zum selben Thema, etwa die Beispiele von FFmpeg und dav1d

    • FFmpeg wird häufig verwendet und ist daher ein klarer Anwendungsfall
    • dav1d wird in wichtigen Browsern und im Android-Betriebssystem eingesetzt, und ein wesentlicher Erfolgsfaktor ist handgeschriebenes SIMD
    • Ein Teil des Codes von dav1d wird pro Tag Billionen Mal ausgeführt und muss daher so schnell wie möglich laufen
    • Der Leistungsunterschied zwischen handgeschriebenem SIMD und vom Compiler erzeugtem SIMD kann bis zu 50 % betragen
    • Ressourcen wie die FFmpeg-Assemblersprachschule sind wichtig, um solche Techniken zu erhalten
  • Ich halte die Verwendung von Intrinsics für wertvoller als das Schreiben von Assembler, aber das Lesen war sehr nützlich

    • Mit Compiler Explorer kann man nachvollziehen, welche Optimierungen der Compiler zur Leistungssteigerung vornimmt
  • Ich finde diesen Leitfaden sehr gut

    • Als ich mich für Low-Level-Themen interessiert habe, hätte ich diesen Leitfaden gern gehabt
  • Ich frage mich, ob das Lernen oder Implementieren von Assembler irgendeinen „Spaßfaktor“ hat

    • Ob es wie bei LISP oder RISC-V Spaß macht, oder ob man es wie COBOL lernt, um mit bestimmten Systemen zu arbeiten
    • Ich habe im Arbeitsalltag keinen Grund, Assembler zu verwenden, frage mich aber, ob es sich aus Spaß lohnt, Zeit hineinzustecken
  • Das Suffix "q" gibt die Pointer-Größe an, auf 64-Bit-Systemen also 8

    • Der Satz wirkt verwirrend
    • "i.e" sollte "i.e.," heißen, und "(" sollte eine öffnende Klammer sein
    • "sizeof" gibt keinen Pointer zurück
  • Lob für den K&R-Verweis

    • Es war das erste Buch, das ich gekauft habe, um C und Programmierung zu lernen
    • Zuerst habe ich C++ gelernt, aber das war zu abstrakt und deshalb schwer zu verstehen
  • Ein Nachteil von Assembler ist, dass der Code architekturabhängig ist

    • Für x86, arm und x86_64 muss jeweils eigener Code geschrieben werden
    • Es gibt keinen guten Weg, portablen Code für SIMD zu schreiben
    • Rust stabilisiert eine portable SIMD-API, und Zig bietet SIMD-Unterstützung, aber FFmpeg könnte mit der Geschwindigkeit immer noch unzufrieden sein
  • Die Ablehnung von Inline-Assembler ist verwirrend

    • Inline-Assembler scheint effizienter zu sein als der Aufruf einer Assemblerfunktion
  • Dieses Material ist perfekt

    • Ich kannte x86-Assembler aus der 386-Ära, aber fortgeschrittenere Prozessoren waren zu komplex
    • Ich würde gern mehr über SIMD in aktuellen CPUs lernen
  • Ich frage mich, ob es noch stimmt, dass Assembler 10-mal schneller ist als C

    • Ob Compiler so stagniert haben, dass sie an handgeschriebenen Assembler nicht mehr annähernd herankommen