Ich habe eine Compare()
Funktion, die wie folgt aussieht:Micro-Optimierung einer C++ Vergleichsfunktion
inline bool Compare(bool greater, int p1, int p2) {
if (greater) return p1>=p2;
else return p1<=p2;
}
I Verzweigung zu optimieren entschied zu vermeiden:
inline bool Compare2(bool greater, int p1, int p2) {
bool ret[2] = {p1<=p2,p1>=p2};
return ret[greater];
}
ich dann, indem Sie diese getestet:
Die Ergebnisse:
Compare(): 3.14ns avg
Compare2(): 1.61ns avg
Ich würde sagen, Fall geschlossen, vermeiden Verzweigung FTW. Aber für die Vollständigkeit, ersetzte ich
a[i] = rand()%2;
mit:
a[i] = true;
und bekam genau die gleiche Messung von ~ 3.14ns. Vermutlich gibt es dann keine Verzweigung, und der Compiler schreibt tatsächlich Compare()
um, um die if
Anweisung zu vermeiden. Aber warum ist Compare2()
schneller?
Leider bin ich Assembler-Analphabet, sonst hätte ich versucht, das selbst zu beantworten.
EDIT: Im Folgenden finden Sie einige Montage:
_Z7Comparebii:
.LFB4:
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
movl %edi, %eax
movl %esi, -8(%rbp)
movl %edx, -12(%rbp)
movb %al, -4(%rbp)
cmpb $0, -4(%rbp)
je .L2
movl -8(%rbp), %eax
cmpl -12(%rbp), %eax
setge %al
jmp .L3
.L2:
movl -8(%rbp), %eax
cmpl -12(%rbp), %eax
setle %al
.L3:
leave
ret
.cfi_endproc
.LFE4:
.size _Z7Comparebii, .-_Z7Comparebii
.section .text._Z8Compare2bii,"axG",@progbits,_Z8Compare2bii,comdat
.weak _Z8Compare2bii
.type _Z8Compare2bii, @function
_Z8Compare2bii:
.LFB5:
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
movl %edi, %eax
movl %esi, -24(%rbp)
movl %edx, -28(%rbp)
movb %al, -20(%rbp)
movw $0, -16(%rbp)
movl -24(%rbp), %eax
cmpl -28(%rbp), %eax
setle %al
movb %al, -16(%rbp)
movl -24(%rbp), %eax
cmpl -28(%rbp), %eax
setge %al
movb %al, -15(%rbp)
movzbl -20(%rbp), %eax
cltq
movzbl -16(%rbp,%rax), %eax
leave
ret
.cfi_endproc
.LFE5:
.size _Z8Compare2bii, .-_Z8Compare2bii
.text
nun der eigentliche Code, der den Test verwenden könnte inlined Versionen der oben genannten zwei Funktionen erfüllt, so besteht die Möglichkeit, das der falsche sein könnte Code zu analysieren. Mit diesem gesagt, sehe ich einen jmp
Befehl in Compare()
, also denke ich, dass es bedeutet, dass es sich verzweigt. Wenn ja, denke ich, diese Frage wird: Warum verbessert der Zweig Prädiktor nicht die Leistung von Compare()
, wenn ich a[i]
von rand()%2
zu true
(oder false
für diese Angelegenheit) ändern?
EDIT2: Ich ersetzt "Verzweigung Vorhersage" mit "Verzweigung", um meine Post sinnvoller zu machen.
'optimieren Zweig zu vermeiden prediction' Isn‘ t das ein Oxymoron? –
Sie müssen den Assembly-Code teilen, denn was passiert, hängt sehr davon ab, welchen Compiler Sie verwenden und auf welcher Optimierungsstufe. –
@ Last Line: Warum postest du dann nicht die Assembly? –