Замена оператора IF (случайное условие) на логическую логику — время выполнения идентично?

(Настройка: Win 7 64, MSVC, 3-е поколение Core i7, 64-битная поддержка, -O2 включена)

Приведенный ниже код имеет три функции — одна имеет оператор IF, который выполняет другой код в зависимости от того, было ли выполнено условие. Я заменил это утверждение IF некоторой логической логикой. Однако сроки идентичны …. Я ожидал, что отсутствие прогнозирования ветвления приведет к более быстрому коду:

#include <iostream>

unsigned long long iterations = 1000000000;

void test1(){
volatile int c = 0;

for(int i=0; i<iterations; i++){
bool condition = __rdtsc() % 2 == 0;
if(condition){
c = 4;
}
else{
c = 5;
}
}
}

void test2(){
volatile int c = 0;

for(int i=0; i<iterations; i++){
bool condition = __rdtsc() % 2 == 0;
c = (4 * condition) + (5 * !condition);
}
}

int main(){
unsigned long long s = 0;
unsigned long long f = 0;
unsigned long long s2 = 0;
unsigned long long f2 = 0;
unsigned int x = 0;
unsigned int y = 0;

start = __rdtscp(&x);
test1();
finish = __rdtscp(&y);

start2 = __rdtscp(&x);
test2();
finish2 = __rdtscp(&y);

std::cout << "1: " << f - s<< std::endl;
std::cout << "2: " << f2- s2<< std::endl;
}

ОБНОВЛЕНИЕ asm:

int main(){
push        rbp
push        rsi
push        rdi
push        r14
sub         rsp,20h
unsigned long long start = 0;
unsigned long long finish = 0;
unsigned long long start2 = 0;
unsigned long long finish2 = 0;
unsigned long long start3 = 0;
unsigned long long finish3 = 0;
unsigned int x = 0;
xor         r8d,r8d
mov         dword ptr [x],r8d
unsigned int y = 0;
mov         dword ptr [y],r8d

start = __rdtscp(&x);
rdtscp
lea         r9,[x]
shl         rdx,20h
mov         dword ptr [r9],ecx
or          rax,rdx
test1();
mov         dword ptr [rsp+60h],r8d
mov         ecx,r8d

start = __rdtscp(&x);
mov         r10,rax
nop         word ptr [rax+rax]
test1();
rdtsc
shl         rdx,20h
or          rax,rdx
xor         al,0FFh
and         al,1
neg         al
sbb         eax,eax
inc         ecx
add         eax,5
mov         dword ptr [rsp+60h],eax
movsxd      rax,ecx
cmp         rax,3E8h
test1();
jb          main+40h (013FFE1280h)
finish = __rdtscp(&y);
rdtscp
lea         r9,[y]
shl         rdx,20h
or          rax,rdx
mov         dword ptr [r9],ecx
mov         rbp,rax

start2 = __rdtscp(&x);
rdtscp
lea         r9,[x]
shl         rdx,20h
mov         dword ptr [r9],ecx
or          rax,rdx
test2();
mov         dword ptr [rsp+60h],r8d
mov         r9d,r8d

start2 = __rdtscp(&x);
mov         r14,rax
nop         word ptr [rax+rax]
test2();
rdtsc
shl         rdx,20h
inc         r9d
or          rax,rdx
xor         al,0FFh
and         al,1
test2();
movzx       ecx,al
lea         eax,[rcx+rcx*8]
mov         dword ptr [rsp+60h],eax
movsxd      rax,r9d
cmp         rax,3E8h
jb          main+0A0h (013FFE12E0h)
finish2 = __rdtscp(&y);

0

Решение

Сгенерированный код не содержит внутренних ветвей ни для одной из функций, поэтому штраф за неправильное предсказание отсутствует.

В первом он преобразует логическое значение в ноль или -1 (около sbb eax,eax) и добавляет его к 5. Это довольно стандартная оптимизация при работе с логическими значениями.

Во втором он умножается на девять (rcx+rcx*8), потому что у вас есть 5 * condition не 5 * !condition,

2

Другие решения


По вопросам рекламы [email protected]