Pregunta

Estoy escribiendo una red Feed Forward en VC ++ usando intrínsecs AVX. Estoy invocando este código a través de Pinvoke en C#. Mi rendimiento al llamar a una función que calcula un bucle grande que incluye la función exp () es de ~ 1000 ms para un tuvo de 160 m. Tan pronto como llamo ningún función que utiliza intrínsecs AVX y luego usa exp (), mi rendimiento cae a aproximadamente ~ 8000 ms para la misma operación. Tenga en cuenta que la función que calcula el exp () es el estándar C, y la llamada que utiliza las intrínsecs AVX puede estar completamente no relacionada en términos de datos que se están procesando. Algún tipo de bandera está siendo tropezada en algún lugar en tiempo de ejecución.

En otras palabras,

A(); // 1000ms calculates 160M exp() 
B(); // completely unrelated but contains AVX
A(); // 8000ms

o, curiosamente,

C(); // contains 128 bit SSE SIMD expressions
A(); // 1000ms

Estoy perdido en cuanto a qué posible mecanismo está sucediendo aquí, o cómo perseguir un Sol'n. Estoy en una CPU Intel 2500K win 7. Versiones expresas de Vs.

Gracias.

¿Fue útil?

Solución

Si usa alguna instrucción AVX256, el "estado superior AVX" se vuelve "sucio", lo que da como resultado un puesto grande si posteriormente utiliza instrucciones de SSE (incluido el punto flotante escalar realizado en los registros XMM). Esto se documenta en el manual de optimización de Intel, que puede Descárgalo gratis (y es una lectura obligada si estás haciendo este tipo de trabajo):

La instrucción AVX siempre modifica los bits superiores de los registros YMM y las instrucciones de SSE no modifican los bits superiores. Desde una perspectiva de hardware, los bits superiores de la colección de registros YMM pueden considerarse en uno de los tres estados:

• Limpio: todos los bits superiores de YMM son cero. Este es el estado cuando el procesador comienza desde el reinicio.

• Modificado y guardado en la región XSAVE El contenido de los bits superiores de los registros YMM coincides datos guardados en la región XSave. Esto sucede cuando después de se ejecuta xsave/xrstor.

• Modificado y no salvado: la ejecución de una instrucción AVX (ya sea de 256 bits o 128 bits) modifica los bits superiores del destino YMM.

La penalización de transición AVX/SSE se aplica cuando el procesador estados está "modificado y no salvado". Usando Vzeroupper Mover los estados del procesador para "limpiar" y evitar la penalización de transición.

Tu rutina B( ) Dirige el estado ymm, por lo que el código SSE en A( ) establos. Insertar un VZEROUPPER instrucción entre B y A para evitar el problema.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top