Politique d’interdiction des « optimisations » de déplacement conditionnel dans les shaders avec `mix()` + `step()`
(iquilezles.org)Introduction
- Cet article vise à corriger certaines idées reçues sur les branches sur GPU.
- Certains sites éducatifs diffusent des informations erronées, et l’objectif est de les rectifier.
Problème
- Un exemple de code utilisant l’opérateur ternaire pour implémenter une exécution conditionnelle dans du code GPU est présenté.
- Certaines personnes proposent comme « optimisation » de le remplacer par des opérations arithmétiques, mais cela repose sur une mauvaise compréhension.
- L’opérateur ternaire effectue un déplacement conditionnel, implémenté à l’aide de simples opérations sur les bits.
- De vraies branches existent dans le code GPU, mais elles ne sont pas utilisées pour de petits déplacements de registres.
Problèmes de cette mauvaise optimisation
- L’optimisation proposée s’exécute en réalité plus lentement que le code d’origine.
- La fonction
step()est implémentée avec un opérateur ternaire, ce qui ajoute des multiplications et additions inutiles. - Dans le code d’origine, la valeur est déplacée directement de manière conditionnelle.
Analyse du code machine
- Le code machine généré par les compilateurs AMD et Microsoft permet de confirmer que le GPU n’effectue pas de branchement.
- Il réalise le déplacement conditionnel à l’aide d’une comparaison et d’un masque binaire.
Conclusion
-
Les propositions d’optimisation utilisant la fonction
step()relèvent d’une information erronée, et il faut les corriger. -
Cette mauvaise information circule depuis plus de 20 ans, et il est nécessaire de la rectifier.
-
Inigo Quilez - étudie l’infographie depuis 1994.
1 commentaires
Commentaire Hacker News
Je suis convaincu que la conclusion de l’article est correcte, mais l’argument serait plus solide si la génération de code des deux versions était fournie, et pas seulement celle de la meilleure
J’aimerais qu’il existe un bon moyen de savoir dans quels cas un
ifforce réellement une branchemix/lerpplus coûteux, c’est parce qu’ils craignent de créer une branche, même si le surcoût est parfois faiblev = x > y ? a : b;fonctionne réellement, mais il est préoccupant qu’unifsoit une branche dans certains cas et pas dans d’autresCet article est aussi lié : corriger les mauvais conseils sur l’écriture de branches sur GPU
Je me demande pourquoi le compilateur ne reconnaît pas que la version « optimisée » est équivalente
step()et d’optimiser séparément les casstep()=0.0etstep()==1.0Je suis déjà tombé sur ce problème. Claude/ChatGPT le proposent aussi comme optimisation, mais cela dégrade les performances
Je me demande comment savoir si une fonction OpenGL est émulée au lieu d’appeler directement une fonctionnalité de base du GPU
Lorsqu’on écrit du code, il faut de l’expérience pour avoir la certitude qu’il n’y aura pas de branche conditionnelle
Explication de la manière dont les variantes de la fonction
mixfonctionnent sur les vecteurs