Некоторые легко запоминающиеся и соответственно неуправляемые неназначенные (на IANA) порты:
27182 (e)
31415 (pi)
60221 (avagadro's)
Одно правило при программировании - не оптимизировать микро.
Другое правило заключается в написании четкого кода.
Но в этом случае применяется другое правило. Если вы пишете оптимизированный код, избегайте любого кода, который может вызвать ветвления, так как вы можете вызвать нежелательные дампы конвейера процессора из-за неудачного предсказания ветвлений.
Помните также, что в ассемблере нет типов bool
и int
как таковых: просто регистры, так что вы, вероятно, обнаружите, что все преобразования будут оптимизированы. Поэтому
b += a;
побеждает для меня; это также яснее.
Компиляторам разрешается предполагать, что базовое значение 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
, создавая более длинную цепочку зависимостей.
При этом я бы беспокоился об этом виде микрооптимизации только в том случае, если вы фактически выполняете свой код под профилировщиком, а результаты указывают на этот конкретный код (или на какой-то жесткий цикл, который его включает); в общем, вы должны написать разумный, семантически правильный код и сосредоточиться на использовании правильных алгоритмов / структур данных. Микрооптимизация наступает позже.
В моей программе это не сработает, поскольку на самом деле это операция типа:
blockquote>b+=(a==c)
Это должно быть еще лучше для оптимизатора Так как у него даже нет никаких сомнений относительно того, откуда исходит
bool
- он может просто принять решение прямо из регистра флагов. Как вы можете видеть , здесь gcc производит довольно схожий код для двух случаев, clang точно такой же, в то время как VC ++, как обычно, создает нечто более условное (acmov
) вif
случай. [тысяча сто тридцать-один]