- La dernière version Sep 0.10.0 atteint une vitesse remarquable de parsing CSV de 21 Go/s sur un AMD 9950X
- Les performances progressent fortement grâce à la prise en charge d’AVX-512 et au contournement des problèmes liés aux registres de masque
- Un nouveau parseur AVX-512-to-256 surpasse les parseurs AVX2 et AVX-512 existants
- En environnement multithread, 1 million de lignes sont traitées en 72 ms avec une bande passante de 8 Go/s
- Grâce à une optimisation continue du logiciel et du matériel, les performances ont été multipliées par environ 3 en deux ans
Sortie de Sep 0.10.0 et vue d’ensemble des gains de performance
- Dans sa récente version 0.10.0, Sep a optimisé la prise en charge des CPU compatibles AVX-512 (par ex. AMD 9950X, Zen 5) et mis à jour ses benchmarks
- La dernière version affiche un résultat impressionnant de 21 Go/s pour le parsing CSV de bas niveau
- Par rapport à la version précédente, cela représente une hausse marquée depuis 18 Go/s
- Les détails des améliorations sont disponibles dans les releases GitHub et le README de Sep
- L’article explique comment du code C# basé sur SIMD et de l’assembleur SIMD x64 ont permis d’améliorer les performances en contournant l’inefficacité du code machine AVX-512 de .NET 9.0
Évolution des performances de Sep
- L’évolution de Sep, de la version 0.1.0 à 0.10.0, de .NET 7.0 à 9.0, et de l’AMD 5950X (Zen 3) au 9950X (Zen 5), est présentée visuellement
- Les benchmarks sont réalisés en mono-thread et peuvent varier légèrement selon les releases
- Le message clé est que les grands refactorings (comme la réécriture de la structure interne en 0.2.0) et l’accumulation de petites optimisations ont continuellement amélioré les performances
- Grâce aux progrès conjoints du matériel et du logiciel, la vitesse de parsing a été multipliée par environ 3 en deux ans pour atteindre 21 Go/s
- Le seul changement de génération matérielle (5950X→9950X, 4,9→5,7 GHz) justifie déjà un gain supérieur à 1,2x
Génération de code AVX-512 et problème des registres de masque
- Sep prend en charge AVX-512 depuis la version 0.2.3, mais son usage des registres de masque AVX-512 (k1-k8) restait limité
- Sous .NET 8, l’absence de prise en charge directe des registres de masque entraînait des copies et conversions répétées entre registres normaux, ce qui dégradait les performances
- Au début, faute de CPU dédié compatible AVX-512, des tests limités sur un Xeon Silver 4316 avaient confirmé qu’il s’agissait malgré tout de l’option la plus rapide
Upgrade vers le 9950X et comparaison AVX-512 vs AVX2
- Après un récent upgrade CPU de Zen 3 (5950X) vers Zen 5 (9950X), les benchmarks de Sep ont atteint 18 Go/s
- En comparant directement les parseurs AVX-512 et AVX2, résultat quelque peu surprenant, AVX2 s’est montré environ 10 % plus rapide, à près de 20 Go/s
- Cela suggère que l’inefficacité du traitement des registres de masque par le JIT .NET reste un problème
Code du parseur, analyse assembleur et nouveau parseur AVX-512-to-256
- Tous les parseurs de Sep traitent des spans de caractères de 16K et utilisent des comparaisons basées sur des registres SIMD (
Vector256, etc.)
- SIMD permet d’identifier rapidement les caractères spéciaux (retours à la ligne, guillemets, délimiteurs, etc.) puis de les convertir en bitmasks afin d’optimiser les opérations ensemblistes
- Le parseur basé sur AVX-512 souffrait de nombreuses opérations superflues à cause des transferts répétés entre registres de masque (
k1, etc.) et registres généraux (zmm, etc.)
- Dans la version 0.10.0, l’appel à
MoveMask est avancé afin de réduire au minimum les conversions de masque inutiles, ce qui diminue le nombre d’instructions assembleur
- Le parseur AVX2, dépourvu de registres de masque, a une structure bien plus simple et s’est révélé en pratique plus rapide qu’AVX-512
- Le nouveau parseur AVX-512-to-256 lit les données avec AVX-512 puis contourne entièrement le problème du traitement des masques via des instructions de conversion 256 bits ; son implémentation est plus simple et il dépasse 21 Go/s
Récapitulatif des benchmarks des différents parseurs
- Les benchmarks comparant tous les types de parseurs via une variable d’environnement montrent que le parseur AVX-512-to-256 est le plus rapide avec 21,5 Go/s
- Les parseurs basés sur AVX2 et
Vector256 affichent aussi des performances très proches, à moins de 5 % d’écart
- Les parseurs
Vector128 et Vector512 sont 5 à 10 % plus lents qu’AVX2, et Vector512 est même plus lent que Vector128
- Le parseur
IndexOfAny est nettement plus lent que les autres parseurs SIMD. Vector64 n’étant pas accéléré sur le 9950X, ses performances sont très faibles
- Les parseurs SIMD basés sur AVX-512 et AVX2 démontrent des performances écrasantes face aux parseurs CSV comparables
Benchmarks de haut niveau : comparaison 5950X vs 9950X
- Sur une base de 1 million de lignes d’assets de packages, Sep_MT enregistre 72 ms (8 Go/s) sur le 9950X contre 119 ms (4,9 Go/s) sur le 5950X
- Sur des données de charge réelle (float, etc.), le 9950X atteint également une bande passante multithread d’environ 8 Go/s
- Le changement de génération (5950X→9950X) apporte un gain d’environ 1,5 à 1,6x en parsing applicatif réel
- Face aux bibliothèques CSV concurrentes (Sylvan, ReadLine, CsvHelper, etc.), Sep démontre un débit de traitement nettement supérieur et une allocation de ressources minimale
Conclusion et résumé
- Sep 0.10.0 repousse les limites des performances du parsing CSV en combinant optimisations logicielles et fonctionnalités matérielles récentes (AVX-512, fréquence élevée)
- La clé de cette avancée réside dans la conception de nouveaux algorithmes SIMD, ainsi que dans l’amélioration du code JIT .NET et de la structure assembleur
- L’effet cumulé des gains de performance progressifs et du changement de génération d’architecture sur une courte période est particulièrement impressionnant
- Dans le domaine du parsing CSV, Sep s’impose concrètement comme une solution de très haute performance, multiplateforme et extensible
1 commentaires
Commentaires sur Hacker News
llama.cppet l’inférence Vulkan marchent bien, donc j’aimerais que d’autres logiciels offrent un support du même genre.'\n','\r',';','“') suivies de trois opérations or, on peut utiliser une astuce classique : un seul shuffle, une seule comparaison et zéro opération or. J’ai présenté cette technique dans un billet de blog, si ça intéresse. Cela dit, dans cet article aussi, ils ont réduit les opérations or avecvpternlogdetvpor.protobufn’est pas un format si difficile, et pourtant son adoption peine à décoller.