Domanda

Di seguito è una clip da un elenco di due sequenze di assemblaggio Pentium. Abbiamo un anello esterno che sta cercando di tanto i nostri sequenze e sta facendo una chiamata attraverso il tavolo per arrivare a queste routine. Pertanto, la chiamata esterna è stato fatto dalla stessa posizione ogni volta. Le due sequenze differire dal fatto che il primo ha un'istruzione minore della seconda.

I risultati che otteniamo su due macchine Intel sono molto diverse.

L'istruzione CPUID racconta la Famiglia, modello, e un passo.

La macchina 1: Famiglia 6, Modello 15 Stepping 11. CPUZ segnala "Intel Core 2 Duo E6750"
Le istruzioni vengono eseguite presso statisticamente alla stessa velocità.

Macchina 2: famiglia 15, Model 3, Fare un passo 3. CPUZ segnala "Intel Pentium 4"
La prima sequenza dura circa 8% più lunga della seconda sequenza.

Non possiamo spiegare l'aumento del tempo. Non ci dovrebbe essere diverso bandiera hold-off, la previsione di rami, registrarsi problemi di utilizzo, ecc Almeno non che si possa dire.

Qualcuno ha un idea del perché la prima sequenza sarebbe necessario più tempo per eseguire sul una macchina?

Modifica: Aggiunta "ereg XOR PTR, 0" per la prima sequenza non rendere la temporizzazione corrisponde la seconda sul Pentium 4. curioso

.

Prima sequenza:

00000040               ALUSHIFT_AND_C_V_E LABEL NEAR
00000040  0F B7 04 55       MOVZX   EAX, gwr[(SIZEOF WORD) * EDX]       ; EAX = 0000000000000000 LLLLLLLLLLLLLLLL
   00000000 E
00000048  0F B7 14 4D       MOVZX   EDX, gwr[(SIZEOF WORD) * ECX]       ; EDX = 0000000000000000 RRRRRRRRRRRRRRRR
   00000000 E
00000050  23 C2             AND     EAX, EDX                            ; AX = L&R      (result)
00000052  A3 00000000 E     MOV     dvalue, EAX                         ; Save the temporary ALU/Shifter result
00000057  C3                RET                                         ; Return

Seconda sequenza:

00000060               ALUSHIFT_AND_C_V_NE LABEL NEAR
00000060  0F B7 04 55       MOVZX   EAX, gwr[(SIZEOF WORD) * EDX]       ; EAX = 0000000000000000 LLLLLLLLLLLLLLLL
   00000000 E
00000068  0F B7 14 4D       MOVZX   EDX, gwr[(SIZEOF WORD) * ECX]       ; EDX = 0000000000000000 RRRRRRRRRRRRRRRR
   00000000 E
00000070  23 C2             AND     EAX, EDX                            ; AX = L&R      (result)
00000072  80 35 00000000 E  XOR     BYTE PTR ereg, 1                    ; E = ~E
   01
00000079  A3 00000000 E     MOV     dvalue, EAX                         ; Save the temporary ALU/Shifter result
0000007E  C3                RET                                         ; Return
È stato utile?

Soluzione

Non

Dopo il Pentium I o II, la maggior parte delle ottimizzazioni eseguite dal compilatore, erano come necessarie. Il chip si decompone queste istruzioni in ops micro e quindi ottimizzare per voi. t potrebbero essere le differenze ramo predizione tra i chip o il fatto che la XOR + RET è altrettanto costoso come RET pianura. Io non sono come familiarità con ciò che i modelli di Pentium si sta guardando sopra per dire. Un'altra possibilità è che potrebbe anche essere una differenza problema di cache-line o hardware.

Ci può essere qualcosa nella documentazione Intel o non ci può.

A prescindere. codificatori di montaggio esperti sanno che l'unica verità è ottenuta tramite test, che è quello che sta facendo.

Altri suggerimenti

Si scopre che v'è una certa curiosa interazione con cui si trova il codice che causa l'aumento. Anche se tutto è allineato cache, commutando i blocchi di codice ha causato l'aumento del tempo sulla Pentium-4

Grazie a tutti coloro che hanno trovato il tempo di indagare questo o vedere le cose.

È possibile aggiungere uno, due, ecc PON di fronte a questo codice (e cambiare niente altro) per spostare in cui queste terre nella cache per vedere se ci sono effetti di cache (o semplicemente disattivare la cache). Attenzione però così piccolo come un NOP supplementare può modificare un'istruzione altrove che non può più raggiungere qualcosa usando relativamente al pc di indirizzamento, causando forse più byte di istruzioni che causano sia il codice in prova a muoversi più di desiderato, nonché, eventualmente, una reazione a catena di altri relativamente indirizzata istruzioni per modificare.

Anche se si gioca la partita della cache la natura della bestia qui è la magia all'interno del chip che accetta un flusso di istruzioni e lo divide in mezzo le unità di esecuzione.

Tweak e il test è quello che fa veramente prestazioni, alla fine, anche se non capisco perché. Anche se, non appena ci si sposta che il codice per un chip più vecchio o più recente chip o diversa scheda madre o una stessa famiglia di chip ma diverso passo tutti i tweaks prestazioni possono girare su di voi.

Qualche mese fa, ho avuto qualcosa di simile accadere a me. Il mio progetto ha un configure-switch per abilitare l'uso di __thread per le variabili thread-locale. Senza di essa, sarebbe utilizzare pthread_getspecific e simili. Quest'ultimo fa ogni punta tanto quanto la versione __thread più una chiamata di funzione più alcune istruzioni aggiuntive per l'impostazione di argomenti, il salvataggio dei registri, e così via. È interessante notare che la versione più laborioso è stato costantemente più veloce. Solo su Pentium 4, però. Tutti gli altri chip si sono comportati in modo sano.

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