Pourquoi devons-nous attendre les E / S?


28

Il a toujours été connu que les opérations sur disque sont lentes et nous connaissons les raisons pour lesquelles elles sont lentes. La question ici est donc de savoir pourquoi devons-nous attendre les E / S ou pourquoi existe-t-il une chose telle que IOWait, etc.?

Je veux dire que j'ai remarqué que lorsque vous effectuez des tâches d'E / S en arrière-plan, votre ordinateur devient beaucoup plus lent, j'ai particulièrement remarqué que lorsque vous utilisez Linux, si vous effectuez des tâches d'E / S plus longues , le système d'exploitation devient presque inutilisable jusqu'à ce qu'ils soient terminés.

En effet, j'ai également trouvé ce sujet dans un article, il y a un extrait:

L'attente des E / S est de 12,1%. Ce serveur possède 8 cœurs (via cat / proc / cpuinfo). Ceci est très proche de (1/8 cœurs = 0,125)

Donc, fondamentalement, cela signifie qu'il ralentit beaucoup l'ordinateur, pourquoi? Je veux dire OK, maintenant l'ordinateur normal est au moins 2 cœurs, parfois 4 ou parfois ils en ont plus à cause de l'hyperthreading ou quelque chose comme ça. Mais maintenant, la question est de savoir pourquoi le processeur doit en fait rester là, ne faisant pratiquement rien d'autre que d'attendre les E / S? Je veux dire l'idée de base ou l'architecture de la gestion des processus, maintenant je ne sais pas si c'est le système d'exploitation qui est responsable de cela, ou est-ce que cela se résume à la partie matérielle, mais cela devrait être possible pour le processeur d'attendre ou de vérifiez régulièrement, tout en effectuant de nombreuses autres tâches et en ne retournant au processus d'E / S que lorsqu'il est prêt. En effet, si c'est une tâche si difficile et que le processeur doit attendre, pourquoi n'est-ce pas? t que géré par le matériel plus efficacement alors? Par exemple, il pourrait y avoir une sorte de mini processeur qui l'attendrait et fournirait la petite partie des données au processeur réel dès qu'il reviendrait au processus et donc le processus serait répété et nous n'aurions pas de consacrer pratiquement tout un cœur de processeur au processus de copie de données ... Ou serais-je celui qui devrait inventer ce genre de choses et obtenir un prix Nobel pour cela? : S

Maintenant d'accord, je le mets vraiment du point de vue des observateurs et je ne suis pas vraiment allé aussi loin dans le sujet, mais je ne comprends vraiment pas pourquoi le processeur doit fonctionner avec la vitesse du disque dur, alors qu'il pourrait simplement faites autre chose et revenez au disque dur une fois qu'il est prêt. L'idée n'est pas d'accélérer l'application qui a besoin de cette opération d'E / S ou du processus de copie ou autre, mais l'idée est d'affecter de manière minimale la consommation du processeur tout en effectuant cette opération, afin que le système d'exploitation puisse l'utiliser pour d'autres processus et l'utilisateur. n'aurait pas à ressentir un décalage informatique général lors de certaines opérations de copie ...


41
"alors qu'il pourrait simplement faire autre chose" - comme? Il doit fonctionner avec des données. Si ces données ne sont pas dans le cache CPU L1, il doit les récupérer dans le cache L2. S'il n'est pas dans le cache L2, il doit être récupéré à partir du L3 (s'il en a un). S'il n'est pas du tout sur les caches en cours, il doit accéder à la mémoire principale. S'il n'est pas dans la mémoire principale ... il doit accéder au disque dur.
Odé le

39
L'ordinateur fait autre chose; le noyau bloque le thread jusqu'à la fin de l'opération d'E / S, laissant ainsi s'exécuter d'autres threads / processus. Mais si tout est en attente sur le disque IO, il n'y a rien d'autre à faire.
Colonel Thirty Two du

6
Vous devez attendre que les programmes atteignent la tour d'E / S et vous envoient leurs frisbees!
Almo

1
@immibis Correct! :)
Almo

2
Les systèmes d'exploitation généralement modernes font ce que vous vous plaignez qu'ils ne font pas - les opérations d'E / S sont envoyées au matériel approprié et des interruptions sont générées par le matériel pour signifier que les opérations sont effectuées. Les processus en attente sur IO sont généralement bloqués pendant l'attente (cela peut être modifié). Si de nombreux processus attendent sur IO et qu'aucun autre processus n'a quoi que ce soit à faire par le CPU, alors il n'y a pas grand-chose à faire. Vous pourriez également vous retrouver dans l'enfer swap mem. L'écriture de programmes pour utiliser efficacement le CPU, la mémoire et les E / S requiert des compétences spéciales, et ce qui est en cours d'exécution affecte également ce qui fonctionne le mieux.
nategoose

Réponses:


19

Les schémas d'E / S que vous décrivez sont couramment utilisés dans les ordinateurs.

pourquoi le CPU doit en fait rester là, ne faisant pratiquement rien d'autre que d'attendre les E / S?

Il s'agit de la méthode d'E / S la plus simple possible: les E / S programmées . De nombreux systèmes embarqués et microprocesseurs bas de gamme n'ont qu'une seule instruction d'entrée et une seule instruction de sortie. Le processeur doit exécuter une séquence explicite d'instructions pour chaque caractère lu ou écrit.

mais il devrait être possible pour le processeur d'attendre ou de vérifier régulièrement, tout en effectuant de nombreuses autres tâches et en ne retournant au processus d'E / S que lorsqu'il est prêt

De nombreux ordinateurs personnels ont d'autres schémas d'E / S. Au lieu d'attendre dans une boucle étroite que le périphérique soit prêt ( attente occupée ), la CPU démarre le périphérique d'E / S lui demandant de générer une interruption lorsqu'elle est terminée ( E / S pilotée par interruption ).

Bien que les E / S déclenchées par interruption soient un pas en avant (par rapport aux E / S programmées), elles nécessitent une interruption pour chaque caractère transmis et c'est cher ...

Par exemple, il pourrait y avoir une sorte de mini processeur qui l'attendrait et fournirait la petite partie des données au processeur réel dès qu'il reviendrait au processus et donc le processus serait répété et nous n'aurions pas pour consacrer pratiquement tout un cœur de processeur au processus de copie de données ...

La solution à de nombreux problèmes consiste à demander à quelqu'un d'autre de faire le travail! :-)

Le contrôleur / puce DMA (accès direct à la mémoire) permet des E / S programmées, mais à quelqu'un d'autre de le faire!

Avec DMA, le CPU n'a qu'à initialiser quelques registres et il est libre de faire autre chose jusqu'à la fin du transfert (et une interruption est déclenchée).

Même le DMA n'est pas totalement gratuit: les périphériques à haute vitesse peuvent utiliser de nombreux cycles de bus pour les références de mémoire et les références de périphériques ( vol de cycle ) et le CPU doit attendre (la puce DMA a toujours une priorité de bus plus élevée).

L'attente des E / S est de 12,1%. Ce serveur possède 8 cœurs (via cat / proc / cpuinfo). Ceci est très proche de (1/8 cœurs = 0,125)

Je pense que cela vient de: Comprendre les E / S disque - quand devriez-vous vous inquiéter?

Eh bien, ce n'est pas étrange: le système (mySQL) doit récupérer toutes les lignes avant de manipuler les données et il n'y a pas d'autres activités.

Ici, il n'y a pas de problème d'architecture informatique / OS. C'est juste la façon dont l'exemple est défini.

Il peut tout au plus s'agir d'un problème de réglage du SGBDR ou d'un problème de requête SQL (index manquant, mauvais plan de requête, mauvaise requête ...)


24

Il est possible d'écrire des E / S asynchrones où vous dites au système d'exploitation d'envoyer un disque en lecture / écriture, puis allez faire autre chose et vérifiez plus tard si c'est fait. C'est loin d'être nouveau. Une méthode plus ancienne utilise un autre thread pour l'IO.

Cependant, cela nécessite que vous ayez quelque chose à faire pendant que cette lecture est en cours d'exécution et vous ne serez pas autorisé à toucher le tampon que vous avez transmis pour le résultat.

Il est également beaucoup plus facile de programmer lorsque vous supposez que tout bloque les E / S.

Lorsque vous appelez une fonction de lecture bloquante, vous savez qu'elle ne reviendra pas tant que quelque chose n'aura pas été lu et immédiatement après que vous pourrez commencer à la traiter.

La boucle de lecture typique est un bon exemple

//variables that the loop uses
char[1024] buffer;
while((read = fread(buffer, 1024, 1, file))>0){
    //use buffer
}

Sinon, vous devez enregistrer l'état actuel de la fonction (généralement sous la forme d'un rappel + pointeur userData) et le transmettre + l'identifiant de l'opération de lecture à une select()boucle de type. Là, si une opération est terminée, elle mappera l'identifiant de l'opération de lecture au rappel + pointeur de données et invoquera le rappel avec des informations sur l'opération terminée.

void callback(void* buffer, int result, int fd, void* userData){
    if(result<=0){
    //done, free buffer and continue to normal processing
    }
    //use buffer

    int readID = async_read(fd, buffer, userData->buff_size);
    registerCallback(readId, callback, userData);
}

Cela signifie également que chaque fonction qui pourrait finir par utiliser cette lecture asynchrone devrait pouvoir gérer une continuation asynchrone. C'est un changement non trivial dans la plupart des programmes, vous demandez aux gens qui essaient de se lancer dans C # asynchrone à ce sujet.


Cependant, les E / S synchrones et les E / S asynchrones ne sont pas la cause du ralentissement général. L'échange de pages est également une opération qui doit attendre sur IO. Le planificateur passera simplement à un autre programme qui n'attend pas sur IO s'il en existe un (l' attente IO est lorsque le processeur est inactif et qu'une opération IO est en attente ).

Le vrai problème est que le disque dur et le CPU utilisent le même canal pour communiquer avec la RAM ; le bus mémoire. Et à moins que vous n'utilisiez RAID, il n'y a qu'un seul disque pour obtenir les données. Cela est aggravé si vous utilisez également une application graphique intensive, la communication avec le GPU interfère également.

En d'autres termes, le véritable goulot d'étranglement se situe probablement dans le matériel plutôt que dans le logiciel.


6
"Cependant, les E / S synchrones et les E / S asynchrones ne sont pas la cause du ralentissement général." Alors, pourquoi avez-vous décidé de vous concentrer sur ce sujet relativement avancé alors que la question porte sur les bases?
svick

1
Vous devriez probablement mentionner quelque chose à propos de DMA
Alec Teal

2
Fait amusant: il existe en fait un mécanisme très ancien qui permet aux programmes de faire autre chose tout en effectuant des E / S sans avoir à gérer les rappels; ça s'appelle des fils .
user253751

2
Bonne discussion sur les avantages / inconvénients de la synchronisation / async IO. Mais êtes-vous sûr que c'est la raison du ralentissement? En général, je trouve que les ralentissements sous forte charge d'E / S sont d'abord dus à un logiciel mal architecturé, ou lorsque ce n'est pas le cas, puis parce que le système utilise un seul disque lent (c'est-à-dire non SSD), et tout essaie d'y accéder simultanément . Je blâmerais un goulot d'étranglement sur la capacité du disque à répondre aux demandes avant de le blâmer sur la saturation du bus mémoire. Vous avez besoin d' un stockage vraiment haut de gamme pour saturer un bus mémoire moderne.
2015

9

Ayez confiance que le traitement d'autres choses en attendant les E / S est assez rationalisé, presque aussi rationalisé que possible. Lorsque vous voyez que votre ordinateur n'attend les E / S que 12,1% du temps, cela signifie qu'il fait en fait beaucoup d'autres choses en parallèle. S'il devait vraiment attendre les E / S sans rien faire d'autre, il attendrait 99,9% du temps, c'est ainsi que les E / S sont lentes.

La seule façon de faire plus de choses en parallèle est de prédire ce que l'utilisateur pourrait vouloir faire ensuite, et nous ne sommes pas encore très bons dans ce genre de prédiction. Donc, si l'utilisateur effectue une opération qui nécessite la lecture d'un secteur particulier à partir du disque dur, et que ce secteur ne se trouve pas déjà dans le cache, alors le système d'exploitation commencera le très long processus de lecture de ce secteur, et il va essayer de voir s'il y a autre chose à faire dans l'intervalle. S'il y a un autre utilisateur qui veut un secteur différent, il mettra également cette demande en file d'attente. À un moment donné, toutes les demandes ont été mises en file d'attente et nous ne pouvons rien faire d'autre que d'attendre que la première d'entre elles soit satisfaite avant de pouvoir continuer. C'est juste une réalité de la vie.

MODIFIER:

Trouver une solution au problème de la façon de faire d'autres choses tout en faisant des E / S serait un exploit admirable, car ce serait en même temps une solution au problème de la façon de faire d'autres choses en veille. Un exploit incroyable qui serait, car cela signifierait que vous trouveriez du travail pour votre ordinateur, alors qu'il n'en a pas.

Vous voyez, c'est ce qui se passe: votre ordinateur est assis 99,99% du temps, sans rien faire. Quand vous lui donnez quelque chose à faire, il s'en va et le fait. Si ce faisant, il doit attendre les E / S, il reste là et attend. S'il a autre chose à faire lors des E / S, il le fait aussi. Mais s'il n'a rien d'autre à faire que les E / S, il doit rester là et attendre que les E / S soient terminées. Il n'y a aucun moyen de contourner cela, sinon en vous inscrivant à SETI @ Home.


Eh bien, l'exemple de 12,1% provenait d'un site Web et l'exemple provenait d'un serveur avec 8 cœurs, l'idée était que presque un cœur entier était juste réservé pour ces opérations, sûr que les autres cœurs étaient libres de faire quoi que ce soit et avec 8 cœurs vous êtes bien, mais que faire si vous n'avez qu'un seul cœur? : /
Arturas M

3
@ArturasM Soit vous avez mal compris ce que dit le site Web, soit l'auteur du site Web a mal compris quelque chose. Un ordinateur avec un seul cœur passerait moins de temps à attendre les E / S (puisque toutes les tâches qui n'attendent pas les E / S, qui s'exécutent sur les autres cœurs tandis qu'un cœur est inactif, devraient toutes s'exécuter sur le seul coeur). Les E / S mettent un certain temps à se produire, que vous l'attendiez ou non - avoir le temps de l'attendre est un symptôme de n'avoir rien d'autre à voir avec ce temps.
Random832

6

Le système d'exploitation (sauf s'il s'agit d'un système embarqué de très bas niveau ou de quelque chose d'exotique similaire) s'en occupe déjà: si votre application doit attendre les E / S, elle se bloquera généralement sur ces E / S et un autre thread ou application deviendra actif. L'ordonnanceur décide lequel.

Ce n'est que s'il n'y a aucun autre thread ou application en cours d'exécution que vous accumulez réellement le temps d'attente. Dans l'article que vous avez cité (merci à @manlio pour le lien), c'est le cas: vous avez 12,1% d'attente contre 87,4% d'inactivité, ce qui signifie qu'un cœur attend que les E / S se terminent tandis que le reste ne fait rien. du tout. Donnez à ce système quelque chose à faire, de préférence plusieurs choses, et le pourcentage d'attente devrait chuter.

L'un des principaux objectifs de la conception d'applications d'aujourd'hui est de garantir que même s'il n'y a qu'une seule application en cours d'exécution, et même si cette application attend à un moment donné des E / S, l'application peut toujours continuer sur un autre morceau de travail. Les threads sont une approche à cela, les E / S non bloquantes une autre, mais cela dépend beaucoup du type de travail que vous faites, si vous pouvez réellement faire quelque chose sans les données que vous attendez.

lorsque vous utilisez Linux, si vous effectuez des tâches d'E / S plus longues, le système d'exploitation devient presque inutilisable jusqu'à ce qu'elles soient terminées.

C'est généralement une indication d'une situation liée aux E / S. J'ose dire que le système ne ralentit pas car il ne peut pas faire assez de traitement CPU. Il est plus probable que cela soit lent car un certain nombre de choses dépendent des données du disque dur, qui est occupé à ce moment-là. Il peut s'agir d'applications que vous souhaitez exécuter mais qui doivent charger leurs fichiers exécutables, fichiers de bibliothèque, icônes, polices et autres ressources. Il peut s'agir d'applications que vous avez déjà en cours d'exécution, mais qui ont échangé une partie de leur mémoire et ont maintenant besoin de l'échanger à nouveau pour continuer. Il peut s'agir d'un démon qui, pour une raison ou une autre, pense qu'il doit non seulement écrire une ligne dans un fichier journal, mais également vider ce fichier journal avant de répondre à une demande.

Vous pouvez utiliser des outils tels que iotoppour voir comment la capacité d'E / S est allouée aux processus et ionicepour définir les priorités d'E / S pour les processus. Par exemple, sur une machine de bureau, vous pouvez classer tous les traitements de données en bloc dans la idleclasse de planification, de sorte que le moment où une application interactive a besoin de bande passante d'E / S, le traitement en bloc soit suspendu jusqu'à ce que l'application interactive soit terminée.


5

Cela dépend de votre code d'application. Je suppose que votre code fonctionne sous Linux.

Vous pouvez utiliser le multithread (par exemple, les pthreads POSIX ) pour que les threads liés au calcul effectuent des calculs tandis que d'autres threads liés aux IO effectuent les IO (et l'attendent). Vous pouvez même avoir votre application exécutant plusieurs processus communiquant avec la communication inter-processus (IPC), voir pipe (7) , fifo (7) , socket (7) , unix (7) , shm_overview (7) , sem_overview (7) , mmap (2) , eventfd (2) et lire Advanced Linux Programming etc ....

Vous pouvez utiliser des E / S non bloquantes , par exemple passer O_NOBLOCKpour ouvrir (2) etc etc etc ...; alors vous devrez interroger (2) et / ou utiliser le SIGIO signal (7) ... et gérer l' EWOULDBLOCKerreur de read (2) etc ...

Vous pouvez utiliser les E / S asynchrones POSIX, voir aio (7)

Pour l'accès aux fichiers, vous pouvez donner des indices sur le cache de page , par exemple avec madvise (2) après mmap (2) et avec posix_fadvise (2) ; voir aussi le readahead spécifique à Linux (2)

Mais vous atteindriez éventuellement un goulot d'étranglement matériel (le bus, la RAM, etc ...). Voir aussi ionice (1)


1

J'ajoute un autre point de vue que d'autres, peut-être controversé:

Son problème typique des systèmes d'exploitation Linux. Décalage spécifique (recherchez "Décalage de la souris Linux"). Windows n'a pas ce problème. J'ai Windows 7 et Linux Mint à double démarrage. Même lorsque vous utilisez intensivement le disque sous Windows, Windows se sent bien, la souris se déplace normalement. Dans Linux opposé, il ne semble pas si lisse et parfois la souris traîne même pendant la navigation Web normale.

C'est probablement parce que la philosophie et l'histoire de ces deux systèmes sont différentes. Windows est depuis le début conçu pour les utilisateurs ordinaires, ses systèmes d'exploitation principalement graphiques. Et pour les utilisateurs de Windows, un comportement système non fluide et l'arrêt de la souris signalent que quelque chose ne va pas. Les programmeurs de Microsofts ont donc travaillé dur pour concevoir l'ensemble du système afin de minimiser les cas où les systèmes semblent lents. À l'opposé, Linux n'est pas initialement un système graphique, le bureau n'est qu'un ajout tiers ici. Et Linux est principalement conçu pour les pirates utilisant la ligne de commande. Faites avancer les choses. Linux n'est tout simplement pas conçu pour un comportement fluide, les sentiments n'ont pas d'importance ici.

Remarque: je ne dis pas que Windows est meilleur que Linux, je dis simplement qu'ils ont une philosophie globale différente, ce qui dans un environnement complexe peut conduire à un comportement / sentiment de haut niveau différent de ces systèmes.


Le retard de la souris Linux pourrait probablement être évité ou atténué par une configuration minutieuse du système (c'est-à-dire en utilisant nice& ionicesur des processus affamés). Et j'utilise Linux et je n'ai presque jamais connu ce retard de souris Linux (sauf lors de la surcharge de mon ordinateur ...)
Basile Starynkevitch

BTW, Linux est principalement un système d'exploitation serveur.
Basile Starynkevitch

Je noterai que j'ai rencontré un retard sur l'interface utilisateur et la souris sur Windows 7, même pendant les périodes où le Gestionnaire des tâches et le Moniteur de ressources indiquaient une faible utilisation de la mémoire et une faible activité du processeur et du disque.
8bittree
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.