1 points par GN⁺ 2025-05-18 | 1 commentaires | Partager sur WhatsApp
  • KVSplit est un projet open source qui permet d’exécuter de grands LLM et de longues fenêtres de contexte sur Apple Silicon
  • Grâce à une allocation de précision séparée pour les clés et les valeurs, il atteint jusqu’à 72 % de réduction mémoire avec moins de 1 % de dégradation de qualité
  • Il est optimisé pour les puces M1/M2/M3 et le framework Metal
  • Il démontre des améliorations de vitesse d’exécution et des économies mémoire au moyen de benchmarks mesurés et d’outils de visualisation
  • Il propose une installation simple, une comparaison en une commande, ainsi que divers outils de benchmark et d’analyse

Introduction : pourquoi KVSplit est important

KVSplit est un outil open source qui permet d’exécuter de grands LLM et des fenêtres de contexte bien plus longues sur Apple Silicon (M1/M2/M3) en appliquant une quantification avec des précisions différentes aux clés et aux valeurs à l’intérieur du cache KV. Il dépasse la limite des projets existants, qui quantifient les clés et les valeurs de la même manière, en réduisant drastiquement l’utilisation mémoire tout en maintenant la dégradation de qualité à un niveau presque imperceptible. Les benchmarks réels, les performances et les métriques de qualité sont tous publiés, ce qui le rend crédible, et la prise en charge de Metal ainsi que des outils intuitifs de comparaison et de visualisation améliorent l’efficacité de développement.

Ses principaux avantages par rapport aux projets comparables sont les suivants :

  • Séparation de la précision clé/valeur pour une gestion mémoire plus efficace
  • Spécialisation Apple Silicon et prise en charge d’une optimisation complète pour le framework Metal
  • Intégration de benchmarks, perplexité, mesures mémoire/vitesse/qualité et visualisation
  • Installation en une commande, compatibilité avec les modèles, intégration à llama.cpp
  • Visualisation en temps réel des économies mémoire et divers outils de tests comparatifs

Caractéristiques principales et points clés

Vue d’ensemble

  • Avec KVSplit, il devient possible d’exécuter sur Apple Silicon des LLM bien plus grands et des longueurs de contexte plus importantes qu’auparavant
  • En attribuant une précision de quantification différente aux clés et aux valeurs, il obtient à la fois des économies mémoire et des gains de vitesse
  • Jusqu’à 72 % d’économie mémoire, amélioration de vitesse (5 à 15 %↑) et moins de 1 % de dégradation de qualité ont été confirmés
  • Prise en charge complète de Metal, avec accélération optimale sur Apple Silicon

Principaux résultats de benchmark

  • Dans la configuration K8V4 (clés 8 bits, valeurs 4 bits)
    • 59 % d’économie mémoire et 0,86 % de dégradation de qualité (sur la base de la perplexité)
    • Gain de vitesse de 5,7 % par rapport à FP16
  • Dans la configuration K4V4 (clés/valeurs toutes deux en 4 bits)
    • Jusqu’à 72 % d’économie mémoire
    • Environ 6 % de perte de qualité. Recommandé pour des usages moins sensibles à la qualité

Comparaison des effets de réduction mémoire

  • Par rapport à FP16 à 176 MB (8K tokens)
    • K8V8 (clés/valeurs 8 bits) : 93.5MB (47%)
    • K8V4 (clés 8 bits, valeurs 4 bits) : 71.5MB (41%)
    • K4V4 (clés/valeurs 4 bits) : 49.5MB (28%)

Fonctionnalités principales

  • Quantification individuelle des clés et des valeurs du cache KV
  • Optimisation complète pour Apple Silicon et Metal
  • Scripts d’analyse de benchmark/qualité (perplexité)/utilisation mémoire
  • Outils de visualisation et génération de graphiques de qualité publication
  • Configuration en une commande et comparaison en temps réel

Structure des dossiers du projet

  • llama.cpp : inclut un build optimisé pour Metal
  • models : stockage des fichiers de modèles
  • scripts : inclut les scripts de benchmark/installation/comparaison/visualisation
  • results, plots : stockage des résultats de benchmark et des fichiers de visualisation
  • README.md

Enseignements scientifiques et résultats expérimentaux

Phénomène clé du cache KV

  • Les vecteurs de clés ont une sensibilité à la quantification bien plus élevée que les vecteurs de valeurs → il faut attribuer une précision plus élevée aux clés pour préserver la qualité
  • K8V4 est le sweet spot : la répartition clés 8 bits / valeurs 4 bits offre le meilleur compromis qualité-mémoire
    • 59 % d’économie mémoire, seulement 0,86 % de dégradation de la perplexité, et une vitesse supérieure à FP16
  • K4V8, malgré le même nombre total de bits que K8V4, provoque une dégradation de qualité plus de 7 fois plus importante → preuve de l’importance de la précision côté clés

Implications globales

  • Il permet à la fois l’efficacité mémoire et la préservation de la qualité du modèle → il devient possible d’exécuter des contextes bien plus longs et des modèles plus grands sur du matériel grand public

Exemples d’utilisation et recommandations de configuration

Exemples d’exécution avec différentes précisions de quantification

  • Par défaut (FP16) : ./llama.cpp/build/bin/llama-cli -m models/your-model.gguf -p "prompt" -t 8 --flash-attn
  • K8V4 recommandé : --kvq 8
  • K4V8 (DÉMO) : --kvq-key 4 --kvq-val 8
  • K4V4 (réduction maximale) : --kvq 4

Exemple de contexte long

  • Contexte 32K : FP16 nécessite ~1.4GB, mais K8V4 peut fonctionner avec ~400MB

Explication des flags en ligne de commande

  • -t 8 : nombre de threads, 8 recommandé pour M1/M2/M3
  • --flash-attn : optimisation pour Apple Silicon
  • --kvq N : définit les clés/valeurs toutes deux sur N bits
  • --kvq-key, --kvq-val : prise en charge d’un réglage individuel
  • -c N : nombre de tokens de contexte (plus il est élevé, plus l’effet de KVSplit est important)
  • -n N : nombre de tokens générés
  • -f FILE : fichier document en entrée
  • -m MODEL : chemin du modèle

Benchmark avancé et visualisation

  • benchmark_kvsplit.py mesure, selon la configuration et la longueur de séquence, la mémoire/la vitesse/la perplexité/les caractéristiques de mise à l’échelle
  • visualize_results.py génère des graphiques de niveau publication scientifique
  • Les résultats sont automatiquement enregistrés en CSV/JSON et un résumé est fourni

Optimisation Apple Silicon et visualisation mémoire

  • Utilisation complète du framework Metal
  • Effet décisif sur les modèles M1/M2/M3 à forte contrainte mémoire
  • capture_memory.sh permet de visualiser en temps réel les économies mémoire
  • En raison d’un alignement de pages personnalisé, la réduction réelle peut légèrement différer de la valeur théorique

Récapitulatif des fonctionnalités

  • Précision en bits indépendante pour les clés/valeurs et quantification personnalisée
  • Optimisation complète pour Apple Silicon et Metal
  • Benchmarks complets mémoire/vitesse/qualité
  • Visualisation de qualité publication, comparaison en temps réel et prise en charge de la capture mémoire
  • Interface d’installation et d’utilisation ultra-simple

Citations et recherches de référence

  • "More for Keys, Less for Values: Adaptive KV Cache Quantization" (2024)
  • "Unifying KV Cache Compression for Large Language Models with LeanKV" (2025)
  • Implémentation de base : [llama.cpp], modèle de test : [TinyLlama]

Recommandations de configuration et plans futurs

  • K8V4 (clés 8 bits / valeurs 4 bits) : perte de qualité de 0,86 %, réduction mémoire de 59 %, vitesse +5,7 %, soit le meilleur équilibre
  • K4V4 : réduction mémoire maximale (72 %), baisse de qualité d’environ 6 %. Adapté aux usages où la mémoire est la priorité absolue
  • Particulièrement performant pour l’exécution de contextes longs, avec des contextes 2 à 3 fois plus longs possibles

Feuille de route

  • Précision adaptative fondée sur l’importance des tokens
  • Quantification individuelle par couche
  • Optimisation sur mesure selon le modèle (Mistral, Phi-3, etc.)
  • Démo web et prise en charge mobile (iOS/iPadOS) prévues

Licence et contribution

  • Licence MIT
  • Tout développeur ou chercheur en IA peut contribuer via une Issue ou une PR

1 commentaires

 
GN⁺ 2025-05-18
Avis Hacker News
  • Expression d’intérêt trouvant cela intéressant, question sur l’intuition expliquant pourquoi ce phénomène apparaît et sur le cheminement qui a mené à cette découverte, suggestion d’améliorations orientées utilisateur comme le fait que l’étape d’application du patch dans le script d’installation n’est pas finalisée et l’usage de git submodule, ainsi que proposition de séparer llama.cpp et les dépendances Python pour mieux prendre en compte divers environnements Python

    • Réponse indiquant que c’est une bonne question, avec l’explication que la différence principale est liée au rôle central de l’attention : les clés déterminent quels tokens doivent être pris en compte pour former le schéma d’attention, tandis que les valeurs ne transmettent que l’information donnée ; si la quantification des vecteurs de clé est trop agressive, la distorsion affecte toutes les interactions entre tokens, alors que les erreurs sur les vecteurs de valeur n’affectent que l’information de ce token ; analogie avec une cote de rayon en bibliothèque : si la clé est fausse, on retrouve un livre complètement différent ; mathématiquement, les clés passent dans le softmax, où de petites erreurs peuvent être fortement amplifiées, alors que les valeurs sont combinées par moyenne linéaire, ce qui tend à compenser les erreurs ; l’auteur dit avoir lui-même découvert cette asymétrie dans un article et avoir voulu la vérifier quantitativement sur Apple Silicon, et promet d’améliorer l’installation ainsi que la gestion des dépendances Python
    • Remarque signalant que le patch n’est en réalité pas appliqué à llama.cpp, que le code d’analyse des arguments a déjà été déplacé dans arg.cpp, ce qui rend le patch sans effet, et que les options de quantification K/V ont déjà été ajoutées à llama.cpp en 2023 ; doute sur l’utilité même du patch, qui semble simplement modifier les arguments en ligne de commande, et forte recommandation d’éviter d’exécuter un install.sh d’un nouveau dépôt pour appliquer un patch aussi simple
  • Question sur la possibilité de faire cela aussi avec MLX, avec l’idée que MLX est plus rapide et que cette approche pourrait aider les utilisateurs Mac à bénéficier en pratique de conversations longues à bonne vitesse

    • Réponse disant que c’est probablement possible, mais que l’auteur est justement en train d’explorer MLX plus en profondeur ; impression que le framework lui-même est bien conçu, mais qu’il reste immature faute d’exemples de code ou d’informations de benchmarking ; remarque personnelle disant que les bindings Haskell sont en fait ce qui l’enthousiasme le plus, car la lazy evaluation pourrait être adaptée et qu’une structure de graphe de compilation purement fonctionnelle pourrait bien s’y prêter, avec l’idée que le ML en Haskell serait intéressant
  • Question sur l’existence d’une différence réelle avec les options --cache-type-k, --cache-type-v

    • Avis très tranché selon lequel ce projet LLM ressemble surtout à une tentative de récolter des étoiles GitHub et n’apporte en réalité rien de différent par rapport à une fonctionnalité existante
    • Souvenir que le support 4 bits n’existait pas sur MLX/MPS, voire que le 8 bits était insuffisant, et que la prise en charge de bf16 n’a été ajoutée que récemment ; par le passé, sur les GPU Apple, l’approche type_k/v semblait limitée au minimum à 16 bits (f16/bf16), donc sans bien connaître l’intérieur de llama.cpp, cela pourrait être légèrement différent
    • Accord bref indiquant que cette différence intrigue aussi l’intervenant
  • Après lecture du code, conclusion que le patch est inutile, avec confirmation via un lien de PR que la fonctionnalité a déjà été intégrée à llama.cpp en 2023 ; mise en garde contre le fait d’inciter à exécuter install.sh pour appliquer un patch au lieu d’utiliser simplement un fork du dépôt ; critique d’une structure confuse du dépôt avec plusieurs fichiers de patch, du code dupliqué et des patches qui s’écrasent les uns les autres ; en pratique, le dépôt ne ferait qu’ajouter l’option --kvq, alors qu’il existe déjà des options séparées de quantification K/V ; soupçon que l’auteur ne pouvait pas ignorer cette fonctionnalité existante ; recommandation de ne pas exécuter les scripts d’un dépôt fournissant des scripts complexes ; critique supplémentaire expliquant que le post HN et le nombre d’étoiles GitHub sont élevés, mais que le contenu est trompeur, et inquiétude face au fait que l’auteur continue d’éviter les questions ; conclusion ajoutant que le dépôt et les scripts mélangent du code ancien de llama.cpp avec la structure récente, ce qui accroît encore la confusion

    • Réponse disant avoir lui aussi relevé plusieurs éléments suspects, mais avoir attendu une explication de l’auteur au cas où quelque chose lui aurait échappé ; constat qu’il y a de nombreux signaux d’alerte et, à la vue de l’activité GitHub, soupçon d’une stratégie consistant à inonder des projets populaires de code généré par LLM
    • Commentaire disant qu’enfin quelqu’un parle de façon raisonnable, et que le simple fait qu’il faille patcher au lieu d’utiliser un fork du projet d’origine constitue déjà un risque de confiance ; soupçon sur l’identité GitHub de l’auteur lui-même, tendance à soumettre en masse des PR avec des résidus de génération LLM à des projets populaires pour se faire passer pour contributeur, et inquiétude quant au début d’une pollution informationnelle ou d’un effondrement de la confiance lié à l’IA
  • Question sur la possibilité d’appliquer une quantification KV différenciée (K8V4, etc.) à des modèles déjà convertis au format .gguf, et sur d’éventuelles limitations selon le type de modèle ou la configuration du tokenizer

    • Réponse expliquant que le principal avantage de KVSplit est justement de fonctionner immédiatement avec des modèles .gguf existants, sans conversion spéciale ; la quantification ne s’applique qu’au cache KV à l’exécution et est indépendante des poids du modèle ; les drapeaux --kvq-key et --kvq-val servent seulement à définir le format de stockage mémoire ; l’auteur dit avoir testé avec succès divers modèles comme LLama-3, Mistral, Phi-2/Phi-3, TinyLlama, Qwen, etc. ; en revanche, cela reste limité au backend Metal de llama.cpp, et comme Flash Attention contourne actuellement les formats personnalisés de cache KV, l’option -fa 0 est nécessaire ; sinon, cela devrait fonctionner avec toute architecture Transformer utilisant l’attention
  • Question demandant si ce patch est plus rapide ou meilleur sur des Apple Silicon à grande capacité mémoire, comme 64 Go ou 128 Go, avec mention de rumeurs selon lesquelles l’extension de la fenêtre de contexte est en pratique lente sur Apple Silicon, et interrogation sur l’intérêt concret avec beaucoup de mémoire

    • Réponse expliquant que le gain mémoire de KVSplit est proportionnel à la longueur du contexte, ce qui augmente l’avantage absolu sur les Mac à grande capacité ; sur un Mac Studio 128 Go, cela permettrait de gérer des contextes de plusieurs centaines de milliers de tokens ; toutefois, cela n’accélère pas fondamentalement le calcul et améliore seulement l’efficacité mémoire ; un benchmark montre une hausse de débit de 14,5 % avec le réglage K8V4, mais cela serait dû à l’efficacité des accès mémoire ; pour les gros modèles, la lenteur vient surtout des limites de calcul, indépendamment de la RAM ou de l’optimisation du cache KV ; autrement dit, KVSplit est utile lorsqu’on bute sur une limite mémoire, et en pratique il est préférable d’attribuer de plus grandes fenêtres de contexte à des modèles plus petits, comme les 7B à 13B ; si l’on veut à la fois de très gros modèles et des fenêtres extrêmement longues, des GPU de classe serveur restent plus adaptés, mais cette approche repousse tout de même les limites possibles sur matériel Apple
  • Expression d’intérêt et demande d’une explication un peu plus haut niveau : possibilité d’utiliser un modèle 2048 tokens avec une fenêtre étendue à 4–6k, ou un modèle 128k avec une fenêtre 256k+, ainsi que question sur les cas d’usage idéaux des modèles locaux

    • Réponse indiquant qu’une configuration K8V4 permet une réduction mémoire de 59 %, ce qui peut augmenter la longueur maximale de contexte jusqu’à 2,4× ; un modèle 2048 tokens peut ainsi monter à environ 5000 tokens, et un modèle 8K à environ 19,5K ; exemples d’usage réels sur MacBook : traiter un livre entier d’un coup, analyser une grande base de code ou conserver de longs historiques de conversation dans une application interactive ; l’économie de mémoire croît linéairement avec la longueur de contexte ; d’après l’expérience rapportée, à 8K de contexte, le cache KV passe de 176 Mo à 72 Mo, et à 128k le gain se chiffre en gigaoctets ; solution particulièrement utile lorsqu’on rencontre des erreurs OOM dues à la longueur d’entrée
    • Réponse disant que cette économie mémoire réduit les ressources nécessaires pour un modèle donné et peut donc être exploitée de multiples façons selon l’objectif ; toutefois, étendre la fenêtre de contexte elle-même n’est pas simple pour un non-spécialiste, et il vaut mieux utiliser un modèle déjà entraîné pour une fenêtre plus grande ; les modèles locaux peuvent servir à des usages variés hors ligne, pour des raisons de sécurité ou d’expérimentation, mais pour la plupart des gens, ils servent surtout à des essais de réglage et de tuning
  • Éloge disant que c’est une très bonne idée et une tentative intéressante, avec question supplémentaire sur l’applicabilité aux GPU et sur la possibilité de la combiner avec d’autres techniques de quantification

    • Réponse expliquant que cette méthode devrait probablement s’appliquer de la même façon aux GPU NVIDIA/AMD, car le besoin d’une précision plus élevée pour les clés que pour les valeurs est indépendant du matériel ; le backend CUDA de llama.cpp prend déjà en charge des réglages séparés via --cache-type-k et --cache-type-v ; le patch actuel est spécialisé pour Metal, mais le principe est transposable tel quel ; cela peut aussi être combiné avec d’autres techniques de quantification, car la quantification du cache KV n’intervient qu’à l’exécution et n’entre pas en conflit avec la quantification des poids ; il s’agit d’une étape distincte du pipeline de conversion ; en revanche, des moteurs comme vLLM ou TensorRT-LLM, qui utilisent une autre structure de cache, nécessiteraient une implémentation spécifique ; sur GPU, le plus grand effet viendrait d’une intégration directe dans une architecture FlashAttention, où les gains mémoire pourraient se traduire directement en gains de vitesse
  • Message indiquant ne pas bien comprendre certains points, percevoir quelque chose d’étrange, recommander de ne pas exécuter le script et signaler l’avoir dénoncé

  • Question sur l’évolution des performances : même si l’on peut placer un contexte plus long en mémoire, la vitesse de calcul ne devrait-elle pas rester la même ?

    • Réponse disant qu’en pratique, sur le même modèle et le même prompt, avec des types de cache fp16, q8 et q4, la vitesse d’itération semble similaire ; l’auteur n’a pas vérifié le fonctionnement interne, mais s’attendait à ce que les vecteurs soient packés pour un traitement SIMD en bloc en 4 ou 8 bits, alors qu’il a plutôt eu l’impression que ce n’était pas le cas