{"id":593,"date":"2026-10-09T11:57:36","date_gmt":"2026-10-09T09:57:36","guid":{"rendered":"https:\/\/www.ranksignal.fr\/blog\/?p=593"},"modified":"2026-10-14T16:59:47","modified_gmt":"2026-10-14T14:59:47","slug":"flashattention-et-pagedattention","status":"publish","type":"post","link":"https:\/\/www.ranksignal.fr\/blog\/inference\/flashattention-et-pagedattention\/","title":{"rendered":"FlashAttention et PagedAttention : \u00e0 quoi servent-elles ?"},"content":{"rendered":"<p><\/p>\n<p>Dans la documentation d&rsquo;un <a href=\"\/blog\/inference\/quand-utiliser-un-moteur-d-inference\/\" title=\"moteur d&#x27;inf\u00e9rence\">moteur d&rsquo;inf\u00e9rence<\/a>, deux noms se suivent comme des jumeaux : FlashAttention, PagedAttention. M\u00eame suffixe, m\u00eame rayon, et pourtant ils ne s&rsquo;occupent pas de la m\u00eame chose : l&rsquo;un touche \u00e0 la mani\u00e8re de calculer l&rsquo;attention, l&rsquo;autre \u00e0 l&rsquo;endroit o\u00f9 l&rsquo;on range ce qu&rsquo;elle laisse derri\u00e8re elle. \u00c0 la fin, tu sauras dire lequel fait quoi, et pourquoi on n&rsquo;a jamais \u00e0 choisir entre les deux.<\/p>\n<p><strong>Sommaire<\/strong><\/p>\n<ul>\n<li><a href=\"#l-essentiel-en-30-secondes\">L&rsquo;essentiel en 30 secondes<\/a><\/li>\n<li><a href=\"#deux-noms-jumeaux-deux-metiers-differents\">Deux noms jumeaux, deux m\u00e9tiers diff\u00e9rents<\/a><\/li>\n<li><a href=\"#l-atelier-et-l-entrepot-deux-memoires-deux-vitesses\">L&rsquo;atelier et l&rsquo;entrep\u00f4t : deux m\u00e9moires, deux vitesses<\/a><\/li>\n<li><a href=\"#flashattention-calculer-sur-le-plan-de-travail\">FlashAttention : calculer sur le plan de travail<\/a><\/li>\n<li><a href=\"#le-cache-kv-ce-locataire-qui-grossit\">Le cache KV, ce locataire qui grossit<\/a><\/li>\n<li><a href=\"#pagedattention-ranger-par-pages-plutot-que-d-un-seul-tenant\">PagedAttention : ranger par pages plut\u00f4t que d&rsquo;un seul tenant<\/a><\/li>\n<li><a href=\"#trois-idees-recues-a-ecarter\">Trois id\u00e9es re\u00e7ues \u00e0 \u00e9carter<\/a><\/li>\n<li><a href=\"#ou-les-trouver-en-pratique\">O\u00f9 les trouver en pratique<\/a><\/li>\n<\/ul>\n<h2 id=\"l-essentiel-en-30-secondes\">L&rsquo;essentiel en 30 secondes<\/h2>\n<ul>\n<li>FlashAttention est une s\u00e9rie de noyaux d&rsquo;attention qui <strong>r\u00e9duisent les lectures et \u00e9critures en m\u00e9moire<\/strong> : m\u00eame op\u00e9ration math\u00e9matique, sans stocker de grosses matrices interm\u00e9diaires.<\/li>\n<li>PagedAttention est une technique de gestion m\u00e9moire : elle range le cache KV en <strong>pages de taille fixe<\/strong>, ce qui r\u00e9duit fragmentation et duplication.<\/li>\n<li>Elles ne r\u00e8glent pas le m\u00eame probl\u00e8me : <strong>l&rsquo;une le calcul, l&rsquo;autre la m\u00e9moire<\/strong>.<\/li>\n<li>Ni l&rsquo;une ni l&rsquo;autre ne d\u00e9grade les r\u00e9ponses : ce sont des optimisations <strong>sans perte de qualit\u00e9<\/strong>.<\/li>\n<li>L&rsquo;attention reste <strong>quadratique<\/strong> : elles changent la fa\u00e7on de l&rsquo;ex\u00e9cuter, pas sa complexit\u00e9.<\/li>\n<\/ul>\n<h2 id=\"deux-noms-jumeaux-deux-metiers-differents\">Deux noms jumeaux, deux m\u00e9tiers diff\u00e9rents<\/h2>\n<p>Commen\u00e7ons par les d\u00e9finitions les plus courtes possibles. <strong>FlashAttention<\/strong> d\u00e9signe une s\u00e9rie d&rsquo;articles de recherche et de noyaux d&rsquo;attention optimis\u00e9s, con\u00e7us pour r\u00e9duire les lectures et \u00e9critures en m\u00e9moire. <strong>PagedAttention<\/strong> d\u00e9signe une technique de gestion m\u00e9moire : elle stocke le cache KV en pages de taille fixe.<\/p>\n<p>Mises c\u00f4te \u00e0 c\u00f4te, les deux id\u00e9es se distinguent presque ligne \u00e0 ligne :<\/p>\n<table>\n<thead>\n<tr>\n<th><\/th>\n<th>FlashAttention<\/th>\n<th>PagedAttention<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Ce qu&rsquo;elle touche<\/td>\n<td>le calcul de l&rsquo;attention<\/td>\n<td>le rangement du cache KV<\/td>\n<\/tr>\n<tr>\n<td>Ce qu&rsquo;elle \u00e9vite<\/td>\n<td>l&rsquo;\u00e9criture puis la relecture de grosses matrices interm\u00e9diaires<\/td>\n<td>la fragmentation et la duplication de la m\u00e9moire<\/td>\n<\/tr>\n<tr>\n<td>L\u00e0 o\u00f9 elle rapporte<\/td>\n<td>les charges limit\u00e9es par le calcul (prefill, vid\u00e9o)<\/td>\n<td>les grands caches, les longs contextes<\/td>\n<\/tr>\n<tr>\n<td>Qualit\u00e9 des r\u00e9ponses<\/td>\n<td>inchang\u00e9e<\/td>\n<td>inchang\u00e9e<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Garde cette image en t\u00eate pour la suite : FlashAttention, c&rsquo;est une fa\u00e7on de cuisiner ; PagedAttention, une fa\u00e7on de ranger le garde-manger. Deux gestes diff\u00e9rents, pour un m\u00eame repas.<\/p>\n<h2 id=\"l-atelier-et-l-entrepot-deux-memoires-deux-vitesses\">L&rsquo;atelier et l&rsquo;entrep\u00f4t : deux m\u00e9moires, deux vitesses<\/h2>\n<p>Pour comprendre ce que FlashAttention \u00e9conomise, il faut savoir que le GPU poss\u00e8de deux sortes de m\u00e9moire. La <strong>VRAM<\/strong> est la grande : de la m\u00e9moire \u00e0 haute bande passante (HBM3, HBM3e ou HBM4), de quelques dizaines \u00e0 quelques centaines de gigaoctets. Sur la puce elle-m\u00eame vit la <strong>SRAM<\/strong>, plus rapide et plus ch\u00e8re, qui se compte en kilo- ou m\u00e9gaoctets, sous forme de caches.<\/p>\n<p>Pense \u00e0 un cuisinier. L&rsquo;entrep\u00f4t est vaste mais lointain ; le plan de travail est minuscule mais \u00e0 port\u00e9e de main. Le travail efficace consiste \u00e0 rapporter les ingr\u00e9dients une fois, tout pr\u00e9parer sur le plan de travail, puis ne ressortir que le plat fini. Une impl\u00e9mentation na\u00efve de l&rsquo;attention fait l&rsquo;inverse : elle fait trois allers-retours.<\/p>\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6adef46ac30fd&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6adef46ac30fd\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1152\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/10\/b1_ch04_attention_naive_contre_fusionnee-scaled.png\" alt=\"Attention na\u00efve en trois allers-retours (\u00e9crire S, relire S pour \u00e9crire P, relire P pour \u00e9crire O) face \u00e0 un noyau fusionn\u00e9 qui garde S et P dans la m\u00e9moire rapide et n'\u00e9crit O qu'une fois\" class=\"wp-image-205\" srcset=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/10\/b1_ch04_attention_naive_contre_fusionnee-scaled.png 2560w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/10\/b1_ch04_attention_naive_contre_fusionnee-300x135.png 300w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/10\/b1_ch04_attention_naive_contre_fusionnee-1024x461.png 1024w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/10\/b1_ch04_attention_naive_contre_fusionnee-768x346.png 768w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/10\/b1_ch04_attention_naive_contre_fusionnee-1536x691.png 1536w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/10\/b1_ch04_attention_naive_contre_fusionnee-2048x922.png 2048w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Dans la colonne de gauche, chaque \u00e9tape lit ses entr\u00e9es en m\u00e9moire, calcule, puis \u00e9crit un r\u00e9sultat que l&rsquo;\u00e9tape suivante relira. <\/figcaption><\/figure>\n\n\n<p>Les ordres de grandeur expliquent pourquoi cela compte. Un de ces tableaux interm\u00e9diaires, pour une s\u00e9quence de 4096 tokens, p\u00e8se environ 32 Mio en FP16. Sur un H100, le cache L1 de chaque SM fait <strong>256 Ko<\/strong>, et le cache L2 global 50 Mo au total. Le tableau ne tient donc pas d&rsquo;un bloc dans la m\u00e9moire la plus rapide, ce qui explique qu&rsquo;on le traite par morceaux.<\/p>\n<blockquote>\n<p><strong>\ud83d\udca1 Intuition<\/strong> R\u00e9duire les lectures et \u00e9critures, ce n&rsquo;est pas faire moins de calculs : c&rsquo;est cesser de payer le trajet jusqu&rsquo;\u00e0 l&rsquo;entrep\u00f4t pour des r\u00e9sultats qui ne servent qu&rsquo;une fois.<\/p>\n<\/blockquote>\n<h2 id=\"flashattention-calculer-sur-le-plan-de-travail\">FlashAttention : calculer sur le plan de travail<\/h2>\n<p>C\u00f4t\u00e9 math\u00e9matiques, rien ne change. C&rsquo;est toujours l&rsquo;attention d&rsquo;origine :<\/p>\n<p><p class=\"ql-center-displayed-equation\" style=\"line-height: 45px;\"><span class=\"ql-right-eqno\"> &nbsp; <\/span><span class=\"ql-left-eqno\"> &nbsp; <\/span><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/ql-cache\/quicklatex.com-b4a0c8ab6def29e3f6029fce3672b97c_l3.png\" height=\"45\" width=\"321\" class=\"ql-img-displayed-equation quicklatex-auto-format\" alt=\"&#92;&#91; &#92;&#109;&#97;&#116;&#104;&#114;&#109;&#123;&#65;&#116;&#116;&#101;&#110;&#116;&#105;&#111;&#110;&#125;&#40;&#81;&#44;&#75;&#44;&#86;&#41;&#61;&#92;&#109;&#97;&#116;&#104;&#114;&#109;&#123;&#115;&#111;&#102;&#116;&#109;&#97;&#120;&#125;&#92;&#33;&#92;&#108;&#101;&#102;&#116;&#40;&#92;&#102;&#114;&#97;&#99;&#123;&#81;&#75;&#94;&#123;&#84;&#125;&#125;&#123;&#92;&#115;&#113;&#114;&#116;&#123;&#100;&#95;&#107;&#125;&#125;&#92;&#114;&#105;&#103;&#104;&#116;&#41;&#86;&#46;&#92;&#93;\" title=\"Rendered by QuickLaTeX.com\"\/><\/p><\/p>\n<p>Ici <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/ql-cache\/quicklatex.com-2c758bec4c272382411b95fc0e7ee250_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#81;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"14\" style=\"vertical-align: -4px;\"\/> (requ\u00eates), <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/ql-cache\/quicklatex.com-ea9c87a513e4a72624155d392fae86e2_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#75;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"16\" style=\"vertical-align: 0px;\"\/> (cl\u00e9s) et <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/ql-cache\/quicklatex.com-63ada879859a9e41fd935f035b7313bc_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#86;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"14\" style=\"vertical-align: 0px;\"\/> (valeurs) sont les trois tableaux issus de l&rsquo;entr\u00e9e ; <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/ql-cache\/quicklatex.com-b73f56284f1a0b59708c7dbc60f522ed_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#81;&#75;&#94;&#123;&#84;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"40\" style=\"vertical-align: -4px;\"\/> met chaque requ\u00eate en face de chaque cl\u00e9, puis la softmax ram\u00e8ne chaque score \u00e0 un poids compris entre 0 et 1, avec lequel on p\u00e8se les valeurs. Entre le d\u00e9but et la fin, deux tableaux carr\u00e9s apparaissent : les scores <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/ql-cache\/quicklatex.com-520cb534cd5b6bed768a61515b57cb7e_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#83;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"12\" style=\"vertical-align: 0px;\"\/> et les poids <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/ql-cache\/quicklatex.com-650eb7688af6737ac325425b5c9a5982_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#80;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"14\" style=\"vertical-align: 0px;\"\/>. FlashAttention a pour principe de traiter l&rsquo;attention <strong>par petits blocs<\/strong> plut\u00f4t que de stocker ces grandes matrices interm\u00e9diaires, d&rsquo;o\u00f9 un calcul plus rapide et moins de m\u00e9moire utilis\u00e9e.<\/p>\n<p>Le prix de cette sobri\u00e9t\u00e9, c&rsquo;est la complexit\u00e9 du code. L&rsquo;algorithme d&rsquo;attention traditionnel tient en quelques dizaines de lignes ; FlashAttention en demande <strong>des dizaines de milliers<\/strong>, pour exprimer la m\u00eame op\u00e9ration de fa\u00e7on plus \u00e9conome sur un GPU pr\u00e9cis. Les compilateurs rep\u00e8rent seuls les fusions simples, mais pas celle-l\u00e0 : elle exige des noyaux fusionn\u00e9s \u00e0 la main, branch\u00e9s comme modules d&rsquo;extension au moment de l&rsquo;inf\u00e9rence.<\/p>\n<p>Ce travail sur mesure se retrouve dans les versions successives. De nombreux mod\u00e8les d&rsquo;images utilisent d&#8217;embl\u00e9e FlashAttention 2, mais les versions 3 et 4 de FlashAttention donnent de <strong>meilleures performances sur Hopper et Blackwell<\/strong> respectivement. La version 3 s&rsquo;appuie sur CUTLASS, une biblioth\u00e8que de gabarits pour \u00e9crire des noyaux performants ; la version 4 repose beaucoup sur le d\u00e9coupage en tuiles des chargements, des calculs et des \u00e9critures, ex\u00e9cut\u00e9s dans des pipelines asynchrones.<\/p>\n<p>Porter des noyaux \u00e9crits \u00e0 la main d&rsquo;une g\u00e9n\u00e9ration de GPU \u00e0 la suivante demande un effort d&rsquo;ing\u00e9nierie substantiel : un noyau pens\u00e9 pour un H100 n&rsquo;exploite sans doute pas un B200, et l&rsquo;inverse peut \u00eatre incompatible avec Hopper. L\u00e0 o\u00f9 FlashAttention rapporte le plus : le <a href=\"\/blog\/inference\/l-etape-du-prefill-d-un-llm\/\" title=\"prefill des LLM\">prefill des LLM<\/a> et la g\u00e9n\u00e9ration de vid\u00e9o, deux charges limit\u00e9es par le calcul.<\/p>\n<h2 id=\"le-cache-kv-ce-locataire-qui-grossit\">Le cache KV, ce locataire qui grossit<\/h2>\n<p>Passons \u00e0 l&rsquo;autre jumeau, avec un cas simple. Un mod\u00e8le \u00e9crit son quinzi\u00e8me jeton. Pour cela, il lui faut tout le contexte pr\u00e9c\u00e9dent : sans m\u00e9moire, il recalculerait les cl\u00e9s et les valeurs des jetons 1 \u00e0 14, d&rsquo;o\u00f9 un co\u00fbt quadratique. Le <strong>cache KV<\/strong> garde ces cl\u00e9s et ces valeurs : chacune n&rsquo;est calcul\u00e9e qu&rsquo;une fois, et l&rsquo;attention n&rsquo;a plus \u00e0 traiter que le nouveau jeton, pour un co\u00fbt proche du lin\u00e9aire.<\/p>\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6adef46ac3670&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6adef46ac3670\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"2249\" height=\"981\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/10\/b2_ch10_cache_kv.png\" alt=\"Cache KV : sans cache, tout est recalcul\u00e9 \u00e0 chaque \u00e9tape ; avec cache, les jetons d\u00e9j\u00e0 vus sont relus en m\u00e9moire et un seul nouveau jeton est calcul\u00e9\" class=\"wp-image-575\" srcset=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/10\/b2_ch10_cache_kv.png 2249w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/10\/b2_ch10_cache_kv-300x131.png 300w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/10\/b2_ch10_cache_kv-1024x447.png 1024w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/10\/b2_ch10_cache_kv-768x335.png 768w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/10\/b2_ch10_cache_kv-1536x670.png 1536w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/10\/b2_ch10_cache_kv-2048x893.png 2048w\" sizes=\"auto, (max-width: 2249px) 100vw, 2249px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Regarde le panneau de droite sous l&rsquo;angle de la place occup\u00e9e : chaque case bleu clair est une portion de m\u00e9moire qu&rsquo;il faut garder disponible, et la rang\u00e9e s&rsquo;allonge \u00e0 chaque \u00e9tape. Le temps gagn\u00e9 se paie en espace.<\/figcaption><\/figure>\n\n\n<p>Cet espace n&rsquo;est pas anodin. Le cache se conserve pour chaque jeton, dans chaque t\u00eate d&rsquo;attention de <strong>chaque couche<\/strong>, ce qui limite la taille de fen\u00eatre de contexte utilisable. Comme r\u00e8gle de budget, pr\u00e9vois en plus des poids du mod\u00e8le une marge d&rsquo;<strong>au moins 50 %<\/strong> pour lui, davantage pour les longs contextes ou les grandes tailles de lot. Sans cette marge, l&rsquo;inf\u00e9rence est lente ou plante.<\/p>\n<p>Un autre co\u00fbt s&rsquo;ajoute \u00e0 la place prise : les caches KV prennent du temps \u00e0 lire. Et si chaque cache doit occuper un seul bloc continu de m\u00e9moire, la VRAM se d\u00e9coupe peu \u00e0 peu en trous inutilisables : c&rsquo;est la fragmentation, que PagedAttention est l\u00e0 pour combattre.<\/p>\n<h2 id=\"pagedattention-ranger-par-pages-plutot-que-d-un-seul-tenant\">PagedAttention : ranger par pages plut\u00f4t que d&rsquo;un seul tenant<\/h2>\n<p>L&rsquo;id\u00e9e de PagedAttention (\u00ab attention pagin\u00e9e \u00bb) est emprunt\u00e9e aux syst\u00e8mes d&rsquo;exploitation : elle g\u00e8re le cache KV comme un <strong>syst\u00e8me de m\u00e9moire virtuelle<\/strong>. Au lieu d&rsquo;un bloc continu, le cache est d\u00e9coup\u00e9 en petites pages de taille fixe, accessibles par une table de correspondance qui dit o\u00f9 chacune se trouve.<\/p>\n<p>Imagine un roman dont chaque partie serait rang\u00e9e dans un rayon diff\u00e9rent de la biblioth\u00e8que, avec un sommaire qui indique le rayon de chacune. Tu lis dans l&rsquo;ordre sans que les parties aient besoin d&rsquo;\u00eatre voisines. Pour le cache, cela signifie qu&rsquo;il se loge dans des emplacements dispers\u00e9s, sans exiger un seul tenant.<\/p>\n<p>Les b\u00e9n\u00e9fices d\u00e9crits tiennent en trois mots : moins de fragmentation, moins de duplication, et une <strong>consommation r\u00e9duite sur les longs contextes<\/strong>, avec \u00e0 la cl\u00e9 une latence moindre. Aucun calcul n&rsquo;est modifi\u00e9 ; seul l&rsquo;endroit o\u00f9 l&rsquo;on range change.<\/p>\n<blockquote>\n<p><strong>\ud83d\udccc \u00c0 retenir<\/strong> FlashAttention agit sur l&rsquo;\u00e9tape de calcul de l&rsquo;attention, PagedAttention sur la m\u00e9moire qui conserve son historique. Elles s&rsquo;ajoutent l&rsquo;une \u00e0 l&rsquo;autre.<\/p>\n<\/blockquote>\n<h2 id=\"trois-idees-recues-a-ecarter\">Trois id\u00e9es re\u00e7ues \u00e0 \u00e9carter<\/h2>\n<h3>\u00ab Ce sont deux versions de la m\u00eame optimisation \u00bb<\/h3>\n<p>Non. Elles visent deux endroits diff\u00e9rents de la cha\u00eene : le noyau qui calcule, et la gestion m\u00e9moire du cache. Ce sont deux approches g\u00e9n\u00e9rales, distinctes, pour optimiser l&rsquo;attention standard, et l&rsquo;une n&rsquo;a pas vocation \u00e0 remplacer l&rsquo;autre.<\/p>\n<h3>\u00ab Elles rendent l&rsquo;attention moins co\u00fbteuse sur le papier \u00bb<\/h3>\n<p>Elles ne touchent pas \u00e0 la complexit\u00e9 : l&rsquo;attention reste quadratique avec la longueur de la s\u00e9quence. Pour changer cela, il faut un autre algorithme, comme l&rsquo;attention \u00e0 fen\u00eatre glissante, qui regarde seulement les <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/ql-cache\/quicklatex.com-dfee5c980777976ae8cf6541893fb572_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#119;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"13\" style=\"vertical-align: 0px;\"\/> derniers tokens, mais qui sacrifie un peu de qualit\u00e9 pour gagner du temps et de la place. FlashAttention et PagedAttention restent du c\u00f4t\u00e9 des am\u00e9liorations d&rsquo;impl\u00e9mentation, sans perte, ce qui compte car de petites erreurs d&rsquo;attention s&rsquo;accumulent vite.<\/p>\n<h3>\u00ab Elles ne concernent que le texte \u00bb<\/h3>\n<p>Les mod\u00e8les d&rsquo;images et de vid\u00e9os ont eux aussi une attention exigeante en calcul. Pour eux, l&rsquo;optimisation commence par la s\u00e9lection des noyaux : on essaie FlashAttention, DeepGemm, CuTe ou CUTLASS pour voir <strong>lesquels conviennent le mieux<\/strong> au mod\u00e8le.<\/p>\n<h2 id=\"ou-les-trouver-en-pratique\">O\u00f9 les trouver en pratique<\/h2>\n<p>Bonne nouvelle : tu n&rsquo;as presque jamais \u00e0 les \u00e9crire. La plupart des ing\u00e9nieurs ne r\u00e9digeront jamais leurs propres noyaux, mais la s\u00e9lection de noyaux, c&rsquo;est-\u00e0-dire le choix du meilleur parmi plusieurs, fait partie de l&rsquo;optimisation. Elle est <strong>le plus souvent automatique<\/strong> : PyTorch comme TensorRT-LLM l&rsquo;incluent dans leur compilation.<\/p>\n<p>Les briques existent d\u00e9j\u00e0. CUTLASS fournit des gabarits pour \u00e9crire des noyaux performants, CuTe des abstractions pour les op\u00e9rations par tuiles sur les architectures r\u00e9centes, et FlashInfer une biblioth\u00e8que de noyaux d&rsquo;attention optimis\u00e9s pour l&rsquo;inf\u00e9rence des LLM, avec des fonctions d&rsquo;\u00e9chantillonnage fusionn\u00e9es. TensorRT-LLM apporte de son c\u00f4t\u00e9 un noyau, XQA, pour une attention rapide.<\/p>\n<p>Ces noyaux de bas niveau se logent tout en bas d&rsquo;une pile logicielle qui va de CUDA et PyTorch jusqu&rsquo;aux moteurs d&rsquo;inf\u00e9rence : ils apportent des gains consid\u00e9rables sans que tu aies \u00e0 y toucher.<\/p>","protected":false},"excerpt":{"rendered":"<p>FlashAttention acc\u00e9l\u00e8re le calcul de l&rsquo;attention, PagedAttention range mieux le cache KV : deux id\u00e9es m\u00e9moire, deux r\u00f4les, et comment les distinguer.<\/p>\n","protected":false},"author":1,"featured_media":592,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17],"tags":[],"class_list":["post-593","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-inference"],"_links":{"self":[{"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/posts\/593","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/comments?post=593"}],"version-history":[{"count":4,"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/posts\/593\/revisions"}],"predecessor-version":[{"id":764,"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/posts\/593\/revisions\/764"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/media\/592"}],"wp:attachment":[{"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/media?parent=593"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/categories?post=593"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/tags?post=593"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}