Perché il completamento del blocco I / O vuole così tanto tempo per l'attraversamento CPU?
-
19-09-2019 - |
Domanda
Sto cercando di spremere il massimo delle prestazioni di un driver Linux per blocco di un dispositivo di storage high-end. Un problema che mi ha un po 'stumped al momento è questo: se un'attività utente avvia un'operazione di I / O (lettura o scrittura) da una CPU, e l'interrupt dispositivo avviene su un'altra CPU, io incorrere circa 80 microsecondi di ritardo prima l'operazione riprende l'esecuzione.
posso vedere questo utilizzando O_DIRECT contro il dispositivo di blocco grezzo, quindi questo non è cache della pagina o filesystem- correlati. Il driver utilizza make_request
ricevere le operazioni, quindi ha nessuna coda richiesta e non utilizzare qualsiasi kernel di I / O scheduler (dovrete avere fiducia in me, è il modo più veloce in questo modo).
io posso dimostrare a me stesso che il problema si verifica tra chiamando bio_endio
su una CPU e la mansione riprogrammato su un'altra CPU. Se il compito è sulla stessa CPU, inizia molto rapidamente, e se il compito è su un'altra CPU fisica, ci vuole molto più tempo - di solito circa 80 microsecondi più visualizzata sul sistema di test corrente (x86_64 su Intel 5520 chipset [NUMA] ).
Posso raddoppiare immediatamente le mie prestazioni impostando il processo e l'IRQ cpu affinità con la stessa CPU fisico, ma questo non è un buon lungo termine solution-- io preferirei essere in grado di ottenere buone prestazioni, non importa dove l'I / Os origine. E ho un solo IRQ modo che io possa guidare solo per una CPU alla volta -. Non va bene se molti thread sono in esecuzione su molte CPU
Posso vedere questo problema su kernel da CentOS 5.4 del 2.6.18 alla 2.6.32 linea principale.
Quindi la domanda è: perché ci vuole più tempo per il processo utente a riprendere, se ho chiamato bio_endio
da un altro CPU? E 'questo un problema di pianificazione? E c'è un modo per eliminare o ridurre il ritardo?
Soluzione 4
Sembra che ho frainteso il problema un po ': sembra essere correlato alla cache miss; quando la gestione di allarmi CPU non è stata la CPU che ha iniziato la I / O, la CPU può colpire utilizzo del 100%, e poi tutto rallenta, dando l'impressione che ci sia un lungo ritardo la comunicazione tra le CPU.
Grazie a tutti per le loro idee.
Altri suggerimenti
Se hai finito il tuo I / O su un particolare della CPU, allora questo processore è immediatamente libero di iniziare a lavorare su un nuovo thread - se hai finito il tuo I / O sullo stesso processore come il filo della richiesta, poi la prossima thread è probabile che sia quello che ho finito / o per.
D'altra parte, se hai finito su un processore diverso, il filo che ha richiesto l'I / O non arrivare a eseguire immediatamente - si deve aspettare fino a quando tutto quello che è attualmente in esecuzione termina il suo quantum o comunque cede la CPU <. / p>
Per quanto ho capito.
Potrebbe essere solo la latenza inerente rilasciare l'IPI dalla CPU che ha completato la bio alla CPU dove l'attività viene pianificata - Per testare questo, provare l'avvio con idle=poll
Questa patch è stato appena pubblicato LKML, attuazione QUEUE_FLAG_SAME_CPU
nello strato dispositivo di blocco, che viene descritta come:
Aggiungi una bandiera per fare richiesta completa su cpu in cui viene presentata richiesta. Il Bandiera implica
QUEUE_FLAG_SAME_COMP
. Di di default, è fuori.
Sembra che potrebbe essere proprio quello che serve ...