В настоящее время я экспериментирую с созданием высокооптимизированных, многократно используемых функций для моей библиотеки. Например, я пишу функцию «является степенью 2» следующим образом:
template<class IntType>
inline bool is_power_of_two( const IntType x )
{
return (x != 0) && ((x & (x - 1)) == 0);
}
Это переносимая, не требующая обслуживания реализация в виде встроенного шаблона C ++. Этот код компилируется VC ++ 2008 в следующий код с ветвями:
is_power_of_two PROC
test rcx, rcx
je SHORT $LN3@is_power_o
lea rax, QWORD PTR [rcx-1]
test rax, rcx
jne SHORT $LN3@is_power_o
mov al, 1
ret 0
$LN3@is_power_o:
xor al, al
ret 0
is_power_of_two ENDP
Я также нашел реализацию здесь: "Битовый тиддлер" , который будет закодирован в сборке для x64 следующим образом:
is_power_of_two_fast PROC
test rcx, rcx
je SHORT NotAPowerOfTwo
lea rax, [rcx-1]
and rax, rcx
neg rax
sbb rax, rax
inc rax
ret
NotAPowerOfTwo:
xor rax, rax
ret
is_power_of_two_fast ENDP
Я протестировал обе подпрограммы, написанные отдельно от C ++ в модуле сборки (файл .asm), а вторая работает примерно на 20% быстрее!
И все же издержки вызова функции значительны: если я сравним реализацию второй сборки "is_power_of_two_fast" с inline'd-версией функции шаблона, последняя быстрее, несмотря на ветви!
К сожалению, новые соглашения для x64 указывают, что встроенная сборка недопустима. Вместо этого следует использовать «внутренние функции».
Теперь вопрос: могу ли я реализовать более быструю версию "is_power_of_two_fast" как собственную встроенную функцию или нечто подобное, чтобы ее можно было использовать inline? Или, в качестве альтернативы, можно ли каким-то образом заставить компилятор создать версию функции с низкой ветвью?