Actualmente estoy experimentando con la creación de funciones altamente optimizadas y reutilizables para una biblioteca mía. Por ejemplo, escribo la función "es potencia de 2" de la siguiente manera:¿Es posible la función "intrínseca personalizada" para x64 en lugar del montaje en línea?
template<class IntType>
inline bool is_power_of_two(const IntType x)
{
return (x != 0) && ((x & (x - 1)) == 0);
}
Este es un portátil, la implementación de bajo mantenimiento como una plantilla de línea C++. Este código se compila por VC++ 2008 para el siguiente código con ramas:
is_power_of_two PROC
test rcx, rcx
je SHORT [email protected]_power_o
lea rax, QWORD PTR [rcx-1]
test rax, rcx
jne SHORT [email protected]_power_o
mov al, 1
ret 0
[email protected]_power_o:
xor al, al
ret 0
is_power_of_two ENDP
He encontrado también la implementación de aquí: "The bit twiddler", que se codifica en el montaje para x64 de la siguiente manera:
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
I probado ambas subrutinas escritas separadamente de C++ en un módulo de ensamblaje (archivo .asm), ¡y el segundo funciona aproximadamente un 20% más rápido!
Sin embargo, la sobrecarga de la llamada de función es considerable: si comparo la implementación del segundo conjunto "is_power_of_two_fast" con la versión en línea de la función de plantilla, ¡esta última es más rápida a pesar de las ramas!
Desafortunadamente, las nuevas convenciones para x64 especifican que no está permitido el ensamblaje en línea. Uno debería usar "funciones intrínsecas".
Ahora la pregunta: ¿puedo implementar la versión más rápida "is_power_of_two_fast" como una función intrínseca personalizada o algo similar, para que pueda usarse en línea? O, alternativamente, ¿es posible obligar de algún modo al compilador a producir la versión de baja ramificación de la función?
GCC y ICC todavía permitir el ensamblaje en línea – hirschhornsalz
Evitar la rama mediante el uso de y en lugar de &&. –
@drhirsch: gracias, lo recuerdo. @ Hans Passant: Ya lo intenté, pero me lleva a un código más lento (demasiadas instrucciones). –