← Retour aux articles
August 4, 2026
5 min de lecture

Un contexte d’une journée complète bat-il un contexte de dix minutes ? Attention flash et question de longueur de séquence

Un contexte d’une journée complète bat-il un contexte de dix minutes ? Attention flash et question de longueur de séquence
#deep-learning
#attention
#Flash-Attention
#GPU
#optimization

Voici la question à laquelle cet article répond : si un transformateur pouvait suivre une journée de négociation entière avec une résolution d'une seconde au lieu d'une fenêtre de dix minutes, prédirait-il mieux ?

Jusqu'à récemment, on ne pouvait même pas demander. Besoins d’attention standards O(N2)\mathcal{O}(N^2) mémoire, donc une journée de 23 400 étapes à 12 têtes dans float16 nécessite environ 12,9 Go pour la matrice de score seule – plus que les paramètres du modèle et plus que ce que la plupart des cartes vous donnent. La question a été résolue par l'arithmétique avant que quiconque puisse la tester.

Flash Attention (Dao et al., 2022) l'ouvre. Non pas en rapprochant l'attention - il calcule exactement le même résultat - mais en restructurant le calcul pour qu'il soit IO-aware, minimisant ainsi le trafic entre les niveaux de mémoire GPU. C'est là le contenu vraiment intéressant ici, et la majeure partie de cet article est consacrée à son fonctionnement : le carrelage, la récurrence online-softmax, le Θ(N2d2/M)\Theta(N^2 d^2 / M) Liaison IO et recalcul par passe arrière.

Mais le mécanisme est le catalyseur et non la revendication. "Un contexte plus long est préférable" est une déclaration empirique sur les marchés et la position de ce blog - de Temporal Fusion Transformers, qui a révélé que les transformateurs vanille sur les modèles récurrents de surajustement et de courte période de séries financières restent compétitifs à haute fréquence – va dans l’autre sens. L’article se termine donc sur la mesure, pas sur le mécanisme.

Pourquoi l'attention est liée à la mémoire

L'attention calcule softmax(QK/dk)V\text{softmax}(\mathbf{Q}\mathbf{K}^\top / \sqrt{d_k})\mathbf{V} — la primitive elle-même, dans un contexte commercial, est couverte dans Temporal Fusion Transformers for Multi-Horizon Portfolio Forecasting. Tout le problème n’en est qu’une : la matrice de score intermédiaire S=QK/dk\mathbf{S} = \mathbf{Q}\mathbf{K}^\top/\sqrt{d_k} est N×NN \times N, il est écrit en mémoire, relu pour le softmax, réécrit et relu pour le matmul final - et il doit être conservé pour la rétropropagation.

L'intensité arithmétique de l'attention est min(d,N)\approx \min(d, N), donc environ 64 FLOP/octet à d=64d = 64 — bien à gauche de la pointe de la crête A100. Il se situe sur le plafond de bande passante incliné, et non sur le plafond de calcul plat : le GPU passe plus de temps à se déplacer. S\mathbf{S} autour que de multiplier quoi que ce soit. Le cadre de ligne de toit utilisé – point de faîte, plafond incliné ou plat, et pourquoi le même raisonnement décide si un GPU vaut la peine d'être acheté – est construit avec des chiffres mesurés dans [Quand le GPU paie] (/en/blog/post/when-gpu-pays-off-sweep-roofline).

La hiérarchie de la mémoire exploitée par l'algorithme

Niveau de mémoire Taille Bande passante Latence
HBM (mémoire à large bande passante) 40-80 Go 2,0 To/s ~400 ns
SRAM (sur puce, mémoire partagée) 20 Mo 19 To/s ~4 ns

La SRAM représente environ 10 fois la bande passante et 100 fois la latence inférieure, à un millième de la capacité. Tout ce que fait Flash Attention découle de cet échange : renoncer à de la capacité, acheter de la bande passante et de la latence. La même démarche « restructurer l'algorithme plutôt que d'acheter du matériel », mesurée sur un backtest du processeur, est l'échelle de vitesse de backtest.

L'algorithme Flash Attention

Flash Attention traite l'attention dans des tuiles dimensionnées pour tenir dans la SRAM et ne matérialise jamais l'intégralité de l'attention. N×NN \times N matrice dans HBM du tout.

Partition Q\mathbf{Q} dans Tr=N/BrT_r = \lceil N/B_r \rceil blocs de rangées et K,V\mathbf{K}, \mathbf{V} dans Tc=N/BcT_c = \lceil N/B_c \rceil blocs de colonnes, avec Br,BcB_r, B_c choisi pour qu'une tuile et ses accumulateurs tiennent sur la puce. Pour chaque bloc de requête, parcourez tous les blocs clé-valeur :

For each query block Q_i:
    Initialize: O_i = 0, m_i = -inf, l_i = 0    # output, running max, running sum
    For each KV block (K_j, V_j):
        1. Load Q_i, K_j, V_j from HBM to SRAM
        2. Compute S_ij = Q_i @ K_j^T / sqrt(d)  # in SRAM
        3. Compute local max: m_ij = rowmax(S_ij)
        4. Compute P_ij = exp(S_ij - m_ij)        # in SRAM
        5. Compute local sum: l_ij = rowsum(P_ij)
        6. Update running statistics:
           m_new = max(m_i, m_ij)
           l_new = l_i * exp(m_i - m_new) + l_ij * exp(m_ij - m_new)
           O_i = O_i * (l_i * exp(m_i - m_new) / l_new)
                + P_ij @ V_j * (exp(m_ij - m_new) / l_new)
           m_i = m_new, l_i = l_new
    Write O_i to HBM

La récurrence softmax en ligne

L'astuce qui rend le carrelage possible est online softmax. Un softmax naïf a besoin de deux passages sur la ligne : un pour trouver le maximum (pour la stabilité numérique), un pour exponentier et normaliser. Deux passages sur une ligne que vous refusez de stocker sont une contradiction : Flash Attention continue d'exécuter des statistiques et de se redimensionner au fur et à mesure.

Après les blocs 1,,j1, \ldots, j:

m(j)=max(m(j1),max(Sij))m^{(j)} = \max(m^{(j-1)}, \max(\mathbf{S}_{ij})) (j)=(j1)em(j1)m(j)+keSijkm(j)\ell^{(j)} = \ell^{(j-1)} \cdot e^{m^{(j-1)} - m^{(j)}} + \sum_k e^{S_{ijk} - m^{(j)}}

et la sortie de l'accumulateur est corrigée du même facteur :

Oi(j)=(j1)(j)em(j1)m(j)Oi(j1)+1(j)emijm(j)PijVj\mathbf{O}_i^{(j)} = \frac{\ell^{(j-1)}}{\ell^{(j)}} \cdot e^{m^{(j-1)} - m^{(j)}} \cdot \mathbf{O}_i^{(j-1)} + \frac{1}{\ell^{(j)}} \cdot e^{m_{ij} - m^{(j)}} \cdot \mathbf{P}_{ij}\mathbf{V}_j

Chaque fois qu'un nouveau bloc augmente le maximum en cours d'exécution, la sortie précédemment accumulée est redimensionnée rétroactivement par em(j1)m(j)e^{m^{(j-1)} - m^{(j)}} — comme si le nouveau maximum était connu depuis le début. Le résultat est algébriquement identique au softmax en deux passes. En arithmétique exacte, ce n’est pas une approximation ; c'est une réassociation. (En précision finie, c'est un chemin d'arrondi différent, qui compte — voir le contrôle d'exactitude ci-dessous.)

Complexité des E/S

C'est la déclaration officielle de la victoire. Flash Attention effectue

Θ(N2d2M)\Theta\left(\frac{N^2 d^2}{M}\right)

accès HBM, où MM est la taille de la SRAM, par contre Θ(Nd+N2)\Theta(Nd + N^2) pour la mise en œuvre standard. Noter que MM apparaît dans le dénominateur : plus le bloc-notes sur la puce est grand, moins il y a d'allers-retours, c'est pourquoi l'algorithme est indiqué en termes de hiérarchie de mémoire plutôt qu'en nombre de FLOP. Pour typique d=64d = 64 et M100M \approx 100 Ko, le ratio favorise Flash Attention avec environ 5 à 10 fois moins d'accès.

Passe arrière : recalculer au lieu de stocker

La rétropropagation par l'attention nécessite normalement le P\mathbf{P} matrice que la passe avant a tout simplement refusé de conserver. Flash Attention recalcule les tuiles de Q,K\mathbf{Q}, \mathbf{K} pendant le passage en arrière, stocker uniquement la sortie O\mathbf{O} et les statistiques softmax (m,)(m, \ell) - les deux O(N)\mathcal{O}(N), pas O(N2)\mathcal{O}(N^2). Il échange une quantité modeste d'arithmétique redondante contre le terme de mémoire qui constituait tout le problème. C'est la même affaire que le point de contrôle de dégradé, appliqué à la granularité des tuiles au sein d'un seul opérateur.

FA2 : parallélisme

Flash Attention 2 (Dao, 2023) a conservé l'algorithme et corrigé la planification :

  1. Moins de FLOP non matmul. FA1 a consacré du temps réel au redimensionnement, à la recherche du maximum et à l'exponentiation – des opérations qui s'exécutent sur des cœurs CUDA, et non sur des cœurs tenseurs. FA2 reporte le redimensionnement à la fin de la boucle interne.
  2. Parallélisme sur la longueur de la séquence. FA1 effectue la parallélisme sur les lots et les têtes uniquement. FA2 parallélise également sur les blocs de requêtes. Cela est particulièrement important pour le cas du trading, où vous avez souvent une très longue séquence par actif et une taille de lot de 1 à 4 – exactement le régime dans lequel le parallélisme par lots et têtes affame le GPU.
  3. Partitionnement du travail de chaîne. Chaque chaîne prend un sous-ensemble différent de blocs de requête plutôt que de diviser un calcul de score et de le réduire entre les chaînes, supprimant ainsi une réduction de chaîne croisée.

Résultat rapporté : ~70 % des FLOP maximaux théoriques sur A100 contre ~35 % pour FA1.

FA3 : Mécanique de la trémie

Flash Attention 3 (Dao, Shah, 2024) est spécifique à l'architecture du H100 :

  1. Spécialisation de distorsion asynchrone. L'accélérateur de mémoire tenseur (TMA) de Hopper déplace HBM → SRAM de manière asynchrone. FA3 divise les chaînes en producteurs émettant des charges TMA pour le prochain bloc KV et en consommateurs calculant sur le bloc actuel, de sorte que le mouvement des données se cache derrière l'arithmétique.
  2. Matmul et softmax entrelacés. QiKj\mathbf{Q}_i\mathbf{K}_j^\top pour un bloc s'exécute sur des cœurs tenseurs tandis que le softmax du bloc précédent s'exécute sur des cœurs CUDA - deux unités matérielles différentes, véritablement concurrentes plutôt que découpées dans le temps.
  3. FP8 avec traitement incohérent. H100 effectue FP8 avec un débit 2x FP16. L’attention naïve du FP8 est détruite par les valeurs aberrantes ; FA3 fait tourner les vecteurs de manière aléatoire avant la quantification par bloc pour répartir l'ampleur des valeurs aberrantes sur les coordonnées, signalée avec une erreur numérique 2,6 fois inférieure à celle du FP8 naïf.
Version GPU Utilisation Accélération vs Standard
FA1 A100 ~35% 2-4x
FA2 A100 ~70% 5-7x
FA3 (FP16) H100 ~75% 3-5x contre FA2
FA3 (FP8) H100 ~75% 1,6x contre FA3 FP16

Le masquage causal est l'endroit où le trading bénéficie d'une remise

Le masquage causal est obligatoire pour les séries chronologiques – le modèle ne doit pas s’intéresser à l’avenir – et, sous le carrelage, il ne s’agit pas d’un coût supplémentaire mais d’une économie. Toute tuile dont les clés sont entièrement dans le futur par rapport à ses requêtes est ignorée purement et simplement, jamais chargée et jamais calculée, ce qui réduit environ la moitié du travail. Dans PyTorch, c'est is_causal=True; rien d'autre n'est requis.

L'intégration est de huit lignes

Presque aucun du code dont vous avez besoin ne concerne Flash Attention. Échangez le chemin explicite de la matrice de score pour le noyau fusionné :

scores = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(d_head)
scores = scores.masked_fill(causal_mask, float("-inf"))
out = torch.matmul(torch.softmax(scores, dim=-1), v)

out = torch.nn.functional.scaled_dot_product_attention(
    q, k, v,
    dropout_p=self.dropout if self.training else 0.0,
    is_causal=True,
)

C'est tout le changement. q, k, v sont en forme (batch, heads, seq, head_dim); le masque causal a disparu parce que le noyau le construit. Pour un modèle commercial PyTorch annoté complet dans lequel intégrer cela - projection d'entrée, blocs et tête haut/plat/bas à 3 classes - utilisez DeepLOB, et pour un pipeline de formation complet, voir Temporal Fusion Transformers. Construire ici une quatrième copie de cet échafaudage n’apprendrait rien.

Exigences : capacité de calcul >= 8,0 (A100, H100, RTX 3090+), entrées demi-précision, PyTorch >= 2,0. Vérifier le chemin rapide réellement engagé avec torch.backends.cuda.sdp_kernel diagnostic et torch.cuda.max_memory_allocated() — SDPA revient silencieusement au noyau mathématique si une condition préalable échoue, et un repli silencieux ressemble exactement à un modèle de travail qui est simplement lent.

La mesure : le contexte plus long est-il payant ?

Tout ce qui précède indique qu'un contexte 32K ou 128K est désormais abordable. Cela ne dit rien quant à savoir si c'est utile. L'expérience honnête :

Former la même architecture à N{512,4096,32768}N \in \{512, 4096, 32768\} avec SDPA-Flash sur la série BTC utilisée ailleurs dans cette série, maintenant les paramètres, l'optimiseur et la cible fixes de sorte que la longueur de la séquence soit la seule variable. Signalez deux choses :

  1. Coût. Horloge murale mesurée par époque et torch.cuda.max_memory_allocated() à chaque NN.
  2. Avantage. Performances prédictives hors échantillon par rapport NN, lors d'une division en marche avant.

Une version antérieure de cet article contenait un tableau des chiffres de mémoire par longueur de séquence dérivé analytiquement de la O(N)\mathcal{O}(N) formule d'activation. Ces lignes ont été supprimées : elles n'ont jamais été mesurées et elles étaient en désaccord avec la propre arithmétique du budget mémoire de l'article. Un nombre dérivé présenté dans un tableau de résultats est un résultat fabriqué, et ce blog ne le fournit pas.

La propriété intéressante de cette expérience est qu'elle est publiable dans les deux sens. Si les performances hors échantillon augmentent de façon monotone avec NN, cela justifie tout le programme à contexte long. S'il atteint un plateau à quelques milliers de pas, ou se dégrade, c'est une pièce plus solide - un compagnon de [l'honnête négatif] (/en/blog/post/honest-negative-no-robust-edge) – et cela signifierait que le mur de mémoire n’a jamais été la contrainte majeure sur les transformateurs commerciaux.

Plus de contexte signifie plus de capacité, donc plus de surface de surapprentissage

Il y a une raison spécifique de s’attendre à un résultat nul ou négatif. Transformateurs de fusion temporelle documente déjà que les transformateurs vanille s'appliquent naïvement au surajustement des séries financières : ils manquent de biais inductifs temporels et les modèles récurrents à courte période restent compétitifs à haute fréquence. L'extension du contexte de 512 à 32 768 étapes n'ajoute pas d'informations proportionnelles à la longueur ; le décalage marginal du 32 000ème d’une série de prix quasi efficace n’apporte que très peu de choses. Ce qu'il ajoute de manière fiable, c'est la valeur des paramètres à adapter.

Alors le balayage NN doit être traité comme ce qu'il est : une recherche de sélection de modèle, avec le même mécanisme que ce blog applique à toutes les autres recherches. Trois longueurs de séquence multipliées par tout ce qui varie est un décompte d'essais, et le gagnant doit effacer un Rapport de Sharpe dégonflé calculé par rapport à ce décompte d'essais et une porte PBO, et pas seulement battre ses voisins. Sinon, « le contexte long gagne » ne se distingue pas du choix du meilleur de trois courses bruyantes.

Un contrôle d'exactitude, car "exact" demande beaucoup de travail

Flash Attention est exact en arithmétique exacte. La recommandation qui y est attachée – exécuter en fp16 ou bf16, et sur H100, considérer FP8 – ne l’est pas. Ce sont des affirmations distinctes et la seconde domine dans la pratique : réassocier une somme et passer à la moitié de la précision sont tous deux des perturbations, et l'article qui a introduit la garantie d'ordre ne devrait alors pas agiter à la main celui de la précision.

Le blog dispose déjà du bon instrument. Le piège de précision GPU établit la norme : une faible précision ne vous avertit pas, elle renvoie des erreurs plausibles et vous prouvez l'exactitude avec un oracle de parité sur une quantité discrète en aval - les échanges comptent - et non par des courbes oculaires. Appliqué ici :

  • Attention au calcul avec SDPA-Flash dans bf16 et avec une implémentation de référence fp64 sur des entrées identiques ; rapporte l'erreur relative maximale sur le tenseur de sortie.
  • Poussez-le jusqu'à la décision : pour un modèle qui émet une étiquette haut/plat/bas, indiquez combien d'étiquettes basculent entre les deux chemins, en fraction du total des décisions.

Un désaccord petit, limité et explicable est la signature d’une voie rapide et correcte. Une recommandation illimitée signifie que la recommandation FP8 n’a jamais été sûre pour ce modèle. Aucun des deux numéros n'est connu jusqu'à son exécution.

Quand l'atteindre

Comprimé en décision, qui a la même forme que le guide de décision GPU :

  • Au-dessus de ~2 000 pas de temps sur un GPU CUDA : oui, sans condition. Il s'agit d'un changement sur une ligne produisant une sortie exacte, et la victoire augmente avec NN. Il n'y a aucun scénario où vous voulez que le résultat soit matérialisé N×NN \times N chemin à la place.
  • En dessous d'environ 512 pas de temps, sur CPU ou avec des architectures sans attention (CNN, SSM comme Mamba) : non pertinent. À gauche de la crête, la surcharge fixe représente le coût total et l'attention n'a jamais été votre goulot d'étranglement.
  • Les seuils ci-dessus sont du folklore, pas des mesures — ils proviennent de la littérature générale, et le croisement sur votre propre modèle et carte est une référence en dix lignes. Exécutez-le plutôt que de vous fier aux chiffres ronds.

Conclusion

Flash Attention est un résultat propre et véritablement important : en respectant la hiérarchie de la mémoire et en réassociant le softmax, il calcule l'attention exacte avec O(N)\mathcal{O}(N) mémoire au lieu de O(N2)\mathcal{O}(N^2), et le Θ(N2d2/M)\Theta(N^2 d^2 / M) IObound explique précisément pourquoi. Son adoption dans un transformateur de trading est un changement sur une seule ligne sans coût de précision en arithmétique exacte et avec un gain de mémoire important.

Ce qu'il ne fait pas, c'est répondre à la question en haut. Cela convertit « un contexte d’une journée complète est impossible » en « un contexte d’une journée complète est bon marché », ce qui représente une modification du coût de l’expérience, et non de son résultat. Le mur de la mémoire qui s'effondre est une invitation à mesurer, et la mesure est ce qui transforme ce résumé papier en une découverte.

Références

  1. Dao, T., Fu, D.Y., Ermon, S., Rudra, A., Re, C. "FlashAttention : attention exacte rapide et efficace en mémoire avec prise en compte des IO." NeurIPS (2022). arXiv:2205.14135
  2. Dao, T. « FlashAttention-2 : une attention plus rapide avec un meilleur parallélisme et un meilleur partitionnement du travail. » ICLR (2024). arXiv:2307.08691
  3. Dao, T., Shah, J. « FlashAttention-3 : attention rapide et précise avec asynchronie et faible précision ». NeurIPS (2024). arXiv:2407.08608
  4. Vaswani, A., et coll. "L'attention est tout ce dont vous avez besoin." NeurIPS (2017).
  5. Milakov, M., Gimelshein, N. "Calcul du normalisateur en ligne pour softmax." arXiv :1805.02867 (2018).
blog.disclaimer

Authors

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

Gardez une longueur d'avance sur le marché

Abonnez-vous à notre newsletter pour des insights exclusifs sur le trading IA, des analyses de marché et des mises à jour de la plateforme.

Nous respectons votre vie privée. Désabonnement possible à tout moment.