5

Estoy escribiendo un rendimiento crítico, proyecto de C++ donde el 70% de las veces se utiliza el módulo principal 200 línea de procesamiento de datos numéricos.Cómo: Inline Assembler en C++ (en Visual Studio 2010)

me gustaría para optimizar el núcleo usando ensamblador en línea, pero estoy completamente nuevo en esto. Sin embargo, conozco algunos lenguajes de ensamblaje x86, incluido el utilizado por GCC y NASM.

todo lo que sé:

tengo que poner las instrucciones de ensamblador en _asm{} donde yo quiero que sean.

Problema:

  • no tengo idea de por dónde empezar. ¿Cuál es el registro en el momento en que entra en juego mi montaje en línea?
+14

Recuerda que "simplemente escribirlo en ASM" no lo va a hacer más rápido. Para que pueda hacer eso, necesita ser mejor en la optimización de ASM que el compilador. –

Respuesta

12

Puede acceder a las variables por su nombre y copiarlas en los registros. He aquí un ejemplo de MSDN:

int power2(int num, int power) 
{ 
    __asm 
    { 
     mov eax, num ; Get first argument 
     mov ecx, power ; Get second argument 
     shl eax, cl  ; EAX = EAX * (2 to the power of CL) 
    } 
    // Return with result in EAX 
} 

Using C or C++ in ASM blocks podría ser también interesante para usted.

+0

Esto no funcionará para x64 – paulm

6

No hay nada en los registros. como se ejecuta el bloque _asm. Necesitas mover cosas a los registros. Si hay una variable 'a', entonces usted tendría que

__asm { 
    mov eax, [a] 
} 

Vale la pena señalar que VS2010 viene con Microsoft de ensamblador. Haga clic con el botón derecho en un proyecto, vaya a las reglas de compilación y active las reglas de compilación del ensamblador, y el IDE procesará los archivos .asm.

Ésta es una solución algo mejor que apoya proyectos VS2010 32 y 64 bits y la palabra clave __asm ​​no funciona en 64 bits construye. Debe utilizar ensamblador externo para el código de 64 bits:/

7

El compilador de Microsoft es muy pobre en optimizaciones cuando el conjunto se involucra en línea. Tiene que hacer una copia de seguridad de los registros porque si usa eax, entonces no moverá eax a otro registro gratuito, continuará usando eax. El ensamblador de GCC está mucho más avanzado en este frente.

Para evitar esto Microsoft comenzó a ofrecer intrinsics. Estas son una forma muy diferente de hacer su optimización, ya que le permite al compilador trabajar con usted. Como Chris mencionó que el ensamblaje en línea no funciona en x64 con el compilador de MS, así que en esa plataforma REALMENTE es mejor que simplemente utilices los intrínsecos.

Son fáciles de usar y dar un buen rendimiento. Voy a admitir que a menudo soy capaz de exprimir un poco más ciclos fuera de ella mediante el uso de un ensamblador externo, sino que son buenos sangrienta para la mejora de la productividad que proporcionan

+7

No llamaría al compilador deficiente, realmente no tiene forma de saber si pretendía cambiar un registro para el siguiente código C o si desea escribir su propio código sin afectarlo El resto del mundo. Cuando la gente culpa a los compiladores, generalmente encuentro que simplemente no entienden todo lo que está involucrado. – Blindy

+0

PUEDO decir que es pobre en esas circunstancias porque ES pobre. SÍ sé qué está pasando allí y TAMBIÉN sé que Microsoft recomienda no usar el ensamblaje en línea EXACTAMENTE por ese motivo. – Goz

+0

@Blindy "realmente no tiene forma de saber si ..." - Bueno, GCC sí lo sabe. Porque proporciona medios para declarar la 'interfaz' del ensamblaje en línea al resto del programa. – JimmyB

0

Ir a la primera fruta madura ...

Como han dicho otros, el compilador de Microsoft es bastante pobre en optimización. Puede ahorrarse un gran esfuerzo simplemente invirtiendo en un compilador decente, como el ICC de Intel, y volver a compilar el código "tal cual". Puede obtener una licencia de evaluación gratuita de 30 días de Intel y probarla.

Además, si tiene la opción de construir un ejecutable de 64 bits, ejecutar en el modo de 64 bits puede generar una mejora del 30% en el rendimiento, debido al aumento de x2 en el número de registros disponibles.

2

Prefiero escribir funciones completas en el ensamblaje en lugar de usar el ensamblaje inline. Esto le permite intercambiar la función de lenguaje de alto nivel con la de ensamblaje durante el proceso de compilación. Además, no tiene que preocuparse de que las optimizaciones del compilador se interpongan.

Antes de escribir una sola línea de ensamblaje, imprima la lista del idioma del conjunto para su función. Esto te proporciona una base sobre la cual construir o modificar. Otra herramienta útil es el entrelazado de ensamblaje con el código fuente. Esto le dirá cómo el compilador está codificando declaraciones específicas.

Si necesita insertar el ensamblaje en línea para una función grande, cree una nueva función para el código que necesita alinear. Nuevamente reemplace con C++ o ensamble durante el tiempo de compilación.

Estas son mis sugerencias, Su kilometraje puede variar (YMMV).

1

Me gusta mucho el ensamblaje, así que no voy a ser un negacionista aquí. Parece que ha perfilado su código y encontrado el 'punto de acceso', que es la forma correcta de comenzar. También asumo que las 200 líneas en cuestión no usan muchas construcciones de alto nivel como vector.

Tengo que dar un poco de advertencia: si el cálculo numérico involucra matemáticas de coma flotante, te espera un mundo de dolor, específicamente un conjunto completo de specialized instructions, y un valor universitario de algorithmic study.

Dicho todo esto: si yo fuera usted, pasaría por el código en cuestión en el depurador VS, utilizando la vista Desensamblaje. Si te sientes cómodo leyendo el código a medida que avanzas, es una buena señal. Después de eso, realice una compilación de Liberación (Debug desactiva la optimización) y genere una lista de ASM para ese módulo. Luego si cree que puede mejorar ... tiene un lugar para comenzar. Las respuestas de otras personas se vincularon a la documentación de MSDN, que es realmente bastante escasa pero aún es un comienzo razonable.