2 points par GN⁺ 2025-02-23 | 1 commentaires | Partager sur WhatsApp

Présentation

  • Bienvenue au cours de langage assembleur de FFmpeg. Ce cours fournit les bases de la manière dont le langage assembleur est écrit dans FFmpeg.

Connaissances requises

  • Une connaissance du langage C est nécessaire, en particulier des pointeurs.
  • Des connaissances en mathématiques de niveau lycée sont nécessaires (scalaires et vecteurs, addition, multiplication, etc.).

Qu’est-ce que le langage assembleur ?

  • Le langage assembleur est un langage de programmation qui permet d’écrire du code correspondant directement aux instructions traitées par le CPU.
  • La majeure partie du code assembleur de FFmpeg utilise le SIMD (Single Instruction Multiple Data), aussi appelé programmation vectorielle.
  • Le SIMD est bien adapté au traitement de grandes quantités de données stockées séquentiellement en mémoire, comme les images, la vidéo et l’audio.

Pourquoi écrire en langage assembleur ?

  • Pour accélérer le traitement multimédia. Une implémentation en assembleur peut apporter un gain de performance de plus de 10x.
  • Dans FFmpeg, on écrit directement le code assembleur sans utiliser d’intrinsics. Les intrinsics sont en général 10 à 15 % plus lents que de l’assembleur écrit à la main.

Types de langage assembleur

  • Ce cours se concentre sur le langage assembleur x86 64 bits. Il est aussi connu sous le nom d’amd64 et fonctionne également sur les CPU Intel.
  • Il existe deux syntaxes pour l’assembleur x86 : AT&T et Intel, et nous utiliserons la syntaxe Intel.

Ressources complémentaires

  • La programmation assembleur dans FFmpeg est centrée sur le traitement d’image haute performance et adopte une approche particulière.
  • Les schémas du livre "The Art of 64-bit assembly" peuvent être utiles.

Registres

  • Les registres sont les zones où le CPU traite les données. Le CPU ne manipule pas directement la mémoire : il charge les données dans les registres, les traite, puis les réécrit en mémoire.

Registres à usage général

  • Les registres à usage général (GPR) peuvent contenir des données ou des adresses mémoire. Dans le code assembleur de FFmpeg, les GPR servent principalement d’appui.

Registres vectoriels

  • Les registres vectoriels (SIMD) contiennent plusieurs éléments de données. Il existe différents types de registres vectoriels.
  • La plupart des calculs de compression et de décompression vidéo reposent sur des entiers.

Inclusion de x86inc.asm

  • x86inc.asm est une couche d’abstraction légère utilisée dans FFmpeg, x264 et dav1d pour faciliter le travail des programmeurs assembleur.

Code assembleur scalaire simple

  • Le fonctionnement du code assembleur scalaire est expliqué à l’aide d’un exemple.

Comprendre une fonction vectorielle de base

  • Un premier exemple de fonction SIMD explique la signification de chaque ligne.
  • Des instructions comme movu et paddb sont utilisées pour effectuer des opérations vectorielles.
  • La fonction modifie les données de ses arguments et ne renvoie aucune valeur.

1 commentaires

 
GN⁺ 2025-02-23
Commentaire Hacker News
  • Il existe aussi d'autres ressources sur le même sujet, comme les cas de FFmpeg et de dav1d

    • FFmpeg est souvent utilisé, donc cela constitue un cas d'usage clair
    • dav1d est utilisé dans les principaux navigateurs et dans le système d'exploitation Android, et un facteur majeur de son succès est le SIMD écrit à la main
    • Une partie du code de dav1d est exécutée des milliers de milliards de fois par jour, elle doit donc s'exécuter le plus vite possible
    • L'écart de performances entre le SIMD écrit à la main et le SIMD généré par le compilateur peut atteindre 50 %
    • Des ressources comme l'école d'assembleur FFmpeg sont importantes pour maintenir ces techniques
  • Je pense qu'utiliser des fonctions intrinsèques a plus de valeur qu'écrire de l'assembleur, mais la lecture de ce document a été très utile

    • J'ai utilisé Compiler Explorer pour comprendre les optimisations que le compilateur effectue afin d'optimiser les performances
  • Je trouve ce guide excellent

    • J'aurais aimé avoir ce guide quand je m'intéressais au bas niveau
  • Je me demande s'il y a du « plaisir » à apprendre ou à pratiquer l'assembleur

    • Je me demande si c'est amusant comme Lisp ou RISC-V, ou si on l'apprend plutôt comme COBOL pour travailler avec certains systèmes précis
    • Je n'ai aucune raison d'utiliser l'assembleur dans mon travail quotidien, mais je me demande si cela vaut le coup d'y consacrer du temps pour le plaisir
  • Le suffixe "q" indique la taille d'un pointeur, qui vaut 8 sur un système 64 bits

    • La phrase semble confuse
    • "i.e" devrait être "i.e.,", et "(" devrait être une parenthèse ouvrante
    • "sizeof" ne renvoie pas un pointeur
  • Des compliments sur la référence à K&R

    • C'était le premier livre que j'ai acheté pour apprendre le C et la programmation
    • J'ai d'abord appris le C++, mais c'était trop abstrait et difficile à comprendre
  • L'inconvénient de l'utilisation de l'assembleur est que le code dépend de l'architecture

    • Il faut écrire un code différent pour x86, arm et x86_64
    • Il n'existe pas de bonne manière d'écrire du code portable pour le SIMD
    • Rust stabilise une API SIMD portable, et Zig fournit une prise en charge du SIMD, mais FFmpeg pourrait toujours juger la vitesse insuffisante
  • L'opposition à l'assembleur inline est déroutante

    • L'assembleur inline semble devoir être plus efficace qu'un appel de fonction en assembleur
  • Cette ressource est parfaite

    • Je connaissais l'assembleur x86 de l'époque du 386, mais les processeurs plus avancés étaient trop complexes
    • J'aimerais en apprendre davantage sur le SIMD des CPU récents
  • Je me demande s'il est toujours vrai que l'assembleur est 10 fois plus rapide que le C

    • Je me demande si les compilateurs ont tellement stagné qu'ils ne peuvent toujours pas approcher l'assembleur écrit à la main