2013-04-26 6 views
6

EDIT: In effetti, ho avuto uno strano errore nel mio codice di temporizzazione che ha portato a questi risultati. Quando ho corretto il mio errore, la versione smart si è conclusa più velocemente come previsto. Il mio codice di temporizzazione si presentava così:Operatore XOR lento

bool x = false; 
before = now(); 
for (int i=0; i<N; ++i) { 
    x ^= smart_xor(A[i],B[i]); 
} 
after = now(); 

avevo fatto la ^= per scoraggiare il mio compilatore di ottimizzare il ciclo for distanza. Ma penso che lo ^= in qualche modo interagisca stranamente con le due funzioni xor. Ho modificato il mio codice temporale per compilare semplicemente una serie di risultati xor e quindi eseguire il calcolo con tale array al di fuori del codice temporizzato. E quelle cose fisse.

Devo eliminare questa domanda?

FINE EDIT

Ho definito due funzioni C++ come segue:

bool smart_xor(bool a, bool b) { 
    return a^b; 
} 

bool dumb_xor(bool a, bool b) { 
    return a?!b:b; 
} 

miei test di sincronizzazione indicano che dumb_xor() è leggermente più veloce (1.31ns vs 1.90ns quando inline, 1.92ns vs 2.21ns quando non inline). Questo mi imbarazza, poiché l'operatore ^ dovrebbe essere una singola macchina. Mi chiedo se qualcuno ha una spiegazione.

Il gruppo si presenta così (se non inline):

.file "xor.cpp" 
    .text 
    .p2align 4,,15 
.globl _Z9smart_xorbb 
    .type _Z9smart_xorbb, @function 
_Z9smart_xorbb: 
.LFB0: 
    .cfi_startproc 
    .cfi_personality 0x3,__gxx_personality_v0 
    movl %esi, %eax 
    xorl %edi, %eax 
    ret 
    .cfi_endproc 
.LFE0: 
    .size _Z9smart_xorbb, .-_Z9smart_xorbb 
    .p2align 4,,15 
.globl _Z8dumb_xorbb 
    .type _Z8dumb_xorbb, @function 
_Z8dumb_xorbb: 
.LFB1: 
    .cfi_startproc 
    .cfi_personality 0x3,__gxx_personality_v0 
    movl %esi, %edx 
    movl %esi, %eax 
    xorl $1, %edx 
    testb %dil, %dil 
    cmovne %edx, %eax 
    ret 
    .cfi_endproc 
.LFE1: 
    .size _Z8dumb_xorbb, .-_Z8dumb_xorbb 
    .ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3" 
    .section  .note.GNU-stack,"",@progbits 

sto usando g ++ 4.4.3-4ubuntu5 su un processore Intel Xeon X5570. Ho compilato con -O3.

+0

nanosecondo è probabilmente troppo piccolo per effettuare un confronto significativo. – yngccc

+2

Potrebbe essere necessario mostrare il codice temporale. È facile sbagliare. –

+2

Preferirei 'a! = B' su' a?! B: b'. – Pubby

risposta

4

Dato che il codice "stupido XOR" è significativamente più lungo (e la maggior parte delle istruzioni dipende da una precedente, quindi non verrà eseguito in parallelo), sospetto che tu abbia qualche tipo di errore di misurazione nei risultati.

Il compilatore dovrà produrre due istruzioni per la versione out-of-line di "smart XOR" perché registra i dati in ingresso come non è il registro per dare il risultato di ritorno, quindi i dati devono passare da EDI e ESI a EAX. In una versione inline, il codice dovrebbe essere in grado di utilizzare qualunque registro sia presente prima della chiamata e, se il codice lo consente, il risultato rimane nel registro in cui è entrato.

Chiamare una funzione è out-of-line è probabilmente almeno il tempo di esecuzione del codice effettivo nella funzione.

Sarebbe utile se si showes il test-cablaggio che si utilizza per il benchmarking troppo ...

5

io non credo che tu benchmark il codice correttamente.

si può vedere nel complessivo generato che la funzione è smart_xor:

movl %esi, %eax 
xorl %edi, %eax 

mentre la funzione dumb_xor è:

movl %esi, %edx 
movl %esi, %eax 
xorl $1, %edx 
testb %dil, %dil 
cmovne %edx, %eax 

Così, ovviamente, il primo sarà più veloce.
In caso contrario, si verificano problemi di benchmarking.

Quindi potresti voler regolare il tuo codice di benchmarking ... E ricorda che dovrai eseguire molte chiamate per avere una media buona e significativa.