C'est pour ça que j'avais mis algorithme entre guillemets... :)
C'est effectivement très très général comme principe (ça colle mieux qu'algo).
Les processeurs modernes n'exécutent pas les instructions dans l'ordre, et tentent notamment de prédire quelles branches de code seront exécutées avant même d'interpréter la condition de la branche.
Par exemple :
a = 42;
b = 72;
if (tableau[a] < 73) {
b++;
}
Il est possible que dans le processeur b soit incrémenté alors que tableau[a] est supérieur à 73. En fait le CPU ne peut pas exécuter le code x86 dans l'ordre suffisamment vite pour atteindre son maximum d'utilisation, c'est juste impossible. Par exemple s'il exécutait ce code dans l'ordre, l'unité arithmétique dormirait la majeure partie du temps. Il vaut mieux qu'elle soit active et fasse une opération alors que l'on n'a pas encore exécuté la comparaison pour savoir si l'opération est requise. Au pire, on jette le résultat et on reprend les opérations depuis l'erreur. Au mieux, on aura le résultat à l'avance. Et là je parle bien d'optimisations réalisées par le CPU, pas par le compilateur.
C'est le principe d'une exécution «Out of Order» et d'une prédiction de branche.
Tu peux jouer avec la commande perf stat pour comprendre ça éventuellement plus concrêtement.
# perf stat echo 'toto'
toto
Performance counter stats for 'echo toto':
0.354665 task-clock (msec) # 0.010 CPUs utilized
1 context-switches # 0.003 M/sec
0 cpu-migrations # 0.000 K/sec
59 page-faults # 0.166 M/sec
1,303,535 cycles # 3.675 GHz
765,605 instructions # 0.59 insn per cycle
154,395 branches # 435.326 M/sec
7,829 branch-misses # 5.07% of all branches
0.034129737 seconds time elapsed
Un CPU moderne est capable d'exécuter bien plus de 0,59 instructions par cycle (et je parle même pas de multi-cœurs). On voit qu'il a fait 5% de branch-misses, ce qui signifie qu'il a fait des mauvaises prédictions dans certains cas... Mais 5% c'est peu d'échecs et de temps perdu par rapport au gain qu'on a lorsqu'on a prédit avec succès...
Là où il y a un problème, c'est quand le processeur rejette un résultat. Ça laisse des traces. Et ça on n'y avait pas suffisamment pensé avant. L'attaque spectre consiste, en simplifié, à exploiter ces traces. De même pour l'attaque meltdown (mais qui profite en plus d'un bug d'intel qui vérifie des droits d'accès a posteriori et pas a priori (!))
[^] # Re: Comment une faille peut-elle toucher plusieurs processeurs de plusieurs fondeurs ?
Posté par Pinaraf . En réponse à la dépêche Deux failles critiques : Meltdown et Spectre. Évalué à 10.
C'est pour ça que j'avais mis algorithme entre guillemets... :)
C'est effectivement très très général comme principe (ça colle mieux qu'algo).
Les processeurs modernes n'exécutent pas les instructions dans l'ordre, et tentent notamment de prédire quelles branches de code seront exécutées avant même d'interpréter la condition de la branche.
Par exemple :
Il est possible que dans le processeur b soit incrémenté alors que tableau[a] est supérieur à 73. En fait le CPU ne peut pas exécuter le code x86 dans l'ordre suffisamment vite pour atteindre son maximum d'utilisation, c'est juste impossible. Par exemple s'il exécutait ce code dans l'ordre, l'unité arithmétique dormirait la majeure partie du temps. Il vaut mieux qu'elle soit active et fasse une opération alors que l'on n'a pas encore exécuté la comparaison pour savoir si l'opération est requise. Au pire, on jette le résultat et on reprend les opérations depuis l'erreur. Au mieux, on aura le résultat à l'avance. Et là je parle bien d'optimisations réalisées par le CPU, pas par le compilateur.
C'est le principe d'une exécution «Out of Order» et d'une prédiction de branche.
Tu peux jouer avec la commande
perf statpour comprendre ça éventuellement plus concrêtement.Un CPU moderne est capable d'exécuter bien plus de 0,59 instructions par cycle (et je parle même pas de multi-cœurs). On voit qu'il a fait 5% de branch-misses, ce qui signifie qu'il a fait des mauvaises prédictions dans certains cas... Mais 5% c'est peu d'échecs et de temps perdu par rapport au gain qu'on a lorsqu'on a prédit avec succès...
Là où il y a un problème, c'est quand le processeur rejette un résultat. Ça laisse des traces. Et ça on n'y avait pas suffisamment pensé avant. L'attaque spectre consiste, en simplifié, à exploiter ces traces. De même pour l'attaque meltdown (mais qui profite en plus d'un bug d'intel qui vérifie des droits d'accès a posteriori et pas a priori (!))
Est-ce plus clair ?