Perché dobbiamo aspettare I / O?

27

È risaputo che le operazioni del disco sono lente e conosciamo i motivi per cui sono lenti. Quindi la domanda qui è perché dobbiamo aspettare I / O o perché esiste una cosa come IOWait, ecc.?

Voglio dire che ho notato che quando esegui alcune attività di I / O in background, il tuo computer diventa molto più lento, ho notato soprattutto che quando usi Linux, se lo stai facendo più a lungo / O, il sistema operativo diventa quasi inutilizzabile fino al completamento.

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

I/O wait is 12.1%. This server has 8 cores (via cat /proc/cpuinfo). This is very close to (1/8 cores = 0.125)

Quindi in pratica significa che sta rallentando il computer molto, perché è così? Voglio dire OK, ora il computer normale sono almeno 2 core, a volte 4 o a volte ne hanno di più a causa di hyperthreading o qualcosa del genere. Ma ora la domanda è: perché la CPU deve effettivamente rimanere lì, praticamente non sta facendo altro che aspettare l'IO? Intendo l'idea di base o l'architettura del processo di gestione, ora non so se è il sistema operativo a essere responsabile di questo, o si tratta di hardware, ma dovrebbe essere possibile per la CPU da attendere o per controlla regolarmente, mentre esegui molte altre attività e torna al processo di I / O solo quando è pronto. Infatti, se è un compito così difficile e la CPU dovrebbe aspettare, perché allora non è gestito in modo più efficiente dall'hardware? Ad esempio, potrebbe esserci una sorta di mini CPU che dovrebbe solo attendere e fornire la piccola parte di dati alla CPU reale non appena ritorna al processo e quindi il processo verrebbe ripetuto e non avremmo dedicare praticamente un intero core della CPU per il processo di copia dei dati ... o sarei io quello che dovrebbe inventare questo genere di cose e ottenere un premio nobel per quello? : S

Ora ok, lo sto davvero mettendo da un punto di vista degli osservatori e non ho approfondito l'argomento, ma davvero non capisco perché la CPU debba lavorare con la velocità dell'HDD, mentre potrebbe solo fare qualcos'altro e tornare su HDD una volta pronto. L'idea non è quella di velocizzare l'applicazione che ha bisogno dell'operazione IO o del processo di copia o altro, ma l'idea è di influenzare minimamente il consumo della CPU durante l'esecuzione di tale operazione, in modo che il sistema operativo possa utilizzarlo per altri processi e l'utente non dovrebbe sentire un ritardo generale del computer quando si eseguono alcune operazioni di copia ...

    
posta Arturas M 08.09.2015 - 14:43
fonte

6 risposte

19

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

why the CPU actually has to stay there, practically not doing anything else than just waiting for IO?

Questo è il metodo I / O più semplice possibile: I / O programmato . Molti sistemi embedded e microprocessori di fascia 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.

but it should be made possible for the cpu to wait or to check regularly, while actually performing lots of other tasks and only going back to the IO process when it's ready

Molti personal computer hanno altri schemi di I / O. Invece di aspettare in un ciclo stretto affinché il dispositivo sia pronto ( busy waiting ), la CPU avvia il dispositivo I / O chiedendo di generare un interrupt quando viene eseguito ( interrupt guidato I / O ).

Sebbene I / O con interrupt sia un passo avanti (rispetto a I / O programmato), richiede un interrupt per ogni carattere trasmesso ed è costoso ...

Like for instance there could be some kind of mini cpu which would just wait for it and deliver the small part of data to the real cpu as soon as it gets back to the process and so the process would be repeated and we wouldn't have to practically dedicate a whole cpu core for the data copy process...

La soluzione a molti problemi sta nell'avere qualcun altro a fare il lavoro! : -)

Il controller / chip DMA (Direct Memory Access) consente l'I / O programmato ma con qualcun altro che lo fa!

Con DMA la CPU deve solo inizializzare alcuni registri ed è libero di fare qualcos'altro fino a quando il trasferimento non è terminato (e viene generato un interrupt).

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

I/O wait is 12.1%. This server has 8 cores (via cat /proc/cpuinfo). This is very close to (1/8 cores = 0.125)

Penso che questo provenga da: Informazioni su I / O su disco - quando dovresti preoccuparti?

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 / sistema operativo del computer. È proprio come è impostato l'esempio.

Al massimo potrebbe essere un problema di ottimizzazione RDBMS o un problema di query SQL (indice mancante, piano di query non valido, query non valida ...)

    
risposta data 08.09.2015 - 15:39
fonte
24

È possibile scrivere un IO asincrono in cui si dice al sistema operativo di inviare un disco in lettura / scrittura e poi fare qualcos'altro e poi controllare se è fatto. È lontano dal nuovo. Un metodo più vecchio 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 passato per il risultato.

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

Quando chiami una funzione di lettura di blocco che conosci non verrà restituita fino a quando qualcosa è stato letto e immediatamente dopo puoi iniziare l'elaborazione su di esso.

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
}

Altrimenti è necessario salvare lo stato della funzione corrente (di solito sotto forma di callback + puntatore userData) e passarlo + identificativo dell'operazione di lettura su un ciclo di tipo select() . Lì, se un'operazione è finita, assocerà l'identificatore dell'operazione di lettura al callback + puntatore dati e invocherà il callback con le informazioni dell'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'I / O sincrono rispetto all'IO asincrono non è la causa del rallentamento generale. Anche lo scambio di pagine è un'operazione che deve attendere su IO. Lo scheduler passerà a un altro programma che non è in attesa su IO se lo è ( L'attesa IO è quando il processore è inattivo e c'è una operazione IO in attesa ).

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 tu non stia utilizzando RAID, c'è solo un singolo disco da cui ottenere i dati. Ciò è peggiorato se si utilizza anche un'applicazione grafica intensiva, quindi la comunicazione con la GPU interferirà anche.

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

    
risposta data 08.09.2015 - 15:35
fonte
9

Abbi fede nel fatto che l'elaborazione di altre cose durante l'attesa per l'I / O è 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 in realtà sta facendo molte altre cose in parallelo. Se dovesse davvero attendere l'I / O senza fare altro, sarebbe il 99,9% del tempo, è così lento I / O.

L'unico modo per fare più cose in parallelo è predire ciò che l'utente potrebbe voler fare dopo, e non siamo ancora molto bravi in quel tipo di previsione. Quindi, se l'utente esegue un'operazione che richiede la lettura di un particolare settore dal disco rigido e che il settore non è già presente nella cache, il sistema operativo inizierà il lunghissimo processo di lettura di quel settore, e cercherò di vedere se c'è qualcos'altro da fare nel frattempo. Se c'è un altro utente che vuole un settore diverso, accoderà anche quella richiesta. Ad un certo punto, tutte le richieste sono state accodate, e non c'è nulla che possiamo fare se non aspettare che il primo sia soddisfatto prima di poter procedere. È solo un dato di fatto.

EDIT:

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

Vedi, questo è 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 I / O, si siede lì e aspetta. Se ha qualcos'altro da fare mentre faccio I / O, lo fa anche questo. Ma se non ha altro da fare oltre all'I / O, allora deve sedersi e attendere che l'I / O sia completato. Non c'è modo di aggirare questo problema, a parte iscrivendosi a SETI @ Home.

    
risposta data 08.09.2015 - 15:38
fonte
6

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

È solo se c'è no altro thread o applicazione che potrebbe essere in esecuzione che stai effettivamente accumulando tempo di attesa. In l'articolo che hai citato ( grazie a @manlio per il collegamento), questo è il caso: hai il 12,1% di attesa in attesa dell'87,4% inattivo, il che significa che un core è in attesa del completamento dell'I / O mentre il resto non sta facendo nulla. Dare a quel sistema qualcosa da fare, preferibilmente più cose e la percentuale di attesa dovrebbe calare.

Uno degli obiettivi principali della progettazione delle applicazioni di oggi è garantire che anche se è in esecuzione una sola applicazione, e anche se quella singola applicazione è a un certo punto in attesa di I / O, l'applicazione può continuare su qualche altro blocco di lavoro. I thread sono un approccio a questo, un altro I / O non bloccante, ma dipende molto dal tipo di lavoro che stai facendo, indipendentemente dal fatto che tu possa effettivamente fare qualcosa senza i dati che stai aspettando.

when using Linux, if you're doing some longer I/O tasks, the OS becomes almost unusable until they are completed.

In genere è un'indicazione di una situazione legata all'I / O. Oserei dire che il sistema non sta rallentando perché non può fare abbastanza elaborazione della CPU. Più probabilmente è lento perché un certo numero 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 file eseguibili, i file di libreria, le icone, i caratteri e altre risorse. Potrebbero essere le applicazioni che hai già in esecuzione, ma che hanno scambiato parte della loro memoria e ora devono essere nuovamente inserite per procedere. Potrebbe trattarsi di un demone che, per una ragione o per l'altra, pensa che non solo deve scrivere una riga in un file di log, ma in realtà svuotare quel file di log prima di rispondere ad alcune richieste.

Puoi usare strumenti come iotop per vedere come la capacità di I / O è allocata ai processi, e ionice per impostare le priorità di I / O per i processi. Ad esempio, su una macchina desktop, è possibile classificare tutta l'elaborazione di dati di massa sulla classe di pianificazione idle , in modo che nel momento in cui un'applicazione interattiva richiede larghezza di banda I / O, l'elaborazione di massa viene sospesa fino all'applicazione interattiva.

    
risposta data 08.09.2015 - 19:41
fonte
5

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

Potresti usare multi- threading (ad esempio POSIX pthreads ) per fare in modo che i thread legati all'elaborazione eseguano alcuni calcoli mentre altri thread legati all'IO stanno eseguendo l'IO (e aspettandolo). Potresti persino avere la tua applicazione in esecuzione diversi processi che comunicano con comunicazione inter-processo (IPC), vedi pipe (7) , fifo (7) , socket (7) , unix(7) , shm_overview (7) , sem_overview (7) , mmap (2) , eventfd (2) e leggi Programmazione Linux avanzata etc ....

Potresti utilizzare IO non bloccante , ad es. passare O_NOBLOCK a aperto (2) ecc ecc ecc ...; quindi dovrai sondare (2) e / o usare SIGIO < a href="http://man7.org/linux/man-pages/man7/signal.7.html"> signal (7) ... e gestisce l'errore EWOULDBLOCK da read(2) ecc ...

Potresti usare POSIX asynchronous IO, vedi aio (7)

Per l'accesso ai file, puoi fornire suggerimenti sulla cache della pagina , ad es. con madvise (2) dopo mmap(2) e con posix_fadvise (2) ; guarda anche lo specifico readahead (2)

per Linux

Ma alla fine si raggiungerà un collo di bottiglia hardware (bus, RAM, ecc.). Vedi anche ionice (1)

    
risposta data 08.09.2015 - 15:35
fonte
1

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

Il tipico problema dei sistemi operativi Linux. In ritardo specifico (ricerca di "Linux mouse lag"). Windows non ha questo problema. Ho il doppio avvio di Windows 7 e Linux Mint. Anche quando si eseguono operazioni intensive su disco in Windows, Windows si sente morbido, il mouse si muove normalmente. In Linux, contrariamente a ciò, non sembra che fumi e mouse a volte siano in ritardo anche durante la normale navigazione sul Web.

È probabilmente dovuto alla diversa filosofia e storia di questi due sistemi. Fin dall'inizio, Windows è progettato per gli utenti ordinari, i suoi sistemi di operazioni principalmente grafici. E per gli utenti di Windows, il comportamento non regolare del sistema e lo spostamento del mouse in movimento indicano che qualcosa non va. Quindi i programmatori di Microsofts hanno lavorato sodo per progettare l'intero sistema per minimizzare i casi quando i sistemi si sentono lenti. Al contrario, Linux non è inizialmente un sistema grafico, desktop è solo un'aggiunta di terze parti qui. E Linux è progettato principalmente per gli hacker che usano la riga di comando. Fai le cose fatte filosofia. Linux semplicemente non è progettato per un buon comportamento in mente, i sentimenti non contano qui.

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

    
risposta data 29.09.2015 - 22:06
fonte

Leggi altre domande sui tag