Uso de las instrucciones de la CPU AVX: bajo rendimiento sin “/ arch: AVX”

Mi código C ++ usa SSE y ahora quiero mejorarlo para que sea compatible con AVX cuando esté disponible. Entonces detecto cuando AVX está disponible y llamo a una función que usa comandos AVX. Uso Win7 SP1 + VS2010 SP1 y una CPU con AVX.

Para usar AVX, es necesario incluir esto:

#include "immintrin.h" 

y luego puede usar funciones AVX intrínsecas como _mm256_mul_ps , _mm256_mul_ps , etc. El problema es que, de manera predeterminada, VS2010 produce código que funciona muy lentamente y muestra la advertencia:

advertencia C4752: se encontraron las Extensiones de Vector Avanzadas de Intel (R); considere usar / arch: AVX

Parece que VS2010 en realidad no usa las instrucciones AVX, sino que las emula. Agregué /arch:AVX a las opciones del comstackdor y obtuve buenos resultados. Pero esta opción le dice al comstackdor que use comandos AVX en todas partes cuando sea posible. ¡Entonces mi código puede bloquearse en la CPU que no es compatible con AVX!

Entonces, la pregunta es cómo hacer que el comstackdor VS2010 produzca código AVX, pero solo cuando especifique los intrínsecos AVX directamente. Para SSE funciona, solo uso las funciones intrínsecas de SSE y produce código SSE sin ninguna opción de comstackción como /arch:SSE . Pero para AVX no funciona por alguna razón.

El comportamiento que está viendo es el resultado de un costoso cambio de estado.

Consulte la página 102 del manual de Agner Fog:

http://www.agner.org/optimize/microarchitecture.pdf

Cada vez que cambie incorrectamente entre las instrucciones SSE y AVX, pagará una penalización de ciclo extremadamente alta (~ 70).

Cuando comstack sin /arch:AVX , VS2010 generará instrucciones de SSE, pero seguirá utilizando AVX siempre que tenga intrínsecos de AVX. Por lo tanto, obtendrás un código que tiene instrucciones SSE y AVX, que tendrán esas penalizaciones de cambio de estado. (VS2010 lo sabe, por lo que emite la advertencia que está viendo).

Por lo tanto, debe usar todas las SSE o todas las AVX. Especificando /arch:AVX le dice al comstackdor que use todo AVX.

Parece que estás intentando crear varias rutas de código: una para SSE y otra para AVX. Para esto, sugiero que separe su código SSE y AVX en dos unidades de comstackción diferentes. (uno comstackdo con /arch:AVX y otro sin) A continuación, /arch:AVX y /arch:AVX un despachador para elegir en función del hardware en el que se ejecuta.

Si necesita mezclar SSE y AVX, asegúrese de usar _mm256_zeroupper() o _mm256_zeroall() apropiada para evitar las penalizaciones de cambio de estado.