Le dernier numéro des Communications of the ACM [1] (CACM) contient un article intitulé Attack of the Killer Microseconds écrit par des ingénieurs de Google, dont David Patterson, qui fut dans des vies antérieures professeur à Berkeley, architecte principal des processeurs SPARC de Sun Microsystems et co-auteur avec John Hennessy (architecte principal des processeurs MIPS et actuel président de l’université Stanford) du manuel de référence sur l’architecture des ordinateurs (pour dire qu’il ne s’agit pas d’élucubrations d’amateurs).
Gérer des échelles de temps très différentes
Depuis le début du millénaire, l’échelle de temps du fonctionnement des processeurs informatiques est la nanoseconde. Les ingénieurs qui les conçoivent ont mis au point des dispositifs d’une habileté diabolique pour accélérer leur fonctionnement, presque toujours implémentés par des procédés matériels, électroniques : pipeline, chargement anticipé des données et des instructions en mémoire cache, exécution dans le désordre (out of order execution), prédiction de branchement.
Pendant ce temps les opérations de lecture et d’écriture sur disque, ainsi que les communications par réseau, se mesurent toujours en millisecondes, et les procédés de nature à les accélérer relèvent le plus souvent du logiciel, surtout le système d’exploitation (sans négliger néanmoins les progrès considérables des techniques de transmission optiques et électro-magnétiques).
Nos auteurs donnent les ordres de grandeur suivants pour 2017 :
En nanosecondes : | En microsecondes : | En millisecondes : |
---|---|---|
Accès registre : 1ns-5ns | réseau local : O(1µs) | Accès disque : O(10ms) |
Accès cache : 4ns-30ns | Mémoire non-volatile : O(1µs) | Clé USB : O(1ms) |
Accès mémoire : 100ns | Mémoire flash rapide : O(10µs) | Internet : O(10ms) |
Les efforts les plus importants (ils se chiffrent en milliards d’euros de recherche-développement) ont porté sur les actions de la première et de la troisième colonne, même si l’on peut noter la relative stagnation des performances des disques durs.
En d’autres termes, voici le nombre d’instructions qu’un processeur moderne peut effectuer pendant les opérations de lecture-écriture suivantes :
Mémoire flash | 225 000 instructions = O(100µs) |
Flash rapide | 20 000 instructions = O(10µs) |
Mémoire NVM | 2 000 instructions = O(1µs) |
Mémoire centrale | 500 instructions = O(100ns) |
Science du système d’exploitation
Une grande part de la science informatique, surtout dans les domaines du système d’exploitation et de l’architecture des machines, se consacre à l’étude de ces questions de temporalités différentes.
Le système d’exploitation a été inventé dans les années 1950 pour concilier ces échelles de temps : si un accès disque prend 10ms pour l’opération physique de déplacement du bras qui porte la tête de lecture, à quoi il convient d’ajouter le temps d’exécution des instructions de commande de l’opération, disons au doigt mouillé 20 000 instructions à 1ns chacune, il reste 9 980 000ns disponibles pour exécuter autant d’instructions. Ne rien faire pendant ce temps serait gaspiller une ressource précieuse, mais exécuter les instructions d’autres programmes (ou d’autres sections du même programme) pendant ce délai, tout en sachant qu’il faudra rendre la main au premier programme quand son accès disque sera terminé, demande des mécanismes de synchronisation raffinés, qui sont une des fonctions du système d’exploitation [2], qui est un logiciel.
Le système d’exploitation, historiquement, améliore le traitement d’événements de l’ordre de la milliseconde, cependant que la micro-électronique s’occupe de nanosecondes. La microseconde est négligée, comme le montre le graphe de la fréquence des mentions de ces trois unités de mesure dans la littérature mondiale depuis leur apparition vers 1920, observée sur books.google.com, aimablement fourni par nos auteurs qui ne travaillent pas chez Google pour rien.
Or, comme nous venons de le voir, le temps consommé par l’accès disque se répartit entre l’opération mécanique (10ms) et la prise en charge par le système d’exploitation (20µs), qui est un temps de latence, certes faible en regard du délai mécanique, mais non négligeable.
Ce que montrent nos auteurs, c’est que l’organisation des traitements informatiques contemporains et les évolutions techniques multiplient les temps de latence, que les dispositifs qui permettent de gagner des millisecondes ou des nanosecondes ne sont pas les mêmes que ceux qui permettent de gagner des microsecondes, et qu’il va donc falloir s’en occuper sérieusement.
Tout se passe dans les nuages
Les traitements informatiques d’aujourd’hui, que ce soit dans les entreprises ou pour les particuliers, sont de plus en plus souvent effectués par des machines virtuelles [3], que leur nature virtuelle, justement, permet de disperser dans les nuages (cloud computing). Le « nuage », en fait, ce sont d’immenses centres de données (datacenters) qui abritent des dizaines de milliers d’ordinateurs. Les données (et les machines virtuelles qui les manipulent) circulent d’abord dans l’Internet, pour atteindre le centre de données sélectionné par le système d’orchestration [4] du nuage, avec un temps de latence en millisecondes.
Mais une fois que la machine virtuelle considérée est arrivée dans le bon centre de données, les problèmes ne sont pas tous résolus.
Gagner des microsecondes
Les bénéfices de la loi de Moore s’amenuisent chaque année, alors pour compenser cette perte de puissance les compagnies du nuage (Amazon, Google, OVH, etc.) répartissent les traitements sur un plus grand nombre de machines virtuelles et physiques. Ainsi, une simple interrogation du moteur de recherche Google (nos auteurs sont bien placés pour le savoir) générera des milliers d’appels de procédures à distance (RPC), c’est-à-dire de communications avec d’autres machines virtuelles, éventuellement implantées sur d’autres machines physiques, pour leur sous-traiter une partie des calculs nécessaires.
Considérons les interactions par le réseau au sein d’un centre de données : à 40 Gbps, un paquet de données est émis en moins d’une microseconde, et à la vitesse de la lumière il met à peu près une microseconde pour parcourir les 200 ou 300 mètres qui le séparent de la machine physique qu’il doit atteindre. De même, les nouvelles technologies de mémoire non-volatile (NVM) qui tendent à remplacer les disques durs auront des temps d’accès inférieurs à la microseconde, cependant que les mémoires flash rapides sont dans la tranche des dix microsecondes.
Bref, les événements à traiter dans les centres de données où se traite aujourd’hui l’essentiel de l’informatique quotidienne ont des temps de latence de l’ordre de la microseconde, et les techniques d’optimisation destinées aux interactions aux échelles de la nanoseconde ou de la milliseconde ne s’adaptent pas bien à cette échelle de la microseconde.
Nos auteurs décomposent ainsi une action élémentaire dans un centre de données : un accès mémoire direct à distance (RDMA) prend 2µs ; les couches de logiciel nécessaires à chaque extrémité de la liaison ajouteront quelques microsecondes ; le passage du contrôle de la couche réseau à la couche traitement demandera une mise en file d’attente, puis le déclenchement d’une interruption ; puis interviendront la couche RPC et pour finir TCP, ce qui amènera notre transaction à près de 100µs. D’autres causes de latence peuvent intervenir de façon imprévisible : si le processeur est en sommeil, il peut mettre des centaines de microsecondes à se réveiller ; interviennent également les mécanismes de copie de données de l’espace noyau à l’espace utilisateur, ou entre plusieurs espace utilisateur distincts, ainsi que les changements de contexte utilisateur. Toutes ces causes de latence pénalisent lourdement les traitements distribués qui sont aujourd’hui la règle, notamment dans les nuages, et les techniques habituelles ne leur apportent pas de solution.
Perspectives
Ces problèmes de temps de latence pénalisants surgissent aujourd’hui parce que des événements qui étaient relativement rares dans les traitements d’hier (appel de procédures à distance, déplacement de machine virtuelle par exemple) sont désormais au cœur des architectures de traitement de données. Tant que ces événements étaient rares, les architectes de système adoptaient des solutions simples, telles que, simplement, attendre la fin de l’action, mais dès lors que ces événements sont fréquents la pénalité encourue devient de moins en moins supportable.
Pour alléger ces pénalités, nos auteurs suggèrent de concevoir à nouveaux frais des optimisations pour les mécanismes de bas niveau, tels que contention de verrou et synchronisation. Les spécialistes du calcul à haute performance (HPC) se sont confrontés à ces problèmes depuis longtemps, mais les solutions qu’ils ont adoptées ne répondent pas forcément très bien aux questions actuelles, parce qu’ils travaillaient généralement dans un contexte où les contraintes économiques étaient faibles, ce qui n’est pas le cas des grands centres de données d’aujourd’hui.
De surcroît, les logiciels déployés par les grands opérateurs tels que Google et Amazon évoluent rapidement, ce qui impose des méthodes de génie logiciel rigoureuses et simplificatrices, impératif ignoré du monde HPC.
Des solutions doivent également être cherchées du côté des processus légers, du parallélisme à grain fin, de la gestion plus efficace des files d’attente, etc. Je ne puis mieux faire que vous recommander la lecture de cet article.