Loi d'Amdahl : formule, exemples et limites
7 min de lecture
La loi d’Amdahl (Amdahl’s law) dit que l’accélération obtenue en parallélisant un travail est plafonnée par la part qui ne peut pas s’exécuter en parallèle. Si une fraction p du travail se répartit sur n processeurs, serveurs ou threads, l’accélération vaut S = 1 / ((1 − p) + p/n), et quelle que soit la taille de n, elle ne dépasse jamais 1 / (1 − p). Avec 95 % de travail parallèle, le plafond est de 20 fois, même sur mille machines.
Les chiffres ci-dessous sont de l’arithmétique, sans aucun test derrière. Les articles cités ont été vérifiés le 1er novembre 2026.
| Fraction parallèle p | n = 2 | n = 8 | n = 64 | n → ∞ |
|---|---|---|---|---|
| 0,50 | 1,33 | 1,78 | 1,97 | 2 |
| 0,90 | 1,82 | 4,71 | 8,77 | 10 |
| 0,95 | 1,90 | 5,93 | 15,42 | 20 |
| 0,99 | 1,98 | 7,48 | 39,26 | 100 |
Que dit la loi en termes simples ?
Un travail ne peut pas finir plus vite que sa part séquentielle, donc des workers supplémentaires ne raccourcissent que le reste. Dès que la part parallèle devient petite face à la part séquentielle, ajouter des workers ne change presque plus le temps total.
Prenez un travail de 10 secondes dont 1 seconde est séquentielle (un verrou, une écriture unique) et 9 secondes se répartissent également, soit p = 0,9. Huit workers le terminent en 1 + 9/8 = 2,125 secondes (4,71 fois plus vite) ; soixante-quatre ont besoin d’environ 1,14 seconde. Rien ne le fait passer sous 1 seconde, donc 10 est le plafond.
D’où vient cette loi ?
Gene Amdahl a présenté l’argument en 1967 à l’AFIPS Spring Joint Computer Conference, dans un article qui défendait l’approche à processeur unique.
Nous n’avons pas lu le texte intégral de Validity of the single processor approach to achieving large scale computing capabilities. Mark Hill et Michael Marty le résument dans Amdahl’s Law in the Multicore Era (IEEE Computer, 2008) : une fraction parallélisable à l’infini sans surcoût d’ordonnancement, le reste totalement séquentiel, et l’accélération décrite sans présenter d’équation (« without presenting an equation »).
Qu’est-ce que cela change pour les tests de charge et de capacité ?
Le débit cesse de croître au rythme des serveurs, threads ou pods dès qu’un composant partagé traite une partie de chaque requête l’une après l’autre. Un test de charge le montre sous la forme d’une courbe de débit qui s’aplatit pendant que vous continuez à ajouter de la capacité.
L’article de Neil Gunther de 2008, cité plus bas, écrit la même loi sous la forme N / (1 + σ(N − 1)), avec σ la fraction séquentielle, et mesure la scalabilité comme le débit à N divisé par le débit à 1. Dans un système web, la part séquentielle est tout ce que chaque requête doit traverser à son tour : un verrou ou une ligne que chaque requête met à jour, une base de données primaire unique qui reçoit toutes les écritures, un consommateur de file unique ou une API tierce limitée en débit.
Comment trouver la part séquentielle dans un test de charge ?
Lancez le même test à plusieurs niveaux de charge et observez quelle ressource sature pendant que le débit s’aplatit. Le composant qui est à sa limite quand la capacité supplémentaire ne rapporte plus rien est la part séquentielle, ou la file d’attente devant elle.
Signes typiques : le débit plafonne alors que la couche applicative a encore du CPU libre, les attentes grossissent à un seul endroit partagé (verrous, connexions à la base, profondeur de file), et le temps de réponse monte au même rythme que les utilisateurs, ce qui est la loi de Little face à un plafond. Une exécution à charge constante ne peut pas le montrer, donc montez la charge par paliers. Le réglage Ramp Up Steps de LoadFocus ajoute les utilisateurs virtuels par lots égaux. Le panneau de capacité de LoadFocus regroupe une exécution terminée par nombre d’utilisateurs virtuels actifs et, sur les offres payantes, liste le p95, les requêtes par seconde et le taux d’erreur par palier pour les exécutions à un seul générateur de charge. Il n’indique un niveau de capacité que si l’exécution a franchi au moins trois paliers, le palier le plus haut valant au moins le double du plus bas. Il n’ajuste aucun modèle de scalabilité : l’ajustement décrit plus bas est à faire vous-même.
Qu’est-ce que la loi de Gustafson ?
C’est le contrepoint : si le problème grandit avec la machine, la part séquentielle reste petite et l’accélération croît presque linéairement. Amdahl fixe le travail, Gustafson fixe le temps d’exécution.
La note de John Gustafson de 1988, Reevaluating Amdahl’s law, rapportait des accélérations de 1016 à 1021 sur un hypercube de 1024 processeurs à Sandia, pour des applications dont la part séquentielle était de 0,4 à 0,8 %, et soutenait que les utilisateurs agrandissent le problème jusqu’à remplir le temps dont ils disposent. Avec s’ la part séquentielle mesurée sur l’exécution parallèle, l’accélération mise à l’échelle, une formule que la note attribue à E. Barsis à Sandia, vaut N + (1 − N)s’.
Avec s’ = 0,05 et 64 processeurs, cela donne 60,85, contre 15,42 selon Amdahl, parce que les deux valeurs de 5 % sont mesurées sur des machines différentes. Dans un système web, Gustafson s’applique quand chaque serveur ajouté travaille sur sa propre part des données ; Amdahl s’applique quand chaque utilisateur supplémentaire touche toujours la même ligne partagée.
Qu’apporte l’Universal Scalability Law ?
Un second terme pour la cohérence, c’est-à-dire le coût de garder des données partagées cohérentes entre workers, qui croît avec le nombre de paires de workers. Avec lui, le débit peut atteindre un maximum puis baisser à mesure que vous ajoutez de la capacité.
L’article de Gunther A General Theory of Computational Scalability Based on Rational Functions (arXiv, 2008) énonce l’Universal Scalability Law (USL) ainsi :
C(N) = N / (1 + σ(N - 1) + κN(N - 1))
peak at N* = sqrt((1 - σ) / κ)
σ représente la contention (sérialisation ou mise en file) et κ la cohérence (copies incohérentes des données) ; avec κ = 0, on retrouve la formule d’Amdahl. Parmi les exemples de Gunther pour le pire cas figure la mise à jour d’enregistrements en base, et il qualifie le débit au-delà de N* de « retrograde », c’est-à-dire décroissant. Avec les valeurs d’exemple σ = 0,05 et κ = 0,001, le maximum se situe vers 31 workers : le débit relatif vaut 9,03 à 32 et 7,82 à 64, là où le terme σ seul prévoit 15,42.
Comment ajuster l’USL sur une série de tests de charge ?
Mesurez le débit à plusieurs niveaux de concurrence, divisez chaque valeur par le débit à un utilisateur, puis estimez σ et κ par la méthode des moindres carrés.
Réarrangée, la formule s’écrit N / C − 1 = σ(N − 1) + κN(N − 1), ce qui est linéaire en σ et κ. Les valeurs ci-dessous sont générées à partir de σ = 0,05 et κ = 0,001 ; mettez dans x vos propres requêtes par seconde par palier :
import numpy as np
n = np.array([1, 2, 4, 8, 16, 32]) # virtual users
x = np.array([50, 95, 172, 284, 402, 452]) # req/s per level
c = x / x[0] # relative capacity
A = np.column_stack([n - 1, n * (n - 1)])
(s, k), *_ = np.linalg.lstsq(A, n / c - 1, rcond=None)
print(f"sigma={s:.3f} kappa={k:.4f}")
print(f"peak near {np.sqrt((1 - s) / k):.0f} users")
Le script affiche sigma=0.050, kappa=0.0010 et un maximum vers 31 utilisateurs. Ne changez que la concurrence d’un palier à l’autre et incluez un palier à un utilisateur, puisque chaque point est divisé par lui.
Où ces modèles cessent-ils d’être utiles ?
Ils résument une courbe de débit en une ou deux constantes, donc ils ne peuvent ni désigner le verrou en cause ni suivre un système qui change sous la charge. Servez-vous-en pour lire une courbe mesurée et la prolonger un peu : un ajustement sur des paliers loin sous le coude dit peu de chose du maximum.
- Paramètres constants. Un cache en cours de préchauffage, un autoscaler ou un pool qui atteint sa limite modifie σ et κ en cours de test.
- Le débit seulement. Le p95 et le p99 peuvent se dégrader en premier : vérifiez aussi la latence de queue.
- Le générateur de charge. S’il sature d’abord, la courbe plate est la sienne.
- Tests fermés. Des utilisateurs virtuels en nombre fixe mesurent un système fermé ; les vrais utilisateurs arrivent à leur propre rythme.
FAQ
Pouvez-vous expliquer la loi d’Amdahl simplement ? Un travail n’est jamais plus rapide que la part qui ne peut pas être partagée. Si un dixième du travail doit s’exécuter en séquence, aucun nombre de workers supplémentaires ne le rend plus de dix fois plus rapide, car ce dixième prend toujours le même temps.
Qu’est-ce que la loi de Gustafson ? La loi de Gustafson dit que lorsque le problème grandit avec le nombre de processeurs, l’accélération croît presque linéairement, selon N + (1 − N)s’, avec s’ la part séquentielle de l’exécution parallèle. John Gustafson l’a publiée en 1988 (en attribuant la formule à son collègue de Sandia E. Barsis) en contrepoint de l’hypothèse d’Amdahl d’un problème de taille fixe.
À lire aussi
- Loi de Little en test de charge : dimensionner et vérifier
- Débit vs latence : comment ils interagissent sous charge
- Modèle de charge ouvert ou fermé : lequel choisir ?
- Latence de queue : définition et mesure sous charge
- Théorie des files d’attente : ce qu’elle dit de la latence
Les affirmations techniques de cet article n'ont pas été relues de façon indépendante.