Domanda

A volte ho incontrato codice che legge TSC con l'istruzione rdtsc, ma le chiamate cpuid a destra prima.

Perché sta chiamando cpuid necessario? Mi rendo conto che possa avere qualcosa a che fare con i valori TSC diversi nuclei che hanno, ma che cosa esattamente che succede quando si chiama queste due istruzioni in sequenza?

È stato utile?

Soluzione

E 'per impedire l'esecuzione out-of-order. Da un link che ormai scomparso dal web (ma che è stato fortuitamente copiato qui prima è scomparsa), questo testo è da un articolo dal titolo "Il monitoraggio delle prestazioni" di un certo John Eckerdal:

  

I processori Pentium Pro e Pentium II supporto out-of-order istruzioni di esecuzione possono essere eseguite in un altro ordine come li avete programmato. Questo può essere una fonte di errori, se non curato.

     

Per evitare questo il programmatore deve serializzare la coda della istruzioni. Questo può essere fatto con l'inserimento di un'istruzione di serializzazione come istruzione CPUID prima che l'istruzione RDTSC.

Altri suggerimenti

Due motivi:

  • Come paxdiablo dice, quando la CPU vede un codice operativo CPUID si assicura vengono eseguite tutte le istruzioni precedenti, quindi il CPUID presa, prima di eventuali istruzioni successive vengono eseguite. Senza un tale istruzione, la pipeline di esecuzione CPU può finire per l'esecuzione di TSC prima dell'istruzione (s) che desideri tempo.
  • Una percentuale significativa di macchine sicuro per sincronizzare i registri TSC attraverso nuclei. In che si desidera leggere da a la bocca del cavallo - bussare te stesso fuori a http://msdn.microsoft.com/en-us/library/ee417693%28VS.85%29.aspx . Così, quando si misura un intervallo tra le letture TSC, a meno che siano prese sullo stesso nucleo avrete un efficace casuale ma possibilmente costante (vedi sotto) Intervallo introdotto - può essere facilmente diversi secondi (sì secondi), anche subito dopo l'avvio . Ciò riflette in modo efficace per quanto tempo il BIOS è stato eseguito su un singolo core, prima dando il via gli altri, più - se avete qualunque opzioni di risparmio energetico brutto - l'aumento deriva causati da core a frequenze diverse o lo spegnimento di nuovo. Quindi, se non avete inchiodato i fili di lettura registri TSC allo stesso nucleo allora avrete bisogno di costruire una sorta di tabella delta cross-core e conoscere l'id nucleo (che viene restituito da CPUID) di ogni campione TSC al fine per compensare questo offset. Questa è un'altra ragione è possibile vedere CPUID fianco RDTSC, e anzi un motivo per cui con le nuove RDTSCP molti sistemi operativi sono la memorizzazione dei numeri di base ID nel più TSC_AUX [31: 0] i dati restituiti. (Disponibile dal Core i7 e Athlon 64 X2, RDTSCP è un molto migliore opzione a tutti gli effetti - il sistema operativo normalmente vi dà l'id di base come detto, atomica alla TSC leggere, e prevenire istruzioni riordino).

CPUID è serializzazione, impedendo esecuzione fuori ordine di RDTSC.

In questi giorni si possono tranquillamente utilizzare al posto LFENCE. E 'documentato come la serializzazione sul flusso di istruzioni (ma non negozi in memoria) su CPU Intel, e ora anche su AMD dopo il loro aggiornamento microcodice per Spectre.

https: // hadibrais.wordpress.com/2018/05/14/the-significance-of-the-x86-lfence-instruction/ spiega di più su LFENCE.

Si veda anche https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/ia-32-ia-64-benchmark -code esecuzione-Paper.pdf di un modo per utilizzare RDTSC P che mantiene CPUID (o LFENCE) fuori dalla regione temporizzato:

LFENCE     ; (or CPUID) Don't start the timed region until everything above has executed
RDTSC           ; EDX:EAX = timestamp
mov  ebx, eax   ; low 32 bits of start time

   code under test

RDTSCP     ; built-in one way barrier stops it from running early
LFENCE     ; (or CPUID) still use a barrier after to prevent anything weird
sub  eax, ebx   ; low 32 bits of end-start

Si veda anche Get conteggio dei cicli della CPU? info sui caveat RDTSC, come constant_tsc e nonstop_tsc .

Come bonus, RDTSCP ti dà un ID nucleo. Si potrebbe utilizzare RDTSCP per l'ora di inizio e, se si desidera controllare per la migrazione di base. Ma se la CPU ha le caratteristiche constant_tsc, tutti i core del pacchetto dovrebbero avere i loro TSC sincronizzati in modo che in genere non è necessario questo su x86 moderna.

Si potrebbe ottenere l'ID del nucleo da CPUID invece, come @ risposta di Tony sottolinea.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top