1 points par GN⁺ 2025-10-04 | 1 commentaires | Partager sur WhatsApp
  • Le kernel d’attention a été refactoré sous une forme persistent, ce qui améliore les performances pour des longueurs de contexte faibles
  • En fp16, avec de grands contextes, une baisse de performances apparaît à cause d’un problème d’ordonnancement des instructions par ptxas dans la partition softmax
  • En fp8, lorsqu’on inclut "cutlass" dans le nom du kernel, on observe un gain d’environ 100 TFLOPS
  • Cette optimisation est analysée comme une astuce d’optimisation codée en dur via le nommage du kernel
  • L’impact sur les performances et son origine relèvent d’un comportement particulier de l’implémentation interne de NVIDIA ptxas

Résumé : refactorisation du kernel Persistent Attention et effet du nommage "cutlass"

Vue d’ensemble

  • Cette Pull Request refactorise le kernel d’attention de Triton selon une approche persistent attention
  • L’objectif principal est d’obtenir une optimisation des performances sur les faibles longueurs de contexte
  • Cependant, pour le type fp16, on constate une dégradation des performances à mesure que la taille du contexte augmente, en raison d’un problème d’ordonnancement des instructions par ptxas dans la partie softmax

Effet de l’adoption du nom "cutlass" en fp8

  • Lorsqu’on utilise un modèle fp8, inclure "cutlass" dans le nom du kernel permet de mesurer un gain de performances pouvant atteindre environ 100 TFLOPS
  • Cela vient du fait que le ptxas de NVIDIA (assembleur PTX) applique en interne une optimisation spéciale lorsque le nom du kernel contient "cutlass"
  • Dans le code réel, lorsque le dtype est float8e5, le nom du kernel est défini comme cutlass_gluon_attention ou équivalent
  • L’analyse de la désassemblage ptxas montre qu’il existe effectivement dans le code interne une condition strstr(kernel_name, "cutlass")

Benchmarks de performance

  • Les données de benchmark avant et après la refactorisation montrent une baisse relative des performances en D=64 par rapport à avant l’application de persistent attention
    • Cela est attribué à un problème d’ordonnancement des instructions dans la partie softmax
  • En revanche, en combinant le type fp8 et le nommage "cutlass", on obtient, pour certains contextes et certaines tailles, un débit nettement plus élevé
  • Résumé de résultats représentatifs :
    • Attention Z=4, H=32, D=64, causal=False :
      • avant application de persistent : triton-fp16 env. 383, triton-fp8 env. 413, cudnn-fp16 env. 565
      • après application de persistent : triton-fp16 env. 360, triton-fp8 env. 370
    • Attention Z=4, H=32, D=128, causal=True :
      • avant application de persistent : triton-fp16 env. 312, triton-fp8 env. 345, cudnn-fp16 env. 553
      • après application de persistent : triton-fp16 env. 356, triton-fp8 env. 351

Découverte et analyse de l’astuce de nommage

  • Lorsqu’une chaîne "cutlass" est incluse dans le nom du kernel, l’analyse de la communauté a confirmé qu’une routine d’optimisation expérimentale est activée dans NVIDIA ptxas
  • ptxas contient une logique codée en dur de correspondance sur le nom (strstr(kernel_name, "cutlass"))
  • Cette astuce correspond à une optimisation agressive et expérimentale, et son éventuel impact sur la précision peut varier selon le matériel et le contexte

Discussions de la communauté

  • Plusieurs reviewers ont posé des questions et mené des analyses sur la comparaison des performances, la précision et la méthode d’optimisation
  • Des échanges ont aussi porté sur le contenu du technical report de Deepseek, ainsi que sur les différences observées sur des architectures spécifiques comme les GPU Hopper
  • La portée réelle de l’optimisation via changement de nom, ainsi que d’éventuels problèmes de stabilité, ont également été soulevés

Conclusion et implications

  • Le fait que le simple nom d’un kernel puisse provoquer une variation de performances réelle au niveau matériel est un phénomène très inhabituel
  • L’existence de triggers d’optimisation cachés dans la stack logicielle NVIDIA (ptxas) suggère que, dans le développement de frameworks IA, les conventions de nommage peuvent aussi influencer les performances
  • En pratique, l’utilisation de cette astuce impose de tester soigneusement la reproductibilité et la stabilité, tout en surveillant de près les politiques d’optimisation du fournisseur matériel

1 commentaires

 
GN⁺ 2025-10-04
Avis Hacker News
  • En désassemblant ptxas, on a confirmé qu’il contient en dur une logique qui détecte les noms de kernel contenant cutlass
    J’imagine que NVIDIA a appliqué ici une optimisation instable, expérimentale et agressive ; l’activer systématiquement pourrait introduire des bugs subtils

    • En pratique, on observe plus souvent de subtiles variations de performances que des bugs subtils
      Les compilateurs GPU sont extrêmement difficiles à concevoir, et dès qu’on essaie d’aller au-delà des optimisations de base, on obtient presque toujours des résultats mitigés avec des problèmes en prime
      Certains kernels deviennent plus rapides, d’autres plus lents, et il est très difficile d’obtenir un gain global de performances
      Il est rare qu’une seule optimisation accélère systématiquement l’ensemble d’une suite de tests
      Mon expérience porte sur des systèmes GPU autres que Nvidia, mais cette situation me paraît très familière
      Nvidia semble aussi avoir trouvé des optimisations qui donnent des résultats remarquables sur certains ensembles de kernels et médiocres sur d’autres, sans réussir à définir un critère fiable pour les activer automatiquement
  • Merci pour ce contexte
    Ce n’est pas mon domaine (et c’est même la première fois que j’entends parler de ce projet), donc ni le titre ni le contenu de la PR ne me parlaient vraiment

  • Ça m’a rappelé le cas d’ATI (AMD) il y a 25 ans, pris en flagrant délit de triche sur le benchmark Quake III quand le simple fait de renommer l’exécutable en quack modifiait les performances
    Liens associés : test de techreport.com, test de hardocp.com, article de 3dcenter.de

    • Au cas où d’autres l’auraient mal compris comme moi, je récapitule
      ATI détectait le nom d’exécutable quake et modifiait entre autres la qualité des textures pour gonfler le score du benchmark
      Les gens ont découvert la supercherie en renommant l’exécutable en quack : la qualité d’image augmentait et le score baissait, ce qui montrait que le pilote ATI dégradait volontairement la qualité pour gagner en vitesse
      Donc ce n’est pas ATI qui a renommé le fichier, ce sont les utilisateurs

    • Ou encore le problème avec Intel C++ Compiler qui vérifiait la présence de la chaîne GenuineIntel dans la sortie
      Le lien Wikipédia correspondant est ici

    • Tous les vendeurs font encore ce genre de choses aujourd’hui
      Les pilotes interceptent la boucle de rendu de jeux populaires pour corriger des bugs, remplacer des shaders par des versions mieux optimisées ou ouvrir des chemins de code plus rapides, entre autres
      En principe, ces changements ne devraient avoir qu’un impact minimal sur le résultat, mais parfois l’intervention est tellement agressive que la qualité en souffre fortement
      Tout ça pour que le jeu tourne plus vite sur leur matériel

    • Il y a un fil de discussion plus approfondi sur ce sujet, à consulter ici
      Fait amusant, il s’agit d’un ancien billet sur exactement la même optimisation cutlass

    • Ce genre de cas est très courant
      Les fabricants de chipsets pour téléphones ont triché sur les benchmarks (VW sur les émissions, Nvidia sur le benchmark 3DMark, Intel sur les benchmarks SPEC pour Xeon, etc.)
      En infographie, c’est presque devenu une convention que les pilotes embarquent des tweaks, réglages et contournements spécifiques à chaque jeu
      (Malheureusement, les bonnes sources disparaissent trop souvent aujourd’hui, ce qui oblige à passer par archive.org. À mon avis, ce genre de mémoire doit être préservé.)
      Liens utiles : triche de benchmark chez Mediatek, scandale des émissions Volkswagen, controverse Nvidia 3DMark, impact du compilateur Intel sur SPEC

  • Du point de vue de quelqu’un qui travaille sur des compilateurs, il arrive que ce type d’optimisation dépende de noms (schéma, sous-chaîne, etc.)
    Même si ça ne plaît pas, c’est parfois comme ça que les choses fonctionnent en pratique
    Ce n’est pas forcément malveillant, et limiter l’optimisation à sa propre bibliothèque peut aussi être un choix plus sûr que de risquer de tout casser à l’échelle générale
    Ou bien cela peut venir du fait que le frontend n’est pas capable de fournir des informations plus fiables, par exemple des informations structurelles

    • Ce n’est probablement pas malveillant, mais ce genre de méthode finit quand même par créer une nouvelle barrière
    • Je peux encore comprendre une dépendance au type de fonction ou au schéma, mais si cela repose uniquement sur un simple nom, ça paraît un peu étrange
    • Même si c’est censé « éviter de casser des choses », quelqu’un peut réutiliser le même nom par hasard et provoquer des problèmes inattendus
      Je ne trouve pas ce genre de méthode très utile
  • À mon avis, il n’y a rien de très nouveau là-dedans

    • Début 2024, SPEC a invalidé 2 600 résultats de benchmarks sur CPU Intel Xeon, parce que le compilateur Intel utilisait des optimisations déloyales pour gonfler les scores (article de Tom's Hardware)
    • Microsoft aussi a déjà été pris dans des cas similaires autour des benchmarks de compilateurs Java/C
    • Et tout le monde semble désormais très motivé à tricher sur les benchmarks d’IA (scandale des benchmarks IA)
  • Ça me rappelle qu’il y a une dizaine d’années, dans une certaine version de Webpack, utiliser le nom de fichier add.svg cassait le build
    Au final, on avait résolu le problème en le renommant en plus.svg

    • Même chose avec numpy
      Certaines personnes ont déjà cassé numpy sans le vouloir simplement en utilisant un fichier nommé secret.py
  • J’apprécie l’honnêteté du message de commit

    • Il y a eu des critiques sur la manière dont le diff du commit était structuré
      Quelqu’un écrit qu’il a « rendu quelque chose environ 100 tflops plus rapide », et il se trouve quand même des gens pour répondre « le message de commit n’est pas terrible »… J’imagine qu’ils n’aimeraient pas non plus le style de commit de John Carmack

    • Personnellement, j’aime ce genre de message direct
      Je trouve ça bien préférable à une avalanche de messages de commit générés par IA du type « refactored X » répétés à l’infini

    • Je pense qu’il vaudrait mieux squash l’historique de commits
      Je ne comprends pas très bien pourquoi cela n’a pas été fait avant la mise en ligne sur GitHub

  • Ça me rappelle l’époque où j’apprenais à utiliser NVIDIA Jetson
    J’avais découvert qu’une seule commande suffisait pour tout accélérer (lien associé)

    • Je me demande si tu parles du mode d’alimentation
      D’après l’article, il y a deux modes, 5 W et 10 W, et 10 W est le mode par défaut ; on pourrait donc presque comprendre que cela ne « va plus vite » que lorsqu’on est passé du mode par défaut au 5 W, sauf si j’ai mal compris quelque chose
  • Il arrive qu’on écrive du code très fortement optimisé dans un langage de haut niveau (C++ ou autre), qu’on attende aussi un résultat très précis au niveau de l’assembleur GPU, et que le compilateur ne produise pas ce qu’on veut
    Si l’on consulte l’équipe en charge du compilateur, elle proposera probablement plusieurs solutions, mais beaucoup sont difficiles à appliquer dans du code open source (par exemple des #pragma propriétaires, des intrinsics, etc.)
    Quand on développe une bibliothèque haute performance, ne pas atteindre le niveau de performances attendu peut tout simplement empêcher la livraison
    Dans ce genre de situation, on finit parfois par devoir recourir à des astuces comme guider certaines transformations de code via le nom des fonctions
    Ce type d’optimisation est courant dans le monde réel, et à mon avis on ne peut pas le mettre sur le même plan qu’une triche de benchmark consistant à réduire la qualité d’image

    • Quelqu’un a aussi demandé pourquoi on n’utilisait pas simplement de l’assembleur inline dans ce cas
  • Ce point avait déjà été discuté lorsque cette PR a été publiée pour la première fois
    Je n’ai pas l’impression qu’il y ait du nouveau
    Discussion précédente

    • Ça me semblait familier, donc j’avais l’impression de l’avoir déjà vu passer
  • J’aimerais qu’il existe une structure économique qui facilite vraiment le partage du code
    Au lieu de pilotes en blob binaire, de basebands et d’autres structures complexes, il serait bien que tout le monde puisse accéder facilement aux informations afin de réduire le temps et les efforts gaspillés
    D’innombrables ingénieurs et chercheurs brillants passent déjà des mois, voire des années, à faire de la rétro-ingénierie et à décoder de la documentation, des schémas de circuits et du code binaire que quelqu’un possède déjà
    CUDA et des entreprises comme NVIDIA sont particulièrement frustrantes

    • Le fond du problème, c’est le coût fixe initial pour développer une base de code logicielle, puis les coûts humains de maintenance, avec en plus un faible coût marginal de distribution (serveurs de téléchargement, par exemple)
      Pour une application desktop, le coût additionnel par utilisateur est pratiquement nul
      Du coup, le logiciel a besoin d’une source de revenus récurrents, mais pas d’un modèle où les revenus continuent d’augmenter proportionnellement au nombre d’utilisateurs
      Ceux qui investissent dans le développement d’un nouveau code doivent pouvoir récupérer leur mise quand le produit devient populaire, mais le financement participatif classique ne répond pas à cette contrainte
      Plus le nombre d’utilisateurs augmente, plus la contribution individuelle nécessaire chute, si bien que même si chacun ne contribue qu’à hauteur de 100 %, 10 % ou même 1 %, la somme totale peut devenir astronomique
      À mon avis, il faudrait donc un système d’engagements sous forme d’enchères
      Ce modèle a aussi ses propres problèmes, notamment le passage d’un mode exclusif à un mode non exclusif, qui est particulièrement délicat
      Si quelques grandes entreprises financent entièrement le développement puis publient le résultat en open source, alors pratiquement tous les autres particuliers et entreprises deviennent de fait des passagers clandestins