2012-11-20 21 views
8

Sto sollevando una meraviglia per quanto riguarda le istruzioni MONITOR-MWAIT vs HLT. Entrambi interrompono il processore, entrambi si attivano su vari trigger esterni (interrupt, ecc.).MWAIT vs HALT in termini di efficienza

Nei miei esperimenti, HLT e la funzione MWAIT quasi la stessa, quando prende in considerazione:

  • Se siete non lo scheduler del sistema operativo, un semplice ciclo con le istruzioni di cui sopra, saranno interrotti abbastanza rapidamente, e poiché MWAIT richiede di ricontrollare la condizione tra MONITOR e MWAIT, qual è la differenza? (Quello che sto chiedendo è, perché non usare HLT al primo posto, e risparmiando il dolore dell'allocazione dell'area di tracciamento (che, se non accuratamente configurato, evita il meccanismo mon/mwait e lo trasforma in un NOP), dal momento che se tu? non è il programmatore del sistema operativo, non c'è possibilità che non ti svegli abbastanza rapidamente per controllare semplicemente il valore in un ciclo HLT ... ??

(sicuramente, MWAIT potrebbe essere più elevato, ho rifugio ho misurato la risoluzione, ma sembra che si sia sovrastato da (presumo) interruzioni e così via .. quindi non riesco a vedere il grande vantaggio

Grazie, Qualsiasi pensiero in quel modo sarebbe molto gradito

risposta

11

Per prestazioni; ciò che conta di più è il tempo impiegato dalla CPU per uscire dal suo stato di "attesa" ogni volta che si aspetta (un IRQ per HLT, o un IRQ o una memoria scritta per MWAIT). Questo ha effetto sulla latenza - ad es. quanto tempo ci vorrà prima che un gestore di interrupt venga avviato o prima che si verifichi effettivamente un cambio di attività. Il tempo impiegato da una CPU per uscire dallo stato di attesa è diverso per le diverse CPU e potrebbe anche essere leggermente diverso per HLT e MWAIT sulla stessa CPU.

Lo stesso vale per il consumo energetico: la potenza consumata durante l'attesa può variare molto tra le diverse CPU (specialmente quando si inizia a pensare a cose come hyper-threading); e il consumo di energia di HLT rispetto a MWAIT potrebbe anche essere leggermente diverso sulla stessa CPU.

Per l'utilizzo, sono destinati a situazioni diverse. HLT è per l'attesa di un IRQ, mentre MWAIT è per aspettare che si verifichi una scrittura di memoria. Ovviamente se stai aspettando che si verifichi una scrittura in memoria, devi decidere se gli IRQ devono interrompere la tua attesa o meno (ad esempio puoi fare CLI quindi MWAIT se vuoi solo aspettare una scrittura in memoria).

Tuttavia, per i sistemi multi-tasking, per lo più sono entrambi utilizzati solo per la stessa cosa - negli scheduler in cui la CPU è inattiva. Prima che fosse introdotto MONITOR/MWAIT, gli scheduler usavano HLT in attesa di lavoro (per ridurre un po 'il consumo di energia). Ciò significa che se un'altra CPU sblocca un'attività, non può semplicemente mettere quell'attività nella coda dello scheduler e deve inviare un (relativamente costoso) "interrupt inter-processore" alla CPU HLTed per eliminarlo dallo stato HLT (altrimenti la CPU continuerà a fare nulla quando c'è lavoro che può/dovrebbe fare). Con MWAIT, questo "interrupt inter-processore" è (potenzialmente) non necessario - è possibile impostare MONITOR per controllare le scritture nella coda dello scheduler, in modo che l'azione di mettere l'attività in coda sia sufficiente a far smettere di attendere una CPU in attesa .

C'è stato anche qualche studio sull'utilizzo di MONITOR/MWAIT per cose come spinlock e sincronizzazione (ad esempio, in attesa che venga rilasciato un blocco conteso). Il risultato finale di questa ricerca è che il tempo impiegato dalla CPU per uscire dallo stato di "attesa" è troppo alto e usare MONITOR/MWAIT come questo causa troppe perdite di prestazioni (a meno che non ci siano difetti di progettazione - ad esempio usando uno spinlock quando dovresti usare un mutex).

Non riesco a pensare ad alcun altro motivo (al di là di scheduler e blocco/sincronizzazione) per utilizzare HLT o MWAIT.

+0

Brendan, grazie mille per questa panoramica molto informativa, hai sicuramente chiarito la nebbia che avevo intorno a questo. Stavo pensando di usare mon/mwait per sincronizzare tra thread e HW (per evitare setEvent da DPC dopo ogni interrupt proveniente dall'HW). Sembra che la latenza attorno a WaitForSingleObj e SetEvent, in confronto a uno spinlock nel thread in attesa (e una var globale), sia molto più alta, quindi mwait sembra un punto da qualche parte nel mezzo .. –

3

MONITOR/MWAIT deve essere utilizzabile "per cose come spinlock e sincronizzazione (ad esempio, in attesa che venga rilasciato un blocco conteso)."

Tuttavia, MONITOR/MWAIT (a) per una ragione incredibilmente stupida e fastidiosa dovevano essere limitati a essere utilizzati solo dal codice del kernel ring 0, non dal codice utente e (b) caricati con il microcode per entrare in basso stati di sospensione del potere.

Alcune aziende hanno implementato istruzioni simili o equivalenti, ad esempio LL/PAUSE di MIPS è approssimativamente equivalente a MONITOR/MWAIT.

+0

KNL ha una implementazione ring 3: https://software.intel.com/en-us/blogs/2016/10/06/intel-xeon-phi-product-family-x200-knl-user-mode-ring-3-monitor-and-mwait – Jeff

+0

Grazie per le notizie sulla modalità utente MWAIT in KNL. Non vedo l'ora di vedere i dati sulle prestazioni. La mia ipotesi è che a meno che non abbiano implementato la previsione del ramo del microcodice, sarà piuttosto lento. –

+0

Quello che i colleghi mi hanno detto è che un ciclo di spin accuratamente sintonizzato con istruzioni di pausa è più veloce di monitor-mwait, ma che se uno è disposto a scambiare un po 'di latenza, allora monitor-mwait dovrebbe essere praticabile. Anche se il vantaggio diretto non è presente, esiste un enorme vantaggio indiretto derivante dai thread dell'hardware di parcheggio in un ambiente con limitazioni di alimentazione, che sono molti supercomputer.Se hai un benchmark, sentiti libero di contattarmi in privato e cercherò di darti dei dati. – Jeff

7

L'istruzione HLT implementa lo stato di alimentazione al minimo più basso (stato C) disponibile per una singola filettatura, mentre l'istruzione MWAIT consente di richiedere tutti gli stati di alimentazione inattiva disponibili e i sottostati.

A livello hardware, l'esecuzione di HLT equivale all'esecuzione di MWAIT con un suggerimento di stato pari a 0. Questo pone il processore nello stato C1, ovvero il clock gating per il core. Se si desidera inserire C-States più profondi per alimentare il gate al core e potenzialmente alimentare il gate, è necessario utilizzare MWAIT.

C'è sempre un compromesso tra risparmio energetico e latenza di uscita per vari stati di alimentazione. Più profondo è lo stato C, maggiore è il risparmio energetico, ma più tempo è necessario per uscire dallo stato C. Dovresti anche notare che i moderni processori x86 limiteranno la profondità dello stato di alimentazione in base alla frequenza degli interrupt (ad esempio se stai ricevendo eventi di interruzione ogni 1 us, l'hardware non tenterà di entrare in uno stato C con un'uscita 2 us latenza).

Oltre all'hardware che inibisce lo stato C inserito, alcuni stati C possono essere inseriti solo attraverso il coordinamento tra i fili. Ad esempio, su un processore Intel x86 con Hyper-threading, entrambi i thread in un core devono richiedere un C-State con power-gated per il power-gating a livello core, e allo stesso modo tutti i core in un pacchetto devono richiedere un package- livello C-state power-gated per il power-gating che si verifica a livello di pacchetto. L'hardware generalmente soddisfa la richiesta più superficiale, quindi se 1 thread richiede C1 e un altro richiede C3, il processore entra in C1.

Se non si controlla il sistema operativo, allora è davvero un punto controverso (poiché MWAIT è disponibile solo in CPL0). Se si "possiede" il sistema operativo, sarà quasi sempre sensato utilizzare MWAIT anziché HLT, poiché in molti casi si ottiene un risparmio energetico molto più elevato e fornisce l'accesso allo stesso stato di alimentazione inattiva di HLT.