Perché dobbiamo aspettare l'I / O?


28

È sempre noto che le operazioni su disco sono lente e conosciamo i motivi per cui sono lente. Quindi la domanda qui è perché dobbiamo aspettare l'I / O o perché esiste qualcosa come IOWait, ecc.?

Voglio dire, ho notato che quando si eseguono alcune attività di I / O in background, il computer in pratica diventa molto più lento, in particolare ho notato che quando si utilizza Linux, se si eseguono attività di I / O più lunghe , il sistema operativo diventa quasi inutilizzabile fino al completamento.

In effetti, ho anche trovato questo argomento in un articolo, c'è uno snippet:

L'attesa I / O è del 12,1%. Questo server ha 8 core (via cat / proc / cpuinfo). Questo è molto vicino a (1/8 core = 0.125)

Quindi in pratica significa che sta rallentando MOLTO il computer, perché? Voglio dire OK, ora i normali computer sono almeno 2 core, a volte 4 o a volte ne hanno di più a causa dell'hyperthreading o qualcosa del genere. Ma ora la domanda è: perché la CPU deve effettivamente rimanere lì, praticamente non facendo altro che aspettare semplicemente IO? Intendo l'idea o l'architettura di base della gestione del processo, ora non so se è il sistema operativo a essere responsabile di ciò, o dipende dalla parte hardware, ma dovrebbe essere possibile che la CPU aspetti o controllare regolarmente, mentre in realtà esegue molte altre attività e torna al processo di I / O solo quando è pronto. In effetti, se è un compito così difficile e la CPU dovrebbe aspettare, perché non lo è quello gestito dall'hardware in modo più efficiente allora? Ad esempio, potrebbe esserci una sorta di mini cpu che aspetterebbe e consegnerebbe la piccola parte di dati alla cpu reale non appena tornerà al processo e quindi il processo si ripeterebbe e non avremmo di dedicare praticamente un intero nucleo della CPU per il processo di copia dei dati ... O sarei io quello che dovrebbe inventare questo tipo di cose e ottenere un premio nobel per quello? :S

Ora va bene, lo sto davvero mettendo ora dal punto di vista degli osservatori e non ho davvero approfondito l'argomento, ma non capisco davvero perché la cpu debba lavorare con la velocità dell'HDD, mentre potrebbe semplicemente fai qualcos'altro e torna all'HDD una volta che è pronto. L'idea non è quella di accelerare l'applicazione che ha bisogno di quell'operazione di I / O o del processo di copia o altro, ma l'idea è di influenzare solo minimamente il consumo di CPU durante l'esecuzione di tale operazione, in modo che il sistema operativo possa utilizzarlo per altri processi e l'utente non dovrei avvertire un ritardo generale del computer quando si eseguono alcune operazioni di copia ...


41
"mentre potrebbe semplicemente fare qualcos'altro" - come? Deve funzionare con i dati. Se i dati non si trovano nella cache L1 della CPU, è necessario recuperarli dalla cache L2. Se non è nella cache L2, deve recuperare da L3 (se ne ha uno). Se non è affatto nelle cache on die, deve accedere alla memoria principale. Se non nella memoria principale ... è necessario accedere all'HDD.
Oded,

39
Il computer fa qualcos'altro; il kernel blocca il thread fino al completamento dell'operazione IO, lasciando funzionare altri thread / processi. Ma se tutto è in attesa su IO del disco, non c'è altro da fare.
Colonnello trentadue

6
Devi aspettare che i programmi raggiungano la torre I / O e ti mandino i loro frisbee!
Almo,

1
@immibis Correct! :)
Almo,

2
In genere i sistemi operativi moderni fanno quello che ti lamenti che non fanno: le operazioni di I / O vengono inviate all'hardware appropriato e gli interruzioni vengono generati dall'hardware per indicare che le operazioni sono state eseguite. I processi in attesa su IO sono generalmente bloccati durante l'attesa (questo può essere modificato). Se molti processi sono in attesa su IO e nessun altro processo ha nulla da fare per la CPU, non c'è molto da fare. Potresti anche finire in Mem-swap Hell. Scrivere programmi per utilizzare in modo efficiente CPU, memoria e I / O richiede competenze speciali e cos'altro è in esecuzione influisce anche su ciò che funziona meglio.
nategoose,

Risposte:


19

Gli schemi I / O che stai descrivendo sono attualmente in uso nei computer.

perché la CPU deve effettivamente rimanere lì, praticamente non facendo altro che aspettare semplicemente IO?

Questo è il metodo I / O più semplice possibile: I / O programmato . Molti sistemi embedded e microprocessori di fascia bassa / bassa hanno solo una singola istruzione di input e una singola istruzione di output. Il processore deve eseguire una sequenza esplicita di istruzioni per ogni carattere letto o scritto.

ma dovrebbe essere possibile per la cpu attendere o controllare regolarmente, mentre in realtà esegue molte altre attività e torna al processo di I / O solo quando è pronto

Molti personal computer hanno altri schemi I / O. Invece di attendere in un ciclo stretto che il dispositivo sia pronto ( attesa di occupato ), la CPU avvia il dispositivo I / O chiedendogli di generare un interruzione al termine ( I / O guidato da interrupt ).

Sebbene l'I / O guidato da interrupt sia un passo avanti (rispetto agli I / O programmati), richiede un interrupt per ogni carattere trasmesso ed è costoso ...

Ad esempio, potrebbe esserci una sorta di mini cpu che aspetterebbe e consegnerebbe la piccola parte di dati alla cpu reale non appena tornerà al processo e quindi il processo si ripeterebbe e non avremmo dedicare praticamente un intero nucleo della cpu al processo di copia dei dati ...

La soluzione a molti problemi sta nel chiedere a qualcun altro di fare il lavoro! :-)

Il controller / chip DMA (accesso diretto alla memoria) consente l'I / O programmato ma è necessario farlo eseguire da qualcun altro!

Con DMA la CPU deve solo inizializzare alcuni registri ed è libero di fare qualcos'altro fino al termine del trasferimento (e viene generato un interrupt).

Anche il DMA non è totalmente gratuito: i dispositivi ad alta velocità possono utilizzare molti cicli di bus per riferimenti di memoria e riferimenti di dispositivi ( furto di cicli ) e la CPU deve attendere (il chip DMA ha sempre una priorità di bus più elevata).

L'attesa I / O è del 12,1%. Questo server ha 8 core (via cat / proc / cpuinfo). Questo è molto vicino a (1/8 core = 0.125)

Penso che questo provenga da: Comprensione dell'I / O del disco - quando dovresti essere preoccupato?

Beh, non è strano: il sistema (mySQL) deve recuperare tutte le righe prima di manipolare i dati e non ci sono altre attività.

Qui non c'è un problema di architettura del computer / sistema operativo. È proprio come viene impostato l'esempio.

Al massimo potrebbe essere un problema di ottimizzazione RDBMS o un problema di query SQL (indice mancante, piano di query errato, query errata ...)


24

È possibile scrivere IO asincrono in cui si dice al sistema operativo di inviare un disco in lettura / scrittura e quindi fare qualcos'altro e poi verificare se è fatto. È tutt'altro che nuovo. Un metodo precedente utilizza un altro thread per l'IO.

Tuttavia ciò richiede che tu abbia qualcosa da fare mentre quella lettura è in esecuzione e non ti sarà permesso di toccare il buffer che hai passato per il risultato.

È anche molto più facile programmare quando si presume che tutto stia bloccando IO.

Quando chiami una funzione di lettura bloccante sai che non tornerà fino a quando qualcosa non è stato letto e subito dopo puoi iniziare l'elaborazione su di essa.

Il tipico ciclo di lettura è un buon esempio

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

In caso contrario, è necessario salvare lo stato della funzione corrente (in genere sotto forma di callback + puntatore userData) e passarlo + identificatore dell'operazione di lettura su un select()ciclo di tipo. Se un'operazione è terminata, mapperà l'identificatore dell'operazione di lettura sul puntatore callback + data e invocherà la callback con le informazioni sull'operazione completata.

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);
}

Questo significa anche che ogni funzione che potrebbe finire per usare quella lettura asincrona dovrebbe essere in grado di gestire una continuazione asincrona. Questo è un cambiamento non banale nella maggior parte dei programmi, chiedi alle persone che cercano di entrare in C # asincrono a riguardo.


Tuttavia, l'IO sincrono e l'IO asincrono non sono la causa del rallentamento generale. Anche lo scambio di pagine è un'operazione che deve attendere su IO. Lo scheduler passerà semplicemente a un altro programma che non è in attesa su IO se presente (l' attesa IO è quando il processore è inattivo e c'è un'operazione di IO in sospeso ).

Il vero problema è che sia l'hard disk che la CPU usano lo stesso canale per comunicare con la RAM ; il bus di memoria. E a meno che non si stia utilizzando RAID, esiste un solo disco per ottenere i dati. Ciò peggiora se si utilizza anche un'applicazione ad alta intensità grafica, quindi anche la comunicazione con la GPU interferirà.

In altre parole, il vero collo di bottiglia è probabilmente nell'hardware piuttosto che nel software.


6
"Comunque IO sincrono vs IO asincrono non è la causa del rallentamento generale." Quindi perché hai deciso di concentrarti su questo argomento relativamente avanzato quando la domanda riguarda le basi?
svick

1
Probabilmente dovresti menzionare qualcosa su DMA
Alec Teal,

2
Curiosità: esiste in realtà un meccanismo molto vecchio che consente ai programmi di fare qualcos'altro mentre eseguono operazioni di I / O senza dover gestire i callback; si chiama thread .
user253751

2
Buona discussione dei pro / contro della sincronizzazione / asincrono IO. Ma sei sicuro che sia la ragione del rallentamento? Generalmente trovo che i rallentamenti sotto carico di IO elevati siano innanzitutto dovuti a software scarsamente progettato o, in caso contrario, perché il sistema utilizza un singolo disco lento (cioè non SSD) e tutto tenta di accedervi contemporaneamente . Incolperei un collo di bottiglia sulla capacità del disco di soddisfare le richieste prima di incolpare la saturazione del bus di memoria. È necessario veramente storage high-end per saturare un moderno bus di memoria.
aroth,

9

Confida che l'elaborazione di altre cose durante l'attesa dell'I / O sia abbastanza semplificata, il più vicino possibile. Quando vedi che il tuo computer è in attesa di I / O solo il 12,1% delle volte, significa che sta effettivamente facendo molte altre cose in parallelo. Se dovesse davvero aspettare l'I / O senza fare altro, starebbe aspettando il 99,9% delle volte, ecco quanto è lento l'I / O.

L'unico modo per fare più cose in parallelo è prevedere ciò che l'utente potrebbe voler fare in seguito, e non siamo ancora molto bravi in ​​quel tipo di previsione. Pertanto, se l'utente esegue un'operazione che richiede la lettura di un determinato settore dal disco rigido e tale settore non si trova già nella cache, il sistema operativo avvierà il lunghissimo processo di lettura di quel settore e proverò a vedere se c'è qualcos'altro da fare nel frattempo. Se c'è un altro utente che desidera un settore diverso, accoderà anche quella richiesta. Ad un certo punto, tutte le richieste sono state messe in coda e non possiamo fare altro che attendere che la prima sia soddisfatta prima di poter procedere. È solo un dato di fatto.

MODIFICARE:

Trovare una soluzione al problema di come fare altre cose mentre si fa I / O sarebbe un'impresa ammirevole, perché allo stesso tempo sarebbe una soluzione al problema di come fare altre cose mentre inattivo. Una prodezza sorprendente che sarebbe, perché significherebbe che troveresti lavoro da fare per il tuo computer, mentre non ne ha.

Vedi, è quello che sta succedendo: il tuo computer è solo seduto il 99,99% delle volte, senza fare nulla. Quando gli dai qualcosa da fare, va e lo fa. Se in tal modo deve attendere l'I / O, si siede lì e aspetta. Se ha qualcos'altro da fare durante l'I / O, lo fa anche quello. Ma se non ha nient'altro da fare oltre all'I / O, deve sedersi lì e attendere il completamento dell'I / O. Non c'è modo di aggirare questo, se non quello di iscriversi a SETI @ Home.


Bene, l'esempio del 12,1% proveniva da un sito Web e l'esempio è stato preso da un server con 8 core, l'idea era che quasi un intero core fosse riservato a quelle operazioni, sicuro che gli altri core fossero liberi di fare qualsiasi cosa e con 8 core sei benestante, ma cosa succede se hai un solo core? : /
Arturas M

3
@ArturasM O hai frainteso quello che dice il sito web, o l'autore del sito ha frainteso qualcosa. Un computer con un solo core passerebbe meno tempo in attesa di I / O (poiché tutte le attività che non sono in attesa di IO, che sono in esecuzione su altri core mentre un core rimane inattivo, dovrebbero essere eseguite sul singolo nucleo). L'I / O richiede un certo periodo di tempo, indipendentemente dal fatto che tu lo aspetti o meno: avere il tempo di aspettare è un sintomo di non avere nient'altro a che fare con quel tempo.
Casuale 832

6

Il sistema operativo (a meno che non sia un sistema incorporato di livello molto basso o qualcosa di simile esotico) si occupa già di questo: se l'applicazione deve attendere l'I / O, di solito si bloccherà su quell'I / O e qualche altro thread o applicazione diventerà attivo. Lo scheduler decide quale.

E 'solo se non v'è nessun altro thread o applicazione che potrebbe essere in esecuzione che si sta effettivamente accumulare tempo di attesa. In questo articolo che hai citato (grazie al @manlio per il link), che è il caso: si dispone di 12,1% in attesa contro il 87,4% di inattività, il che significa che un core è in attesa di I / O a completare, mentre il resto non sta facendo niente affatto. Dai a quel sistema qualcosa da fare, preferibilmente più volte, e la percentuale di attesa dovrebbe scendere.

Uno degli obiettivi più importanti della progettazione delle applicazioni odierne è garantire che anche se sia in esecuzione un'unica applicazione e anche se quella singola applicazione è in qualche modo in attesa di I / O, l'applicazione può comunque continuare su qualche altro pezzo di lavoro. I thread sono un approccio a questo, I / O non bloccante un altro, ma dipende molto dal tipo di lavoro che stai facendo, se puoi effettivamente fare qualcosa senza i dati che stai aspettando.

quando si utilizza Linux, se si stanno eseguendo attività I / O più lunghe, il sistema operativo diventa quasi inutilizzabile fino al completamento.

Questo è in genere un'indicazione di alcune situazioni associate a I / O. Oserei dire che il sistema non sta rallentando perché non può fare abbastanza elaborazione della CPU. Più probabilmente è lento perché una serie di cose dipende dai dati dell'HDD, che è occupato in quel momento. Potrebbe trattarsi di applicazioni che si desidera eseguire ma che devono caricare i loro file eseguibili, file di libreria, icone, caratteri e altre risorse. Potrebbero essere le applicazioni che hai già in esecuzione, ma che hanno scambiato parte della loro memoria e che ora hanno bisogno di essere nuovamente scambiate per procedere. Potrebbe essere un demone che, per un motivo o per l'altro, pensa che non debba solo scrivere una riga in un file di registro, ma effettivamente svuotare quel file di registro prima di rispondere ad una richiesta.

È possibile utilizzare strumenti come iotopvedere come viene allocata la capacità di I / O ai processi e ioniceimpostare priorità di I / O per i processi. Ad esempio su un computer desktop, è possibile classificare tutta l'elaborazione di dati in idleblocco nella classe di pianificazione, in modo che nel momento in cui un'applicazione interattiva necessita della larghezza di banda I / O, l'elaborazione in blocco viene sospesa fino al completamento dell'applicazione interattiva.


5

Dipende dal codice dell'applicazione. Suppongo che il tuo codice sia in esecuzione su Linux.

È possibile utilizzare il multi- threading (ad es. Pthreads POSIX ) per fare in modo che i thread associati al calcolo eseguano alcuni calcoli mentre altri thread associati all'IO stanno eseguendo l'IO (e lo stanno aspettando). È anche possibile che l'applicazione esegua diversi processi che comunicano con la comunicazione tra processi (IPC), vedere pipe (7) , fifo (7) , socket (7) , unix (7) , shm_overview (7) , sem_overview (7) , mmap (2) , eventfd (2) e leggi Advanced Linux Programming ecc ....

È possibile utilizzare IO non bloccanti , ad esempio pass O_NOBLOCKto open (2) etc etc etc ...; quindi dovrai eseguire il polling (2) e / o usare il SIGIO segnale (7) ... e gestire l' EWOULDBLOCKerrore dalla lettura (2) ecc ...

È possibile utilizzare IO asincrono POSIX, vedere aio (7)

Per l'accesso ai file, è possibile fornire suggerimenti alla cache della pagina , ad esempio con madvise (2) dopo mmap (2) e con posix_fadvise (2) ; vedi anche readahead specifico per Linux (2)

Ma alla fine potresti raggiungere alcuni colli di bottiglia hardware (il bus, la RAM, ecc ...). Vedi anche ionice (1)


1

Aggiungo altro punto di vista rispetto ad altri, forse controverso:

Il suo tipico problema dei sistemi operativi Linux. In ritardo specifico (Cerca "ritardo del mouse Linux"). Windows non ha questo problema. Ho doppio avvio Windows 7 e Linux Mint. Anche quando si esegue un intenso funzionamento del disco in Windows, Windows sembra regolare, il mouse si muove normalmente. In Linux al contrario non sembra così smoot e il mouse a volte in ritardo anche durante la normale navigazione web.

Probabilmente è perché diversa filosofia e storia di questi due sistemi. Fin dall'inizio Windows è progettato per gli utenti ordinari, i suoi sistemi operativi principalmente grafici. E per gli utenti Windows, il comportamento non regolare del sistema e l'arresto del mouse indicano che qualcosa non va. Quindi i programmatori di Microsoft hanno lavorato duramente per progettare l'intero sistema per ridurre al minimo i casi in cui i sistemi si sentono lenti. Al contrario, Linux non è inizialmente un sistema grafico, il desktop è solo un'aggiunta di terze parti qui. E Linux è principalmente progettato per gli hacker che usano la riga di comando. Filosofia. Linux non è semplicemente progettato per un comportamento regolare in mente, i sentimenti non contano qui.

Nota: non sto dicendo che Windows sia migliore di Linux, dico semplicemente che hanno una diversa filosofia generale, che in un ambiente complesso può portare a comportamenti / sentimenti di alto livello diversi di questi sistemi.


Il ritardo del mouse Linux potrebbe probabilmente essere evitato o ridotto da un'attenta configurazione del sistema (ad es. Utilizzando nicee ionicesui processi affamati). E io uso Linux e non ho quasi mai sperimentato quel ritardo del mouse Linux (tranne quando sovraccarico il mio computer ...)
Basile Starynkevitch

A proposito, Linux è principalmente un sistema operativo server.
Basile Starynkevitch,

Noterò che ho riscontrato un'interruzione dell'interfaccia utente e del mouse su Windows 7, anche durante i periodi in cui Task Manager e Resource Monitor indicavano un utilizzo di memoria insufficiente e una scarsa attività della CPU e del disco.
8
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.