2017-02-05 3 views
0

Betrachten Sie den folgenden CodeBerechnung Parität parallel

typedef unsigned uint; 

uint parity(uint64_t x) 
    { 
    uint32_t v = x^(x >> 32); 
    v ^= v >> 16; 
    v ^= v >> 8; 
    v ^= v >> 4; 
    v ^= v >> 2; 
    return (uint)(v^(v >> 1)) & 1; 
    } 

Gibt es eine Möglichkeit radikal diesen Code neu zu organisieren eine ernsthafte Verbesserung aufgrund Instruction-Level Parallelität auf etwa ein Intel x86-64 Maschine zu bekommen?

GCC erzeugt den folgenden Code

parity(unsigned long): 
    mov  rax, rdi 
    shr  rax, 32 
    xor  eax, edi 
    mov  edi, eax 
    shr  edi, 16 
    xor  eax, edi 
    mov  edi, eax 
    shr  edi, 8 
    xor  eax, edi 
    mov  edi, eax 
    shr  edi, 4 
    xor  eax, edi 
    mov  edi, eax 
    shr  edi, 2 
    xor  eax, edi 
    mov  edx, eax 
    shr  eax 
    xor  eax, edx 
    and  eax, 1 
    ret 
+1

Was ist '(uint) v'? –

+0

Wenn Sie SSE4.2 haben: 'return _mm_popcnt_u64 (x) & 1;' – Mysticial

+0

Ich habe über Popcnt vergessen - vielen Dank. –

Antwort

-2

In der 32-Bit-Welt würde ich so etwas wie test eax,eax von SETPO EAX folgte direkt in Assembler schreiben.

UPDATE 2017-02-06: @EOF ist richtig, der Testbefehl setzt das Paritätsbit nur nach dem Lowbyte.

+0

Das wäre ein verdammt guter Plan, wenn Sie keinen Popcnt haben. Kann auch auf einem 64-Bit-Prozessor verwendet werden. –

+0

würde 'test rdi, rdi; setpo eax' sei gut? –

+0

eigentlich eine riesige Menge schneller als popcnt auch möglich? –