Могу ли я заменить свои операторы if для экономии времени выполнения? - PullRequest
0 голосов
/ 18 января 2019

Я сейчас пытаюсь улучшить скорость моей программы.

Мне было интересно, поможет ли это заменить все операторы if типа:

bool a=1;
int b=0;
if(a){b++;}

с этим:

bool a=1;
int b=0;

b+=a;

Я не уверен, может ли преобразование из bool в int стать проблемой во времени.

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Компиляторам разрешено предполагать, что базовое значение bool не испорчено, поэтому оптимизирующие компиляторы могут избежать ветвления.

Если мы посмотрим на сгенерированный код для этого искусственного теста

int with_if_bool(bool a, int b) {
    if(a){b++;}
    return b;
}

int with_if_char(unsigned char a, int b) {
    if(a){b++;}
    return b;
}

int without_if(bool a, int b) {
    b += a;
    return b;
}

clang воспользуется этим фактом и сгенерирует точно такой же код без ветвей, который суммирует a и b для версии bool, и вместо этого сгенерирует фактическое сравнение с нулем в случае unsigned char (хотя это все еще код без ветвей ):

with_if_bool(bool, int): # @with_if_bool(bool, int)
  lea eax, [rdi + rsi]
  ret
with_if_char(unsigned char, int): # @with_if_char(unsigned char, int)
  cmp dil, 1
  sbb esi, -1
  mov eax, esi
  ret
without_if(bool, int): # @without_if(bool, int)
  lea eax, [rdi + rsi]
  ret

gcc вместо этого будет обрабатывать bool, как если бы это был unsigned char, без использования его свойств, генерируя код, аналогичный unsigned char случаю clang.

with_if_bool(bool, int):
  mov eax, esi
  cmp dil, 1
  sbb eax, -1
  ret
with_if_char(unsigned char, int):
  mov eax, esi
  cmp dil, 1
  sbb eax, -1
  ret
without_if(bool, int):
  movzx edi, dil
  lea eax, [rdi+rsi]
  ret

Наконец, Visual C ++ будет обрабатывать версии bool и unsigned char одинаково, точно так же, как gcc, хотя и с более наивным кодовым кодом (он использует условное перемещение вместо выполнения арифметики с регистром флагов, который IIRC традиционно использовал для быть менее эффективным, не знаю, для нынешних машин).

a$ = 8
b$ = 16
int with_if_bool(bool,int) PROC ; with_if_bool, COMDAT
  test cl, cl
  lea eax, DWORD PTR [rdx+1]
  cmove eax, edx
  ret 0
int with_if_bool(bool,int) ENDP ; with_if_bool

a$ = 8
b$ = 16
int with_if_char(unsigned char,int) PROC ; with_if_char, COMDAT
  test cl, cl
  lea eax, DWORD PTR [rdx+1]
  cmove eax, edx
  ret 0
int with_if_char(unsigned char,int) ENDP ; with_if_char

a$ = 8
b$ = 16
int without_if(bool,int) PROC ; without_if, COMDAT
  movzx eax, cl
  add eax, edx
  ret 0
int without_if(bool,int) ENDP ; without_if

Во всех случаях ветви не создаются; единственное отличие состоит в том, что на большинстве компиляторов генерируется более сложный код, который зависит от cmp или test, создавая более длинную цепочку зависимостей.

При этом я буду беспокоиться об этом виде микрооптимизации, только если вы фактически запустите свой код под профилировщиком, и результаты указывают на этот конкретный код (или на какой-то жесткий цикл, который его задействует); в общем, вы должны написать разумный, семантически правильный код и сосредоточиться на использовании правильных алгоритмов / структур данных. Микрооптимизация наступит позже.


В моей программе это не сработает, так как на самом деле это операция типа: b+=(a==c)

Это должно быть еще лучше для оптимизатора, так как у него даже нет никаких сомнений относительно того, откуда берется bool - он может просто принять решение прямо из регистра флагов. Как вы можете видеть , здесь gcc выдает довольно схожий код для двух случаев, clang точно такой же, в то время как VC ++, как обычно, выдает нечто более условное (cmov) в if случай.

0 голосов
/ 18 января 2019

Основное правило при программировании - не оптимизировать микро.

Другое правило - писать чистый код.

Но в этом случае применяется другое правило. Если вы пишете оптимизированный код, избегайте любого кода, который может вызвать ветвления, так как вы можете вызвать нежелательные дампы конвейера ЦП из-за неудачного предсказания ветвлений.

Помните также, что в ассемблере нет типов bool и int как таковых: просто регистры, так что вы, вероятно, обнаружите, что все преобразования будут оптимизированы. Поэтому

b += a;

побеждает для меня; это также яснее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...